diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2018-07-20 22:23:42 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2018-07-21 05:52:53 -0400 |
commit | b12d802f72196336afaf5bfc05309a5df882d96c (patch) | |
tree | 839190fd5c1e68f2916169ed7879ab2effb24f50 | |
parent | a462bbb412a14698d56c8f783e4ba72bce4243f3 (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.c | 8 | ||||
-rw-r--r-- | fs/bcachefs/fs.c | 46 |
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; } |