All of lore.kernel.org
 help / color / mirror / Atom feed
From: Amir Goldstein <amir73il@gmail.com>
To: "zhangyi (F)" <yi.zhang@huawei.com>
Cc: overlayfs <linux-unionfs@vger.kernel.org>,
	Miklos Szeredi <miklos@szeredi.hu>, Miao Xie <miaoxie@huawei.com>,
	yangerkun <yangerkun@huawei.com>
Subject: Re: [RFC PATCH v2 2/9] ovl: read feature set from each layer's root dir
Date: Wed, 1 Aug 2018 10:44:13 +0300	[thread overview]
Message-ID: <CAOQ4uxhchdsSudHSnDOQ=yfUoAyUffgOj6-y5CgNc5idMkWuCw@mail.gmail.com> (raw)
In-Reply-To: <20180731093727.26855-3-yi.zhang@huawei.com>

On Tue, Jul 31, 2018 at 12:37 PM, zhangyi (F) <yi.zhang@huawei.com> wrote:
> In order to distinguish the backward compatible and backward
> incompatible features in overlay filesystem, we introduce compatible,
> read-only compatible and incompatible these three kinds of features,
> store them as __be64 bit mask on each layer's root directory via
> "trusted.overlay.feature" xattr, which contains the features of this
> layer.
>
> This patch just read feature bitsets from each layer, doesn't add any
> already known features and doesn't yet use the feature bitsets.
>
> Signed-off-by: zhangyi (F) <yi.zhang@huawei.com>
> Suggested-by: Miklos Szeredi <miklos@szeredi.hu>
> Suggested-by: Amir Goldstein <amir73il@gmail.com>
> ---
>  fs/overlayfs/Makefile    |   2 +-
>  fs/overlayfs/feature.c   | 119 +++++++++++++++++++++++++++++++++++++++++++++++
>  fs/overlayfs/overlayfs.h |  15 ++++++
>  fs/overlayfs/ovl_entry.h |   5 ++
>  fs/overlayfs/super.c     |   5 ++
>  5 files changed, 145 insertions(+), 1 deletion(-)
>  create mode 100644 fs/overlayfs/feature.c
>
> diff --git a/fs/overlayfs/Makefile b/fs/overlayfs/Makefile
> index 30802347a020..219c927069d2 100644
> --- a/fs/overlayfs/Makefile
> +++ b/fs/overlayfs/Makefile
> @@ -5,4 +5,4 @@
>  obj-$(CONFIG_OVERLAY_FS) += overlay.o
>
>  overlay-objs := super.o namei.o util.o inode.o dir.o readdir.o copy_up.o \
> -               export.o
> +               export.o feature.o
> diff --git a/fs/overlayfs/feature.c b/fs/overlayfs/feature.c
> new file mode 100644
> index 000000000000..eed6644a2a31
> --- /dev/null
> +++ b/fs/overlayfs/feature.c
> @@ -0,0 +1,119 @@
> +/*
> + * Overlayfs feature sets support.
> + *
> + * Copyright (C) 2018 Huawei. All Rights Reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + */
> +
> +#include <linux/fs.h>
> +#include <linux/xattr.h>
> +#include "overlayfs.h"
> +
> +/*
> + * Get overlay features from the layer's root dir.
> + *
> + * @realroot: real root dir dentry
> + *
> + * Return on-disk overlay feature struct if success, NULL if no feature
> + * and error ptr if error.
> + */
> +static struct ovl_d_feature *ovl_get_feature(struct dentry *realroot)

It may be more appropriate to use plural (features) for function, struct
and xattr name. Don't feel so strongly about it.

