Hi, Kent,
Give you a friendly ping.🙂
Thanks,
Hongbo
On 2024/7/5 15:19, Hongbo Li wrote:
As i_generation is used in bcachefs, updating this value by ioctl
(FS_IOC_SETVERSION) should be allowed. Here we implement this cmd
to support modify i_generation.
Signed-off-by: Hongbo Li <[email protected]>
---
fs/bcachefs/fs-ioctl.c | 53 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 52 insertions(+), 1 deletion(-)
diff --git a/fs/bcachefs/fs-ioctl.c b/fs/bcachefs/fs-ioctl.c
index aea8132d2c40..33728bbab778 100644
--- a/fs/bcachefs/fs-ioctl.c
+++ b/fs/bcachefs/fs-ioctl.c
@@ -277,6 +277,54 @@ static int bch2_ioc_getversion(struct bch_inode_info
*inode, u32 __user *arg)
return put_user(inode->v.i_generation, arg);
}
+static int bch2_inode_version_set(struct btree_trans *trans,
+ struct bch_inode_info *inode,
+ struct bch_inode_unpacked *bi,
+ void *p)
+{
+ struct bch_fs *c = inode->v.i_sb->s_fs_info;
+ __u32 *generation = p;
+
+ inode->v.i_generation = bi->bi_generation = *generation;
+ bi->bi_ctime = timespec_to_bch2_time(c, current_time(&inode->v));
+
+ return 0;
+}
+
+static int bch2_ioc_setversion(struct bch_fs *c,
+ struct file *file,
+ struct bch_inode_info *inode,
+ void __user *arg)
+{
+ int ret;
+ __u32 generation;
+
+ ret = mnt_want_write_file(file);
+ if (ret)
+ return ret;
+
+ inode_lock(&inode->v);
+ if (!inode_owner_or_capable(file_mnt_idmap(file), &inode->v)) {
+ ret = -EACCES;
+ goto setversion_out;
+ }
+
+ if (get_user(generation, (int __user *) arg)) {
+ ret = -EFAULT;
+ goto setversion_out;
+ }
+
+ mutex_lock(&inode->ei_update_lock);
+ ret = bch2_write_inode(c, inode, bch2_inode_version_set, &generation,
ATTR_CTIME);
+ mutex_unlock(&inode->ei_update_lock);
+
+setversion_out:
+ inode_unlock(&inode->v);
+ mnt_drop_write_file(file);
+
+ return ret;
+}
+
static int bch2_ioc_getlabel(struct bch_fs *c, char __user *user_label)
{
int ret;
@@ -567,7 +615,7 @@ long bch2_fs_file_ioctl(struct file *file, unsigned cmd,
unsigned long arg)
break;
case FS_IOC_SETVERSION:
- ret = -ENOTTY;
+ ret = bch2_ioc_setversion(c, file, inode, (int __user *) arg);
break;
case FS_IOC_GETFSLABEL:
@@ -622,6 +670,9 @@ long bch2_compat_fs_ioctl(struct file *file, unsigned cmd,
unsigned long arg)
case FS_IOC32_GETVERSION:
cmd = FS_IOC_GETVERSION;
break;
+ case FS_IOC32_SETVERSION:
+ cmd = FS_IOC_SETVERSION;
+ break;
case FS_IOC_GETFSLABEL:
case FS_IOC_SETFSLABEL:
break;