Hi,

Comments below.

----- Original Message -----
> From: Andreas Gruenbacher <agrue...@redhat.com>
> 
> Add support for an additional filesystem version (sb_fs_format = 1802).
> When a filesystem with the new version is mounted, the filesystem
> supports "trusted.*" xattrs.
> 
> In addition, version 1802 filesystems implement a form of forward
> compatibility for xattrs: when xattrs with an unknown prefix (ea_type)
> are found on a version 1802 filesystem, those attributes are not shown
> by listxattr, and they are not accessible by getxattr, setxattr, or
> removexattr.
> 
> This mechanism might turn out to be what we need in the future, but if
> not, we can always bump the filesystem version and break compatibility
> instead.
> 
> Signed-off-by: Andrew Price <anpr...@redhat.com>

If this is from Andreas, it should have his Signed-off-by:

> ---
>  fs/gfs2/ops_fstype.c             | 14 +++++++++-
>  fs/gfs2/super.h                  |  4 ++-
>  fs/gfs2/xattr.c                  | 48 +++++++++++++++++++++++++++++---
>  include/uapi/linux/gfs2_ondisk.h |  5 ++--
>  4 files changed, 63 insertions(+), 8 deletions(-)
> 
> diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
> index 52fe78378faa..64ad19bb978c 100644
> --- a/fs/gfs2/ops_fstype.c
> +++ b/fs/gfs2/ops_fstype.c
> @@ -489,6 +489,19 @@ static int init_sb(struct gfs2_sbd *sdp, int silent)
>               goto out;
>       }
>  
> +     switch(sdp->sd_sb.sb_fs_format) {
> +     case GFS2_FS_FORMAT_MAX:
> +             sb->s_xattr = gfs2_xattr_handlers_max;
> +             break;
> +
> +     case GFS2_FS_FORMAT_MIN:
> +             sb->s_xattr = gfs2_xattr_handlers_min;
> +             break;
> +
> +     default:
> +             BUG();
> +     }
> +
>       /* Set up the buffer cache and SB for real */
>       if (sdp->sd_sb.sb_bsize < bdev_logical_block_size(sb->s_bdev)) {
>               ret = -EINVAL;
> @@ -1109,7 +1122,6 @@ static int gfs2_fill_super(struct super_block *sb,
> struct fs_context *fc)
>       sb->s_op = &gfs2_super_ops;
>       sb->s_d_op = &gfs2_dops;
>       sb->s_export_op = &gfs2_export_ops;
> -     sb->s_xattr = gfs2_xattr_handlers;
>       sb->s_qcop = &gfs2_quotactl_ops;
>       sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP;
>       sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE;
> diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h
> index 977079693bdc..08e502dec7ec 100644
> --- a/fs/gfs2/super.h
> +++ b/fs/gfs2/super.h
> @@ -58,7 +58,9 @@ extern struct file_system_type gfs2meta_fs_type;
>  extern const struct export_operations gfs2_export_ops;
>  extern const struct super_operations gfs2_super_ops;
>  extern const struct dentry_operations gfs2_dops;
> -extern const struct xattr_handler *gfs2_xattr_handlers[];
> +
> +extern const struct xattr_handler *gfs2_xattr_handlers_max[];
> +extern const struct xattr_handler **gfs2_xattr_handlers_min;
>  
>  #endif /* __SUPER_DOT_H__ */
>  
> diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
> index 9d7667bc4292..a860a144f3d4 100644
> --- a/fs/gfs2/xattr.c
> +++ b/fs/gfs2/xattr.c
> @@ -70,6 +70,20 @@ static int ea_check_size(struct gfs2_sbd *sdp, unsigned
> int nsize, size_t dsize)
>       return 0;
>  }
>  
> +bool gfs2_eatype_valid(struct gfs2_sbd *sdp, u8 type)

This should be "static bool".

