summaryrefslogtreecommitdiff
path: root/fs/bcachefs/fs-ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/bcachefs/fs-ioctl.c')
-rw-r--r--fs/bcachefs/fs-ioctl.c105
1 files changed, 34 insertions, 71 deletions
diff --git a/fs/bcachefs/fs-ioctl.c b/fs/bcachefs/fs-ioctl.c
index 9fd195f6c85f..afac13fe0a27 100644
--- a/fs/bcachefs/fs-ioctl.c
+++ b/fs/bcachefs/fs-ioctl.c
@@ -109,21 +109,12 @@ static int bch2_set_projid(struct bch_fs *c,
u32 projid)
{
struct bch_qid qid = inode->ei_qid;
- int ret;
-
- if (projid == inode->ei_qid.q[QTYP_PRJ])
- return 0;
qid.q[QTYP_PRJ] = projid;
- ret = bch2_quota_transfer(c, 1 << QTYP_PRJ, qid, inode->ei_qid,
- inode->v.i_blocks +
- inode->ei_quota_reserved);
- if (ret)
- return ret;
-
- inode->ei_qid.q[QTYP_PRJ] = projid;
- return 0;
+ return bch2_fs_quota_transfer(c, inode, qid,
+ 1 << QTYP_PRJ,
+ KEY_TYPE_QUOTA_PREALLOC);
}
static int fssetxattr_inode_update_fn(struct bch_inode_info *inode,
@@ -174,10 +165,7 @@ static int bch2_ioc_fssetxattr(struct bch_fs *c,
mutex_lock(&inode->ei_update_lock);
- mutex_lock(&inode->ei_quota_lock);
ret = bch2_set_projid(c, inode, fa.fsx_projid);
- mutex_unlock(&inode->ei_quota_lock);
-
if (ret)
goto err_unlock;
@@ -191,56 +179,12 @@ err:
return ret;
}
-static int reinherit_attrs_fn(struct bch_inode_info *inode,
- struct bch_inode_unpacked *bi,
- void *p)
-{
- struct bch_inode_info *dir = p;
- u64 src, dst;
- unsigned id;
- int ret = 1;
-
- for (id = 0; id < Inode_opt_nr; id++) {
- if (bi->bi_fields_set & (1 << id))
- continue;
-
- src = bch2_inode_opt_get(&dir->ei_inode, id);
- dst = bch2_inode_opt_get(bi, id);
-
- if (src == dst)
- continue;
-
- __bch2_inode_opt_set(bi, id, src);
- ret = 0;
- }
-
- return ret;
-}
-
-static int __reinherit_attrs(struct bch_fs *c,
- struct bch_inode_info *dir,
- struct bch_inode_info *inode)
-{
- int ret;
-
- mutex_lock(&inode->ei_update_lock);
- ret = bch2_write_inode(c, inode, reinherit_attrs_fn, dir, 0);
- mutex_unlock(&inode->ei_update_lock);
-
- if (ret < 0)
- return ret;
-
- return !ret;
-}
-
-static int reinherit_attrs_trans(struct btree_trans *trans,
- struct bch_inode_info *inode,
-
static int bch2_ioc_reinherit_attrs(struct bch_fs *c,
struct file *file,
- struct bch_inode_info *inode,
+ struct bch_inode_info *src,
const char __user *name)
{
+ struct bch_inode_info *dst;
struct inode *vinode = NULL;
char *kname = NULL;
struct qstr qstr;
@@ -253,33 +197,52 @@ static int bch2_ioc_reinherit_attrs(struct bch_fs *c,
ret = strncpy_from_user(kname, name, BCH_NAME_MAX);
if (unlikely(ret < 0))
- goto err;
+ goto err1;
qstr.hash_len = ret;
qstr.name = kname;
ret = -ENOENT;
- inum = bch2_dirent_lookup(c, inode->v.i_ino,
- &inode->ei_str_hash,
+ inum = bch2_dirent_lookup(c, src->v.i_ino,
+ &src->ei_str_hash,
&qstr);
if (!inum)
- goto err;
+ goto err1;
vinode = bch2_vfs_inode_get(c, inum);
ret = PTR_ERR_OR_ZERO(vinode);
if (ret)
- goto err;
+ goto err1;
+
+ dst = to_bch_ei(vinode);
ret = mnt_want_write_file(file);
if (ret)
- goto err;
+ goto err2;
- ret = __reinherit_attrs(c, inode, to_bch_ei(vinode));
+ bch2_lock_inodes(src, dst);
+
+ if (inode_attr_changing(src, dst, Inode_opt_project)) {
+ ret = bch2_fs_quota_transfer(c, dst,
+ src->ei_qid,
+ 1 << QTYP_PRJ,
+ KEY_TYPE_QUOTA_PREALLOC);
+ if (ret)
+ goto err3;
+ }
+
+ ret = bch2_write_inode(c, dst, bch2_reinherit_attrs_fn, src, 0);
+err3:
+ bch2_unlock_inodes(src, dst);
+
+ /* return true if we did work */
+ if (ret >= 0)
+ ret = !ret;
mnt_drop_write_file(file);
-err:
- if (vinode)
- iput(vinode);
+err2:
+ iput(vinode);
+err1:
kfree(kname);
return ret;