diff options
Diffstat (limited to 'libbcachefs/fs.c')
-rw-r--r-- | libbcachefs/fs.c | 183 |
1 files changed, 83 insertions, 100 deletions
diff --git a/libbcachefs/fs.c b/libbcachefs/fs.c index d3fb0039..aa92066d 100644 --- a/libbcachefs/fs.c +++ b/libbcachefs/fs.c @@ -105,38 +105,19 @@ int __must_check bch2_write_inode_trans(struct btree_trans *trans, void *p) { struct btree_iter *iter = NULL; - 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); - if (IS_ERR(iter)) - return PTR_ERR(iter); + int ret = 0; - /* The btree node lock is our lock on the inode: */ - ret = bch2_btree_iter_traverse(iter); + iter = bch2_inode_peek(trans, inode_u, inode->v.i_ino, + BTREE_ITER_INTENT); + ret = PTR_ERR_OR_ZERO(iter); if (ret) return ret; - *inode_u = inode->ei_inode; - - if (set) { - ret = set(inode, inode_u, p); - if (ret) - return ret; - } - - inode_p = bch2_trans_kmalloc(trans, sizeof(*inode_p)); - if (IS_ERR(inode_p)) - return PTR_ERR(inode_p); - - bch2_inode_pack(inode_p, inode_u); - bch2_trans_update(trans, iter, &inode_p->inode.k_i); + ret = set ? set(inode, inode_u, p) : 0; + if (ret) + return ret; - return 0; + return bch2_inode_write(trans, iter, inode_u); } int __must_check bch2_write_inode(struct bch_fs *c, @@ -465,23 +446,13 @@ static int bch2_create(struct inode *vdir, struct dentry *dentry, return 0; } -static int inode_update_for_link_fn(struct bch_inode_info *inode, - struct bch_inode_unpacked *bi, - void *p) -{ - struct bch_fs *c = inode->v.i_sb->s_fs_info; - - bi->bi_ctime = bch2_current_time(c); - bch2_inode_nlink_inc(bi); - return 0; -} - static int __bch2_link(struct bch_fs *c, struct bch_inode_info *inode, struct bch_inode_info *dir, struct dentry *dentry) { struct btree_trans trans; + struct btree_iter *inode_iter; struct bch_inode_unpacked inode_u; int ret; @@ -489,21 +460,30 @@ static int __bch2_link(struct bch_fs *c, bch2_trans_init(&trans, c, 4, 1024); retry: bch2_trans_begin(&trans); - ret = __bch2_dirent_create(&trans, dir->v.i_ino, &dir->ei_str_hash, mode_to_type(inode->v.i_mode), &dentry->d_name, inode->v.i_ino, - BCH_HASH_SET_MUST_CREATE) ?: - bch2_write_inode_trans(&trans, inode, &inode_u, - inode_update_for_link_fn, - NULL) ?: - bch2_trans_commit(&trans, NULL, - &inode->ei_journal_seq, - BTREE_INSERT_ATOMIC| - BTREE_INSERT_NOUNLOCK); + BCH_HASH_SET_MUST_CREATE); + if (ret) + goto err; + + inode_iter = bch2_inode_peek(&trans, &inode_u, inode->v.i_ino, + BTREE_ITER_INTENT); + ret = PTR_ERR_OR_ZERO(inode_iter); + if (ret) + goto err; + inode_u.bi_ctime = bch2_current_time(c); + bch2_inode_nlink_inc(&inode_u); + + ret = bch2_inode_write(&trans, inode_iter, &inode_u) ?: + bch2_trans_commit(&trans, NULL, + &inode->ei_journal_seq, + BTREE_INSERT_ATOMIC| + BTREE_INSERT_NOUNLOCK); +err: if (ret == -EINTR) goto retry; @@ -534,36 +514,12 @@ static int bch2_link(struct dentry *old_dentry, struct inode *vdir, return 0; } -static int inode_update_dir_for_unlink_fn(struct bch_inode_info *inode, - struct bch_inode_unpacked *bi, - void *p) -{ - struct bch_fs *c = inode->v.i_sb->s_fs_info; - struct bch_inode_info *unlink_inode = p; - - bi->bi_mtime = bi->bi_ctime = bch2_current_time(c); - - bi->bi_nlink -= S_ISDIR(unlink_inode->v.i_mode); - - return 0; -} - -static int inode_update_for_unlink_fn(struct bch_inode_info *inode, - struct bch_inode_unpacked *bi, - void *p) -{ - struct bch_fs *c = inode->v.i_sb->s_fs_info; - - bi->bi_ctime = bch2_current_time(c); - bch2_inode_nlink_dec(bi); - return 0; -} - static int bch2_unlink(struct inode *vdir, struct dentry *dentry) { struct bch_fs *c = vdir->i_sb->s_fs_info; struct bch_inode_info *dir = to_bch_ei(vdir); struct bch_inode_info *inode = to_bch_ei(dentry->d_inode); + struct btree_iter *dir_iter, *inode_iter; struct bch_inode_unpacked dir_u, inode_u; struct btree_trans trans; int ret; @@ -575,25 +531,42 @@ retry: ret = __bch2_dirent_delete(&trans, dir->v.i_ino, &dir->ei_str_hash, - &dentry->d_name) ?: - bch2_write_inode_trans(&trans, dir, &dir_u, - inode_update_dir_for_unlink_fn, - inode) ?: - bch2_write_inode_trans(&trans, inode, &inode_u, - inode_update_for_unlink_fn, - NULL) ?: + &dentry->d_name); + if (ret) + goto btree_err; + + dir_iter = bch2_inode_peek(&trans, &dir_u, dir->v.i_ino, + BTREE_ITER_INTENT); + ret = PTR_ERR_OR_ZERO(dir_iter); + if (ret) + goto btree_err; + + inode_iter = bch2_inode_peek(&trans, &inode_u, inode->v.i_ino, + BTREE_ITER_INTENT); + ret = PTR_ERR_OR_ZERO(inode_iter); + if (ret) + goto btree_err; + + dir_u.bi_mtime = dir_u.bi_ctime = inode_u.bi_ctime = + bch2_current_time(c); + + dir_u.bi_nlink -= S_ISDIR(inode_u.bi_mode); + bch2_inode_nlink_dec(&inode_u); + + ret = bch2_inode_write(&trans, dir_iter, &dir_u) ?: + bch2_inode_write(&trans, inode_iter, &inode_u) ?: bch2_trans_commit(&trans, NULL, &dir->ei_journal_seq, BTREE_INSERT_ATOMIC| BTREE_INSERT_NOUNLOCK| BTREE_INSERT_NOFAIL); +btree_err: if (ret == -EINTR) goto retry; if (ret) goto err; - if (dir->ei_journal_seq > inode->ei_journal_seq) - inode->ei_journal_seq = dir->ei_journal_seq; + journal_seq_copy(inode, dir->ei_journal_seq); bch2_inode_update_after_write(c, dir, &dir_u, ATTR_MTIME|ATTR_CTIME); @@ -883,18 +856,17 @@ err: return ret; } -static int inode_update_for_setattr_fn(struct bch_inode_info *inode, - struct bch_inode_unpacked *bi, - void *p) +void bch2_setattr_copy(struct bch_inode_info *inode, + struct bch_inode_unpacked *bi, + struct iattr *attr) { struct bch_fs *c = inode->v.i_sb->s_fs_info; - struct iattr *attr = p; unsigned int ia_valid = attr->ia_valid; if (ia_valid & ATTR_UID) - bi->bi_uid = from_kuid(inode->v.i_sb->s_user_ns, attr->ia_uid); + bi->bi_uid = from_kuid(c->vfs_sb->s_user_ns, attr->ia_uid); if (ia_valid & ATTR_GID) - bi->bi_gid = from_kgid(inode->v.i_sb->s_user_ns, attr->ia_gid); + bi->bi_gid = from_kgid(c->vfs_sb->s_user_ns, attr->ia_gid); if (ia_valid & ATTR_ATIME) bi->bi_atime = timespec_to_bch2_time(c, attr->ia_atime); @@ -914,15 +886,15 @@ static int inode_update_for_setattr_fn(struct bch_inode_info *inode, mode &= ~S_ISGID; bi->bi_mode = mode; } - - return 0; } -static int bch2_setattr_nonsize(struct bch_inode_info *inode, struct iattr *iattr) +static int bch2_setattr_nonsize(struct bch_inode_info *inode, + struct iattr *attr) { struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_qid qid; struct btree_trans trans; + struct btree_iter *inode_iter; struct bch_inode_unpacked inode_u; struct posix_acl *acl = NULL; int ret; @@ -931,11 +903,11 @@ static int bch2_setattr_nonsize(struct bch_inode_info *inode, struct iattr *iatt qid = inode->ei_qid; - if (iattr->ia_valid & ATTR_UID) - qid.q[QTYP_USR] = from_kuid(&init_user_ns, iattr->ia_uid); + if (attr->ia_valid & ATTR_UID) + qid.q[QTYP_USR] = from_kuid(&init_user_ns, attr->ia_uid); - if (iattr->ia_valid & ATTR_GID) - qid.q[QTYP_GRP] = from_kgid(&init_user_ns, iattr->ia_gid); + if (attr->ia_valid & ATTR_GID) + qid.q[QTYP_GRP] = from_kgid(&init_user_ns, attr->ia_gid); ret = bch2_fs_quota_transfer(c, inode, qid, ~0, KEY_TYPE_QUOTA_PREALLOC); @@ -948,22 +920,33 @@ retry: kfree(acl); acl = NULL; - ret = bch2_write_inode_trans(&trans, inode, &inode_u, - inode_update_for_setattr_fn, iattr) ?: - (iattr->ia_valid & ATTR_MODE - ? bch2_acl_chmod(&trans, inode, iattr->ia_mode, &acl) - : 0) ?: + inode_iter = bch2_inode_peek(&trans, &inode_u, inode->v.i_ino, + BTREE_ITER_INTENT); + ret = PTR_ERR_OR_ZERO(inode_iter); + if (ret) + goto btree_err; + + bch2_setattr_copy(inode, &inode_u, attr); + + if (attr->ia_valid & ATTR_MODE) { + ret = bch2_acl_chmod(&trans, inode, inode_u.bi_mode, &acl); + if (ret) + goto btree_err; + } + + ret = bch2_inode_write(&trans, inode_iter, &inode_u) ?: bch2_trans_commit(&trans, NULL, &inode->ei_journal_seq, BTREE_INSERT_ATOMIC| BTREE_INSERT_NOUNLOCK| BTREE_INSERT_NOFAIL); +btree_err: if (ret == -EINTR) goto retry; if (unlikely(ret)) goto err_trans; - bch2_inode_update_after_write(c, inode, &inode_u, iattr->ia_valid); + bch2_inode_update_after_write(c, inode, &inode_u, attr->ia_valid); if (acl) set_cached_acl(&inode->v, ACL_TYPE_ACCESS, acl); |