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; -- 2.34.1
