|
@@ -1133,6 +1133,30 @@ static struct dentry *d_alloc_and_lookup(struct dentry *parent,
|
|
|
return dentry;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * We already have a dentry, but require a lookup to be performed on the parent
|
|
|
+ * directory to fill in d_inode. Returns the new dentry, or ERR_PTR on error.
|
|
|
+ * parent->d_inode->i_mutex must be held. d_lookup must have verified that no
|
|
|
+ * child exists while under i_mutex.
|
|
|
+ */
|
|
|
+static struct dentry *d_inode_lookup(struct dentry *parent, struct dentry *dentry,
|
|
|
+ struct nameidata *nd)
|
|
|
+{
|
|
|
+ struct inode *inode = parent->d_inode;
|
|
|
+ struct dentry *old;
|
|
|
+
|
|
|
+ /* Don't create child dentry for a dead directory. */
|
|
|
+ if (unlikely(IS_DEADDIR(inode)))
|
|
|
+ return ERR_PTR(-ENOENT);
|
|
|
+
|
|
|
+ old = inode->i_op->lookup(inode, dentry, nd);
|
|
|
+ if (unlikely(old)) {
|
|
|
+ dput(dentry);
|
|
|
+ dentry = old;
|
|
|
+ }
|
|
|
+ return dentry;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* It's more convoluted than I'd like it to be, but... it's still fairly
|
|
|
* small and for now I'd prefer to have fast path as straight as possible.
|
|
@@ -1172,6 +1196,8 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
|
|
|
goto unlazy;
|
|
|
}
|
|
|
}
|
|
|
+ if (unlikely(d_need_lookup(dentry)))
|
|
|
+ goto unlazy;
|
|
|
path->mnt = mnt;
|
|
|
path->dentry = dentry;
|
|
|
if (unlikely(!__follow_mount_rcu(nd, path, inode)))
|
|
@@ -1186,6 +1212,10 @@ unlazy:
|
|
|
dentry = __d_lookup(parent, name);
|
|
|
}
|
|
|
|
|
|
+ if (dentry && unlikely(d_need_lookup(dentry))) {
|
|
|
+ dput(dentry);
|
|
|
+ dentry = NULL;
|
|
|
+ }
|
|
|
retry:
|
|
|
if (unlikely(!dentry)) {
|
|
|
struct inode *dir = parent->d_inode;
|
|
@@ -1202,6 +1232,15 @@ retry:
|
|
|
/* known good */
|
|
|
need_reval = 0;
|
|
|
status = 1;
|
|
|
+ } else if (unlikely(d_need_lookup(dentry))) {
|
|
|
+ dentry = d_inode_lookup(parent, dentry, nd);
|
|
|
+ if (IS_ERR(dentry)) {
|
|
|
+ mutex_unlock(&dir->i_mutex);
|
|
|
+ return PTR_ERR(dentry);
|
|
|
+ }
|
|
|
+ /* known good */
|
|
|
+ need_reval = 0;
|
|
|
+ status = 1;
|
|
|
}
|
|
|
mutex_unlock(&dir->i_mutex);
|
|
|
}
|
|
@@ -1683,6 +1722,16 @@ static struct dentry *__lookup_hash(struct qstr *name,
|
|
|
*/
|
|
|
dentry = d_lookup(base, name);
|
|
|
|
|
|
+ if (dentry && d_need_lookup(dentry)) {
|
|
|
+ /*
|
|
|
+ * __lookup_hash is called with the parent dir's i_mutex already
|
|
|
+ * held, so we are good to go here.
|
|
|
+ */
|
|
|
+ dentry = d_inode_lookup(base, dentry, nd);
|
|
|
+ if (IS_ERR(dentry))
|
|
|
+ return dentry;
|
|
|
+ }
|
|
|
+
|
|
|
if (dentry && (dentry->d_flags & DCACHE_OP_REVALIDATE))
|
|
|
dentry = do_revalidate(dentry, nd);
|
|
|
|