> +{
> +     switch(sdp->sd_sb.sb_fs_format) {
> +     case GFS2_FS_FORMAT_MAX:
> +             return true;
> +
> +     case GFS2_FS_FORMAT_MIN:
> +             return type <= GFS2_EATYPE_SECURITY;
> +
> +     default:
> +             return false;
> +     }
> +}
> +
>  typedef int (*ea_call_t) (struct gfs2_inode *ip, struct buffer_head *bh,
>                         struct gfs2_ea_header *ea,
>                         struct gfs2_ea_header *prev, void *private);
> @@ -77,6 +91,7 @@ typedef int (*ea_call_t) (struct gfs2_inode *ip, struct
> buffer_head *bh,
>  static int ea_foreach_i(struct gfs2_inode *ip, struct buffer_head *bh,
>                       ea_call_t ea_call, void *data)
>  {
> +     struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
>       struct gfs2_ea_header *ea, *prev = NULL;
>       int error = 0;
>  
> @@ -89,9 +104,8 @@ static int ea_foreach_i(struct gfs2_inode *ip, struct
> buffer_head *bh,
>               if (!(bh->b_data <= (char *)ea && (char *)GFS2_EA2NEXT(ea) <=
>                                                 bh->b_data + bh->b_size))
>                       goto fail;
> -             if (!GFS2_EATYPE_VALID(ea->ea_type))
> +             if (!gfs2_eatype_valid(sdp, ea->ea_type))
>                       goto fail;
> -
>               error = ea_call(ip, bh, ea, prev, data);
>               if (error)
>                       return error;
> @@ -344,6 +358,7 @@ static int ea_list_i(struct gfs2_inode *ip, struct
> buffer_head *bh,
>                    struct gfs2_ea_header *ea, struct gfs2_ea_header *prev,
>                    void *private)
>  {
> +     struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
>       struct ea_list *ei = private;
>       struct gfs2_ea_request *er = ei->ei_er;
>       unsigned int ea_size;
> @@ -353,6 +368,8 @@ static int ea_list_i(struct gfs2_inode *ip, struct
> buffer_head *bh,
>       if (ea->ea_type == GFS2_EATYPE_UNUSED)
>               return 0;
>  
> +     BUG_ON(ea->ea_type > GFS2_EATYPE_SECURITY &&
> +            sdp->sd_sb.sb_fs_format == GFS2_FS_FORMAT_MIN);
>       switch (ea->ea_type) {
>       case GFS2_EATYPE_USR:
>               prefix = "user.";
> @@ -366,8 +383,12 @@ static int ea_list_i(struct gfs2_inode *ip, struct
> buffer_head *bh,
>               prefix = "security.";
>               l = 9;
>               break;
> +     case GFS2_EATYPE_TRUSTED:
> +             prefix = "trusted.";
> +             l = 8;
> +             break;
>       default:
> -             BUG();
> +             return 0;
>       }
>  
>       ea_size = l + ea->ea_name_len + 1;
> @@ -1463,7 +1484,25 @@ static const struct xattr_handler
> gfs2_xattr_security_handler = {
>       .set    = gfs2_xattr_set,
>  };
>  
> -const struct xattr_handler *gfs2_xattr_handlers[] = {
> +static bool
> +gfs2_xattr_trusted_list(struct dentry *dentry)
> +{
> +     return capable(CAP_SYS_ADMIN);
> +}
> +
> +static const struct xattr_handler gfs2_xattr_trusted_handler = {
> +     .prefix = XATTR_TRUSTED_PREFIX,
> +     .flags  = GFS2_EATYPE_TRUSTED,
> +     .list   = gfs2_xattr_trusted_list,
> +     .get    = gfs2_xattr_get,
> +     .set    = gfs2_xattr_set,
> +};
> +
> +const struct xattr_handler *gfs2_xattr_handlers_max[] = {
> +     /* GFS2_FS_FORMAT_MAX */
> +     &gfs2_xattr_trusted_handler,
> +
> +     /* GFS2_FS_FORMAT_MIN */
>       &gfs2_xattr_user_handler,
>       &gfs2_xattr_security_handler,
>       &posix_acl_access_xattr_handler,
> @@ -1471,3 +1510,4 @@ const struct xattr_handler *gfs2_xattr_handlers[] = {
>       NULL,
>  };
>  
> +const struct xattr_handler **gfs2_xattr_handlers_min =
> gfs2_xattr_handlers_max + 1;
> diff --git a/include/uapi/linux/gfs2_ondisk.h
> b/include/uapi/linux/gfs2_ondisk.h
> index 07e508e6691b..6ec4291bcc7a 100644
> --- a/include/uapi/linux/gfs2_ondisk.h
> +++ b/include/uapi/linux/gfs2_ondisk.h
> @@ -47,7 +47,7 @@
>  #define GFS2_FORMAT_DE               1200
>  #define GFS2_FORMAT_QU               1500
>  /* These are part of the superblock */
> -#define GFS2_FORMAT_FS               1801
> +#define GFS2_FORMAT_FS               1802
>  #define GFS2_FORMAT_MULTI    1900
>  
>  /*
> @@ -389,8 +389,9 @@ struct gfs2_leaf {
>  #define GFS2_EATYPE_USR              1
>  #define GFS2_EATYPE_SYS              2
>  #define GFS2_EATYPE_SECURITY 3
> +#define GFS2_EATYPE_TRUSTED  4
>  
> -#define GFS2_EATYPE_LAST     3
> +#define GFS2_EATYPE_LAST     4
>  #define GFS2_EATYPE_VALID(x) ((x) <= GFS2_EATYPE_LAST)

GFS2_EATYPE_VALID was replaced by the function and isn't used elsewhere,
so this line should be deleted.
And if we do that, we might as well eliminate GFS2_EATYPE_LAST, or,
alternately, use it in the new function.

Bob

Reply via email to