> +{
> +       struct ovl_d_feature *odf = NULL;
> +       int res;
> +
> +       res = vfs_getxattr(realroot, OVL_XATTR_FEATURE, NULL, 0);
> +       if (res <= 0) {
> +               if (res == -EOPNOTSUPP || res == -ENODATA)
> +                       return NULL;
> +               goto fail;
> +       }
> +
> +       odf = kzalloc(res, GFP_KERNEL);

Don't really see the point in allocating this struct. You can keep the
features buffer on the stack and check res != sizeof(struct ovl_d_feature)
before reading into the buffer.

> +       if (!odf)
> +               return ERR_PTR(-ENOMEM);
> +
> +       res = vfs_getxattr(realroot, OVL_XATTR_FEATURE, odf, res);
> +       if (res < 0)
> +               goto fail;
> +
> +       /* Check validity */
> +       if (res < sizeof(struct ovl_d_feature)) {
> +               res = -EINVAL;
> +               goto invalid;
> +       }
> +       if (odf->magic != OVL_FEATURE_MAGIC) {
> +               res = -EINVAL;
> +               goto invalid;
> +       }
> +
> +       return odf;
> +out:
> +       kfree(odf);
> +       return ERR_PTR(res);
> +fail:
> +       pr_err("overlayfs: failed to get features (%i)\n", res);
> +       goto out;
> +invalid:
> +       pr_err("overlayfs: invalid features (%*phN)\n", res, odf);
> +       goto out;
> +}
> +
> +/*
> + * Get features from each underlying root dir.
> + *
> + * @ofs: overlay filesystem information
> + * @oe: overlay lower stack
> + *
> + * Return 0 if success, errno otherwise.
> + */
> +int ovl_init_feature_set(struct ovl_fs *ofs, struct ovl_entry *oe)
> +{
> +       struct ovl_layer *upper_layer = ofs->upper_layer;
> +       struct dentry *upper = ofs->upperdir;
> +       struct ovl_d_feature *odf;
> +       int i;
> +
> +       /* Get features from the upper root dir */
> +       if (upper_layer) {
> +               odf = ovl_get_feature(upper);
> +               if (IS_ERR(odf))
> +                       return PTR_ERR(odf);
> +
> +               if (odf) {
> +                       upper_layer->compat = be64_to_cpu(odf->compat);
> +                       upper_layer->ro_compat = be64_to_cpu(odf->ro_compat);
> +                       upper_layer->incompat = be64_to_cpu(odf->incompat);
> +                       upper_layer->feature = true;
> +                       kfree(odf);
> +               } else {
> +                       upper_layer->feature = false;
> +               }

Please pass ovl_layer * into ovl_get_feature[s]() and do all this
inside the helper - it is repeated for lower layers.

> +       }
> +
> +       /* Get features from each lower's root dir */
> +       for (i = 0; i < oe->numlower; i++) {
> +               struct ovl_path *lowerpath = &oe->lowerstack[i];
> +               struct ovl_layer *lower_layer = &ofs->lower_layers[i];
> +
> +               odf = ovl_get_feature(lowerpath->dentry);
> +               if (IS_ERR(odf))
> +                       return PTR_ERR(odf);
> +
> +               if (!odf) {
> +                       lower_layer->feature = false;
> +                       continue;
> +               }
> +
> +               lower_layer->compat = be64_to_cpu(odf->compat);
> +               lower_layer->ro_compat = be64_to_cpu(odf->ro_compat);
> +               lower_layer->incompat = be64_to_cpu(odf->incompat);
> +               lower_layer->feature = true;
> +               kfree(odf);
> +       }
> +
> +       return 0;
> +}
> diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
> index 7538b9b56237..745f3b89a99e 100644
> --- a/fs/overlayfs/overlayfs.h
> +++ b/fs/overlayfs/overlayfs.h
> @@ -28,6 +28,7 @@ enum ovl_path_type {
>  #define OVL_XATTR_IMPURE OVL_XATTR_PREFIX "impure"
>  #define OVL_XATTR_NLINK OVL_XATTR_PREFIX "nlink"
>  #define OVL_XATTR_UPPER OVL_XATTR_PREFIX "upper"
> +#define OVL_XATTR_FEATURE OVL_XATTR_PREFIX "feature"
>
>  enum ovl_inode_flag {
>         /* Pure upper dir that may contain non pure upper entries */
> @@ -43,6 +44,17 @@ enum ovl_entry_flag {
>         OVL_E_CONNECTED,
>  };
>
> +/* Features */
> +#define OVL_FEATURE_MAGIC 0xfe
> +
> +/* On-disk format of overlay layer features */
> +struct ovl_d_feature {
u8 version; (it may be 2 if we want to relate to ovl format v2)

> +       u8 magic;               /* 0xfe */

u16 pad; (just for semantically defining the on-disk format zero padding)

> +       __be64 compat;          /* compatible features */
> +       __be64 ro_compat;       /* read-only compatible features */
> +       __be64 incompat;        /* incompatible features */
> +} __packed;
> +
>  /*
>   * The tuple (fh,uuid) is a universal unique identifier for a copy up origin,
>   * where:
> @@ -379,3 +391,6 @@ int ovl_set_origin(struct dentry *dentry, struct dentry *lower,
>
>  /* export.c */
>  extern const struct export_operations ovl_export_operations;
> +
> +/* feature.c */
> +int ovl_init_feature_set(struct ovl_fs *ofs, struct ovl_entry *oe);
> diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h
> index 38ff6689a293..b1b6627f3350 100644
> --- a/fs/overlayfs/ovl_entry.h
> +++ b/fs/overlayfs/ovl_entry.h
> @@ -34,6 +34,11 @@ struct ovl_layer {
>         int idx;
>         /* One fsid per unique underlying sb (upper fsid == 0) */
>         int fsid;
> +       /* Features of this layer */
> +       u64 compat;
> +       u64 ro_compat;
> +       u64 incompat;
> +       bool feature;

Not that size of ovl_layer matters so much, but technically, the
boolean 'feature' can be represented with a single compat feature bit
if we define that the on-disk format is never initialized with all zeros,
so checking !layer->feature is equivalent to checking !layer->compat.

For example the feature OVL_FEATURE_COMPAT_V2
will always be set if features xattrs exists.
I write 'compat' only because old kernel *will* mount an overlay
with this feature set (not knowing to check it), but fsck.overlay
should not have any "official" version that does not check the
"V2" feature.

I did not yet look at all the patches to determine if the 'feature'
boolean is useful by itself, so not ruling it out completely.

Thanks,
Amir.

  reply	other threads:[~2018-08-01  7:44 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-31  9:37 [RFC PATCH v2 0/9] ovl: add feature set support zhangyi (F)
2018-07-31  9:37 ` [RFC PATCH v2 1/9] ovl: store ovl upper root path in ovl_fs zhangyi (F)
2018-08-01  6:48   ` Amir Goldstein
2018-07-31  9:37 ` [RFC PATCH v2 2/9] ovl: read feature set from each layer's root dir zhangyi (F)
2018-08-01  7:44   ` Amir Goldstein [this message]
2018-08-03 12:11     ` zhangyi (F)
2018-07-31  9:37 ` [RFC PATCH v2 3/9] ovl: check file system features can be mounted properly zhangyi (F)
2018-08-01  8:06   ` Amir Goldstein
2018-07-31  9:37 ` [RFC PATCH v2 4/9] ovl: add helper funcs to set upper layer feature set zhangyi (F)
2018-08-01  8:51   ` Amir Goldstein
2018-08-01 11:04     ` Amir Goldstein
2018-07-31  9:37 ` [RFC PATCH v2 5/9] ovl: add redirect dir feature when set redirect xattr to dir zhangyi (F)
2018-08-01 11:03   ` Amir Goldstein
2018-08-03 11:52     ` zhangyi (F)
2018-08-03 20:38       ` Amir Goldstein
2018-07-31  9:37 ` [RFC PATCH v2 6/9] ovl: add index feature if index dir exists zhangyi (F)
2018-08-01 11:15   ` Amir Goldstein
2018-07-31  9:37 ` [RFC PATCH v2 7/9] ovl: add nfs_export feature when nfs_export is enabled zhangyi (F)
2018-08-01 11:20   ` Amir Goldstein
2018-07-31  9:37 ` [RFC PATCH v2 8/9] ovl: force mount underlying layers which have feature sets zhangyi (F)
     [not found]   ` <CAOQ4uxgZcwxENyf5STfNgL6juLoHvOBnWkORpifp0pv04oi8Ww@mail.gmail.com>
2018-08-03 11:25     ` zhangyi (F)
     [not found]       ` <CAOQ4uxjxY1Urjy2fUEkV24ZfxbDjAu1vkJcERNc_7uZVmJ+2YA@mail.gmail.com>
2018-08-06  1:15         ` zhangyi (F)
2018-07-31  9:37 ` [RFC PATCH v2 9/9] ovl: check redirect_dir feature when detect redirect xattr on dir zhangyi (F)
2018-08-01 11:30   ` Amir Goldstein
2018-08-01 11:35     ` Amir Goldstein
2018-08-02 12:30       ` Vivek Goyal

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAOQ4uxhchdsSudHSnDOQ=yfUoAyUffgOj6-y5CgNc5idMkWuCw@mail.gmail.com' \
    --to=amir73il@gmail.com \
    --cc=linux-unionfs@vger.kernel.org \
    --cc=miaoxie@huawei.com \
    --cc=miklos@szeredi.hu \
    --cc=yangerkun@huawei.com \
    --cc=yi.zhang@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.