/* * unionfs_lookup is the only special function which takes a dentry, yet we * do NOT want to call __unionfs_d_revalidate_chain because by definition, * we don't have a valid dentry here yet. */ static struct dentry *unionfs_lookup(struct inode *dir, struct dentry *dentry, /* XXX: pass flags to lower? */ unsigned int flags_unused) { struct dentry *ret, *parent; int err = 0; unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD); parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT); /* * As long as we lock/dget the parent, then can skip validating the * parent now; we may have to rebuild this dentry on the next * ->d_revalidate, however. */ /* allocate dentry private data. We free it in ->d_release */ err = new_dentry_private_data(dentry, UNIONFS_DMUTEX_CHILD); if (unlikely(err)) { ret = ERR_PTR(err); goto out; } ret = unionfs_lookup_full(dentry, parent, INTERPOSE_LOOKUP); if (!IS_ERR(ret)) { if (ret) dentry = ret; /* lookup_full can return multiple positive dentries */ if (dentry->d_inode && !S_ISDIR(dentry->d_inode->i_mode)) { BUG_ON(dbstart(dentry) < 0); unionfs_postcopyup_release(dentry); } unionfs_copy_attr_times(dentry->d_inode); } unionfs_check_inode(dir); if (!IS_ERR(ret)) unionfs_check_dentry(dentry); unionfs_check_dentry(parent); unionfs_unlock_dentry(dentry); /* locked in new_dentry_private data */ out: unionfs_unlock_parent(dentry, parent); unionfs_read_unlock(dentry->d_sb); return ret; }
/* * This is a utility function that fills in a unionfs dentry. * Caller must lock this dentry with unionfs_lock_dentry. * * Returns: 0 (ok), or -ERRNO if an error occurred. * XXX: get rid of _partial_lookup and make callers call _lookup_full directly */ int unionfs_partial_lookup(struct dentry *dentry, struct dentry *parent) { struct dentry *tmp; int err = -ENOSYS; tmp = unionfs_lookup_full(dentry, parent, INTERPOSE_PARTIAL); if (!tmp) { err = 0; goto out; } if (IS_ERR(tmp)) { err = PTR_ERR(tmp); goto out; } /* XXX: need to change the interface */ BUG_ON(tmp != dentry); out: return err; }