summaryrefslogtreecommitdiff
path: root/libbcachefs/fs-ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbcachefs/fs-ioctl.c')
-rw-r--r--libbcachefs/fs-ioctl.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/libbcachefs/fs-ioctl.c b/libbcachefs/fs-ioctl.c
index 24228c8e..6ae67f92 100644
--- a/libbcachefs/fs-ioctl.c
+++ b/libbcachefs/fs-ioctl.c
@@ -4,6 +4,7 @@
#include "chardev.h"
#include "fs.h"
#include "fs-ioctl.h"
+#include "quota.h"
#include <linux/compat.h>
#include <linux/mount.h>
@@ -154,10 +155,32 @@ static int bch2_ioc_fsgetxattr(struct bch_inode_info *inode,
struct fsxattr fa = { 0 };
fa.fsx_xflags = map_flags(bch_flags_to_xflags, inode->ei_inode.bi_flags);
+ fa.fsx_projid = inode->ei_qid.q[QTYP_PRJ];
return copy_to_user(arg, &fa, sizeof(fa));
}
+static int bch2_set_projid(struct bch_fs *c,
+ struct bch_inode_info *inode,
+ 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);
+ if (ret)
+ return ret;
+
+ inode->ei_qid.q[QTYP_PRJ] = projid;
+ return 0;
+}
+
static int bch2_ioc_fssetxattr(struct bch_fs *c,
struct file *file,
struct bch_inode_info *inode,
@@ -185,9 +208,14 @@ static int bch2_ioc_fssetxattr(struct bch_fs *c,
}
mutex_lock(&inode->ei_update_lock);
+ ret = bch2_set_projid(c, inode, fa.fsx_projid);
+ if (ret)
+ goto err_unlock;
+
ret = __bch2_write_inode(c, inode, bch2_inode_flags_set, &flags);
if (!ret)
bch2_inode_flags_to_vfs(inode);
+err_unlock:
mutex_unlock(&inode->ei_update_lock);
err:
inode_unlock(&inode->v);