[PATCH 3/3] xstat: Implement a requestable extra result to procure some inode flags [ver #4]

Michael Kerrisk mtk.manpages at gmail.com
Sat Jul 3 22:27:30 MDT 2010


[CC+=linux-api]

On Fri, Jul 2, 2010 at 1:57 AM, David Howells <dhowells at redhat.com> wrote:
> [This is, for the moment, to be considered an example.  Do we actually want to
>  export these flags?  Should they be a full member of struct xstat?]


Since I suggested the idea, obviously I'm inclined to think they should ;-).

Cheers,

Michael


> Allow an extra result to be requested that makes available some inode flags,
> along the lines of BSD's st_flags and Ext2/3/4's inode flags.  This is
> requested by setting XSTAT_REQUEST_INODE_FLAGS in the request_mask.  If the
> filesystem supports it for that file, then this will be set in result_mask and
> 16 bytes of information will be appended to the xstat buffer, if sufficient
> buffer space is available.
>
> The extra result is laid out according to the following structure:
>
>        struct xstat_inode_flags {
>                unsigned long long      st_flags;
>                unsigned long long      st_supported_flags;
>        };
>
> where the filesystem indicates the flags it supports for that file and the
> flags that are set on that file.  The structure is of length:
>
>        XSTAT_LENGTH_INODE_FLAGS
>
> The flags come in three sets:
>
>  (1) User settable flags (to be consistent with the BSD st_flags field):
>
>        UF_NODUMP       Do not dump this file.
>        UF_IMMUTABLE    This file is immutable.
>        UF_APPEND       This file is append-only.
>        UF_OPAQUE       This directory is opaque (unionfs).
>        UF_NOUNLINK     This file can't be removed or renamed.
>        UF_COMPRESSED   This file is compressed.
>        UF_HIDDEN       This file shouldn't be displayed in a GUI.
>
>     The UF_SETTABLE constant is the union of the above flags.
>
>  (2) Superuser settable flags (to be consistent with the BSD st_flags field):
>
>        SF_ARCHIVED     This file has been archived.
>        SF_IMMUTABLE    This file is immutable.
>        SF_APPEND       This file is append-only.
>        SF_NOUNLINK     This file can't be removed or renamed.
>        SF_HIDDEN       This file is a snapshot inode.
>
>     The SF_SETTABLE constant is the union of the above flags.
>
>  (3) Linux-specific flags:
>
>        XSTAT_LF_MAGIC_FILE     Magic file, such as found in procfs and sysfs.
>        XSTAT_LF_SYNC           File is written synchronously.
>        XSTAT_LF_NOATIME        Atime is not updated on this file.
>        XSTAT_LF_JOURNALLED_DATA Data modifications to this file are journalled.
>        XSTAT_LF_ENCRYPTED      This file is encrypted.
>        XSTAT_LF_SYSTEM         This file is a system file (FAT/NTFS/CIFS).
>        XSTAT_LF_TEMPORARY      This file is a temporary file (NTFS/CIFS).
>        XSTAT_LF_OFFLINE        file is currently unavailable (CIFS).
>
>
> The Ext4 filesystem has been modified to map certain Ext4 inode flags to the
> above:
>
>        EXT4 FLAG               MAPPED TO
>        ======================= =======================================
>        EXT4_COMPR_FL           UF_COMPRESSED
>        EXT4_SYNC_FL            XSTAT_LF_SYNC
>        EXT4_IMMUTABLE_FL       UF_IMMUTABLE and SF_IMMUTABLE
>        EXT4_APPEND_FL          UF_APPEND and SF_APPEND
>        EXT4_NODUMP_FL          UF_NODUMP
>        EXT4_NOATIME_FL         XSTAT_LF_NOATIME
>        EXT4_JOURNAL_DATA_FL    XSTAT_LF_JOURNALLED_DATA
>        EXT4_DIRSYNC_FL         XSTAT_LF_SYNC (directories only)
>
> With this patch applied, the test program given in the patch that introduced
> the xstat() syscalls now does this:
>
>        [root at andromeda ~]# chattr +ia /var/cache/fscache/cull_atimes
>        [root at andromeda ~]# lsattr /var/cache/fscache/cull_atimes
>        ----ia-------e- /var/cache/fscache/cull_atimes
>        [root at andromeda ~]# /tmp/xstat /var/cache/fscache/cull_atimes
>        xstat(/var/cache/fscache/cull_atimes) = 168
>        results=5fef
>          Size: 78088           Blocks: 168        IO Block: 4096    regular file
>        Device: 08:06           Inode: 13          Links: 1
>        Access: (0600/-rw-------)  Uid: 0
>        Gid: 0
>        Access: 2010-06-29 18:17:41.092290108+0100
>        Modify: 2010-06-25 17:25:53.320261493+0100
>        Change: 2010-07-02 00:46:51.278803967+0100
>        Create: 2010-06-25 15:17:39.711172889+0100
>        Inode version: f585ab73h
>        0098: 0000000000060006 0000000e00060027
>
> The extra results are hex dumped at the end in 64-bit chunks.  As can be seen
> above, st_flags=0x0000000000060006 and st_supported_flags=0000000e00060027.
> That's showing that the file now has [SU]F_IMMUTABLE and [SU]F_APPEND enabled.
>
> Note also that XSTAT_REQUEST_INODE_FLAGS (0x4000) is present in the result_mask
> value (0x5fef) returned to userspace, and the amount of data returned by
> xstat() has increased from 152 to 168 as appropriate for 16 bytes of extra
> data.
>
> Signed-off-by: David Howells <dhowells at redhat.com>
> ---
>
>  fs/ext4/ext4.h       |    2 ++
>  fs/ext4/file.c       |    1 +
>  fs/ext4/inode.c      |   50 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  fs/ext4/namei.c      |    2 ++
>  fs/ext4/symlink.c    |    2 ++
>  include/linux/stat.h |   47 ++++++++++++++++++++++++++++++++++++++++++++++-
>  6 files changed, 103 insertions(+), 1 deletions(-)
>
> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
> index 96823f3..26b8dd6 100644
> --- a/fs/ext4/ext4.h
> +++ b/fs/ext4/ext4.h
> @@ -1573,6 +1573,8 @@ extern int  ext4_getattr(struct vfsmount *mnt, struct dentry *dentry,
>                                struct kstat *stat);
>  extern int  ext4_file_getattr(struct vfsmount *mnt, struct dentry *dentry,
>                                struct kstat *stat);
> +extern int  ext4_getattr_extra(struct vfsmount *, struct dentry *,
> +                              struct xstat_extra_result *);
>  extern void ext4_delete_inode(struct inode *);
>  extern int  ext4_sync_inode(handle_t *, struct inode *);
>  extern void ext4_dirty_inode(struct inode *);
> diff --git a/fs/ext4/file.c b/fs/ext4/file.c
> index 18c29ab..657ffa0 100644
> --- a/fs/ext4/file.c
> +++ b/fs/ext4/file.c
> @@ -151,6 +151,7 @@ const struct inode_operations ext4_file_inode_operations = {
>        .truncate       = ext4_truncate,
>        .setattr        = ext4_setattr,
>        .getattr        = ext4_file_getattr,
> +       .getattr_extra  = ext4_getattr_extra,
>  #ifdef CONFIG_EXT4_FS_XATTR
>        .setxattr       = generic_setxattr,
>        .getxattr       = generic_getxattr,
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index f9a730a..efa17d6 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -5595,6 +5595,56 @@ int ext4_file_getattr(struct vfsmount *mnt, struct dentry *dentry,
>        return 0;
>  }
>
> +int ext4_getattr_inode_flags(struct inode *inode,
> +                            struct xstat_extra_result *extra)
> +{
> +       struct ext4_inode_info *ei = EXT4_I(inode);
> +       struct xstat_inode_flags xif = { 0, 0 };
> +
> +#define _(FL, ST)                    \
> +       xif.st_supported_flags |= ST; \
> +       if (ei->i_flags & FL)         \
> +               xif.st_flags |= ST;
> +
> +       _(EXT4_COMPR_FL,        UF_COMPRESSED);
> +       _(EXT4_SYNC_FL,         XSTAT_LF_SYNC);
> +       _(EXT4_IMMUTABLE_FL,    UF_IMMUTABLE | SF_IMMUTABLE);
> +       _(EXT4_APPEND_FL,       UF_APPEND | SF_APPEND);
> +       _(EXT4_NODUMP_FL,       UF_NODUMP);
> +       _(EXT4_NOATIME_FL,      XSTAT_LF_NOATIME);
> +       _(EXT4_JOURNAL_DATA_FL, XSTAT_LF_JOURNALLED_DATA);
> +
> +       if (S_ISDIR(ei->vfs_inode.i_mode))
> +               _(EXT4_DIRSYNC_FL,      XSTAT_LF_SYNC);
> +
> +       return extra->pass_result(extra, ilog2(XSTAT_REQUEST_INODE_FLAGS),
> +                                 &xif, sizeof(xif));
> +}
> +
> +int ext4_getattr_extra(struct vfsmount *mnt, struct dentry *dentry,
> +                      struct xstat_extra_result *extra)
> +{
> +       struct inode *inode = dentry->d_inode;
> +       u64 request_mask = extra->request_mask;
> +       int request, ret;
> +
> +       do {
> +               request = __ffs64(request_mask);
> +               request_mask &= ~(1ULL << request);
> +
> +               switch (request) {
> +               case ilog2(XSTAT_REQUEST_INODE_FLAGS):
> +                       ret = ext4_getattr_inode_flags(inode, extra);
> +                       break;
> +               default:
> +                       ret = 0;
> +                       break;
> +               }
> +
> +       } while (ret == 0 && request_mask);
> +       return ret;
> +}
> +
>  static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks,
>                                      int chunk)
>  {
> diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
> index 0f776c7..3c37b3f 100644
> --- a/fs/ext4/namei.c
> +++ b/fs/ext4/namei.c
> @@ -2543,6 +2543,7 @@ const struct inode_operations ext4_dir_inode_operations = {
>        .rename         = ext4_rename,
>        .setattr        = ext4_setattr,
>        .getattr        = ext4_getattr,
> +       .getattr_extra  = ext4_getattr_extra,
>  #ifdef CONFIG_EXT4_FS_XATTR
>        .setxattr       = generic_setxattr,
>        .getxattr       = generic_getxattr,
> @@ -2556,6 +2557,7 @@ const struct inode_operations ext4_dir_inode_operations = {
>  const struct inode_operations ext4_special_inode_operations = {
>        .setattr        = ext4_setattr,
>        .getattr        = ext4_getattr,
> +       .getattr_extra  = ext4_getattr_extra,
>  #ifdef CONFIG_EXT4_FS_XATTR
>        .setxattr       = generic_setxattr,
>        .getxattr       = generic_getxattr,
> diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
> index d8fe7fb..8c206b2 100644
> --- a/fs/ext4/symlink.c
> +++ b/fs/ext4/symlink.c
> @@ -36,6 +36,7 @@ const struct inode_operations ext4_symlink_inode_operations = {
>        .put_link       = page_put_link,
>        .setattr        = ext4_setattr,
>        .getattr        = ext4_getattr,
> +       .getattr_extra  = ext4_getattr_extra,
>  #ifdef CONFIG_EXT4_FS_XATTR
>        .setxattr       = generic_setxattr,
>        .getxattr       = generic_getxattr,
> @@ -49,6 +50,7 @@ const struct inode_operations ext4_fast_symlink_inode_operations = {
>        .follow_link    = ext4_follow_link,
>        .setattr        = ext4_setattr,
>        .getattr        = ext4_getattr,
> +       .getattr_extra  = ext4_getattr_extra,
>  #ifdef CONFIG_EXT4_FS_XATTR
>        .setxattr       = generic_setxattr,
>        .getxattr       = generic_getxattr,
> diff --git a/include/linux/stat.h b/include/linux/stat.h
> index 9e27f88..4c87878 100644
> --- a/include/linux/stat.h
> +++ b/include/linux/stat.h
> @@ -107,7 +107,8 @@ struct xstat_parameters {
>  #define XSTAT_REQUEST_GEN              0x00001000ULL   /* want/got st_gen */
>  #define XSTAT_REQUEST_DATA_VERSION     0x00002000ULL   /* want/got st_data_version */
>  #define XSTAT_REQUEST__EXTENDED_STATS  0x00003fffULL   /* the stuff in the xstat struct */
> -#define XSTAT_REQUEST__ALL_STATS       0x00003fffULL   /* the defined set of requestables */
> +#define XSTAT_REQUEST_INODE_FLAGS      0x00004000ULL   /* want/got xstat_inode_flags */
> +#define XSTAT_REQUEST__ALL_STATS       0x00007fffULL   /* the defined set of requestables */
>  #define XSTAT_REQUEST__EXTRA_STATS     (XSTAT_REQUEST__ALL_STATS & ~XSTAT_REQUEST__EXTENDED_STATS)
>  };
>
> @@ -140,6 +141,50 @@ struct xstat {
>        unsigned long long      st_extra_results[0]; /* extra requested results */
>  };
>
> +/*
> + * Extra result field for inode flags (XSTAT_REQUEST_INODE_FLAGS)
> + */
> +struct xstat_inode_flags {
> +       /* Flags set on the file
> +        * - the LSW matches the BSD st_flags
> +        * - the MSW are Linux-specific
> +        */
> +       unsigned long long      st_flags;
> +       /* st_flags that users can set */
> +#define UF_SETTABLE    0x0000ffff
> +#define UF_NODUMP      0x00000001      /* do not dump */
> +#define UF_IMMUTABLE   0x00000002      /* immutable */
> +#define UF_APPEND      0x00000004      /* append-only */
> +#define UF_OPAQUE      0x00000008      /* directory is opaque (unionfs) */
> +#define UF_NOUNLINK    0x00000010      /* can't be removed or renamed */
> +#define UF_COMPRESSED  0x00000020      /* file is compressed */
> +#define UF_HIDDEN      0x00008000      /* file shouldn't be displayed in a GUI */
> +
> +       /* st_flags that only root can set */
> +#define SF_SETTABLE    0xffff0000
> +#define SF_ARCHIVED    0x00010000      /* archived */
> +#define SF_IMMUTABLE   0x00020000      /* immutable */
> +#define SF_APPEND      0x00040000      /* append-only */
> +#define SF_NOUNLINK    0x00100000      /* can't be removed or renamed */
> +#define SF_SNAPSHOT    0x00200000      /* snapshot inode */
> +
> +       /* Linux-specific st_flags */
> +#define XSTAT_LF_MAGIC_FILE    (1ULL << 32)    /* magic file, such as /proc/? and /sys/? */
> +#define XSTAT_LF_SYNC          (1ULL << 33)    /* file is written synchronously */
> +#define XSTAT_LF_NOATIME       (1ULL << 34)    /* atime is not updated on file */
> +#define XSTAT_LF_JOURNALLED_DATA (1ULL << 35)  /* data modifications to file are journalled */
> +#define XSTAT_LF_ENCRYPTED     (1ULL << 36)    /* file is encrypted */
> +#define XSTAT_LF_SYSTEM                (1ULL << 37)    /* system file */
> +#define XSTAT_LF_TEMPORARY     (1ULL << 38)    /* temporary file */
> +#define XSTAT_LF_OFFLINE       (1ULL << 39)    /* file is currently unavailable */
> +
> +       /* Which st_flags are actually supported by this filesystem for this
> +        * file */
> +       unsigned long long      st_supported_flags;
> +};
> +#define XSTAT_LENGTH_INODE_FLAGS (sizeof(struct xstat_inode_flags))
> +
> +
>  #ifdef __KERNEL__
>  #define S_IRWXUGO      (S_IRWXU|S_IRWXG|S_IRWXO)
>  #define S_IALLUGO      (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO)
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>



-- 
Michael Kerrisk Linux man-pages maintainer;
http://www.kernel.org/doc/man-pages/
Author of "The Linux Programming Interface", http://blog.man7.org/


More information about the samba-technical mailing list