Re: [PATCH 7/7] btrfs: add FS_IOC_FSSETXATTR ioctl

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <chandansbg@xxxxxxxxx>
> Signed-off-by: David Sterba <dsterba@xxxxxxxx>
> ---
>  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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Filesystem Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux