btrfs-progs: mkfs: rework --subvol CLI option
Change mkfs.btrfs --subvol so that instead of being of the form --subvol DIR:FLAGS, it's instead --subvol MODIFIER:DIR, with MODIFIER being ro, rw, default, or ro-default. Signed-off-by: Mark Harmstone <maharmstone@fb.com>
This commit is contained in:
parent
863aa5df92
commit
93b27d715f
|
@ -155,15 +155,26 @@ OPTIONS
|
|||
contain the files from *rootdir*. Since version 4.14.1 the filesystem size is
|
||||
not minimized. Please see option *--shrink* if you need that functionality.
|
||||
|
||||
-u|--subvol <subdir>:<flags>
|
||||
-u|--subvol <type>:<subdir>
|
||||
Specify that *subdir* is to be created as a subvolume rather than a regular
|
||||
directory. The option *--rootdir* must also be specified, and *subdir* must be an
|
||||
existing subdirectory within it. This option can be specified multiple times.
|
||||
|
||||
*flags* is an optional comma-separated list of modifiers. Valid choices are:
|
||||
*type* is an optional additional modifier. Valid choices are:
|
||||
|
||||
* *default*: create as default subvolume (this can only be specified once)
|
||||
* *ro*: create as readonly subvolume
|
||||
* *default*: create as default subvolume
|
||||
* *ro*: create as read-only subvolume
|
||||
* *rw*: create as read-write subvolume (the default)
|
||||
* *default-ro*: create as read-only default subvolume
|
||||
|
||||
Only one of *default* and *default-ro* may be specified.
|
||||
|
||||
If you wish to create a subvolume with a name containing a colon and you don't
|
||||
want this to be parsed as containing a modifier, you can prefix the path with `./`:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ mkfs.btrfs --rootdir dir --subvol ./ro:subdir /dev/loop0
|
||||
|
||||
If there are hard links inside *rootdir* and *subdir* will split the
|
||||
subvolumes, like the following case::
|
||||
|
|
83
mkfs/main.c
83
mkfs/main.c
|
@ -440,7 +440,7 @@ static const char * const mkfs_usage[] = {
|
|||
"Creation:",
|
||||
OPTLINE("-b|--byte-count SIZE", "set size of each device to SIZE (filesystem size is sum of all device sizes)"),
|
||||
OPTLINE("-r|--rootdir DIR", "copy files from DIR to the image root directory"),
|
||||
OPTLINE("-u|--subvol SUBDIR:FLAGS", "create SUBDIR as subvolume rather than normal directory, can be specified multiple times"),
|
||||
OPTLINE("-u|--subvol TYPE:SUBDIR", "create SUBDIR as subvolume rather than normal directory, can be specified multiple times"),
|
||||
OPTLINE("--shrink", "(with --rootdir) shrink the filled filesystem to minimal size"),
|
||||
OPTLINE("-K|--nodiscard", "do not perform whole device TRIM"),
|
||||
OPTLINE("-f|--force", "force overwrite of existing filesystem"),
|
||||
|
@ -1015,48 +1015,6 @@ static void *prepare_one_device(void *ctx)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int parse_subvol_flags(struct rootdir_subvol *subvol, const char *flags)
|
||||
{
|
||||
char *buf, *orig_buf;
|
||||
int ret;
|
||||
|
||||
buf = orig_buf = strdup(flags);
|
||||
|
||||
if (!buf) {
|
||||
error_msg(ERROR_MSG_MEMORY, NULL);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
char *comma = strstr(buf, ",");
|
||||
|
||||
if (comma)
|
||||
*comma = 0;
|
||||
|
||||
if (!strcmp(buf, "default")) {
|
||||
subvol->is_default = true;
|
||||
} else if (!strcmp(buf, "ro")) {
|
||||
subvol->readonly = true;
|
||||
} else if (buf[0] != 0) {
|
||||
error("unrecognized subvol flag \"%s\"", buf);
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (comma)
|
||||
buf = comma + 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
free(orig_buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BOX_MAIN(mkfs)(int argc, char **argv)
|
||||
{
|
||||
char *file;
|
||||
|
@ -1259,6 +1217,7 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
|
|||
case 'u': {
|
||||
struct rootdir_subvol *subvol;
|
||||
char *colon;
|
||||
bool valid_prefix = false;
|
||||
|
||||
subvol = calloc(1, sizeof(struct rootdir_subvol));
|
||||
if (!subvol) {
|
||||
|
@ -1270,32 +1229,30 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
|
|||
colon = strstr(optarg, ":");
|
||||
|
||||
if (colon) {
|
||||
/* Make sure we choose the last colon in
|
||||
* optarg, in case the subvol name
|
||||
* itself contains a colon. */
|
||||
do {
|
||||
char *colon2;
|
||||
if (!string_has_prefix(optarg, "default:")) {
|
||||
subvol->is_default = true;
|
||||
valid_prefix = true;
|
||||
} else if (!string_has_prefix(optarg, "ro:")) {
|
||||
subvol->readonly = true;
|
||||
valid_prefix = true;
|
||||
} else if (!string_has_prefix(optarg, "rw:")) {
|
||||
subvol->readonly = false;
|
||||
valid_prefix = true;
|
||||
} else if (!string_has_prefix(optarg, "default-ro:")) {
|
||||
subvol->is_default = true;
|
||||
subvol->readonly = true;
|
||||
valid_prefix = true;
|
||||
}
|
||||
}
|
||||
|
||||
colon2 = strstr(colon + 1, ":");
|
||||
|
||||
if (colon2)
|
||||
colon = colon2;
|
||||
if (valid_prefix)
|
||||
subvol->dir = strndup(colon + 1, strlen(colon + 1));
|
||||
else
|
||||
break;
|
||||
} while (true);
|
||||
|
||||
subvol->dir = strndup(optarg, colon - optarg);
|
||||
if (parse_subvol_flags(subvol, colon + 1)) {
|
||||
ret = 1;
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
subvol->dir = strdup(optarg);
|
||||
}
|
||||
|
||||
if (subvol->is_default) {
|
||||
if (has_default_subvol) {
|
||||
error("subvol default flag can only be specified once");
|
||||
error("default subvolume can only be specified once");
|
||||
ret = 1;
|
||||
goto error;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue