^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/ceph/ceph_debug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/namei.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/xattr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "super.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "mds_client.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Directory operations: readdir, lookup, create, link, unlink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * rename, etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Ceph MDS operations are specified in terms of a base ino and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * relative path. Thus, the client can specify an operation on a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * specific inode (e.g., a getattr due to fstat(2)), or as a path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * relative to, say, the root directory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Normally, we limit ourselves to strict inode ops (no path component)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * or dentry operations (a single path component relative to an ino). The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * exception to this is open_root_dentry(), which will open the mount
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * point by name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) const struct dentry_operations ceph_dentry_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static bool __dentry_lease_is_valid(struct ceph_dentry_info *di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static int __dir_lease_try_check(const struct dentry *dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * Initialize ceph dentry state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static int ceph_d_init(struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct ceph_dentry_info *di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dentry->d_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) di = kmem_cache_zalloc(ceph_dentry_cachep, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (!di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) return -ENOMEM; /* oh well */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) di->dentry = dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) di->lease_session = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) di->time = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) dentry->d_fsdata = di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) INIT_LIST_HEAD(&di->lease_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) atomic64_inc(&mdsc->metric.total_dentries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * for f_pos for readdir:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * - hash order:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * (0xff << 52) | ((24 bits hash) << 28) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * (the nth entry has hash collision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * - frag+name order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * ((frag value) << 28) | (the nth entry in frag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define OFFSET_BITS 28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define OFFSET_MASK ((1 << OFFSET_BITS) - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define HASH_ORDER (0xffull << (OFFSET_BITS + 24))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) loff_t ceph_make_fpos(unsigned high, unsigned off, bool hash_order)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) loff_t fpos = ((loff_t)high << 28) | (loff_t)off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (hash_order)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) fpos |= HASH_ORDER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return fpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static bool is_hash_order(loff_t p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return (p & HASH_ORDER) == HASH_ORDER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static unsigned fpos_frag(loff_t p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return p >> OFFSET_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static unsigned fpos_hash(loff_t p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return ceph_frag_value(fpos_frag(p));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static unsigned fpos_off(loff_t p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return p & OFFSET_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static int fpos_cmp(loff_t l, loff_t r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int v = ceph_frag_compare(fpos_frag(l), fpos_frag(r));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return (int)(fpos_off(l) - fpos_off(r));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * make note of the last dentry we read, so we can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * continue at the same lexicographical point,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * regardless of what dir changes take place on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * server.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static int note_last_dentry(struct ceph_dir_file_info *dfi, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) int len, unsigned next_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) char *buf = kmalloc(len+1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) kfree(dfi->last_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) dfi->last_name = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) memcpy(dfi->last_name, name, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) dfi->last_name[len] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) dfi->next_offset = next_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) dout("note_last_dentry '%s'\n", dfi->last_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static struct dentry *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) __dcache_find_get_entry(struct dentry *parent, u64 idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct ceph_readdir_cache_control *cache_ctl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct inode *dir = d_inode(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) unsigned idx_mask = (PAGE_SIZE / sizeof(struct dentry *)) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) loff_t ptr_pos = idx * sizeof(struct dentry *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) pgoff_t ptr_pgoff = ptr_pos >> PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (ptr_pos >= i_size_read(dir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (!cache_ctl->page || ptr_pgoff != page_index(cache_ctl->page)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) ceph_readdir_cache_release(cache_ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) cache_ctl->page = find_lock_page(&dir->i_data, ptr_pgoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (!cache_ctl->page) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) dout(" page %lu not found\n", ptr_pgoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return ERR_PTR(-EAGAIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* reading/filling the cache are serialized by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) i_mutex, no need to use page lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) unlock_page(cache_ctl->page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) cache_ctl->dentries = kmap(cache_ctl->page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) cache_ctl->index = idx & idx_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) spin_lock(&parent->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /* check i_size again here, because empty directory can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * marked as complete while not holding the i_mutex. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (ceph_dir_is_complete_ordered(dir) && ptr_pos < i_size_read(dir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) dentry = cache_ctl->dentries[cache_ctl->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) dentry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) spin_unlock(&parent->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (dentry && !lockref_get_not_dead(&dentry->d_lockref))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) dentry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return dentry ? : ERR_PTR(-EAGAIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * When possible, we try to satisfy a readdir by peeking at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * dcache. We make this work by carefully ordering dentries on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * d_child when we initially get results back from the MDS, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * falling back to a "normal" sync readdir if any dentries in the dir
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * are dropped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * Complete dir indicates that we have all dentries in the dir. It is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * defined IFF we hold CEPH_CAP_FILE_SHARED (which will be revoked by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * the MDS if/when the directory is modified).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static int __dcache_readdir(struct file *file, struct dir_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) int shared_gen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct ceph_dir_file_info *dfi = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct dentry *parent = file->f_path.dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct inode *dir = d_inode(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct dentry *dentry, *last = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct ceph_dentry_info *di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct ceph_readdir_cache_control cache_ctl = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) u64 idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) dout("__dcache_readdir %p v%u at %llx\n", dir, (unsigned)shared_gen, ctx->pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /* search start position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (ctx->pos > 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) u64 count = div_u64(i_size_read(dir), sizeof(struct dentry *));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) while (count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) u64 step = count >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) dentry = __dcache_find_get_entry(parent, idx + step,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) &cache_ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (!dentry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /* use linar search */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (IS_ERR(dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) err = PTR_ERR(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) di = ceph_dentry(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) spin_lock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (fpos_cmp(di->offset, ctx->pos) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) idx += step + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) count -= step + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) count = step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) spin_unlock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) dout("__dcache_readdir %p cache idx %llu\n", dir, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) bool emit_dentry = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) dentry = __dcache_find_get_entry(parent, idx++, &cache_ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (!dentry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) dfi->file_info.flags |= CEPH_F_ATEND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (IS_ERR(dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) err = PTR_ERR(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) spin_lock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) di = ceph_dentry(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (d_unhashed(dentry) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) d_really_is_negative(dentry) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) di->lease_shared_gen != shared_gen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) spin_unlock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) err = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (fpos_cmp(ctx->pos, di->offset) <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) __ceph_dentry_dir_lease_touch(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) emit_dentry = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) spin_unlock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (emit_dentry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) dout(" %llx dentry %p %pd %p\n", di->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) dentry, dentry, d_inode(dentry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) ctx->pos = di->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (!dir_emit(ctx, dentry->d_name.name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) dentry->d_name.len, ceph_present_inode(d_inode(dentry)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) d_inode(dentry)->i_mode >> 12)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) ctx->pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) dput(last);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) last = dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) ceph_readdir_cache_release(&cache_ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (last) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) di = ceph_dentry(last);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) ret = note_last_dentry(dfi, last->d_name.name, last->d_name.len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) fpos_off(di->offset) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) err = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) dput(last);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) /* last_name no longer match cache index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (dfi->readdir_cache_idx >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) dfi->readdir_cache_idx = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) dfi->dir_release_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static bool need_send_readdir(struct ceph_dir_file_info *dfi, loff_t pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (!dfi->last_readdir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (is_hash_order(pos))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return !ceph_frag_contains_value(dfi->frag, fpos_hash(pos));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return dfi->frag != fpos_frag(pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static int ceph_readdir(struct file *file, struct dir_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) struct ceph_dir_file_info *dfi = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct inode *inode = file_inode(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct ceph_inode_info *ci = ceph_inode(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct ceph_mds_client *mdsc = fsc->mdsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) unsigned frag = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) struct ceph_mds_reply_info_parsed *rinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) dout("readdir %p file %p pos %llx\n", inode, file, ctx->pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (dfi->file_info.flags & CEPH_F_ATEND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) /* always start with . and .. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (ctx->pos == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) dout("readdir off 0 -> '.'\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (!dir_emit(ctx, ".", 1, ceph_present_inode(inode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) inode->i_mode >> 12))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) ctx->pos = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (ctx->pos == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) u64 ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) struct dentry *dentry = file->f_path.dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) spin_lock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) ino = ceph_present_inode(dentry->d_parent->d_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) spin_unlock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) dout("readdir off 1 -> '..'\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (!dir_emit(ctx, "..", 2, ino, inode->i_mode >> 12))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) ctx->pos = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) spin_lock(&ci->i_ceph_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) /* request Fx cap. if have Fx, we don't need to release Fs cap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) * for later create/unlink. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) __ceph_touch_fmode(ci, mdsc, CEPH_FILE_MODE_WR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) /* can we use the dcache? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (ceph_test_mount_opt(fsc, DCACHE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) !ceph_test_mount_opt(fsc, NOASYNCREADDIR) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) ceph_snap(inode) != CEPH_SNAPDIR &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) __ceph_dir_is_complete_ordered(ci) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) __ceph_caps_issued_mask_metric(ci, CEPH_CAP_FILE_SHARED, 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) int shared_gen = atomic_read(&ci->i_shared_gen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) spin_unlock(&ci->i_ceph_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) err = __dcache_readdir(file, ctx, shared_gen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (err != -EAGAIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) spin_unlock(&ci->i_ceph_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* proceed with a normal readdir */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) more:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) /* do we have the correct frag content buffered? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (need_send_readdir(dfi, ctx->pos)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) struct ceph_mds_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) int op = ceph_snap(inode) == CEPH_SNAPDIR ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) CEPH_MDS_OP_LSSNAP : CEPH_MDS_OP_READDIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /* discard old result, if any */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (dfi->last_readdir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) ceph_mdsc_put_request(dfi->last_readdir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) dfi->last_readdir = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (is_hash_order(ctx->pos)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) /* fragtree isn't always accurate. choose frag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) * based on previous reply when possible. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (frag == (unsigned)-1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) frag = ceph_choose_frag(ci, fpos_hash(ctx->pos),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) frag = fpos_frag(ctx->pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) dout("readdir fetching %llx.%llx frag %x offset '%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) ceph_vinop(inode), frag, dfi->last_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (IS_ERR(req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return PTR_ERR(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) err = ceph_alloc_readdir_reply_buffer(req, inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) ceph_mdsc_put_request(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) /* hints to request -> mds selection code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) req->r_direct_mode = USE_AUTH_MDS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (op == CEPH_MDS_OP_READDIR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) req->r_direct_hash = ceph_frag_value(frag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) __set_bit(CEPH_MDS_R_DIRECT_IS_HASH, &req->r_req_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) req->r_inode_drop = CEPH_CAP_FILE_EXCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (dfi->last_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) req->r_path2 = kstrdup(dfi->last_name, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (!req->r_path2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) ceph_mdsc_put_request(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) } else if (is_hash_order(ctx->pos)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) req->r_args.readdir.offset_hash =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) cpu_to_le32(fpos_hash(ctx->pos));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) req->r_dir_release_cnt = dfi->dir_release_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) req->r_dir_ordered_cnt = dfi->dir_ordered_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) req->r_readdir_cache_idx = dfi->readdir_cache_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) req->r_readdir_offset = dfi->next_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) req->r_args.readdir.frag = cpu_to_le32(frag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) req->r_args.readdir.flags =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) cpu_to_le16(CEPH_READDIR_REPLY_BITFLAGS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) req->r_inode = inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) ihold(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) req->r_dentry = dget(file->f_path.dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) err = ceph_mdsc_do_request(mdsc, NULL, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) ceph_mdsc_put_request(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) dout("readdir got and parsed readdir result=%d on "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) "frag %x, end=%d, complete=%d, hash_order=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) err, frag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) (int)req->r_reply_info.dir_end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) (int)req->r_reply_info.dir_complete,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) (int)req->r_reply_info.hash_order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) rinfo = &req->r_reply_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (le32_to_cpu(rinfo->dir_dir->frag) != frag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) frag = le32_to_cpu(rinfo->dir_dir->frag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (!rinfo->hash_order) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) dfi->next_offset = req->r_readdir_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) /* adjust ctx->pos to beginning of frag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) ctx->pos = ceph_make_fpos(frag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) dfi->next_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) dfi->frag = frag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) dfi->last_readdir = req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (test_bit(CEPH_MDS_R_DID_PREPOPULATE, &req->r_req_flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) dfi->readdir_cache_idx = req->r_readdir_cache_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (dfi->readdir_cache_idx < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) /* preclude from marking dir ordered */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) dfi->dir_ordered_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) } else if (ceph_frag_is_leftmost(frag) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) dfi->next_offset == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) /* note dir version at start of readdir so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) * we can tell if any dentries get dropped */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) dfi->dir_release_count = req->r_dir_release_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) dfi->dir_ordered_count = req->r_dir_ordered_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) dout("readdir !did_prepopulate\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) /* disable readdir cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) dfi->readdir_cache_idx = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) /* preclude from marking dir complete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) dfi->dir_release_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /* note next offset and last dentry name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (rinfo->dir_nr > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) struct ceph_mds_reply_dir_entry *rde =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) rinfo->dir_entries + (rinfo->dir_nr-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) unsigned next_offset = req->r_reply_info.dir_end ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 2 : (fpos_off(rde->offset) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) err = note_last_dentry(dfi, rde->name, rde->name_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) next_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) } else if (req->r_reply_info.dir_end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) dfi->next_offset = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) /* keep last name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) rinfo = &dfi->last_readdir->r_reply_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) dout("readdir frag %x num %d pos %llx chunk first %llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) dfi->frag, rinfo->dir_nr, ctx->pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) rinfo->dir_nr ? rinfo->dir_entries[0].offset : 0LL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) /* search start position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (rinfo->dir_nr > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) int step, nr = rinfo->dir_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) while (nr > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) step = nr >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (rinfo->dir_entries[i + step].offset < ctx->pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) i += step + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) nr -= step + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) nr = step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) for (; i < rinfo->dir_nr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) struct ceph_mds_reply_dir_entry *rde = rinfo->dir_entries + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) BUG_ON(rde->offset < ctx->pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) ctx->pos = rde->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) dout("readdir (%d/%d) -> %llx '%.*s' %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) i, rinfo->dir_nr, ctx->pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) rde->name_len, rde->name, &rde->inode.in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) BUG_ON(!rde->inode.in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (!dir_emit(ctx, rde->name, rde->name_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) ceph_present_ino(inode->i_sb, le64_to_cpu(rde->inode.in->ino)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) le32_to_cpu(rde->inode.in->mode) >> 12)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) dout("filldir stopping us...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) ctx->pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) ceph_mdsc_put_request(dfi->last_readdir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) dfi->last_readdir = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (dfi->next_offset > 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) frag = dfi->frag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) goto more;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) /* more frags? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (!ceph_frag_is_rightmost(dfi->frag)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) frag = ceph_frag_next(dfi->frag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (is_hash_order(ctx->pos)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) loff_t new_pos = ceph_make_fpos(ceph_frag_value(frag),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) dfi->next_offset, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (new_pos > ctx->pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) ctx->pos = new_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) /* keep last_name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) ctx->pos = ceph_make_fpos(frag, dfi->next_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) kfree(dfi->last_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) dfi->last_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) dout("readdir next frag is %x\n", frag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) goto more;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) dfi->file_info.flags |= CEPH_F_ATEND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) * if dir_release_count still matches the dir, no dentries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) * were released during the whole readdir, and we should have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) * the complete dir contents in our cache.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (atomic64_read(&ci->i_release_count) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) dfi->dir_release_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) spin_lock(&ci->i_ceph_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (dfi->dir_ordered_count ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) atomic64_read(&ci->i_ordered_count)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) dout(" marking %p complete and ordered\n", inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) /* use i_size to track number of entries in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * readdir cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) BUG_ON(dfi->readdir_cache_idx < 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) i_size_write(inode, dfi->readdir_cache_idx *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) sizeof(struct dentry*));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) dout(" marking %p complete\n", inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) __ceph_dir_set_complete(ci, dfi->dir_release_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) dfi->dir_ordered_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) spin_unlock(&ci->i_ceph_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) dout("readdir %p file %p done.\n", inode, file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) static void reset_readdir(struct ceph_dir_file_info *dfi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) if (dfi->last_readdir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) ceph_mdsc_put_request(dfi->last_readdir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) dfi->last_readdir = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) kfree(dfi->last_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) dfi->last_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) dfi->dir_release_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) dfi->readdir_cache_idx = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) dfi->next_offset = 2; /* compensate for . and .. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) dfi->file_info.flags &= ~CEPH_F_ATEND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) * discard buffered readdir content on seekdir(0), or seek to new frag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) * or seek prior to current chunk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) static bool need_reset_readdir(struct ceph_dir_file_info *dfi, loff_t new_pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) struct ceph_mds_reply_info_parsed *rinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) loff_t chunk_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (new_pos == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (is_hash_order(new_pos)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) /* no need to reset last_name for a forward seek when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) * dentries are sotred in hash order */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) } else if (dfi->frag != fpos_frag(new_pos)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) rinfo = dfi->last_readdir ? &dfi->last_readdir->r_reply_info : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (!rinfo || !rinfo->dir_nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) chunk_offset = rinfo->dir_entries[0].offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return new_pos < chunk_offset ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) is_hash_order(new_pos) != is_hash_order(chunk_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int whence)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) struct ceph_dir_file_info *dfi = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) struct inode *inode = file->f_mapping->host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) loff_t retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) inode_lock(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) retval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) switch (whence) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) case SEEK_CUR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) offset += file->f_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) case SEEK_SET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) case SEEK_END:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) retval = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (offset >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (need_reset_readdir(dfi, offset)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) dout("dir_llseek dropping %p content\n", file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) reset_readdir(dfi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) } else if (is_hash_order(offset) && offset > file->f_pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) /* for hash offset, we don't know if a forward seek
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) * is within same frag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) dfi->dir_release_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) dfi->readdir_cache_idx = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (offset != file->f_pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) file->f_pos = offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) file->f_version = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) dfi->file_info.flags &= ~CEPH_F_ATEND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) retval = offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) inode_unlock(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * Handle lookups for the hidden .snap directory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) int ceph_handle_snapdir(struct ceph_mds_request *req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) struct dentry *dentry, int err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) struct inode *parent = d_inode(dentry->d_parent); /* we hold i_mutex */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) /* .snap dir? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (err == -ENOENT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) ceph_snap(parent) == CEPH_NOSNAP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) strcmp(dentry->d_name.name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) fsc->mount_options->snapdir_name) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) struct inode *inode = ceph_get_snapdir(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) dout("ENOENT on snapdir %p '%pd', linking to snapdir %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) dentry, dentry, inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) BUG_ON(!d_unhashed(dentry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) d_add(dentry, inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) * Figure out final result of a lookup/open request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) * Mainly, make sure we return the final req->r_dentry (if it already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) * existed) in place of the original VFS-provided dentry when they
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) * differ.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) * Gracefully handle the case where the MDS replies with -ENOENT and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * no trace (which it may do, at its discretion, e.g., if it doesn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) * care to issue a lease on the negative dentry).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) struct dentry *ceph_finish_lookup(struct ceph_mds_request *req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) struct dentry *dentry, int err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (err == -ENOENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) /* no trace? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (!req->r_reply_info.head->is_dentry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) dout("ENOENT and no trace, dentry %p inode %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) dentry, d_inode(dentry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (d_really_is_positive(dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) d_drop(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) err = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) d_add(dentry, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) dentry = ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) else if (dentry != req->r_dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) dentry = dget(req->r_dentry); /* we got spliced */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) dentry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) return dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) static bool is_root_ceph_dentry(struct inode *inode, struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) return ceph_ino(inode) == CEPH_INO_ROOT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) strncmp(dentry->d_name.name, ".ceph", 5) == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) * Look up a single dir entry. If there is a lookup intent, inform
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) * the MDS so that it gets our 'caps wanted' value in a single op.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) struct ceph_mds_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) int op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) int mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) dout("lookup %p dentry %p '%pd'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) dir, dentry, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (dentry->d_name.len > NAME_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) return ERR_PTR(-ENAMETOOLONG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) /* can we conclude ENOENT locally? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) if (d_really_is_negative(dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) struct ceph_inode_info *ci = ceph_inode(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) struct ceph_dentry_info *di = ceph_dentry(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) spin_lock(&ci->i_ceph_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) dout(" dir %p flags are 0x%lx\n", dir, ci->i_ceph_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (strncmp(dentry->d_name.name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) fsc->mount_options->snapdir_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) dentry->d_name.len) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) !is_root_ceph_dentry(dir, dentry) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) ceph_test_mount_opt(fsc, DCACHE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) __ceph_dir_is_complete(ci) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) __ceph_caps_issued_mask_metric(ci, CEPH_CAP_FILE_SHARED, 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) __ceph_touch_fmode(ci, mdsc, CEPH_FILE_MODE_RD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) spin_unlock(&ci->i_ceph_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) dout(" dir %p complete, -ENOENT\n", dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) d_add(dentry, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) di->lease_shared_gen = atomic_read(&ci->i_shared_gen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) spin_unlock(&ci->i_ceph_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) op = ceph_snap(dir) == CEPH_SNAPDIR ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) CEPH_MDS_OP_LOOKUPSNAP : CEPH_MDS_OP_LOOKUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) req = ceph_mdsc_create_request(mdsc, op, USE_ANY_MDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) if (IS_ERR(req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) return ERR_CAST(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) req->r_dentry = dget(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) req->r_num_caps = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) mask = CEPH_STAT_CAP_INODE | CEPH_CAP_AUTH_SHARED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (ceph_security_xattr_wanted(dir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) mask |= CEPH_CAP_XATTR_SHARED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) req->r_args.getattr.mask = cpu_to_le32(mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) req->r_parent = dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) err = ceph_mdsc_do_request(mdsc, NULL, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) err = ceph_handle_snapdir(req, dentry, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) dentry = ceph_finish_lookup(req, dentry, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) ceph_mdsc_put_request(req); /* will dput(dentry) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) dout("lookup result=%p\n", dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) return dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) * If we do a create but get no trace back from the MDS, follow up with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) * a lookup (the VFS expects us to link up the provided dentry).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) int ceph_handle_notrace_create(struct inode *dir, struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) struct dentry *result = ceph_lookup(dir, dentry, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (result && !IS_ERR(result)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) * We created the item, then did a lookup, and found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) * it was already linked to another inode we already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) * had in our cache (and thus got spliced). To not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) * confuse VFS (especially when inode is a directory),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) * we don't link our dentry to that inode, return an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) * error instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) * This event should be rare and it happens only when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) * we talk to old MDS. Recent MDS does not send traceless
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) * reply for request that creates new inode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) d_drop(result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) return -ESTALE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) return PTR_ERR(result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) static int ceph_mknod(struct inode *dir, struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) umode_t mode, dev_t rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) struct ceph_mds_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) struct ceph_acl_sec_ctx as_ctx = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (ceph_snap(dir) != CEPH_NOSNAP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) return -EROFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (ceph_quota_is_max_files_exceeded(dir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) err = -EDQUOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) err = ceph_pre_init_acls(dir, &mode, &as_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) err = ceph_security_init_secctx(dentry, mode, &as_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) dout("mknod in dir %p dentry %p mode 0%ho rdev %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) dir, dentry, mode, rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_MKNOD, USE_AUTH_MDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (IS_ERR(req)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) err = PTR_ERR(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) req->r_dentry = dget(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) req->r_num_caps = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) req->r_parent = dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) req->r_args.mknod.mode = cpu_to_le32(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) req->r_args.mknod.rdev = cpu_to_le32(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) req->r_dentry_drop = CEPH_CAP_FILE_SHARED | CEPH_CAP_AUTH_EXCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) if (as_ctx.pagelist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) req->r_pagelist = as_ctx.pagelist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) as_ctx.pagelist = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) err = ceph_mdsc_do_request(mdsc, dir, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) if (!err && !req->r_reply_info.head->is_dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) err = ceph_handle_notrace_create(dir, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) ceph_mdsc_put_request(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) ceph_init_inode_acls(d_inode(dentry), &as_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) d_drop(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) ceph_release_acl_sec_ctx(&as_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) static int ceph_create(struct inode *dir, struct dentry *dentry, umode_t mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) bool excl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) return ceph_mknod(dir, dentry, mode, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) static int ceph_symlink(struct inode *dir, struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) const char *dest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) struct ceph_mds_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) struct ceph_acl_sec_ctx as_ctx = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) if (ceph_snap(dir) != CEPH_NOSNAP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) return -EROFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (ceph_quota_is_max_files_exceeded(dir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) err = -EDQUOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) err = ceph_security_init_secctx(dentry, S_IFLNK | 0777, &as_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) dout("symlink in dir %p dentry %p to '%s'\n", dir, dentry, dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SYMLINK, USE_AUTH_MDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) if (IS_ERR(req)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) err = PTR_ERR(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) req->r_path2 = kstrdup(dest, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (!req->r_path2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) ceph_mdsc_put_request(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) req->r_parent = dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) req->r_dentry = dget(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) req->r_num_caps = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) req->r_dentry_drop = CEPH_CAP_FILE_SHARED | CEPH_CAP_AUTH_EXCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) if (as_ctx.pagelist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) req->r_pagelist = as_ctx.pagelist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) as_ctx.pagelist = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) err = ceph_mdsc_do_request(mdsc, dir, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) if (!err && !req->r_reply_info.head->is_dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) err = ceph_handle_notrace_create(dir, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) ceph_mdsc_put_request(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) d_drop(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) ceph_release_acl_sec_ctx(&as_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) static int ceph_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) struct ceph_mds_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) struct ceph_acl_sec_ctx as_ctx = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) int err = -EROFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) int op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (ceph_snap(dir) == CEPH_SNAPDIR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) /* mkdir .snap/foo is a MKSNAP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) op = CEPH_MDS_OP_MKSNAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) dout("mksnap dir %p snap '%pd' dn %p\n", dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) dentry, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) } else if (ceph_snap(dir) == CEPH_NOSNAP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) dout("mkdir dir %p dn %p mode 0%ho\n", dir, dentry, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) op = CEPH_MDS_OP_MKDIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) if (op == CEPH_MDS_OP_MKDIR &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) ceph_quota_is_max_files_exceeded(dir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) err = -EDQUOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) mode |= S_IFDIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) err = ceph_pre_init_acls(dir, &mode, &as_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) err = ceph_security_init_secctx(dentry, mode, &as_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) if (IS_ERR(req)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) err = PTR_ERR(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) req->r_dentry = dget(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) req->r_num_caps = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) req->r_parent = dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) req->r_args.mkdir.mode = cpu_to_le32(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) req->r_dentry_drop = CEPH_CAP_FILE_SHARED | CEPH_CAP_AUTH_EXCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) if (as_ctx.pagelist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) req->r_pagelist = as_ctx.pagelist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) as_ctx.pagelist = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) err = ceph_mdsc_do_request(mdsc, dir, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) if (!err &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) !req->r_reply_info.head->is_target &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) !req->r_reply_info.head->is_dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) err = ceph_handle_notrace_create(dir, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) ceph_mdsc_put_request(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) ceph_init_inode_acls(d_inode(dentry), &as_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) d_drop(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) ceph_release_acl_sec_ctx(&as_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) static int ceph_link(struct dentry *old_dentry, struct inode *dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) struct ceph_mds_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if (ceph_snap(dir) != CEPH_NOSNAP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) return -EROFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) dout("link in dir %p old_dentry %p dentry %p\n", dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) old_dentry, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LINK, USE_AUTH_MDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) if (IS_ERR(req)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) d_drop(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) return PTR_ERR(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) req->r_dentry = dget(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) req->r_num_caps = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) req->r_old_dentry = dget(old_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) req->r_parent = dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) req->r_dentry_drop = CEPH_CAP_FILE_SHARED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) /* release LINK_SHARED on source inode (mds will lock it) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) req->r_old_inode_drop = CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) err = ceph_mdsc_do_request(mdsc, dir, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) d_drop(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) } else if (!req->r_reply_info.head->is_dentry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) ihold(d_inode(old_dentry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) d_instantiate(dentry, d_inode(old_dentry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) ceph_mdsc_put_request(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) static void ceph_async_unlink_cb(struct ceph_mds_client *mdsc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) struct ceph_mds_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) int result = req->r_err ? req->r_err :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) le32_to_cpu(req->r_reply_info.head->result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) if (result == -EJUKEBOX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) /* If op failed, mark everyone involved for errors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) int pathlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) u64 base = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) char *path = ceph_mdsc_build_path(req->r_dentry, &pathlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) &base, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) /* mark error on parent + clear complete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) mapping_set_error(req->r_parent->i_mapping, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) ceph_dir_clear_complete(req->r_parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) /* drop the dentry -- we don't know its status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) if (!d_unhashed(req->r_dentry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) d_drop(req->r_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) /* mark inode itself for an error (since metadata is bogus) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) mapping_set_error(req->r_old_inode->i_mapping, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) pr_warn("ceph: async unlink failure path=(%llx)%s result=%d!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) base, IS_ERR(path) ? "<<bad>>" : path, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) ceph_mdsc_free_path(path, pathlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) iput(req->r_old_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) ceph_mdsc_release_dir_caps(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) static int get_caps_for_async_unlink(struct inode *dir, struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) struct ceph_inode_info *ci = ceph_inode(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) struct ceph_dentry_info *di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) int got = 0, want = CEPH_CAP_FILE_EXCL | CEPH_CAP_DIR_UNLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) spin_lock(&ci->i_ceph_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) if ((__ceph_caps_issued(ci, NULL) & want) == want) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) ceph_take_cap_refs(ci, want, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) got = want;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) spin_unlock(&ci->i_ceph_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) /* If we didn't get anything, return 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if (!got)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) spin_lock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) di = ceph_dentry(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) * - We are holding Fx, which implies Fs caps.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) * - Only support async unlink for primary linkage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if (atomic_read(&ci->i_shared_gen) != di->lease_shared_gen ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) !(di->flags & CEPH_DENTRY_PRIMARY_LINK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) want = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) spin_unlock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) /* Do we still want what we've got? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) if (want == got)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) return got;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) ceph_put_cap_refs(ci, got);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) * rmdir and unlink are differ only by the metadata op code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) static int ceph_unlink(struct inode *dir, struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) struct ceph_mds_client *mdsc = fsc->mdsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) struct inode *inode = d_inode(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) struct ceph_mds_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) bool try_async = ceph_test_mount_opt(fsc, ASYNC_DIROPS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) int err = -EROFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) int op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) if (ceph_snap(dir) == CEPH_SNAPDIR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) /* rmdir .snap/foo is RMSNAP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) dout("rmsnap dir %p '%pd' dn %p\n", dir, dentry, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) op = CEPH_MDS_OP_RMSNAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) } else if (ceph_snap(dir) == CEPH_NOSNAP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) dout("unlink/rmdir dir %p dn %p inode %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) dir, dentry, inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) op = d_is_dir(dentry) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) CEPH_MDS_OP_RMDIR : CEPH_MDS_OP_UNLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) if (IS_ERR(req)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) err = PTR_ERR(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) req->r_dentry = dget(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) req->r_num_caps = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) req->r_parent = dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) req->r_dentry_drop = CEPH_CAP_FILE_SHARED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) req->r_inode_drop = ceph_drop_caps_for_unlink(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) if (try_async && op == CEPH_MDS_OP_UNLINK &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) (req->r_dir_caps = get_caps_for_async_unlink(dir, dentry))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) dout("async unlink on %llu/%.*s caps=%s", ceph_ino(dir),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) dentry->d_name.len, dentry->d_name.name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) ceph_cap_string(req->r_dir_caps));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) set_bit(CEPH_MDS_R_ASYNC, &req->r_req_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) req->r_callback = ceph_async_unlink_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) req->r_old_inode = d_inode(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) ihold(req->r_old_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) err = ceph_mdsc_submit_request(mdsc, dir, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) * We have enough caps, so we assume that the unlink
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) * will succeed. Fix up the target inode and dcache.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) drop_nlink(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) d_delete(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) } else if (err == -EJUKEBOX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) try_async = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) ceph_mdsc_put_request(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) goto retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) err = ceph_mdsc_do_request(mdsc, dir, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) if (!err && !req->r_reply_info.head->is_dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) d_delete(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) ceph_mdsc_put_request(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) struct inode *new_dir, struct dentry *new_dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(old_dir->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) struct ceph_mds_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) int op = CEPH_MDS_OP_RENAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) if (flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) if (ceph_snap(old_dir) != ceph_snap(new_dir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) return -EXDEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) if (ceph_snap(old_dir) != CEPH_NOSNAP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) if (old_dir == new_dir && ceph_snap(old_dir) == CEPH_SNAPDIR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) op = CEPH_MDS_OP_RENAMESNAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) return -EROFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) } else if (old_dir != new_dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) err = ceph_quota_check_rename(mdsc, d_inode(old_dentry),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) new_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) dout("rename dir %p dentry %p to dir %p dentry %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) old_dir, old_dentry, new_dir, new_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) if (IS_ERR(req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) return PTR_ERR(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) ihold(old_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) req->r_dentry = dget(new_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) req->r_num_caps = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) req->r_old_dentry = dget(old_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) req->r_old_dentry_dir = old_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) req->r_parent = new_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) req->r_old_dentry_drop = CEPH_CAP_FILE_SHARED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) req->r_old_dentry_unless = CEPH_CAP_FILE_EXCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) req->r_dentry_drop = CEPH_CAP_FILE_SHARED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) /* release LINK_RDCACHE on source inode (mds will lock it) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) req->r_old_inode_drop = CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) if (d_really_is_positive(new_dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) req->r_inode_drop =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) ceph_drop_caps_for_unlink(d_inode(new_dentry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) err = ceph_mdsc_do_request(mdsc, old_dir, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) if (!err && !req->r_reply_info.head->is_dentry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) * Normally d_move() is done by fill_trace (called by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) * do_request, above). If there is no trace, we need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) * to do it here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) d_move(old_dentry, new_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) ceph_mdsc_put_request(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) * Move dentry to tail of mdsc->dentry_leases list when lease is updated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) * Leases at front of the list will expire first. (Assume all leases have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) * similar duration)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) * Called under dentry->d_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) void __ceph_dentry_lease_touch(struct ceph_dentry_info *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) struct dentry *dn = di->dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) struct ceph_mds_client *mdsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) dout("dentry_lease_touch %p %p '%pd'\n", di, dn, dn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) di->flags |= CEPH_DENTRY_LEASE_LIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) if (di->flags & CEPH_DENTRY_SHRINK_LIST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) di->flags |= CEPH_DENTRY_REFERENCED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) mdsc = ceph_sb_to_client(dn->d_sb)->mdsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) spin_lock(&mdsc->dentry_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) list_move_tail(&di->lease_list, &mdsc->dentry_leases);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) spin_unlock(&mdsc->dentry_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) static void __dentry_dir_lease_touch(struct ceph_mds_client* mdsc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) struct ceph_dentry_info *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) di->flags &= ~(CEPH_DENTRY_LEASE_LIST | CEPH_DENTRY_REFERENCED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) di->lease_gen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) di->time = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) list_move_tail(&di->lease_list, &mdsc->dentry_dir_leases);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) * When dir lease is used, add dentry to tail of mdsc->dentry_dir_leases
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) * list if it's not in the list, otherwise set 'referenced' flag.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) * Called under dentry->d_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) void __ceph_dentry_dir_lease_touch(struct ceph_dentry_info *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) struct dentry *dn = di->dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) struct ceph_mds_client *mdsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) dout("dentry_dir_lease_touch %p %p '%pd' (offset 0x%llx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) di, dn, dn, di->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) if (!list_empty(&di->lease_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) if (di->flags & CEPH_DENTRY_LEASE_LIST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) /* don't remove dentry from dentry lease list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) * if its lease is valid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) if (__dentry_lease_is_valid(di))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) di->flags |= CEPH_DENTRY_REFERENCED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) if (di->flags & CEPH_DENTRY_SHRINK_LIST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) di->flags |= CEPH_DENTRY_REFERENCED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) di->flags &= ~CEPH_DENTRY_LEASE_LIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) mdsc = ceph_sb_to_client(dn->d_sb)->mdsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) spin_lock(&mdsc->dentry_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) __dentry_dir_lease_touch(mdsc, di),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) spin_unlock(&mdsc->dentry_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) static void __dentry_lease_unlist(struct ceph_dentry_info *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) struct ceph_mds_client *mdsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) if (di->flags & CEPH_DENTRY_SHRINK_LIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) if (list_empty(&di->lease_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) mdsc = ceph_sb_to_client(di->dentry->d_sb)->mdsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) spin_lock(&mdsc->dentry_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) list_del_init(&di->lease_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) spin_unlock(&mdsc->dentry_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) KEEP = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) DELETE = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) TOUCH = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) STOP = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) struct ceph_lease_walk_control {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) bool dir_lease;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) bool expire_dir_lease;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) unsigned long nr_to_scan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) unsigned long dir_lease_ttl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) static unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) __dentry_leases_walk(struct ceph_mds_client *mdsc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) struct ceph_lease_walk_control *lwc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) int (*check)(struct dentry*, void*))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) struct ceph_dentry_info *di, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) struct dentry *dentry, *last = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) struct list_head* list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) LIST_HEAD(dispose);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) unsigned long freed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) list = lwc->dir_lease ? &mdsc->dentry_dir_leases : &mdsc->dentry_leases;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) spin_lock(&mdsc->dentry_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) list_for_each_entry_safe(di, tmp, list, lease_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) if (!lwc->nr_to_scan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) --lwc->nr_to_scan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) dentry = di->dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) if (last == dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) if (!spin_trylock(&dentry->d_lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) if (__lockref_is_dead(&dentry->d_lockref)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) list_del_init(&di->lease_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) ret = check(dentry, lwc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) if (ret & TOUCH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) /* move it into tail of dir lease list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) __dentry_dir_lease_touch(mdsc, di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) if (!last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) last = dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) if (ret & DELETE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) /* stale lease */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) di->flags &= ~CEPH_DENTRY_REFERENCED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) if (dentry->d_lockref.count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) /* update_dentry_lease() will re-add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) * it to lease list, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) * ceph_d_delete() will return 1 when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) * last reference is dropped */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) list_del_init(&di->lease_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) di->flags |= CEPH_DENTRY_SHRINK_LIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) list_move_tail(&di->lease_list, &dispose);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) dget_dlock(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) spin_unlock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) if (ret & STOP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) spin_unlock(&mdsc->dentry_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) while (!list_empty(&dispose)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) di = list_first_entry(&dispose, struct ceph_dentry_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) lease_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) dentry = di->dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) spin_lock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) list_del_init(&di->lease_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) di->flags &= ~CEPH_DENTRY_SHRINK_LIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) if (di->flags & CEPH_DENTRY_REFERENCED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) spin_lock(&mdsc->dentry_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) if (di->flags & CEPH_DENTRY_LEASE_LIST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) list_add_tail(&di->lease_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) &mdsc->dentry_leases);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) __dentry_dir_lease_touch(mdsc, di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) spin_unlock(&mdsc->dentry_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) freed++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) spin_unlock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) /* ceph_d_delete() does the trick */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) return freed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) static int __dentry_lease_check(struct dentry *dentry, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) struct ceph_dentry_info *di = ceph_dentry(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) if (__dentry_lease_is_valid(di))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) return STOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) ret = __dir_lease_try_check(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) if (ret == -EBUSY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) return KEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) if (ret > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) return TOUCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) return DELETE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) static int __dir_lease_check(struct dentry *dentry, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) struct ceph_lease_walk_control *lwc = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) struct ceph_dentry_info *di = ceph_dentry(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) int ret = __dir_lease_try_check(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) if (ret == -EBUSY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) return KEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) if (ret > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) if (time_before(jiffies, di->time + lwc->dir_lease_ttl))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) return STOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) /* Move dentry to tail of dir lease list if we don't want
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) * to delete it. So dentries in the list are checked in a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) * round robin manner */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) if (!lwc->expire_dir_lease)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) return TOUCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) if (dentry->d_lockref.count > 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) (di->flags & CEPH_DENTRY_REFERENCED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) return TOUCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) /* invalidate dir lease */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) di->lease_shared_gen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) return DELETE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) int ceph_trim_dentries(struct ceph_mds_client *mdsc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) struct ceph_lease_walk_control lwc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) unsigned long count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) unsigned long freed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) spin_lock(&mdsc->caps_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) if (mdsc->caps_use_max > 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) mdsc->caps_use_count > mdsc->caps_use_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) count = mdsc->caps_use_count - mdsc->caps_use_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) spin_unlock(&mdsc->caps_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) lwc.dir_lease = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) lwc.nr_to_scan = CEPH_CAPS_PER_RELEASE * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) freed = __dentry_leases_walk(mdsc, &lwc, __dentry_lease_check);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) if (!lwc.nr_to_scan) /* more invalid leases */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) if (lwc.nr_to_scan < CEPH_CAPS_PER_RELEASE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) lwc.nr_to_scan = CEPH_CAPS_PER_RELEASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) lwc.dir_lease = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) lwc.expire_dir_lease = freed < count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) lwc.dir_lease_ttl = mdsc->fsc->mount_options->caps_wanted_delay_max * HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) freed +=__dentry_leases_walk(mdsc, &lwc, __dir_lease_check);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) if (!lwc.nr_to_scan) /* more to check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) return freed > 0 ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) * Ensure a dentry lease will no longer revalidate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) void ceph_invalidate_dentry_lease(struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) struct ceph_dentry_info *di = ceph_dentry(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) spin_lock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) di->time = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) di->lease_shared_gen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) di->flags &= ~CEPH_DENTRY_PRIMARY_LINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) __dentry_lease_unlist(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) spin_unlock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) * Check if dentry lease is valid. If not, delete the lease. Try to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) * renew if the least is more than half up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) static bool __dentry_lease_is_valid(struct ceph_dentry_info *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) struct ceph_mds_session *session;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) if (!di->lease_gen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) session = di->lease_session;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) if (session) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) u32 gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) unsigned long ttl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) spin_lock(&session->s_gen_ttl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) gen = session->s_cap_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) ttl = session->s_cap_ttl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) spin_unlock(&session->s_gen_ttl_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) if (di->lease_gen == gen &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) time_before(jiffies, ttl) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) time_before(jiffies, di->time))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) di->lease_gen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) static int dentry_lease_is_valid(struct dentry *dentry, unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) struct ceph_dentry_info *di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) struct ceph_mds_session *session = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) u32 seq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) int valid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) spin_lock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) di = ceph_dentry(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) if (di && __dentry_lease_is_valid(di)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) valid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) if (di->lease_renew_after &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) time_after(jiffies, di->lease_renew_after)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) * We should renew. If we're in RCU walk mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) * though, we can't do that so just return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) * -ECHILD.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) if (flags & LOOKUP_RCU) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) valid = -ECHILD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) session = ceph_get_mds_session(di->lease_session);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) seq = di->lease_seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) di->lease_renew_after = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) di->lease_renew_from = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) spin_unlock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) if (session) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) ceph_mdsc_lease_send_msg(session, dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) CEPH_MDS_LEASE_RENEW, seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) ceph_put_mds_session(session);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) dout("dentry_lease_is_valid - dentry %p = %d\n", dentry, valid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) return valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) * Called under dentry->d_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) static int __dir_lease_try_check(const struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) struct ceph_dentry_info *di = ceph_dentry(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) struct inode *dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) struct ceph_inode_info *ci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) int valid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) if (!di->lease_shared_gen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) if (IS_ROOT(dentry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) dir = d_inode(dentry->d_parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) ci = ceph_inode(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) if (spin_trylock(&ci->i_ceph_lock)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) if (atomic_read(&ci->i_shared_gen) == di->lease_shared_gen &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) valid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) spin_unlock(&ci->i_ceph_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) valid = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) if (!valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) di->lease_shared_gen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) return valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) * Check if directory-wide content lease/cap is valid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) struct ceph_mds_client *mdsc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) struct ceph_inode_info *ci = ceph_inode(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) int valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) int shared_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) spin_lock(&ci->i_ceph_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) valid = __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) if (valid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) __ceph_touch_fmode(ci, mdsc, CEPH_FILE_MODE_RD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) shared_gen = atomic_read(&ci->i_shared_gen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) spin_unlock(&ci->i_ceph_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) if (valid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) struct ceph_dentry_info *di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) spin_lock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) di = ceph_dentry(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) if (dir == d_inode(dentry->d_parent) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) di && di->lease_shared_gen == shared_gen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) __ceph_dentry_dir_lease_touch(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) valid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) spin_unlock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) dout("dir_lease_is_valid dir %p v%u dentry %p = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) dir, (unsigned)atomic_read(&ci->i_shared_gen), dentry, valid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) return valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) * Check if cached dentry can be trusted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) int valid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) struct dentry *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) struct inode *dir, *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) struct ceph_mds_client *mdsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) if (flags & LOOKUP_RCU) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) parent = READ_ONCE(dentry->d_parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) dir = d_inode_rcu(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) if (!dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) return -ECHILD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) inode = d_inode_rcu(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) parent = dget_parent(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) dir = d_inode(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) inode = d_inode(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) dout("d_revalidate %p '%pd' inode %p offset 0x%llx\n", dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) dentry, inode, ceph_dentry(dentry)->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) mdsc = ceph_sb_to_client(dir->i_sb)->mdsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) /* always trust cached snapped dentries, snapdir dentry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) if (ceph_snap(dir) != CEPH_NOSNAP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) dout("d_revalidate %p '%pd' inode %p is SNAPPED\n", dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) dentry, inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) valid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) } else if (inode && ceph_snap(inode) == CEPH_SNAPDIR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) valid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) valid = dentry_lease_is_valid(dentry, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) if (valid == -ECHILD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) return valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) if (valid || dir_lease_is_valid(dir, dentry, mdsc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) if (inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) valid = ceph_is_any_caps(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) valid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) if (!valid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) struct ceph_mds_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) int op, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) u32 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) if (flags & LOOKUP_RCU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) return -ECHILD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) percpu_counter_inc(&mdsc->metric.d_lease_mis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) op = ceph_snap(dir) == CEPH_SNAPDIR ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) CEPH_MDS_OP_LOOKUPSNAP : CEPH_MDS_OP_LOOKUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) req = ceph_mdsc_create_request(mdsc, op, USE_ANY_MDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) if (!IS_ERR(req)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) req->r_dentry = dget(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) req->r_num_caps = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) req->r_parent = dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) mask = CEPH_STAT_CAP_INODE | CEPH_CAP_AUTH_SHARED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) if (ceph_security_xattr_wanted(dir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) mask |= CEPH_CAP_XATTR_SHARED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) req->r_args.getattr.mask = cpu_to_le32(mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) err = ceph_mdsc_do_request(mdsc, NULL, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) switch (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) if (d_really_is_positive(dentry) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) d_inode(dentry) == req->r_target_inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) valid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) case -ENOENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) if (d_really_is_negative(dentry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) valid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) ceph_mdsc_put_request(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) dout("d_revalidate %p lookup result=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) dentry, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) percpu_counter_inc(&mdsc->metric.d_lease_hit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) dout("d_revalidate %p %s\n", dentry, valid ? "valid" : "invalid");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) if (!valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) ceph_dir_clear_complete(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) if (!(flags & LOOKUP_RCU))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) dput(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) return valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) * Delete unused dentry that doesn't have valid lease
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) * Called under dentry->d_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) static int ceph_d_delete(const struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) struct ceph_dentry_info *di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) /* won't release caps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) if (d_really_is_negative(dentry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) if (ceph_snap(d_inode(dentry)) != CEPH_NOSNAP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) /* vaild lease? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) di = ceph_dentry(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) if (di) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) if (__dentry_lease_is_valid(di))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) if (__dir_lease_try_check(dentry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) * Release our ceph_dentry_info.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) static void ceph_d_release(struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) struct ceph_dentry_info *di = ceph_dentry(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) dout("d_release %p\n", dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) atomic64_dec(&fsc->mdsc->metric.total_dentries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) spin_lock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) __dentry_lease_unlist(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) dentry->d_fsdata = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) spin_unlock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) ceph_put_mds_session(di->lease_session);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) kmem_cache_free(ceph_dentry_cachep, di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) * When the VFS prunes a dentry from the cache, we need to clear the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) * complete flag on the parent directory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) * Called under dentry->d_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) static void ceph_d_prune(struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) struct ceph_inode_info *dir_ci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) struct ceph_dentry_info *di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) dout("ceph_d_prune %pd %p\n", dentry, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) /* do we have a valid parent? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) if (IS_ROOT(dentry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) /* we hold d_lock, so d_parent is stable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) dir_ci = ceph_inode(d_inode(dentry->d_parent));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) if (dir_ci->i_vino.snap == CEPH_SNAPDIR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) /* who calls d_delete() should also disable dcache readdir */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) if (d_really_is_negative(dentry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) /* d_fsdata does not get cleared until d_release */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) if (!d_unhashed(dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) __ceph_dir_clear_complete(dir_ci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) /* Disable dcache readdir just in case that someone called d_drop()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) * or d_invalidate(), but MDS didn't revoke CEPH_CAP_FILE_SHARED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) * properly (dcache readdir is still enabled) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) di = ceph_dentry(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) if (di->offset > 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) di->lease_shared_gen == atomic_read(&dir_ci->i_shared_gen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) __ceph_dir_clear_ordered(dir_ci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) * read() on a dir. This weird interface hack only works if mounted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) * with '-o dirstat'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) static ssize_t ceph_read_dir(struct file *file, char __user *buf, size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) struct ceph_dir_file_info *dfi = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) struct inode *inode = file_inode(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) struct ceph_inode_info *ci = ceph_inode(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) int left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) const int bufsize = 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) if (!ceph_test_mount_opt(ceph_sb_to_client(inode->i_sb), DIRSTAT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) return -EISDIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) if (!dfi->dir_info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) dfi->dir_info = kmalloc(bufsize, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) if (!dfi->dir_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) dfi->dir_info_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) snprintf(dfi->dir_info, bufsize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) "entries: %20lld\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) " files: %20lld\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) " subdirs: %20lld\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) "rentries: %20lld\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) " rfiles: %20lld\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) " rsubdirs: %20lld\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) "rbytes: %20lld\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) "rctime: %10lld.%09ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) ci->i_files + ci->i_subdirs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) ci->i_files,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) ci->i_subdirs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) ci->i_rfiles + ci->i_rsubdirs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) ci->i_rfiles,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) ci->i_rsubdirs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) ci->i_rbytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) ci->i_rctime.tv_sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) ci->i_rctime.tv_nsec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) if (*ppos >= dfi->dir_info_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) size = min_t(unsigned, size, dfi->dir_info_len-*ppos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) left = copy_to_user(buf, dfi->dir_info + *ppos, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) if (left == size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) *ppos += (size - left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) return size - left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) * Return name hash for a given dentry. This is dependent on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) * the parent directory's hash function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) unsigned ceph_dentry_hash(struct inode *dir, struct dentry *dn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) struct ceph_inode_info *dci = ceph_inode(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) unsigned hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) switch (dci->i_dir_layout.dl_dir_hash) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) case 0: /* for backward compat */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) case CEPH_STR_HASH_LINUX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) return dn->d_name.hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) spin_lock(&dn->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) hash = ceph_str_hash(dci->i_dir_layout.dl_dir_hash,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) dn->d_name.name, dn->d_name.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) spin_unlock(&dn->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) return hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) const struct file_operations ceph_dir_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) .read = ceph_read_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) .iterate = ceph_readdir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) .llseek = ceph_dir_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) .open = ceph_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) .release = ceph_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) .unlocked_ioctl = ceph_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) .compat_ioctl = compat_ptr_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) .fsync = ceph_fsync,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) .lock = ceph_lock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) .flock = ceph_flock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) const struct file_operations ceph_snapdir_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) .iterate = ceph_readdir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) .llseek = ceph_dir_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) .open = ceph_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) .release = ceph_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) const struct inode_operations ceph_dir_iops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) .lookup = ceph_lookup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) .permission = ceph_permission,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) .getattr = ceph_getattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) .setattr = ceph_setattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) .listxattr = ceph_listxattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) .get_acl = ceph_get_acl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) .set_acl = ceph_set_acl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) .mknod = ceph_mknod,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) .symlink = ceph_symlink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) .mkdir = ceph_mkdir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) .link = ceph_link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) .unlink = ceph_unlink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) .rmdir = ceph_unlink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) .rename = ceph_rename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) .create = ceph_create,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) .atomic_open = ceph_atomic_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) const struct inode_operations ceph_snapdir_iops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) .lookup = ceph_lookup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) .permission = ceph_permission,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) .getattr = ceph_getattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) .mkdir = ceph_mkdir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) .rmdir = ceph_unlink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) .rename = ceph_rename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) const struct dentry_operations ceph_dentry_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) .d_revalidate = ceph_d_revalidate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) .d_delete = ceph_d_delete,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) .d_release = ceph_d_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) .d_prune = ceph_d_prune,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) .d_init = ceph_d_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) };