Commit e6e4dbe8 authored by Omar Sandoval's avatar Omar Sandoval Committed by Chris Mason

Btrfs: remove all subvol options before mounting top-level

Currently, setup_root_args() substitutes 's/subvol=[^,]*/subvolid=0/'.
But, this means that if the user passes both a subvol and subvolid for
some reason, we won't actually mount the top-level when we recursively
mount. For example, consider:

mkfs.btrfs -f /dev/sdb
mount /dev/sdb /mnt
btrfs subvol create /mnt/subvol1 # subvolid=257
btrfs subvol create /mnt/subvol2 # subvolid=258
umount /mnt
mount -osubvol=/subvol1,subvolid=258 /dev/sdb /mnt

In the final mount, subvol=/subvol1,subvolid=258 becomes
subvolid=0,subvolid=258, and the last option takes precedence, so we
mount subvol2 and try to look up subvol1 inside of it, which fails.

So, instead, do a thorough scan through the argument list and remove any
subvol= and subvolid= options, then append subvolid=0 to the end. This
implicitly makes subvol= take precedence over subvolid=, but we're about
to add a stricter check for that. This also makes setup_root_args() more
generic, which we'll need soon.
Reviewed-by: default avatarDavid Sterba <dsterba@suse.cz>
Signed-off-by: default avatarOmar Sandoval <osandov@osandov.com>
Signed-off-by: default avatarChris Mason <clm@fb.com>
parent 773cd04e
...@@ -1133,52 +1133,36 @@ static inline int is_subvolume_inode(struct inode *inode) ...@@ -1133,52 +1133,36 @@ static inline int is_subvolume_inode(struct inode *inode)
} }
/* /*
* This will strip out the subvol=%s argument for an argument string and add * This will add subvolid=0 to the argument string while removing any subvol=
* subvolid=0 to make sure we get the actual tree root for path walking to the * and subvolid= arguments to make sure we get the top-level root for path
* subvol we want. * walking to the subvol we want.
*/ */
static char *setup_root_args(char *args) static char *setup_root_args(char *args)
{ {
unsigned len = strlen(args) + 2 + 1; char *buf, *dst, *sep;
char *src, *dst, *buf;
/* if (!args)
* We need the same args as before, but with this substitution: return kstrdup("subvolid=0", GFP_NOFS);
* s!subvol=[^,]+!subvolid=0!
*
* Since the replacement string is up to 2 bytes longer than the
* original, allocate strlen(args) + 2 + 1 bytes.
*/
src = strstr(args, "subvol="); /* The worst case is that we add ",subvolid=0" to the end. */
/* This shouldn't happen, but just in case.. */ buf = dst = kmalloc(strlen(args) + strlen(",subvolid=0") + 1, GFP_NOFS);
if (!src)
return NULL;
buf = dst = kmalloc(len, GFP_NOFS);
if (!buf) if (!buf)
return NULL; return NULL;
/* while (1) {
* If the subvol= arg is not at the start of the string, sep = strchrnul(args, ',');
* copy whatever precedes it into buf. if (!strstarts(args, "subvol=") &&
*/ !strstarts(args, "subvolid=")) {
if (src != args) { memcpy(dst, args, sep - args);
*src++ = '\0'; dst += sep - args;
strcpy(buf, args); *dst++ = ',';
dst += strlen(args); }
if (*sep)
args = sep + 1;
else
break;
} }
strcpy(dst, "subvolid=0"); strcpy(dst, "subvolid=0");
dst += strlen("subvolid=0");
/*
* If there is a "," after the original subvol=... string,
* copy that suffix into our buffer. Otherwise, we're done.
*/
src = strchr(src, ',');
if (src)
strcpy(dst, src);
return buf; return buf;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment