* [PATCH] btrfs: adds FS_IOC_FSSETXATTR/FS_IOC_FSGETXATTR ioctl interface support
@ 2017-04-04 16:06 Chandan Jay Sharma
2017-04-05 13:01 ` David Sterba
0 siblings, 1 reply; 2+ messages in thread
From: Chandan Jay Sharma @ 2017-04-04 16:06 UTC (permalink / raw)
To: linux-btrfs; +Cc: dsterba, Chandan Jay Sharma
This patch adds FS_IOC_FSSETXATTR/FS_IOC_FSGETXATTR ioctl interface support
for btrfs. Extended file attributes are 32 bit values (FS_XFLAGS_SYNC,
FS_XFLAG_IMMUTABLE, etc) which have one-to-one mapping to the flag values
that can be stored in inode->i_flags (i.e. S_SYNC, S_IMMUTABLE, etc).
The flags can be set/unset to enable/disable file attributes.
These attributes are listed/modified by lsattr/chattr.
Signed-off-by: Chandan Jay Sharma <chandansbg@gmail.com>
---
fs/btrfs/ioctl.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 148 insertions(+)
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index dabfc7a..5d8486b 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -132,6 +132,25 @@ static unsigned int btrfs_flags_to_ioctl(unsigned int flags)
return iflags;
}
+/* Transfer ioctl flags to btrfs internal flags */
+static unsigned int btrfs_ioctl_to_flags(unsigned int iflags)
+{
+ unsigned int flags = 0;
+
+ if (iflags & FS_SYNC_FL)
+ flags |= BTRFS_INODE_SYNC;
+ if (iflags & FS_IMMUTABLE_FL)
+ flags |= BTRFS_INODE_IMMUTABLE;
+ if (iflags & FS_APPEND_FL)
+ flags |= BTRFS_INODE_APPEND;
+ if (iflags & FS_NODUMP_FL)
+ flags |= BTRFS_INODE_NODUMP;
+ if (iflags & FS_NOATIME_FL)
+ flags |= BTRFS_INODE_NOATIME;
+
+ return flags;
+}
+
/*
* Update inode->i_flags based on the btrfs internal flags.
*/
@@ -157,6 +176,75 @@ void btrfs_update_iflags(struct inode *inode)
}
/*
+ * Propagate flags from i_flags to BTRFS_I(inode)->flags
+ */
+void btrfs_get_inode_flags(struct btrfs_inode *ip)
+{
+ unsigned int vfs_fl;
+ unsigned long old_fl, new_fl;
+
+ do {
+ vfs_fl = ip->vfs_inode.i_flags;
+ old_fl = ip->flags;
+ new_fl = old_fl & ~(BTRFS_INODE_SYNC|BTRFS_INODE_APPEND|
+ BTRFS_INODE_IMMUTABLE|BTRFS_INODE_NOATIME|
+ BTRFS_INODE_DIRSYNC);
+ if (vfs_fl & S_SYNC)
+ new_fl |= BTRFS_INODE_SYNC;
+ if (vfs_fl & S_APPEND)
+ new_fl |= BTRFS_INODE_APPEND;
+ if (vfs_fl & S_IMMUTABLE)
+ new_fl |= BTRFS_INODE_IMMUTABLE;
+ if (vfs_fl & S_NOATIME)
+ new_fl |= BTRFS_INODE_NOATIME;
+ if (vfs_fl & S_DIRSYNC)
+ new_fl |= BTRFS_INODE_DIRSYNC;
+ } while (cmpxchg(&ip->flags, old_fl, new_fl) != old_fl);
+}
+
+/*
+ * Translate btrfs internal flags BTRFS_I(inode)->flags to xflags.
+ */
+static inline unsigned int btrfs_flags_to_xflags(unsigned int flags)
+{
+ unsigned int xflags = 0;
+
+ if (flags & BTRFS_INODE_SYNC)
+ xflags |= FS_XFLAG_SYNC;
+ if (flags & BTRFS_INODE_IMMUTABLE)
+ xflags |= FS_XFLAG_IMMUTABLE;
+ if (flags & BTRFS_INODE_APPEND)
+ xflags |= FS_XFLAG_APPEND;
+ if (flags & BTRFS_INODE_NODUMP)
+ xflags |= FS_XFLAG_NODUMP;
+ if (flags & BTRFS_INODE_NOATIME)
+ xflags |= FS_XFLAG_NOATIME;
+
+ return xflags;
+}
+
+/*
+ * Transfer xflags flags to ioctl flags.
+ */
+static inline unsigned int btrfs_xflags_to_ioctl(unsigned int xflags)
+{
+ unsigned int flags = 0;
+
+ if (xflags & FS_XFLAG_SYNC)
+ flags |= FS_SYNC_FL;
+ if (xflags & FS_XFLAG_IMMUTABLE)
+ flags |= FS_IMMUTABLE_FL;
+ if (xflags & FS_XFLAG_APPEND)
+ flags |= FS_APPEND_FL;
+ if (xflags & FS_XFLAG_NODUMP)
+ flags |= FS_NODUMP_FL;
+ if (xflags & FS_XFLAG_NOATIME)
+ flags |= FS_NOATIME_FL;
+
+ return flags;
+}
+
+/*
* Inherit flags from the parent inode.
*
* Currently only the compression flags and the cow flags are inherited.
@@ -5504,6 +5592,62 @@ static int btrfs_ioctl_set_features(struct file *file, void __user *arg)
return ret;
}
+static int btrfs_ioctl_fsgetxattr(struct file *file, void __user *arg)
+{
+ struct fsxattr fa;
+ struct btrfs_inode *ip = BTRFS_I(file_inode(file));
+
+ memset(&fa, 0, sizeof(struct fsxattr));
+ btrfs_get_inode_flags(ip);
+ fa.fsx_xflags = btrfs_flags_to_xflags(ip->flags);
+
+ if (copy_to_user((struct fsxattr __user *)arg,
+ &fa, sizeof(fa)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int btrfs_ioctl_fssetxattr(struct file *file, void __user *arg)
+{
+ struct inode *inode = file_inode(file);
+ struct btrfs_inode *ip = BTRFS_I(inode);
+ struct btrfs_root *root = ip->root;
+ struct fsxattr fa;
+ unsigned int flags;
+ int err;
+
+ /* Make sure caller has proper permission */
+ if (!inode_owner_or_capable(inode))
+ return -EPERM;
+
+ if (btrfs_root_readonly(root))
+ return -EROFS;
+
+ memset(&fa, 0, sizeof(struct fsxattr));
+ if (copy_from_user(&fa, (struct fsxattr __user *)arg,
+ sizeof(fa)))
+ return -EFAULT;
+
+ flags = btrfs_xflags_to_ioctl(fa.fsx_xflags);
+
+ if (btrfs_mask_flags(inode->i_mode, flags) != flags)
+ return -EOPNOTSUPP;
+
+ err = mnt_want_write_file(file);
+ if (err)
+ return err;
+
+ inode_lock(inode);
+ ip->flags = (ip->flags | btrfs_ioctl_to_flags(flags));
+ btrfs_update_iflags(inode);
+ inode_unlock(inode);
+
+ mnt_drop_write_file(file);
+
+ return 0;
+}
+
long btrfs_ioctl(struct file *file, unsigned int
cmd, unsigned long arg)
{
@@ -5638,6 +5782,10 @@ long btrfs_ioctl(struct file *file, unsigned int
return btrfs_ioctl_get_features(file, argp);
case BTRFS_IOC_SET_FEATURES:
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;
--
2.9.3
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] btrfs: adds FS_IOC_FSSETXATTR/FS_IOC_FSGETXATTR ioctl interface support
2017-04-04 16:06 [PATCH] btrfs: adds FS_IOC_FSSETXATTR/FS_IOC_FSGETXATTR ioctl interface support Chandan Jay Sharma
@ 2017-04-05 13:01 ` David Sterba
0 siblings, 0 replies; 2+ messages in thread
From: David Sterba @ 2017-04-05 13:01 UTC (permalink / raw)
To: Chandan Jay Sharma; +Cc: linux-btrfs, dsterba
On Tue, Apr 04, 2017 at 09:36:39PM +0530, Chandan Jay Sharma wrote:
> This patch adds FS_IOC_FSSETXATTR/FS_IOC_FSGETXATTR ioctl interface support
> for btrfs. Extended file attributes are 32 bit values (FS_XFLAGS_SYNC,
> FS_XFLAG_IMMUTABLE, etc) which have one-to-one mapping to the flag values
> that can be stored in inode->i_flags (i.e. S_SYNC, S_IMMUTABLE, etc).
> The flags can be set/unset to enable/disable file attributes.
> These attributes are listed/modified by lsattr/chattr.
Ok.
> Signed-off-by: Chandan Jay Sharma <chandansbg@gmail.com>
> ---
> fs/btrfs/ioctl.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 148 insertions(+)
>
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index dabfc7a..5d8486b 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -132,6 +132,25 @@ static unsigned int btrfs_flags_to_ioctl(unsigned int flags)
> return iflags;
> }
>
> +/* Transfer ioctl flags to btrfs internal flags */
Please mention which ioctl as we now have 2 that do a similar thing.
> +static unsigned int btrfs_ioctl_to_flags(unsigned int iflags)
> +{
> + unsigned int flags = 0;
> +
> + if (iflags & FS_SYNC_FL)
> + flags |= BTRFS_INODE_SYNC;
> + if (iflags & FS_IMMUTABLE_FL)
> + flags |= BTRFS_INODE_IMMUTABLE;
> + if (iflags & FS_APPEND_FL)
> + flags |= BTRFS_INODE_APPEND;
> + if (iflags & FS_NODUMP_FL)
> + flags |= BTRFS_INODE_NODUMP;
> + if (iflags & FS_NOATIME_FL)
> + flags |= BTRFS_INODE_NOATIME;
> +
> + return flags;
> +}
> +
> /*
> * Update inode->i_flags based on the btrfs internal flags.
> */
> @@ -157,6 +176,75 @@ void btrfs_update_iflags(struct inode *inode)
> }
>
> /*
> + * Propagate flags from i_flags to BTRFS_I(inode)->flags
> + */
> +void btrfs_get_inode_flags(struct btrfs_inode *ip)
> +{
> + unsigned int vfs_fl;
> + unsigned long old_fl, new_fl;
> +
> + do {
> + vfs_fl = ip->vfs_inode.i_flags;
> + old_fl = ip->flags;
> + new_fl = old_fl & ~(BTRFS_INODE_SYNC|BTRFS_INODE_APPEND|
> + BTRFS_INODE_IMMUTABLE|BTRFS_INODE_NOATIME|
> + BTRFS_INODE_DIRSYNC);
The list of supported flags should be declared in a header, something
like
#define BTRFS_INODE_FLAGS_MASK (BTRFS_INODE_SYNC |
BTRFS_INODE_APPEND |
BTRFS_INODE_IMMUTABLE |
BTRFS_INODE_NOATIME |
BTRFS_INODE_DIRSYNC)
> + if (vfs_fl & S_SYNC)
> + new_fl |= BTRFS_INODE_SYNC;
> + if (vfs_fl & S_APPEND)
> + new_fl |= BTRFS_INODE_APPEND;
> + if (vfs_fl & S_IMMUTABLE)
> + new_fl |= BTRFS_INODE_IMMUTABLE;
> + if (vfs_fl & S_NOATIME)
> + new_fl |= BTRFS_INODE_NOATIME;
> + if (vfs_fl & S_DIRSYNC)
> + new_fl |= BTRFS_INODE_DIRSYNC;
> + } while (cmpxchg(&ip->flags, old_fl, new_fl) != old_fl);
> +}
> +
> +/*
> + * Translate btrfs internal flags BTRFS_I(inode)->flags to xflags.
Maybe also reference the related ioctl.
> + */
> +static inline unsigned int btrfs_flags_to_xflags(unsigned int flags)
> +{
> + unsigned int xflags = 0;
> +
> + if (flags & BTRFS_INODE_SYNC)
> + xflags |= FS_XFLAG_SYNC;
> + if (flags & BTRFS_INODE_IMMUTABLE)
> + xflags |= FS_XFLAG_IMMUTABLE;
> + if (flags & BTRFS_INODE_APPEND)
> + xflags |= FS_XFLAG_APPEND;
> + if (flags & BTRFS_INODE_NODUMP)
> + xflags |= FS_XFLAG_NODUMP;
> + if (flags & BTRFS_INODE_NOATIME)
> + xflags |= FS_XFLAG_NOATIME;
> +
> + return xflags;
> +}
> +
> +/*
> + * Transfer xflags flags to ioctl flags.
> + */
> +static inline unsigned int btrfs_xflags_to_ioctl(unsigned int xflags)
> +{
> + unsigned int flags = 0;
> +
> + if (xflags & FS_XFLAG_SYNC)
> + flags |= FS_SYNC_FL;
> + if (xflags & FS_XFLAG_IMMUTABLE)
> + flags |= FS_IMMUTABLE_FL;
> + if (xflags & FS_XFLAG_APPEND)
> + flags |= FS_APPEND_FL;
> + if (xflags & FS_XFLAG_NODUMP)
> + flags |= FS_NODUMP_FL;
> + if (xflags & FS_XFLAG_NOATIME)
> + flags |= FS_NOATIME_FL;
> +
> + return flags;
> +}
> +
> +/*
> * Inherit flags from the parent inode.
> *
> * Currently only the compression flags and the cow flags are inherited.
> @@ -5504,6 +5592,62 @@ static int btrfs_ioctl_set_features(struct file *file, void __user *arg)
> return ret;
> }
>
> +static int btrfs_ioctl_fsgetxattr(struct file *file, void __user *arg)
> +{
> + struct fsxattr fa;
> + struct btrfs_inode *ip = BTRFS_I(file_inode(file));
> +
> + memset(&fa, 0, sizeof(struct fsxattr));
> + btrfs_get_inode_flags(ip);
> + fa.fsx_xflags = btrfs_flags_to_xflags(ip->flags);
> +
> + if (copy_to_user((struct fsxattr __user *)arg,
> + &fa, sizeof(fa)))
> + return -EFAULT;
> +
> + return 0;
> +}
> +
> +static int btrfs_ioctl_fssetxattr(struct file *file, void __user *arg)
> +{
> + struct inode *inode = file_inode(file);
> + struct btrfs_inode *ip = BTRFS_I(inode);
> + struct btrfs_root *root = ip->root;
> + struct fsxattr fa;
> + unsigned int flags;
> + int err;
> +
> + /* Make sure caller has proper permission */
> + if (!inode_owner_or_capable(inode))
> + return -EPERM;
> +
> + if (btrfs_root_readonly(root))
> + return -EROFS;
> +
> + memset(&fa, 0, sizeof(struct fsxattr));
> + if (copy_from_user(&fa, (struct fsxattr __user *)arg,
> + sizeof(fa)))
> + return -EFAULT;
> +
> + flags = btrfs_xflags_to_ioctl(fa.fsx_xflags);
> +
> + if (btrfs_mask_flags(inode->i_mode, flags) != flags)
> + return -EOPNOTSUPP;
Please see btrfs_ioctl_setflags what's needs do be done here
- verify that the requested flags are supported
- start transaction
- update the flags
- inode_inc_iversion
- update ctime
- update the inode
- end transaction
> + err = mnt_want_write_file(file);
> + if (err)
> + return err;
> +
> + inode_lock(inode);
> + ip->flags = (ip->flags | btrfs_ioctl_to_flags(flags));
> + btrfs_update_iflags(inode);
> + inode_unlock(inode);
> +
> + mnt_drop_write_file(file);
> +
> + return 0;
> +}
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2017-04-05 13:01 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-04 16:06 [PATCH] btrfs: adds FS_IOC_FSSETXATTR/FS_IOC_FSGETXATTR ioctl interface support Chandan Jay Sharma
2017-04-05 13:01 ` David Sterba
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.