From: NeilBrown <[email protected]>

Some ->lookup handlers will need to drop and retake the parent lock, so
they can safely use d_alloc_parallel().

->lookup can be called with the parent lock either exclusive or shared.

A new flag, LOOKUP_SHARED, tells ->lookup how the parent is locked.

This is rather ugly, but will be gone by the end of the series when
->lookup is *always* called with a shared lock on the parent.

Signed-off-by: NeilBrown <[email protected]>
---
 fs/namei.c            | 7 ++++---
 include/linux/namei.h | 3 ++-
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index d31c3db7eb5e..eed388ee8a30 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1928,7 +1928,7 @@ static noinline struct dentry *lookup_slow(const struct 
qstr *name,
        struct inode *inode = dir->d_inode;
        struct dentry *res;
        inode_lock_shared(inode);
-       res = __lookup_slow(name, dir, flags);
+       res = __lookup_slow(name, dir, flags | LOOKUP_SHARED);
        inode_unlock_shared(inode);
        return res;
 }
@@ -1942,7 +1942,7 @@ static struct dentry *lookup_slow_killable(const struct 
qstr *name,
 
        if (inode_lock_shared_killable(inode))
                return ERR_PTR(-EINTR);
-       res = __lookup_slow(name, dir, flags);
+       res = __lookup_slow(name, dir, flags | LOOKUP_SHARED);
        inode_unlock_shared(inode);
        return res;
 }
@@ -4407,6 +4407,7 @@ static struct dentry *lookup_open(struct nameidata *nd, 
struct file *file,
        struct dentry *dentry;
        int error, create_error = 0;
        umode_t mode = op->mode;
+       unsigned int shared_flag = (op->open_flag & O_CREAT) ? 0 : 
LOOKUP_SHARED;
 
        if (unlikely(IS_DEADDIR(dir_inode)))
                return ERR_PTR(-ENOENT);
@@ -4474,7 +4475,7 @@ static struct dentry *lookup_open(struct nameidata *nd, 
struct file *file,
 
        if (d_in_lookup(dentry)) {
                struct dentry *res = dir_inode->i_op->lookup(dir_inode, dentry,
-                                                            nd->flags);
+                                                            nd->flags | 
shared_flag);
                d_lookup_done(dentry);
                if (unlikely(res)) {
                        if (IS_ERR(res)) {
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 2ad6dd9987b9..b3346a513d8f 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -37,8 +37,9 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT};
 #define LOOKUP_CREATE          BIT(17) /* ... in object creation */
 #define LOOKUP_EXCL            BIT(18) /* ... in target must not exist */
 #define LOOKUP_RENAME_TARGET   BIT(19) /* ... in destination of rename() */
+#define LOOKUP_SHARED          BIT(20) /* Parent lock is held shared */
 
-/* 4 spare bits for intent */
+/* 3 spare bits for intent */
 
 /* Scoping flags for lookup. */
 #define LOOKUP_NO_SYMLINKS     BIT(24) /* No symlink crossing. */
-- 
2.50.0.107.gf914562f5916.dirty


Reply via email to