From: NeilBrown <[email protected]> When performing a get_name export_operation, ceph sends a LOOKUPNAME op to the server. When it gets a reply it tries to look up the name locally and if the name exists in the dcache with the wrong inode, it discards the result and tries again.
If it doesn't find the name in the dcache it will allocate a new dentry and never make any use of it. The dentry is never instantiated and is assigned to ->r_dentry which is then freed by post-op cleanup. As this is a waste, and as there is a plan to remove d_alloc(), this code is discarded. Also try_lookup_noperm() is used in place of full_name_hash() and d_lookup(), and QSTR_LEN() is used to initialise dname. Signed-off-by: NeilBrown <[email protected]> --- fs/ceph/inode.c | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 59f9f6948bb2..0982fbda2a82 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -15,6 +15,7 @@ #include <linux/sort.h> #include <linux/iversion.h> #include <linux/fscrypt.h> +#include <linux/namei.h> #include "super.h" #include "mds_client.h" @@ -1623,33 +1624,17 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req) ceph_fname_free_buffer(parent_dir, &oname); goto done; } - dname.name = oname.name; - dname.len = oname.len; - dname.hash = full_name_hash(parent, dname.name, dname.len); + dname = QSTR_LEN(oname.name, oname.len); tvino.ino = le64_to_cpu(rinfo->targeti.in->ino); tvino.snap = le64_to_cpu(rinfo->targeti.in->snapid); retry_lookup: - dn = d_lookup(parent, &dname); + dn = try_lookup_noperm(&dname, parent); doutc(cl, "d_lookup on parent=%p name=%.*s got %p\n", parent, dname.len, dname.name, dn); - - if (!dn) { - dn = d_alloc(parent, &dname); - doutc(cl, "d_alloc %p '%.*s' = %p\n", parent, - dname.len, dname.name, dn); - if (!dn) { - dput(parent); - ceph_fname_free_buffer(parent_dir, &oname); - err = -ENOMEM; - goto done; - } - if (is_nokey) { - spin_lock(&dn->d_lock); - dn->d_flags |= DCACHE_NOKEY_NAME; - spin_unlock(&dn->d_lock); - } - err = 0; - } else if (d_really_is_positive(dn) && + if (IS_ERR(dn)) + /* should be impossible */ + dn = NULL; + if (dn && d_really_is_positive(dn) && (ceph_ino(d_inode(dn)) != tvino.ino || ceph_snap(d_inode(dn)) != tvino.snap)) { doutc(cl, " dn %p points to wrong inode %p\n", -- 2.50.0.107.gf914562f5916.dirty
