struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent, struct au_branch *br, struct nameidata *nd) { struct dentry *h_dentry; int err; struct nameidata h_nd; if (au_test_fs_null_nd(h_parent->d_sb)) return vfsub_lookup_one_len(name->name, h_parent, name->len); au_h_nd(&h_nd, nd); h_nd.path.dentry = h_parent; h_nd.path.mnt = br->br_mnt; err = __lookup_one_len(name->name, &h_nd.last, NULL, name->len); h_dentry = ERR_PTR(err); if (!err) { path_get(&h_nd.path); h_dentry = vfsub_lookup_hash(&h_nd); path_put(&h_nd.path); } AuTraceErrPtr(h_dentry); return h_dentry; }
static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino, struct au_nfsd_si_lock *nsi_lock) { struct dentry *dentry, *parent; struct file *file; struct inode *dir; struct find_name_by_ino arg; int err; parent = path->dentry; if (nsi_lock) si_read_unlock(parent->d_sb); file = vfsub_dentry_open(path, au_dir_roflags); dentry = (void *)file; if (IS_ERR(file)) goto out; dentry = ERR_PTR(-ENOMEM); arg.name = __getname_gfp(GFP_NOFS); if (unlikely(!arg.name)) goto out_file; arg.ino = ino; arg.found = 0; do { arg.called = 0; /* smp_mb(); */ err = vfsub_readdir(file, find_name_by_ino, &arg); } while (!err && !arg.found && arg.called); dentry = ERR_PTR(err); if (unlikely(err)) goto out_name; dentry = ERR_PTR(-ENOENT); if (!arg.found) goto out_name; /* do not call au_lkup_one() */ dir = parent->d_inode; mutex_lock(&dir->i_mutex); dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen); mutex_unlock(&dir->i_mutex); AuTraceErrPtr(dentry); if (IS_ERR(dentry)) goto out_name; AuDebugOn(au_test_anon(dentry)); if (unlikely(!dentry->d_inode)) { dput(dentry); dentry = ERR_PTR(-ENOENT); } out_name: __putname(arg.name); out_file: fput(file); out: if (unlikely(nsi_lock && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0)) if (!IS_ERR(dentry)) { dput(dentry); dentry = ERR_PTR(-ESTALE); } AuTraceErrPtr(dentry); return dentry; }
static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino, struct au_nfsd_si_lock *nsi_lock) { struct dentry *dentry, *parent; struct file *file; struct inode *dir; struct find_name_by_ino arg; int err; parent = path->dentry; LKTRTrace("%.*s, i%lu\n", AuDLNPair(parent), (unsigned long)ino); if (nsi_lock) si_read_unlock(parent->d_sb); path_get(path); file = dentry_open(parent, path->mnt, au_dir_roflags); dentry = (void *)file; if (IS_ERR(file)) goto out; dentry = ERR_PTR(-ENOMEM); arg.name = __getname(); if (unlikely(!arg.name)) goto out_file; arg.ino = ino; arg.found = 0; do { arg.called = 0; /* smp_mb(); */ err = vfsub_readdir(file, find_name_by_ino, &arg, /*dlgt*/0); } while (!err && !arg.found && arg.called); dentry = ERR_PTR(err); if (unlikely(err)) goto out_name; dentry = ERR_PTR(-ENOENT); if (!arg.found) goto out_name; /* do not call au_lkup_one(), nor dlgt */ dir = parent->d_inode; vfsub_i_lock(dir); dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen); vfsub_i_unlock(dir); AuTraceErrPtr(dentry); if (IS_ERR(dentry)) goto out_name; AuDebugOn(au_test_anon(dentry)); if (unlikely(!dentry->d_inode)) { dput(dentry); dentry = ERR_PTR(-ENOENT); } out_name: __putname(arg.name); out_file: fput(file); out: if (unlikely(nsi_lock && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0)) if (!IS_ERR(dentry)) { dput(dentry); dentry = ERR_PTR(-ESTALE); } AuTraceErrPtr(dentry); return dentry; }