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 noinline_for_stack int au_do_h_d_reval(struct dentry *h_dentry, struct nameidata *nd, struct dentry *dentry, aufs_bindex_t bindex) { int err, valid; int (*reval)(struct dentry *, struct nameidata *); err = 0; reval = NULL; if (h_dentry->d_op) reval = h_dentry->d_op->d_revalidate; if (!reval) goto out; AuDbg("b%d\n", bindex); if (au_test_fs_null_nd(h_dentry->d_sb)) /* it may return tri-state */ valid = reval(h_dentry, NULL); else { struct nameidata h_nd; int locked; struct dentry *parent; au_h_nd(&h_nd, nd); parent = nd->path.dentry; locked = (nd && nd->path.dentry != dentry); if (locked) di_read_lock_parent(parent, AuLock_IR); BUG_ON(bindex > au_dbend(parent)); h_nd.path.dentry = au_h_dptr(parent, bindex); BUG_ON(!h_nd.path.dentry); h_nd.path.mnt = au_sbr(parent->d_sb, bindex)->br_mnt; path_get(&h_nd.path); valid = reval(h_dentry, &h_nd); path_put(&h_nd.path); if (locked) di_read_unlock(parent, AuLock_IR); } if (unlikely(valid < 0)) err = valid; else if (!valid) err = -EINVAL; out: AuTraceErr(err); return err; }
int vfsub_create(struct inode *dir, struct path *path, int mode) { int err; struct dentry *d; IMustLock(dir); d = path->dentry; path->dentry = d->d_parent; err = security_path_mknod(path, d, mode, 0); path->dentry = d; if (unlikely(err)) goto out; if (au_test_fs_null_nd(dir->i_sb)) err = vfs_create(dir, path->dentry, mode, NULL); else { struct nameidata h_nd; memset(&h_nd, 0, sizeof(h_nd)); h_nd.flags = LOOKUP_CREATE; h_nd.intent.open.flags = O_CREAT | vfsub_fmode_to_uint(FMODE_READ); h_nd.intent.open.create_mode = mode; h_nd.path.dentry = path->dentry->d_parent; h_nd.path.mnt = path->mnt; path_get(&h_nd.path); err = vfs_create(dir, path->dentry, mode, &h_nd); path_put(&h_nd.path); } if (!err) { struct path tmp = *path; int did; vfsub_update_h_iattr(&tmp, &did); if (did) { tmp.dentry = path->dentry->d_parent; vfsub_update_h_iattr(&tmp, /*did*/NULL); } /*ignore*/ } out: return err; }