On 2018/04/21 2:02, David Sterba wrote: > The new ioctl is an extension to the FS_IOC_SETFLAGS and adds new > flags and is extensible. Don't get fooled by the XATTR in the name, it > does not have anything in common with the extended attributes, > incidentally also abbreviated as XATTRs. > > This patch allows to set the xflags portion of the fsxattr structure, > other items have no meaning and non-zero values will result in > EOPNOTSUPP. > > Currently supported xflags: > > - APPEND > - IMMUTABLE > - NOATIME > - NODUMP > - SYNC > > The structure of btrfs_ioctl_fssetxattr copies btrfs_ioctl_setflags but > is simpler on the flag setting side. > > The original patch was written by Chandan Jay Sharma but was incomplete > and no further revision has been sent. > > Based-on-patches-by: Chandan Jay Sharma <chandan...@gmail.com> > Signed-off-by: David Sterba <dste...@suse.com> > --- > fs/btrfs/ioctl.c | 94 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 94 insertions(+) > > diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c > index 52b12ab9b82b..4fd61f191bba 100644 > --- a/fs/btrfs/ioctl.c > +++ b/fs/btrfs/ioctl.c > @@ -388,6 +388,98 @@ static int btrfs_ioctl_fsgetxattr(struct file *file, > void __user *arg) > return 0; > } > > +static int btrfs_ioctl_fssetxattr(struct file *file, void __user *arg) > +{ > + struct inode *inode = file_inode(file); > + struct btrfs_inode *binode = BTRFS_I(inode); > + struct btrfs_root *root = binode->root; > + struct btrfs_trans_handle *trans; > + struct fsxattr fa; > + unsigned oldflags; > + unsigned old_i_flags; > + int ret = 0; > + > + if (!inode_owner_or_capable(inode)) > + return -EPERM; > + > + if (btrfs_root_readonly(root)) > + return -EROFS; > + > + memset(&fa, 0, sizeof(fa)); > + if (copy_from_user(&fa, arg, sizeof(fa))) > + return -EFAULT; > + > + ret = check_xflags(fa.fsx_xflags); > + if (ret) > + return ret; > + > + if (fa.fsx_extsize != 0 || fa.fsx_projid != 0 || fa.fsx_cowextsize != 0) > + return -EOPNOTSUPP; > + > + ret = mnt_want_write_file(file); > + if (ret) > + return ret; > + > + inode_lock(inode); > + > + oldflags = binode->flags; > + old_i_flags = inode->i_flags; > + > + /* We need the capabilities to change append-only or immutable inode */ > + if (((oldflags & (BTRFS_INODE_APPEND | BTRFS_INODE_IMMUTABLE)) || > + (fa.fsx_xflags & (FS_XFLAG_APPEND | FS_XFLAG_IMMUTABLE))) && > + !capable(CAP_LINUX_IMMUTABLE)) { > + ret = -EPERM; > + goto out_unlock; > + } > + > + if (fa.fsx_xflags & FS_XFLAG_SYNC) > + binode->flags |= BTRFS_INODE_SYNC; > + else > + binode->flags &= ~BTRFS_INODE_SYNC; > + if (fa.fsx_xflags & FS_XFLAG_IMMUTABLE) > + binode->flags |= BTRFS_INODE_IMMUTABLE; > + else > + binode->flags &= ~BTRFS_INODE_IMMUTABLE; > + if (fa.fsx_xflags & FS_XFLAG_APPEND) > + binode->flags |= BTRFS_INODE_APPEND; > + else > + binode->flags &= ~BTRFS_INODE_APPEND; > + if (fa.fsx_xflags & FS_XFLAG_NODUMP) > + binode->flags |= BTRFS_INODE_NODUMP; > + else > + binode->flags &= ~BTRFS_INODE_NODUMP; > + if (fa.fsx_xflags & FS_XFLAG_NOATIME) > + binode->flags |= BTRFS_INODE_NOATIME; > + else > + binode->flags &= ~BTRFS_INODE_NOATIME; > + > + /* 1 item for the inode */ > + trans = btrfs_start_transaction(root, 1); > + if (IS_ERR(trans)) { > + ret = PTR_ERR(trans); > + goto out_drop; > + } > + > + btrfs_sync_inode_flags_to_i_flags(inode); > + inode_inc_iversion(inode); > + inode->i_ctime = current_time(inode); > + ret = btrfs_update_inode(trans, root, inode); > + > + btrfs_end_transaction(trans);
Shouldn't out_drop label be here? Otherwise, above "goto out_drop" won't unlock nor restore the flag value. > + > + if (ret) { > + binode->flags = oldflags; > + inode->i_flags = old_i_flags; > + } > + > +out_unlock: > + inode_unlock(inode); > +out_drop: > + mnt_drop_write_file(file); > + return ret; > +} > + > static int btrfs_ioctl_getversion(struct file *file, int __user *arg) > { > struct inode *inode = file_inode(file); > @@ -5620,6 +5712,8 @@ long btrfs_ioctl(struct file *file, unsigned int > return btrfs_ioctl_set_features(file, argp); > case FS_IOC_FSGETXATTR: > return btrfs_ioctl_fsgetxattr(file, argp); > + case FS_IOC_FSSETXATTR: > + return btrfs_ioctl_fssetxattr(file, argp); > } > > return -ENOTTY; > -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html