summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2018-07-20 22:23:42 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2018-07-21 05:52:53 -0400
commitb12d802f72196336afaf5bfc05309a5df882d96c (patch)
tree839190fd5c1e68f2916169ed7879ab2effb24f50
parenta462bbb412a14698d56c8f783e4ba72bce4243f3 (diff)
bcachefs: Use ei_update_lock consistently
This is prep work for using deferred btree updates for inode updates - the way inodes are done now we're relying on btree locking for ei_inode and ei_update_lock could probably be removed, but it'll actually be needed when we switch to deferred updates. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--fs/bcachefs/acl.c8
-rw-r--r--fs/bcachefs/fs.c46
2 files changed, 51 insertions, 3 deletions
diff --git a/fs/bcachefs/acl.c b/fs/bcachefs/acl.c
index a74c6cf6c5bb..9406b1d9bb10 100644
--- a/fs/bcachefs/acl.c
+++ b/fs/bcachefs/acl.c
@@ -300,13 +300,14 @@ int bch2_set_acl(struct inode *vinode, struct posix_acl *acl, int type)
umode_t mode = inode->v.i_mode;
int ret;
+ mutex_lock(&inode->ei_update_lock);
+ bch2_trans_init(&trans, c);
+
if (type == ACL_TYPE_ACCESS && acl) {
ret = posix_acl_update_mode(&inode->v, &mode, &acl);
if (ret)
- return ret;
+ goto err;
}
-
- bch2_trans_init(&trans, c);
retry:
bch2_trans_begin(&trans);
@@ -332,6 +333,7 @@ retry:
set_cached_acl(&inode->v, type, acl);
err:
bch2_trans_exit(&trans);
+ mutex_unlock(&inode->ei_update_lock);
return ret;
}
diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c
index 7b76e48c8571..ed3cd3e8782a 100644
--- a/fs/bcachefs/fs.c
+++ b/fs/bcachefs/fs.c
@@ -47,6 +47,30 @@ static void journal_seq_copy(struct bch_inode_info *dst,
} while ((v = cmpxchg(&dst->ei_journal_seq, old, journal_seq)) != old);
}
+static inline int ptrcmp(void *l, void *r)
+{
+ return (l > r) - (l < r);
+}
+
+#define __bch2_lock_inodes(_lock, ...) \
+do { \
+ struct bch_inode_info *a[] = { NULL, __VA_ARGS__ }; \
+ unsigned i; \
+ \
+ bubble_sort(&a[1], ARRAY_SIZE(a) - 1 , ptrcmp); \
+ \
+ for (i = ARRAY_SIZE(a) - 1; a[i]; --i) \
+ if (a[i] != a[i - 1]) { \
+ if (_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__)
+
/*
* I_SIZE_DIRTY requires special handling:
*
@@ -110,6 +134,8 @@ int __must_check bch2_write_inode_trans(struct btree_trans *trans,
struct bkey_inode_buf *inode_p;
int ret;
+ lockdep_assert_held(&inode->ei_update_lock);
+
iter = bch2_trans_get_iter(trans, BTREE_ID_INODES,
POS(inode->v.i_ino, 0),
BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
@@ -274,6 +300,9 @@ __bch2_create(struct bch_inode_info *dir, struct dentry *dentry,
goto err;
}
+ if (!tmpfile)
+ mutex_lock(&dir->ei_update_lock);
+
bch2_trans_init(&trans, c);
retry:
bch2_trans_begin(&trans);
@@ -317,6 +346,7 @@ retry:
bch2_inode_update_after_write(c, dir, &dir_u,
ATTR_MTIME|ATTR_CTIME);
journal_seq_copy(dir, inode->ei_journal_seq);
+ mutex_unlock(&dir->ei_update_lock);
}
bch2_vfs_inode_init(c, inode, &inode_u);
@@ -355,6 +385,9 @@ out:
posix_acl_release(acl);
return inode;
err_trans:
+ if (!tmpfile)
+ mutex_unlock(&dir->ei_update_lock);
+
bch2_trans_exit(&trans);
make_bad_inode(&inode->v);
iput(&inode->v);
@@ -422,6 +455,7 @@ static int __bch2_link(struct bch_fs *c,
struct bch_inode_unpacked inode_u;
int ret;
+ mutex_lock(&inode->ei_update_lock);
bch2_trans_init(&trans, c);
retry:
bch2_trans_begin(&trans);
@@ -447,6 +481,7 @@ retry:
bch2_inode_update_after_write(c, inode, &inode_u, ATTR_CTIME);
bch2_trans_exit(&trans);
+ mutex_unlock(&inode->ei_update_lock);
return ret;
}
@@ -507,6 +542,7 @@ static int bch2_unlink(struct inode *vdir, struct dentry *dentry)
struct btree_trans trans;
int ret;
+ bch2_lock_inodes(dir, inode);
bch2_trans_init(&trans, c);
retry:
bch2_trans_begin(&trans);
@@ -539,6 +575,7 @@ retry:
ATTR_MTIME);
err:
bch2_trans_exit(&trans);
+ bch2_unlock_inodes(dir, inode);
return ret;
}
@@ -699,6 +736,11 @@ static int bch2_rename2(struct inode *src_vdir, struct dentry *src_dentry,
return ret;
}
+ bch2_lock_inodes(i.src_dir,
+ i.dst_dir,
+ i.src_inode,
+ i.dst_inode);
+
bch2_trans_init(&trans, c);
retry:
bch2_trans_begin(&trans);
@@ -746,6 +788,10 @@ retry:
ATTR_CTIME);
err:
bch2_trans_exit(&trans);
+ bch2_unlock_inodes(i.src_dir,
+ i.dst_dir,
+ i.src_inode,
+ i.dst_inode);
return ret;
}