bcachefs: Improve bch2_lock_inodes()
authorKent Overstreet <kent.overstreet@gmail.com>
Mon, 24 Jun 2019 22:24:38 +0000 (18:24 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:23 +0000 (17:08 -0400)
Can now be used for the two different types of locks we have so far

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/fs-ioctl.c
fs/bcachefs/fs.c
fs/bcachefs/fs.h

index 4dca716217a61d651ae9f90577b9fbe7e02f4db5..0cf2621ec4fc6a05dc1a91f886ef8a0320c299dd 100644 (file)
@@ -205,7 +205,7 @@ static int bch2_ioc_reinherit_attrs(struct bch_fs *c,
        if (ret)
                goto err2;
 
-       bch2_lock_inodes(src, dst);
+       bch2_lock_inodes(INODE_UPDATE_LOCK, src, dst);
 
        if (inode_attr_changing(src, dst, Inode_opt_project)) {
                ret = bch2_fs_quota_transfer(c, dst,
@@ -218,7 +218,7 @@ static int bch2_ioc_reinherit_attrs(struct bch_fs *c,
 
        ret = bch2_write_inode(c, dst, bch2_reinherit_attrs_fn, src, 0);
 err3:
-       bch2_unlock_inodes(src, dst);
+       bch2_unlock_inodes(INODE_UPDATE_LOCK, src, dst);
 
        /* return true if we did work */
        if (ret >= 0)
index afe930532224f3ff0577ca31fee232fde1dde7ad..c806ebad9cde5ef2743eaf7804ebf245d54b270c 100644 (file)
@@ -657,7 +657,7 @@ static int bch2_unlink(struct inode *vdir, struct dentry *dentry)
        struct btree_trans trans;
        int ret;
 
-       bch2_lock_inodes(dir, inode);
+       bch2_lock_inodes(INODE_UPDATE_LOCK, dir, inode);
        bch2_trans_init(&trans, c, 4, 1024);
 retry:
        bch2_trans_begin(&trans);
@@ -690,7 +690,7 @@ retry:
                                      ATTR_MTIME);
 err:
        bch2_trans_exit(&trans);
-       bch2_unlock_inodes(dir, inode);
+       bch2_unlock_inodes(INODE_UPDATE_LOCK, dir, inode);
 
        return ret;
 }
@@ -871,7 +871,8 @@ static int bch2_rename2(struct mnt_idmap *idmap,
 
        bch2_trans_init(&trans, c, 8, 2048);
 
-       bch2_lock_inodes(i.src_dir,
+       bch2_lock_inodes(INODE_UPDATE_LOCK,
+                        i.src_dir,
                         i.dst_dir,
                         i.src_inode,
                         i.dst_inode);
@@ -969,7 +970,8 @@ err:
                                       1 << QTYP_PRJ,
                                       KEY_TYPE_QUOTA_NOCHECK);
 
-       bch2_unlock_inodes(i.src_dir,
+       bch2_unlock_inodes(INODE_UPDATE_LOCK,
+                          i.src_dir,
                           i.dst_dir,
                           i.src_inode,
                           i.dst_inode);
index e72d6a58b3222d0a2df2519f3b043310c1e63ec8..de07f0f1dd510b08f61c599a8bb5f5d50399a946 100644 (file)
@@ -57,24 +57,42 @@ static inline int ptrcmp(void *l, void *r)
        return cmp_int(l, r);
 }
 
-#define __bch2_lock_inodes(_lock, ...)                                 \
+enum bch_inode_lock_op {
+       INODE_LOCK              = (1U << 0),
+       INODE_UPDATE_LOCK       = (1U << 1),
+};
+
+#define bch2_lock_inodes(_locks, ...)                                  \
 do {                                                                   \
        struct bch_inode_info *a[] = { NULL, __VA_ARGS__ };             \
        unsigned i;                                                     \
                                                                        \
-       bubble_sort(&a[1], ARRAY_SIZE(a) - 1 , ptrcmp);                 \
+       bubble_sort(&a[1], ARRAY_SIZE(a) - 1, ptrcmp);                  \
                                                                        \
-       for (i = ARRAY_SIZE(a) - 1; a[i]; --i)                          \
+       for (i = 1; i < ARRAY_SIZE(a); i++)                             \
                if (a[i] != a[i - 1]) {                                 \
-                       if (_lock)                                      \
+                       if (_locks & INODE_LOCK)                        \
+                               down_write_nested(&a[i]->v.i_rwsem, i); \
+                       if (_locks & INODE_UPDATE_LOCK)                 \
                                mutex_lock_nested(&a[i]->ei_update_lock, i);\
-                       else                                            \
-                               mutex_unlock(&a[i]->ei_update_lock);    \
                }                                                       \
 } while (0)
 
-#define bch2_lock_inodes(...)  __bch2_lock_inodes(true, __VA_ARGS__)
-#define bch2_unlock_inodes(...)        __bch2_lock_inodes(false, __VA_ARGS__)
+#define bch2_unlock_inodes(_locks, ...)                                        \
+do {                                                                   \
+       struct bch_inode_info *a[] = { NULL, __VA_ARGS__ };             \
+       unsigned i;                                                     \
+                                                                       \
+       bubble_sort(&a[1], ARRAY_SIZE(a) - 1, ptrcmp);                  \
+                                                                       \
+       for (i = 1; i < ARRAY_SIZE(a); i++)                             \
+               if (a[i] != a[i - 1]) {                                 \
+                       if (_locks & INODE_LOCK)                        \
+                               up_write(&a[i]->v.i_rwsem);             \
+                       if (_locks & INODE_UPDATE_LOCK)                 \
+                               mutex_unlock(&a[i]->ei_update_lock);    \
+               }                                                       \
+} while (0)
 
 static inline struct bch_inode_info *file_bch_inode(struct file *file)
 {