From: Stanislav Brabec <sbrabec@suse.cz>
To: Karel Zak <kzak@redhat.com>
Cc: util-linux@vger.kernel.org, David Sterba <dsterba@suse.cz>
Subject: Re: [PATCH] tests: add btrfs mount tests (fails!)
Date: Wed, 9 Mar 2016 20:13:26 +0100 [thread overview]
Message-ID: <56E075D6.2040704@suse.cz> (raw)
In-Reply-To: <56C72E9B.3050402@suse.cz>
On Feb 19, 2016 at 16:02 Stanislav Brabec wrote:
> On Feb 11 2016 at 14:47 Stanislav Brabec wrote:
>> There are missing umount commands in the middle of the test, which
>> trigger following problem:
>>
>> Additionally, I am working on a reproducer of an invalid "mount -a"
>> behavior triggered by kernel bug reporting false subvol.
>
>> I already have a possible fix for it, but I want to confirm that it is
>> correct before sending it upstream.
>
> I finally found a reproducer.
>
Well, now I have a real reproducer that is not triggered by another bug.
My findings:
1) The way to reproduce is extremely obscure, because not only subvolid
has to match, but also target.
2) There is no way to fix it in an easy way. I suggested a new
algorithm searching for shortest subvol, but it would be vulnerable to
bad evaluation as well.
So I decided to keep the code as it is.
Way to reproduce:
To confuse the algorithm, there has to be a mounted something else into
the target than fstab specifies.
Step 1:
/dev/loop0 /btrfs_mnt_root btrfs subvol=/ 0 0
/btrfs_mnt_root/d0/dd0/ddd0/s1/d1/dd1/ddd1/s2/bind-mnt /btrfs_mnt_bind btrfs bind,private 0 0
It will create following mountinfo:
299 72 0:83 / /btrfs_mnt_root rw,relatime shared:211 - btrfs /dev/loop0 rw,space_cache,subvolid=5,subvol=/
312 72 0:83 /d0/dd0/ddd0/s1/d1/dd1/ddd1/s2/bind-mnt /btrfs_mnt_bind rw,relatime shared:211 - btrfs /dev/loop0 rw,space_cache,subvolid=258,subvol=/d0/dd0/ddd0/s1/d1/dd1/ddd1/s2/bind-mnt
Note that subvolid 258 does not correspond to / nor to
d0/dd0/ddd0/s1/d1/dd1/ddd1/s2/bind-mnt, but it corresponds to
d0/dd0/ddd0/s1/d1/dd1/ddd1/s2.
Now remove both lines from fstab and add:
/dev/loop0 /btrfs_mnt_bind btrfs defaults 0 0
Default subvolume is d0/dd0/ddd0/s1/d1/dd1/ddd1/s2, but the algorithm
(both the existing and the previously suggested one) falsely assumes
that it is /d0/dd0/ddd0/s1/d1/dd1/ddd1/s2/bind-mnt, because both
subvolid and target match.
In theory, the new fstab should cause mounting the default subvolume
over the existing one, but nothing happens.
Summary:
- The full fix would mean evaluation of the btrfs subvolume tree
structure (several ioctl() with possible need of disk lookups) just
to find, whether it is already mounted or no.
- The reproducer is really obscure, and nothing from a real life cannot
trigger it.
- The full fix will be vulnerable to another unfixable problems (e. g.
when somebody changes the default subvolume path while the device is
mounted).
=> I propose to keep this part of code with a known bug.
Here is the the previously proposed (obsolete) fix:
---
libmount/src/tab.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/libmount/src/tab.c b/libmount/src/tab.c
index 102ed25..556d835 100644
--- a/libmount/src/tab.c
+++ b/libmount/src/tab.c
@@ -1224,6 +1224,18 @@ static char *remove_mountpoint_from_path(const char *path, const char *mnt)
}
#ifdef HAVE_BTRFS_SUPPORT
+/* All currently existing kernels reports incorrect values for bind
+ * mounts. Instead of subvol/subvolid of a subvolume used for creating of bind
+ * mount, it reports subvolid corresponding to nearest upper subvol node and
+ * subvol pointing to the current dir relative to btrfs root.
+ *
+ * The current kernel btrfs implementation has not access to proper VFS
+ * structures, so it is just guessing. Fixing this will need refactoring of
+ * kernel btrfs subvol implementation. It is not expected to happen anytime
+ * soon. Set this define to suppose that kernels are buggy, and don't blindly
+ * trust to the reported mountinfo values. */
+#define KERNEL_BTRFS_REPORTS_FALSE_SUBVOL 1
+
static int get_btrfs_fs_root(struct libmnt_table *tb, struct libmnt_fs *fs, char **root)
{
char *vol = NULL, *p;
@@ -1236,6 +1248,12 @@ static int get_btrfs_fs_root(struct libmnt_table *tb, struct libmnt_fs *fs, char
char *target;
struct libmnt_fs *f;
char subvolidstr[sizeof(stringify_value(UINT64_MAX))];
+#ifdef KERNEL_BTRFS_REPORTS_FALSE_SUBVOL
+ struct libmnt_fs *t;
+ struct libmnt_iter itr;
+ char *optval = NULL;
+ size_t optvalsz = 0, valsz, bestvalsz = PATH_MAX;
+#endif
DBG(BTRFS, ul_debug(" found subvolid=%s, checking", vol));
@@ -1248,9 +1266,24 @@ static int get_btrfs_fs_root(struct libmnt_table *tb, struct libmnt_fs *fs, char
goto err;
DBG(BTRFS, ul_debug(" tring target=%s subvolid=%s", target, subvolidstr));
+#ifndef KERNEL_BTRFS_REPORTS_FALSE_SUBVOL
f = mnt_table_find_target_with_option(tb, target,
"subvolid", subvolidstr,
MNT_ITER_BACKWARD);
+#else
+ f = NULL;
+ valsz = strlen(subvolidstr);
+ mnt_reset_iter(&itr, MNT_ITER_BACKWARD);
+ while (mnt_table_next_fs(tb, &itr, &t) == 0) {
+ if (mnt_fs_streq_target(t, target)
+ && mnt_fs_get_option(t, "subvolid", &optval, &optvalsz) == 0
+ && optvalsz == valsz
+ && strncmp(optval, subvolidstr, optvalsz) == 0
+ && optvalsz < bestvalsz)
+ f = t;
+ }
+#endif
+
if (!tb->cache)
free(target);
if (!f)
@@ -1271,6 +1304,12 @@ static int get_btrfs_fs_root(struct libmnt_table *tb, struct libmnt_fs *fs, char
char *target;
struct libmnt_fs *f;
char default_id_str[sizeof(stringify_value(UINT64_MAX))];
+#ifdef KERNEL_BTRFS_REPORTS_FALSE_SUBVOL
+ struct libmnt_fs *t;
+ struct libmnt_iter itr;
+ char *optval = NULL;
+ size_t optvalsz = 0, valsz, bestvalsz = PATH_MAX;
+#endif
DBG(BTRFS, ul_debug(" subvolid/subvol not found, checking default"));
@@ -1295,9 +1334,24 @@ static int get_btrfs_fs_root(struct libmnt_table *tb, struct libmnt_fs *fs, char
DBG(BTRFS, ul_debug(" tring target=%s default subvolid=%s",
target, default_id_str));
+#ifndef KERNEL_BTRFS_REPORTS_FALSE_SUBVOL
f = mnt_table_find_target_with_option(tb, target,
"subvolid", default_id_str,
MNT_ITER_BACKWARD);
+#else
+ f = NULL;
+ valsz = strlen(default_id_str);
+ mnt_reset_iter(&itr, MNT_ITER_BACKWARD);
+ while (mnt_table_next_fs(tb, &itr, &t) == 0) {
+ if (mnt_fs_streq_target(t, target)
+ && mnt_fs_get_option(t, "subvolid", &optval, &optvalsz) == 0
+ && optvalsz == valsz
+ && strncmp(optval, default_id_str, optvalsz) == 0
+ && optvalsz < bestvalsz)
+ f = t;
+ }
+#endif
+
if (!tb->cache)
free(target);
if (!f)
--
2.7.2
--
Best Regards / S pozdravem,
Stanislav Brabec
software developer
---------------------------------------------------------------------
SUSE LINUX, s. r. o. e-mail: sbrabec@suse.com
Lihovarská 1060/12 tel: +49 911 7405384547
190 00 Praha 9 fax: +420 284 084 001
Czech Republic http://www.suse.cz/
PGP: 830B 40D5 9E05 35D8 5E27 6FA3 717C 209F A04F CD76
next prev parent reply other threads:[~2016-03-09 19:13 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-02-02 18:00 [PATCH] tests: add btrfs mount tests Stanislav Brabec
2016-02-02 20:14 ` [PATCH] tests: add btrfs mount tests (fails!) Stanislav Brabec
2016-02-03 17:00 ` Stanislav Brabec
2016-02-03 18:39 ` Stanislav Brabec
2016-02-10 16:03 ` another mount -a problem, not related to btrfs Stanislav Brabec
2016-02-11 9:43 ` [PATCH] tests: add btrfs mount tests (fails!) Karel Zak
2016-02-11 13:47 ` Stanislav Brabec
2016-02-11 16:34 ` Stanislav Brabec
2016-02-11 18:07 ` [PATCH] tests: add btrfs mount tests Stanislav Brabec
2016-02-12 9:38 ` Karel Zak
2016-02-12 10:07 ` [PATCH] tests: add btrfs mount tests (fails!) Karel Zak
2016-02-19 15:02 ` Stanislav Brabec
2016-03-09 19:13 ` Stanislav Brabec [this message]
2016-03-14 1:20 ` [PATCH] tests: add btrfs mount tests Ruediger Meier
2016-03-14 14:19 ` Stanislav Brabec
2016-03-14 23:27 ` Ruediger Meier
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=56E075D6.2040704@suse.cz \
--to=sbrabec@suse.cz \
--cc=dsterba@suse.cz \
--cc=kzak@redhat.com \
--cc=util-linux@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 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.