Linux Overlay Filesystem development
 help / color / mirror / Atom feed
From: Giuseppe Scrivano <giuseppe@scrivano.org>
To: Amir Goldstein <amir73il@gmail.com>
Cc: fstests@vger.kernel.org,  linux-unionfs@vger.kernel.org
Subject: Re: [PATCH fstests v2] overlay: add a test for redirect_dir=followdata
Date: Tue, 10 Nov 2026 15:02:31 +0100	[thread overview]
Message-ID: <878q30ss20.fsf@scrivano.org> (raw)
In-Reply-To: <CAOQ4uxjsNEyB0H8CqGp9En1bFCH92bYAu8UJ8SovXUeaG=z-DA@mail.gmail.com> (Amir Goldstein's message of "Tue, 10 Nov 2026 12:43:47 +0100")

Hi Amir,

Amir Goldstein <amir73il@gmail.com> writes:

> On Mon, Nov 9, 2026 at 2:40 PM Giuseppe Scrivano <giuseppe@scrivano.org> wrote:
>>
>> Test that data-only layers select redirect_dir=followdata, which follows
>> redirects from lower to lowerdata from any lower layer, with userxattr
>> and trusted xattrs, and that redirect_dir=nofollow is refused with
>> data-only layers.
>>
>> Also test following an absolute redirect past a lower layer that has the
>> parent directory of the target, which failed with EIO before the fix
>> "ovl: do not always clear absolute_redirect".
>>
>> Signed-off-by: Giuseppe Scrivano <giuseppe@scrivano.org>
>> Reviewed-by: Amir Goldstein <amir73il@gmail.com>
>> ---
>>  common/overlay        |  15 +++++
>>  tests/overlay/090     | 149 ++++++++++++++++++++++++++++++++++++++++++
>>  tests/overlay/090.out |  43 ++++++++++++
>>  3 files changed, 207 insertions(+)
>>  create mode 100755 tests/overlay/090
>>  create mode 100644 tests/overlay/090.out
>>
>> diff --git a/common/overlay b/common/overlay
>> index 8e89d6e4..382960c3 100644
>> --- a/common/overlay
>> +++ b/common/overlay
>> @@ -286,6 +286,21 @@ _require_scratch_overlay_datadir_without_metacopy()
>>
>>  }
>>
>> +# Check kernel support for the "redirect_dir=followdata" mount option
>> +_require_scratch_overlay_redirect_followdata()
>> +{
>> +       local lowerdir="$OVL_BASE_SCRATCH_MNT/$OVL_UPPER"
>> +       local datadir="$OVL_BASE_SCRATCH_MNT/$OVL_LOWER"
>> +
>> +       _scratch_mkfs > /dev/null 2>&1
>> +       _overlay_scratch_mount_opts \
>> +               -o"lowerdir+=$lowerdir,datadir+=$datadir" \
>> +               -o"userxattr,redirect_dir=followdata" > /dev/null 2>&1 || \
>> +               _notrun "overlay redirect_dir=followdata not supported on ${SCRATCH_DEV}"
>> +
>> +       _scratch_unmount
>> +}
>> +
>>
>>  # Helper function to check underlying dirs of overlay filesystem
>>  _overlay_fsck_dirs()
>> diff --git a/tests/overlay/090 b/tests/overlay/090
>> new file mode 100755
>> index 00000000..6eeeacdf
>> --- /dev/null
>> +++ b/tests/overlay/090
>> @@ -0,0 +1,149 @@
>> +#! /bin/bash
>> +# SPDX-License-Identifier: GPL-2.0
>> +# Copyright (c) 2026 Giuseppe Scrivano.  All Rights Reserved.
>> +#
>> +# FS QA Test 090
>> +#
>> +# Test the redirect_dir=followdata mount option.
>> +#
>> +# Data-only layers select redirect_dir=followdata, which follows redirects
>> +# from any lower layer to a data-only layer, and cannot be used with
>> +# redirect_dir=nofollow.
>> +#
>> +# Also test following an absolute redirect past a lower layer that has the
>> +# parent directory of the redirect target, with metacopy=on.
>> +#
>> +. ./common/preamble
>> +_begin_fstest auto quick metacopy redirect attr
>> +
>> +# Import common functions.
>> +. ./common/filter
>> +. ./common/attr
>> +
>> +# We use non-default scratch underlying overlay dirs, we need to check
>> +# them explicitly after test.
>> +_require_scratch_nocheck
>> +_require_attrs user
>> +_require_attrs trusted
>> +_require_scratch_overlay_redirect_followdata
>> +_require_scratch_overlay_features redirect_dir metacopy
>> +_require_scratch_overlay_lowerdata_layers
>> +
>> +data=$OVL_BASE_SCRATCH_MNT/data
>> +l1=$OVL_BASE_SCRATCH_MNT/lower1
>> +l2=$OVL_BASE_SCRATCH_MNT/lower2
>> +l3=$OVL_BASE_SCRATCH_MNT/lower3
>> +upper=$OVL_BASE_SCRATCH_MNT/upper
>> +work=$OVL_BASE_SCRATCH_MNT/work
>> +layers="$l3:$l2:$l1::$data"
>> +
>> +# Make a metacopy file <file> with the redirect <redirect>, for both
>> +# userxattr and trusted xattr mounts
>> +make_stub()
>> +{
>> +       local file=$1 redirect=$2 x
>> +
>> +       touch $file
>> +       for x in user.overlay. ${OVL_XATTR_METACOPY%metacopy}; do
>> +               $SETFATTR_PROG -n ${x}metacopy $file
>> +               $SETFATTR_PROG -n ${x}redirect -v $redirect $file
>> +       done
>> +       truncate -s 4 $file
>> +}
>> +
>> +# Mount the layers $layers with the options <opts>, print redirect_dir=followdata
>> +# if the mount shows it and <opts> has userxattr or redirect_dir (otherwise it
>> +# depends on the kernel config), and the content of each of the following files,
>> +# or the error reading it
>> +check()
>> +{
>> +       local opts=$1 f
>> +
>> +       shift
>> +       echo "== $opts"
>> +       _overlay_scratch_mount_dirs "$layers" $upper $work -o $opts
>> +       case $opts in
>> +       *userxattr*|*redirect_dir=*)
>> +               _fs_options $OVL_BASE_SCRATCH_MNT | grep -o redirect_dir=followdata
>> +               ;;
>> +       esac
>> +       for f; do
>> +               echo "$f: $(cat $SCRATCH_MNT/$f 2>&1 | sed 's/^cat: .*: //')"
>> +       done
>> +       _unmount $SCRATCH_MNT
>> +}
>> +
>> +# Mounting the layers $layers with the options <opts> must fail
>> +check_fail()
>> +{
>> +       local opts=$1
>> +
>> +       echo "== $opts"
>> +       _overlay_scratch_mount_dirs "$layers" $upper $work -o $opts \
>> +               >> $seqres.full 2>&1 && echo "mount succeeded" && \
>> +               _unmount $SCRATCH_MNT
>> +}
>> +
>> +_scratch_mkfs
>> +mkdir -p $data/base $l1/base $l2/base $l3 $upper $work
>> +echo -n "data" > $data/base/file
>> +
>> +make_stub $l1/s1 /base/file
>> +make_stub $l2/s2 /base/file
>> +make_stub $l3/s3 /base/file
>> +# The redirect target in a lower layer below s3, which is not looked up
>> +echo -n "lowr" > $l2/base/file
>> +# Redirects that are not followed: relative, directory, upper
>> +echo -n "lowr" > $l2/reltarget
>> +make_stub $l3/rel reltarget
>> +mkdir $l3/dir
>> +$SETFATTR_PROG -n user.overlay.redirect -v /base $l3/dir
>> +$SETFATTR_PROG -n $OVL_XATTR_REDIRECT -v /base $l3/dir
>> +make_stub $upper/up /base/file
>> +
>> +# followdata is selected by default with userxattr and a data-only layer
>> +check userxattr s1 s2 s3
>> +check userxattr,redirect_dir=followdata s1 s2 s3 rel dir up
>> +# a data-only layer cannot be used without following redirects
>> +check_fail userxattr,redirect_dir=nofollow
>> +check_fail userxattr,redirect_dir=off
>
> The test looks good but this expectation of failure is problematic.
>
> First of all the test would fail with redirect_always_follow=N
> because that makes redirect_dir=off => followdata
>
> But I also think that redirect_dir=off should not fail with
> redirect_always_follow=Y.
>
> I will explain with the documentation.
> You documentation v2 patch says:
>
> :A data-only layer selects "redirect_dir=followdata", unless
> "redirect_dir=follow"
> :or "redirect_dir=on" is in effect.
>
> So it implies redirect_dir=off => followdata
>
> All that redirect_dir=off really means is "don't create redirects".
>
> I amended the document as follows to clarify that:
>
> - "redirect_dir=on":
>     Redirects are created and followed.
> - "redirect_dir=follow":
>     Redirects are not created, but followed.
> - "redirect_dir=followdata":
>     Redirects are not created.
>     Only redirects from lower to lowerdata are followed.
> - "redirect_dir=nofollow":
>     Redirects are not created and not followed.
> - "redirect_dir=off":
>     Redirects are not created.
>     Which redirects are followed depends on "redirect_always_follow" in the
>     kernel/module config, on data-only lower layers and on the "userxattr"
>     mount option.
>
> Made this off => followdata change in the code and pushed to ovl-fixes:
>
> -static int ovl_redirect_follow_mode(size_t nr_data)
> +int ovl_redirect_follow_mode(bool follow_lower, size_t nr_data)
>  {
> -       return ovl_redirect_always_follow ? OVL_REDIRECT_FOLLOW :
> -                                           ovl_redirect_nofollow_mode(nr_data);
> +       if (ovl_redirect_always_follow && follow_lower)
> +               return OVL_REDIRECT_FOLLOW;
> +
> +       /* Data-only layers cannot be used without following redirects
> to them */
> +       return nr_data ? OVL_REDIRECT_FOLLOWDATA : OVL_REDIRECT_NOFOLLOW;
>  }
>
>  /*
> @@ -137,7 +140,7 @@ static int ovl_redirect_follow_mode(size_t nr_data)
>  static int ovl_redirect_mode_def(void)
>  {
>         return ovl_redirect_dir_def ? OVL_REDIRECT_ON :
> -                                     ovl_redirect_follow_mode(0);
> +                                     ovl_redirect_follow_mode(true, 0);
>  }
>
>  static const struct constant_table ovl_parameter_verity[] = {
> @@ -896,6 +899,9 @@ int ovl_fs_params_verify(const struct ovl_fs_context *ctx,
>         struct ovl_opt_set set = ctx->set;
>         /* The requested redirect_dir=, for reporting conflicts with it */
>         int redirect_opt = config->redirect_mode;
> +       /* The redirect follow mode for redirect_dir=off and for the default */
> +       int follow_mode = ovl_redirect_follow_mode(!config->userxattr,
> +                                                  ctx->nr_data);
>
>         /* Workdir/index are useless in non-upper mount */
>         if (!config->upperdir) {
> @@ -922,9 +928,12 @@ int ovl_fs_params_verify(const struct ovl_fs_context *ctx,
>                 config->uuid = OVL_UUID_NULL;
>         }
>
> -       /* Resolve redirect_dir=off to the default redirect follow mode */
> +       /*
> +        * Resolve redirect_dir=off to the default redirect follow mode.
> +        * With userxattr, redirects are not followed to lower by default.
> +        */
>         if (config->redirect_mode == OVL_REDIRECT_OFF)
> -               config->redirect_mode = ovl_redirect_follow_mode(ctx->nr_data);
> +               config->redirect_mode = follow_mode;
>
>         /*
>          * This is to make the logic below simpler.  It doesn't make any other
> @@ -1038,7 +1047,7 @@ int ovl_fs_params_verify(const struct ovl_fs_context *ctx,
>                  * userxattr.
>                  */
>                 if (!set.redirect)
> -                       config->redirect_mode =
> ovl_redirect_nofollow_mode(ctx->nr_data);
> +                       config->redirect_mode = follow_mode;
>                 config->metacopy = false;
>         }
>
>
> Please amend the test and test with the latest ovl-fixes:
> d0d57557b76de ovl: follow lower to lowerdata redirects from any lower layer

I've tested this modified version and it works fine.  Do you want me to
send a v3 or will you amend it?

Thanks,
Giuseppe

  reply	other threads:[~2026-11-10 14:02 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-09 13:38 [PATCH fstests v2] overlay: add a test for redirect_dir=followdata Giuseppe Scrivano
2026-11-10 11:43 ` Amir Goldstein
2026-11-10 14:02   ` Giuseppe Scrivano [this message]
2026-11-10 14:27     ` Amir Goldstein

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=878q30ss20.fsf@scrivano.org \
    --to=giuseppe@scrivano.org \
    --cc=amir73il@gmail.com \
    --cc=fstests@vger.kernel.org \
    --cc=linux-unionfs@vger.kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox