|
@@ -372,6 +372,30 @@ void release_open_intent(struct nameidata *nd)
|
|
|
fput(nd->intent.open.file);
|
|
|
}
|
|
|
|
|
|
+static inline struct dentry *
|
|
|
+do_revalidate(struct dentry *dentry, struct nameidata *nd)
|
|
|
+{
|
|
|
+ int status = dentry->d_op->d_revalidate(dentry, nd);
|
|
|
+ if (unlikely(status <= 0)) {
|
|
|
+ /*
|
|
|
+ * The dentry failed validation.
|
|
|
+ * If d_revalidate returned 0 attempt to invalidate
|
|
|
+ * the dentry otherwise d_revalidate is asking us
|
|
|
+ * to return a fail status.
|
|
|
+ */
|
|
|
+ if (!status) {
|
|
|
+ if (!d_invalidate(dentry)) {
|
|
|
+ dput(dentry);
|
|
|
+ dentry = NULL;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ dput(dentry);
|
|
|
+ dentry = ERR_PTR(status);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return dentry;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Internal lookup() using the new generic dcache.
|
|
|
* SMP-safe
|
|
@@ -386,12 +410,9 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name,
|
|
|
if (!dentry)
|
|
|
dentry = d_lookup(parent, name);
|
|
|
|
|
|
- if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
|
|
|
- if (!dentry->d_op->d_revalidate(dentry, nd) && !d_invalidate(dentry)) {
|
|
|
- dput(dentry);
|
|
|
- dentry = NULL;
|
|
|
- }
|
|
|
- }
|
|
|
+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate)
|
|
|
+ dentry = do_revalidate(dentry, nd);
|
|
|
+
|
|
|
return dentry;
|
|
|
}
|
|
|
|
|
@@ -484,10 +505,9 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s
|
|
|
*/
|
|
|
mutex_unlock(&dir->i_mutex);
|
|
|
if (result->d_op && result->d_op->d_revalidate) {
|
|
|
- if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) {
|
|
|
- dput(result);
|
|
|
+ result = do_revalidate(result, nd);
|
|
|
+ if (!result)
|
|
|
result = ERR_PTR(-ENOENT);
|
|
|
- }
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
@@ -767,12 +787,12 @@ need_lookup:
|
|
|
goto done;
|
|
|
|
|
|
need_revalidate:
|
|
|
- if (dentry->d_op->d_revalidate(dentry, nd))
|
|
|
- goto done;
|
|
|
- if (d_invalidate(dentry))
|
|
|
- goto done;
|
|
|
- dput(dentry);
|
|
|
- goto need_lookup;
|
|
|
+ dentry = do_revalidate(dentry, nd);
|
|
|
+ if (!dentry)
|
|
|
+ goto need_lookup;
|
|
|
+ if (IS_ERR(dentry))
|
|
|
+ goto fail;
|
|
|
+ goto done;
|
|
|
|
|
|
fail:
|
|
|
return PTR_ERR(dentry);
|