Following patches are going to implement one of unclaimed features listed in the btrfs wiki: https://btrfs.wiki.kernel.org/index.php/Project_ideas#Set_mount_options_permanently Previous v1 post and discussion can be referred from: http://lwn.net/Articles/516898/ v2: - Allow operator [+-=] like chmod for setting options - Save options by words instead of internal bits. (e.g. kernel code will translate a word "ssd_spread" to 2 internal bits "SSD" and "SSD_SPREAD". However this behavior might be changed if kernel updates.) Special thanks to Kazuhiro Yamashita for his time and efforts. Again, your comments/reviews are welcomed. Thanks, H.Seto -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
This patch adds mount-option command that can set/get/clear default
mount options.
Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
---
Makefile | 4 +-
btrfs-parse-mntopt.c | 109 +++++++++++++++++++++++++++++
btrfs-parse-mntopt.h | 66 ++++++++++++++++++
btrfs.c | 1 +
cmds-mount.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++
commands.h | 2 +
ctree.h | 7 ++-
7 files changed, 371 insertions(+), 3 deletions(-)
create mode 100644 btrfs-parse-mntopt.c
create mode 100644 btrfs-parse-mntopt.h
create mode 100644 cmds-mount.c
diff --git a/Makefile b/Makefile
index 4894903..c25d982 100644
--- a/Makefile
+++ b/Makefile
@@ -5,10 +5,10 @@ objects = ctree.o disk-io.o radix-tree.o extent-tree.o
print-tree.o \
root-tree.o dir-item.o file-item.o inode-item.o \
inode-map.o crc32c.o rbtree.o extent-cache.o extent_io.o \
volumes.o utils.o btrfs-list.o btrfslabel.o repair.o \
- send-stream.o send-utils.o qgroup.o
+ send-stream.o send-utils.o qgroup.o btrfs-parse-mntopt.o
cmds_objects = cmds-subvolume.o cmds-filesystem.o cmds-device.o cmds-scrub.o \
cmds-inspect.o cmds-balance.o cmds-send.o cmds-receive.o \
- cmds-quota.o cmds-qgroup.o
+ cmds-quota.o cmds-qgroup.o cmds-mount.o
CHECKFLAGS= -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise \
-Wuninitialized -Wshadow -Wundef
diff --git a/btrfs-parse-mntopt.c b/btrfs-parse-mntopt.c
new file mode 100644
index 0000000..66a924d
--- /dev/null
+++ b/btrfs-parse-mntopt.c
@@ -0,0 +1,109 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ctree.h"
+#include "btrfs-parse-mntopt.h"
+
+void btrfs_parse_string2mntopt(u64 *optval, int optnum, char **options)
+{
+ char *p, *opts;
+ int i, j;
+ u64 newval = *optval;
+ char overwrite = 0;
+
+ for (i = 0; i < optnum; i++) {
+ char *token, *save_ptr;
+ char revert = 0;
+ u64 orders = 0;
+
+ opts = options[i];
+
+ switch (*opts) {
+ case ''='':
+ if (overwrite) {
+ fprintf(stderr, "''='' operator may only be specified
once.\n");
+ return;
+ }
+ if (i) {
+ fprintf(stderr, "cannot use operator ''='' with
''+/-''.\n");
+ return;
+ }
+ if (!*(opts + 1)) {
+ fprintf(stderr, "no options after ''=''.\n");
+ return;
+ }
+ overwrite = 1;
+ opts++;
+ break;
+ case ''-'':
+ revert = 1;
+ case ''+'':
+ if (overwrite) {
+ fprintf(stderr, "cannot use operator ''='' with
''+/-''.\n");
+ return;
+ }
+ if (!*(opts + 1)) {
+ fprintf(stderr, "no options after ''%c''.\n",
*opts);
+ return;
+ }
+ opts++;
+ break;
+ default:
+ fprintf(stderr, "options must be specified with
''+/-/=''.\n");
+ return;
+ }
+
+ for (token = strtok_r(opts, ",", &save_ptr); token != NULL;
+ token = strtok_r(NULL, ",", &save_ptr)) {
+ char *arg;
+
+ arg = strchr(token, ''='');
+ if (arg) {
+ /* TBD: compress=<type> */
+ fprintf(stderr, "format ''option=arg'' is not
supported.\n");
+ return;
+ }
+
+ for (j = 0; tokens[j].pattern != NULL; j++) {
+ if (!strcmp(token, tokens[j].pattern)) {
+ orders |= (1 << tokens[j].token);
+ break;
+ }
+ }
+ if (!tokens[j].pattern) {
+ fprintf(stderr, "unknown option ''%s''.\n",
token);
+ printf("supported options : ");
+ btrfs_parse_mntopt2string(-1);
+ return;
+ }
+ }
+
+ if (overwrite)
+ newval = orders;
+ else if (revert)
+ newval &= ~orders;
+ else
+ newval |= orders;
+ }
+
+ *optval = newval;
+}
+
+void btrfs_parse_mntopt2string(u64 optval)
+{
+ if (!optval)
+ printf("no default options\n");
+ else {
+ int i, cont = 0;
+
+ for (i = 0; tokens[i].pattern != NULL; i++) {
+ if (optval & (1 << tokens[i].token)) {
+ if (cont)
+ printf(",");
+ printf("%s", tokens[i].pattern);
+ cont = 1;
+ }
+ }
+ printf("\n");
+ }
+}
diff --git a/btrfs-parse-mntopt.h b/btrfs-parse-mntopt.h
new file mode 100644
index 0000000..784a942
--- /dev/null
+++ b/btrfs-parse-mntopt.h
@@ -0,0 +1,66 @@
+/* btrfs-parse-mntopt.h */
+
+struct match_token {
+ int token;
+ const char *pattern;
+};
+
+typedef struct match_token match_table_t[];
+
+/* copy & pasted from super.c */
+enum {
+ Opt_degraded, Opt_subvol, Opt_subvolid, Opt_device, Opt_nodatasum,
+ Opt_nodatacow, Opt_max_inline, Opt_alloc_start, Opt_nobarrier, Opt_ssd,
+ Opt_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl, Opt_compress,
+ Opt_compress_type, Opt_compress_force, Opt_compress_force_type,
+ Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard,
+ Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed,
+ Opt_enospc_debug, Opt_subvolrootid, Opt_defrag, Opt_inode_cache,
+ Opt_no_space_cache, Opt_recovery, Opt_skip_balance,
+ Opt_check_integrity, Opt_check_integrity_including_extent_data,
+ Opt_check_integrity_print_mask, Opt_fatal_errors,
+ Opt_err,
+};
+
+static match_table_t tokens = {
+/* {Opt_degraded, "degraded"}, ... never be default */
+/* {Opt_subvol, "subvol=%s"}, ... not supported */
+/* {Opt_subvolid, "subvolid=%d"}, ... not supported */
+/* {Opt_device, "device=%s"}, ... not supported */
+ {Opt_nodatasum, "nodatasum"},
+ {Opt_nodatacow, "nodatacow"},
+ {Opt_nobarrier, "nobarrier"},
+/* {Opt_max_inline, "max_inline=%s"}, ... not supported */
+/* {Opt_alloc_start, "alloc_start=%s"}, ... not supported */
+/* {Opt_thread_pool, "thread_pool=%d"}, ... not supported */
+ {Opt_compress, "compress"},
+/* {Opt_compress_type, "compress=%s"}, ... TBD? */
+ {Opt_compress_force, "compress-force"},
+/* {Opt_compress_force_type, "compress-force=%s"}, ... TBD? */
+ {Opt_ssd, "ssd"},
+ {Opt_ssd_spread, "ssd_spread"},
+ {Opt_nossd, "nossd"},
+ {Opt_noacl, "noacl"},
+ {Opt_notreelog, "notreelog"},
+ {Opt_flushoncommit, "flushoncommit"},
+/* {Opt_ratio, "metadata_ratio=%d"}, ... not supported */
+ {Opt_discard, "discard"},
+ {Opt_space_cache, "space_cache"},
+ {Opt_clear_cache, "clear_cache"},
+ {Opt_user_subvol_rm_allowed, "user_subvol_rm_allowed"},
+/* {Opt_enospc_debug, "enospc_debug"}, ... never be default */
+/* {Opt_subvolrootid, "subvolrootid=%d"}, ... not supported */
+ {Opt_defrag, "autodefrag"},
+ {Opt_inode_cache, "inode_cache"},
+ {Opt_no_space_cache, "nospace_cache"},
+ {Opt_recovery, "recovery"},
+ {Opt_skip_balance, "skip_balance"},
+ {Opt_check_integrity, "check_int"},
+ {Opt_check_integrity_including_extent_data, "check_int_data"},
+/* {Opt_check_integrity_print_mask, "check_int_print_mask=%d"},
+ {Opt_fatal_errors, "fatal_errors=%s"}, ... not supported */
+ {Opt_err, NULL}, /* must be end */
+};
+
+void btrfs_parse_string2mntopt(u64 *optval, int optnum, char **options);
+void btrfs_parse_mntopt2string(u64 optval);
diff --git a/btrfs.c b/btrfs.c
index a229cee..608869d 100644
--- a/btrfs.c
+++ b/btrfs.c
@@ -250,6 +250,7 @@ const struct cmd_group btrfs_cmd_group = {
{ "receive", cmd_receive, NULL, &receive_cmd_group, 0 },
{ "quota", cmd_quota, NULL, "a_cmd_group, 0 },
{ "qgroup", cmd_qgroup, NULL, &qgroup_cmd_group, 0 },
+ { "mount-option", cmd_mount, NULL, &mount_cmd_group, 0 },
{ "help", cmd_help, cmd_help_usage, NULL, 0 },
{ "version", cmd_version, cmd_version_usage, NULL, 0 },
{ 0, 0, 0, 0, 0 }
diff --git a/cmds-mount.c b/cmds-mount.c
new file mode 100644
index 0000000..1752019
--- /dev/null
+++ b/cmds-mount.c
@@ -0,0 +1,185 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License v2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include "ioctl.h"
+#include "ctree.h"
+#include "transaction.h"
+#include "commands.h"
+#include "disk-io.h"
+#include "utils.h"
+#include "btrfs-parse-mntopt.h"
+
+static int mount_check_device(char *device)
+{
+ int ret;
+
+ ret = check_mounted(device);
+ if (ret == 1) {
+ fprintf(stderr, "%s is mounted\n", device);
+ return 1;
+ }
+ if (ret < 0) {
+ fprintf(stderr, "error checking %s mount status with %d(%s)\n",
+ device, ret, strerror(-1*ret));
+ return 1;
+ }
+ return 0;
+}
+
+static int mount_set_common(char *device, int numopts, char **options)
+{
+ struct btrfs_root *root;
+ struct btrfs_trans_handle *trans;
+ u64 optval = 0;
+ int ret;
+
+ root = open_ctree(device, 0, 1);
+ if (!root) {
+ fprintf(stderr, "error opening ctree of %s\n", device);
+ return 1;
+ }
+
+ if (numopts) {
+ optval = btrfs_super_default_mount_opt(&root->fs_info->super_copy);
+ btrfs_parse_string2mntopt(&optval, numopts, options);
+ }
+
+ trans = btrfs_start_transaction(root, 1);
+ btrfs_set_super_default_mount_opt(&root->fs_info->super_copy,
optval);
+ ret = btrfs_commit_transaction(trans, root);
+
+ close_ctree(root);
+
+ return ret;
+}
+
+static int mount_show_common(char *device)
+{
+ struct btrfs_root *root;
+ u64 def_opt;
+
+ root = open_ctree(device, 0, 0);
+ if (!root) {
+ fprintf(stderr, "error opening ctree of %s\n", device);
+ return 1;
+ }
+
+ def_opt = btrfs_super_default_mount_opt(&root->fs_info->super_copy);
+ btrfs_parse_mntopt2string(def_opt);
+
+ close_ctree(root);
+
+ return 0;
+}
+
+static const char * const cmd_set_mntopt_usage[] = {
+ "btrfs mount-option set [[+-=]<mount-option>,...]
<device>",
+ "Set default mount options",
+ NULL
+};
+
+static int cmd_set_mntopt(int argc, char **argv)
+{
+ char *device;
+
+ if (check_argc_min(argc, 2)) {
+ usage(cmd_set_mntopt_usage);
+ return 1;
+ }
+
+ device = argv[argc - 1];
+ if (mount_check_device(device))
+ return 1;
+
+ if (argc == 2) {
+ /* get mount option */
+ return mount_show_common(device);
+ }
+ /* set mount option */
+ /*
+ * Note:
+ * argv[0] = "btrfs mount-option set"
+ * argv[*] = <options>
+ * argv[n] = <device>
+ */
+ return mount_set_common(device, argc - 2, &argv[1]);
+}
+
+static const char * const cmd_get_mntopt_usage[] = {
+ "btrfs mount-option get <device>",
+ "Get default mount options",
+ NULL
+};
+
+static int cmd_get_mntopt(int argc, char **argv)
+{
+ char *device;
+
+ if (check_argc_exact(argc, 2)) {
+ usage(cmd_get_mntopt_usage);
+ return 1;
+ }
+
+ device = argv[argc - 1];
+ if (mount_check_device(device))
+ return 1;
+
+ return mount_show_common(device);
+};
+
+static const char * const cmd_clear_mntopt_usage[] = {
+ "btrfs mount-option clear <device>",
+ "Clear default mount options",
+ NULL
+};
+
+static int cmd_clear_mntopt(int argc, char **argv)
+{
+ char *device;
+
+ if (check_argc_exact(argc, 2)) {
+ usage(cmd_clear_mntopt_usage);
+ return 1;
+ }
+
+ device = argv[argc - 1];
+ if (mount_check_device(device))
+ return 1;
+
+ return mount_set_common(device, 0, NULL);
+};
+
+static const char * const mount_cmd_group_usage[] = {
+ "btrfs mount-option <command> [<args>]",
+ NULL
+};
+
+const struct cmd_group mount_cmd_group = {
+ mount_cmd_group_usage, NULL, {
+ { "set", cmd_set_mntopt, cmd_set_mntopt_usage, NULL, 0 },
+ { "get", cmd_get_mntopt, cmd_get_mntopt_usage, NULL, 0 },
+ { "clear", cmd_clear_mntopt, cmd_clear_mntopt_usage, NULL, 0},
+ {0, 0, 0, 0, 0 }
+ }
+};
+
+int cmd_mount(int argc, char **argv)
+{
+ return handle_command_group(&mount_cmd_group, argc, argv);
+}
diff --git a/commands.h b/commands.h
index bb6d2dd..fea30fd 100644
--- a/commands.h
+++ b/commands.h
@@ -92,6 +92,7 @@ extern const struct cmd_group send_cmd_group;
extern const struct cmd_group receive_cmd_group;
extern const struct cmd_group quota_cmd_group;
extern const struct cmd_group qgroup_cmd_group;
+extern const struct cmd_group mount_cmd_group;
int cmd_subvolume(int argc, char **argv);
int cmd_filesystem(int argc, char **argv);
@@ -103,6 +104,7 @@ int cmd_send(int argc, char **argv);
int cmd_receive(int argc, char **argv);
int cmd_quota(int argc, char **argv);
int cmd_qgroup(int argc, char **argv);
+int cmd_mount(int argc, char **argv);
/* subvolume exported functions */
int test_issubvolume(char *path);
diff --git a/ctree.h b/ctree.h
index 7f55229..363a118 100644
--- a/ctree.h
+++ b/ctree.h
@@ -402,8 +402,11 @@ struct btrfs_super_block {
__le64 cache_generation;
+ /* default mount options */
+ __le64 default_mount_opt;
+
/* future expansion */
- __le64 reserved[31];
+ __le64 reserved[30];
u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE];
struct btrfs_root_backup super_roots[BTRFS_NUM_BACKUP_ROOTS];
} __attribute__ ((__packed__));
@@ -1820,6 +1823,8 @@ BTRFS_SETGET_STACK_FUNCS(super_csum_type, struct
btrfs_super_block,
csum_type, 16);
BTRFS_SETGET_STACK_FUNCS(super_cache_generation, struct btrfs_super_block,
cache_generation, 64);
+BTRFS_SETGET_STACK_FUNCS(super_default_mount_opt, struct btrfs_super_block,
+ default_mount_opt, 64);
static inline int btrfs_super_csum_size(struct btrfs_super_block *s)
{
--
1.7.7.6
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs"
in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Hidetoshi Seto
2012-Oct-12 03:24 UTC
[PATCH v2 2/4] Btrfs-progs: add mount-option command man page
Add mount-option command man page. Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> --- man/btrfs.8.in | 25 +++++++++++++++++++++++++ 1 files changed, 25 insertions(+), 0 deletions(-) diff --git a/man/btrfs.8.in b/man/btrfs.8.in index 4b0a9f9..85d5030 100644 --- a/man/btrfs.8.in +++ b/man/btrfs.8.in @@ -52,6 +52,12 @@ btrfs \- control a btrfs filesystem \fBbtrfs\fP \fBinspect-internal logical-resolve\fP [-Pv] \fI<logical>\fP \fI<path>\fP .PP +\fBbtrfs\fP \fBmount-option set\fP \fI[[<+/-/=><option>,...]...]\fP \fI<device>\fP +.PP +\fBbtrfs\fP \fBmount-option get\fP \fI<device>\fP +.PP +\fBbtrfs\fP \fBmount-option clear\fP \fI<device>\fP +.PP \fBbtrfs\fP \fBhelp|\-\-help|\-h \fP\fI\fP .PP \fBbtrfs\fP \fB<command> \-\-help \fP\fI\fP @@ -319,6 +325,25 @@ skip the path resolving and print the inodes instead .IP -v 5 verbose mode. print count of returned paths and all ioctl() return values .RE +.TP + +\fBmount-option set\fP \fI[<+/-/=><option>,...]...]\fP \fI<device>\fP +With some operators \fB+\fP,\fB-\fP,\fB=\fP and some options, +set default mount options to the \fI<device>\fP. +These \fB+\fP,\fB-\fP,\fB=\fP operators mean like \fBchmod\fP operators. +The operator \fB+\fP causes the selected mount options to be added to existing +default mount options of the \fI<device>\fP; \fB-\fP causes them to be removed; +and \fB=\fP causes them to be added and causes unmentioned options to be removed. +Without options, print default mount options of the \fI<device>\fR. +.TP + +\fBmount-option get\fP \fI<device>\fP +Print default mount options of the \fI<device>\fR. +.TP + +\fBmount-option clear\fP \fI<device>\fP +Clear default mount options of the \fI<device>\fR. +.TP .SH EXIT STATUS \fBbtrfs\fR returns a zero exist status if it succeeds. Non zero is returned in -- 1.7.7.6 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hidetoshi Seto
2012-Oct-12 03:24 UTC
[PATCH v2 3/4] btrfs: make subroutine __btrfs_parse_options
Separate long switch statement to be reused.
Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
---
fs/btrfs/super.c | 431 +++++++++++++++++++++++++++---------------------------
1 files changed, 214 insertions(+), 217 deletions(-)
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 83d6f9f..d51aaee 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -349,6 +349,214 @@ static match_table_t tokens = {
{Opt_err, NULL},
};
+static int __btrfs_parse_options(struct btrfs_fs_info *info, int token,
+ substring_t *args)
+{
+ bool compress_force = false;
+ char *compress_type;
+ char *num;
+ int intarg;
+
+ switch (token) {
+ case Opt_degraded:
+ pr_info("btrfs: allowing degraded mounts\n");
+ btrfs_set_opt(info->mount_opt, DEGRADED);
+ break;
+ case Opt_subvol:
+ case Opt_subvolid:
+ case Opt_subvolrootid:
+ case Opt_device:
+ /*
+ * These are parsed by btrfs_parse_early_options
+ * and can be happily ignored here.
+ */
+ break;
+ case Opt_nodatasum:
+ pr_info("btrfs: setting nodatasum\n");
+ btrfs_set_opt(info->mount_opt, NODATASUM);
+ break;
+ case Opt_nodatacow:
+ pr_info("btrfs: setting nodatacow\n");
+ btrfs_set_opt(info->mount_opt, NODATACOW);
+ btrfs_set_opt(info->mount_opt, NODATASUM);
+ break;
+ case Opt_compress_force:
+ case Opt_compress_force_type:
+ compress_force = true;
+ case Opt_compress:
+ case Opt_compress_type:
+ if (token == Opt_compress ||
+ token == Opt_compress_force ||
+ strcmp(args[0].from, "zlib") == 0) {
+ compress_type = "zlib";
+ info->compress_type = BTRFS_COMPRESS_ZLIB;
+ btrfs_set_opt(info->mount_opt, COMPRESS);
+ } else if (strcmp(args[0].from, "lzo") == 0) {
+ compress_type = "lzo";
+ info->compress_type = BTRFS_COMPRESS_LZO;
+ btrfs_set_opt(info->mount_opt, COMPRESS);
+ btrfs_set_fs_incompat(info, COMPRESS_LZO);
+ } else if (strncmp(args[0].from, "no", 2) == 0) {
+ compress_type = "no";
+ info->compress_type = BTRFS_COMPRESS_NONE;
+ btrfs_clear_opt(info->mount_opt, COMPRESS);
+ btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS);
+ compress_force = false;
+ } else
+ return -EINVAL;
+
+ if (compress_force) {
+ btrfs_set_opt(info->mount_opt, FORCE_COMPRESS);
+ pr_info("btrfs: force %s compression\n", compress_type);
+ } else
+ pr_info("btrfs: use %s compression\n", compress_type);
+ break;
+ case Opt_ssd:
+ pr_info("btrfs: use ssd allocation scheme\n");
+ btrfs_set_opt(info->mount_opt, SSD);
+ break;
+ case Opt_ssd_spread:
+ pr_info("btrfs: use spread ssd allocation scheme\n");
+ btrfs_set_opt(info->mount_opt, SSD);
+ btrfs_set_opt(info->mount_opt, SSD_SPREAD);
+ break;
+ case Opt_nossd:
+ pr_info("btrfs: not using ssd allocation scheme\n");
+ btrfs_set_opt(info->mount_opt, NOSSD);
+ btrfs_clear_opt(info->mount_opt, SSD);
+ btrfs_clear_opt(info->mount_opt, SSD_SPREAD);
+ break;
+ case Opt_nobarrier:
+ pr_info("btrfs: turning off barriers\n");
+ btrfs_set_opt(info->mount_opt, NOBARRIER);
+ break;
+ case Opt_thread_pool:
+ intarg = 0;
+ match_int(&args[0], &intarg);
+ if (intarg)
+ info->thread_pool_size = intarg;
+ break;
+ case Opt_max_inline:
+ num = match_strdup(&args[0]);
+ if (num) {
+ info->max_inline = memparse(num, NULL);
+ kfree(num);
+
+ if (info->max_inline) {
+ info->max_inline = max_t(u64,
+ info->max_inline,
+ info->tree_root->sectorsize);
+ }
+ pr_info("btrfs: max_inline at %llu\n",
+ (unsigned long long)info->max_inline);
+ }
+ break;
+ case Opt_alloc_start:
+ num = match_strdup(&args[0]);
+ if (num) {
+ info->alloc_start = memparse(num, NULL);
+ kfree(num);
+ pr_info("btrfs: allocations start at %llu\n",
+ (unsigned long long)info->alloc_start);
+ }
+ break;
+ case Opt_noacl:
+ info->sb->s_flags &= ~MS_POSIXACL;
+ break;
+ case Opt_notreelog:
+ pr_info("btrfs: disabling tree log\n");
+ btrfs_set_opt(info->mount_opt, NOTREELOG);
+ break;
+ case Opt_flushoncommit:
+ pr_info("btrfs: turning on flush-on-commit\n");
+ btrfs_set_opt(info->mount_opt, FLUSHONCOMMIT);
+ break;
+ case Opt_ratio:
+ intarg = 0;
+ match_int(&args[0], &intarg);
+ if (intarg) {
+ info->metadata_ratio = intarg;
+ pr_info("btrfs: metadata ratio %d\n",
+ info->metadata_ratio);
+ }
+ break;
+ case Opt_discard:
+ btrfs_set_opt(info->mount_opt, DISCARD);
+ break;
+ case Opt_space_cache:
+ btrfs_set_opt(info->mount_opt, SPACE_CACHE);
+ break;
+ case Opt_no_space_cache:
+ pr_info("btrfs: disabling disk space caching\n");
+ btrfs_clear_opt(info->mount_opt, SPACE_CACHE);
+ break;
+ case Opt_inode_cache:
+ pr_info("btrfs: enabling inode map caching\n");
+ btrfs_set_opt(info->mount_opt, INODE_MAP_CACHE);
+ break;
+ case Opt_clear_cache:
+ pr_info("btrfs: force clearing of disk cache\n");
+ btrfs_set_opt(info->mount_opt, CLEAR_CACHE);
+ break;
+ case Opt_user_subvol_rm_allowed:
+ btrfs_set_opt(info->mount_opt, USER_SUBVOL_RM_ALLOWED);
+ break;
+ case Opt_enospc_debug:
+ btrfs_set_opt(info->mount_opt, ENOSPC_DEBUG);
+ break;
+ case Opt_defrag:
+ pr_info("btrfs: enabling auto defrag");
+ btrfs_set_opt(info->mount_opt, AUTO_DEFRAG);
+ break;
+ case Opt_recovery:
+ pr_info("btrfs: enabling auto recovery");
+ btrfs_set_opt(info->mount_opt, RECOVERY);
+ break;
+ case Opt_skip_balance:
+ btrfs_set_opt(info->mount_opt, SKIP_BALANCE);
+ break;
+#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
+ case Opt_check_integrity_including_extent_data:
+ pr_info("btrfs: enabling check integrity including extent data\n");
+ btrfs_set_opt(info->mount_opt,
+ CHECK_INTEGRITY_INCLUDING_EXTENT_DATA);
+ btrfs_set_opt(info->mount_opt, CHECK_INTEGRITY);
+ break;
+ case Opt_check_integrity:
+ pr_info("btrfs: enabling check integrity\n");
+ btrfs_set_opt(info->mount_opt, CHECK_INTEGRITY);
+ break;
+ case Opt_check_integrity_print_mask:
+ intarg = 0;
+ match_int(&args[0], &intarg);
+ if (intarg) {
+ info->check_integrity_print_mask = intarg;
+ pr_info("btrfs: check_integrity_print_mask 0x%x\n",
+ info->check_integrity_print_mask);
+ }
+ break;
+#else
+ case Opt_check_integrity_including_extent_data:
+ case Opt_check_integrity:
+ case Opt_check_integrity_print_mask:
+ pr_err("btrfs: support for check_integrity* not compiled in!\n");
+ return -EINVAL;
+#endif
+ case Opt_fatal_errors:
+ if (strcmp(args[0].from, "panic") == 0)
+ btrfs_set_opt(info->mount_opt, PANIC_ON_FATAL_ERROR);
+ else if (strcmp(args[0].from, "bug") == 0)
+ btrfs_clear_opt(info->mount_opt, PANIC_ON_FATAL_ERROR);
+ else
+ return -EINVAL;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
/*
* Regular mount options parser. Everything that is needed only when
* reading in a new superblock is parsed here.
@@ -358,12 +566,9 @@ int btrfs_parse_options(struct btrfs_root *root, char
*options)
{
struct btrfs_fs_info *info = root->fs_info;
substring_t args[MAX_OPT_ARGS];
- char *p, *num, *orig = NULL;
+ char *p, *orig = NULL;
u64 cache_gen;
- int intarg;
int ret = 0;
- char *compress_type;
- bool compress_force = false;
cache_gen = btrfs_super_cache_generation(root->fs_info->super_copy);
if (cache_gen)
@@ -388,222 +593,14 @@ int btrfs_parse_options(struct btrfs_root *root, char
*options)
continue;
token = match_token(p, tokens, args);
- switch (token) {
- case Opt_degraded:
- printk(KERN_INFO "btrfs: allowing degraded mounts\n");
- btrfs_set_opt(info->mount_opt, DEGRADED);
- break;
- case Opt_subvol:
- case Opt_subvolid:
- case Opt_subvolrootid:
- case Opt_device:
- /*
- * These are parsed by btrfs_parse_early_options
- * and can be happily ignored here.
- */
- break;
- case Opt_nodatasum:
- printk(KERN_INFO "btrfs: setting nodatasum\n");
- btrfs_set_opt(info->mount_opt, NODATASUM);
- break;
- case Opt_nodatacow:
- printk(KERN_INFO "btrfs: setting nodatacow\n");
- btrfs_set_opt(info->mount_opt, NODATACOW);
- btrfs_set_opt(info->mount_opt, NODATASUM);
- break;
- case Opt_compress_force:
- case Opt_compress_force_type:
- compress_force = true;
- case Opt_compress:
- case Opt_compress_type:
- if (token == Opt_compress ||
- token == Opt_compress_force ||
- strcmp(args[0].from, "zlib") == 0) {
- compress_type = "zlib";
- info->compress_type = BTRFS_COMPRESS_ZLIB;
- btrfs_set_opt(info->mount_opt, COMPRESS);
- } else if (strcmp(args[0].from, "lzo") == 0) {
- compress_type = "lzo";
- info->compress_type = BTRFS_COMPRESS_LZO;
- btrfs_set_opt(info->mount_opt, COMPRESS);
- btrfs_set_fs_incompat(info, COMPRESS_LZO);
- } else if (strncmp(args[0].from, "no", 2) == 0) {
- compress_type = "no";
- info->compress_type = BTRFS_COMPRESS_NONE;
- btrfs_clear_opt(info->mount_opt, COMPRESS);
- btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS);
- compress_force = false;
- } else {
- ret = -EINVAL;
- goto out;
- }
-
- if (compress_force) {
- btrfs_set_opt(info->mount_opt, FORCE_COMPRESS);
- pr_info("btrfs: force %s compression\n",
- compress_type);
- } else
- pr_info("btrfs: use %s compression\n",
- compress_type);
- break;
- case Opt_ssd:
- printk(KERN_INFO "btrfs: use ssd allocation scheme\n");
- btrfs_set_opt(info->mount_opt, SSD);
- break;
- case Opt_ssd_spread:
- printk(KERN_INFO "btrfs: use spread ssd "
- "allocation scheme\n");
- btrfs_set_opt(info->mount_opt, SSD);
- btrfs_set_opt(info->mount_opt, SSD_SPREAD);
- break;
- case Opt_nossd:
- printk(KERN_INFO "btrfs: not using ssd allocation "
- "scheme\n");
- btrfs_set_opt(info->mount_opt, NOSSD);
- btrfs_clear_opt(info->mount_opt, SSD);
- btrfs_clear_opt(info->mount_opt, SSD_SPREAD);
- break;
- case Opt_nobarrier:
- printk(KERN_INFO "btrfs: turning off barriers\n");
- btrfs_set_opt(info->mount_opt, NOBARRIER);
- break;
- case Opt_thread_pool:
- intarg = 0;
- match_int(&args[0], &intarg);
- if (intarg)
- info->thread_pool_size = intarg;
- break;
- case Opt_max_inline:
- num = match_strdup(&args[0]);
- if (num) {
- info->max_inline = memparse(num, NULL);
- kfree(num);
-
- if (info->max_inline) {
- info->max_inline = max_t(u64,
- info->max_inline,
- root->sectorsize);
- }
- printk(KERN_INFO "btrfs: max_inline at %llu\n",
- (unsigned long long)info->max_inline);
- }
- break;
- case Opt_alloc_start:
- num = match_strdup(&args[0]);
- if (num) {
- info->alloc_start = memparse(num, NULL);
- kfree(num);
- printk(KERN_INFO
- "btrfs: allocations start at %llu\n",
- (unsigned long long)info->alloc_start);
- }
- break;
- case Opt_noacl:
- root->fs_info->sb->s_flags &= ~MS_POSIXACL;
- break;
- case Opt_notreelog:
- printk(KERN_INFO "btrfs: disabling tree log\n");
- btrfs_set_opt(info->mount_opt, NOTREELOG);
- break;
- case Opt_flushoncommit:
- printk(KERN_INFO "btrfs: turning on flush-on-commit\n");
- btrfs_set_opt(info->mount_opt, FLUSHONCOMMIT);
- break;
- case Opt_ratio:
- intarg = 0;
- match_int(&args[0], &intarg);
- if (intarg) {
- info->metadata_ratio = intarg;
- printk(KERN_INFO "btrfs: metadata ratio %d\n",
- info->metadata_ratio);
- }
- break;
- case Opt_discard:
- btrfs_set_opt(info->mount_opt, DISCARD);
- break;
- case Opt_space_cache:
- btrfs_set_opt(info->mount_opt, SPACE_CACHE);
- break;
- case Opt_no_space_cache:
- printk(KERN_INFO "btrfs: disabling disk space caching\n");
- btrfs_clear_opt(info->mount_opt, SPACE_CACHE);
- break;
- case Opt_inode_cache:
- printk(KERN_INFO "btrfs: enabling inode map caching\n");
- btrfs_set_opt(info->mount_opt, INODE_MAP_CACHE);
- break;
- case Opt_clear_cache:
- printk(KERN_INFO "btrfs: force clearing of disk cache\n");
- btrfs_set_opt(info->mount_opt, CLEAR_CACHE);
- break;
- case Opt_user_subvol_rm_allowed:
- btrfs_set_opt(info->mount_opt, USER_SUBVOL_RM_ALLOWED);
- break;
- case Opt_enospc_debug:
- btrfs_set_opt(info->mount_opt, ENOSPC_DEBUG);
- break;
- case Opt_defrag:
- printk(KERN_INFO "btrfs: enabling auto defrag");
- btrfs_set_opt(info->mount_opt, AUTO_DEFRAG);
- break;
- case Opt_recovery:
- printk(KERN_INFO "btrfs: enabling auto recovery");
- btrfs_set_opt(info->mount_opt, RECOVERY);
- break;
- case Opt_skip_balance:
- btrfs_set_opt(info->mount_opt, SKIP_BALANCE);
- break;
-#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
- case Opt_check_integrity_including_extent_data:
- printk(KERN_INFO "btrfs: enabling check integrity"
- " including extent data\n");
- btrfs_set_opt(info->mount_opt,
- CHECK_INTEGRITY_INCLUDING_EXTENT_DATA);
- btrfs_set_opt(info->mount_opt, CHECK_INTEGRITY);
- break;
- case Opt_check_integrity:
- printk(KERN_INFO "btrfs: enabling check integrity\n");
- btrfs_set_opt(info->mount_opt, CHECK_INTEGRITY);
- break;
- case Opt_check_integrity_print_mask:
- intarg = 0;
- match_int(&args[0], &intarg);
- if (intarg) {
- info->check_integrity_print_mask = intarg;
- printk(KERN_INFO "btrfs:"
- " check_integrity_print_mask 0x%x\n",
- info->check_integrity_print_mask);
- }
- break;
-#else
- case Opt_check_integrity_including_extent_data:
- case Opt_check_integrity:
- case Opt_check_integrity_print_mask:
- printk(KERN_ERR "btrfs: support for check_integrity*"
- " not compiled in!\n");
- ret = -EINVAL;
- goto out;
-#endif
- case Opt_fatal_errors:
- if (strcmp(args[0].from, "panic") == 0)
- btrfs_set_opt(info->mount_opt,
- PANIC_ON_FATAL_ERROR);
- else if (strcmp(args[0].from, "bug") == 0)
- btrfs_clear_opt(info->mount_opt,
- PANIC_ON_FATAL_ERROR);
- else {
- ret = -EINVAL;
- goto out;
- }
- break;
- case Opt_err:
- printk(KERN_INFO "btrfs: unrecognized mount option "
- "''%s''\n", p);
+ if (token == Opt_err) {
+ pr_info("btrfs: unrecognized mount option
''%s''\n", p);
ret = -EINVAL;
- goto out;
- default:
break;
}
+ ret = __btrfs_parse_options(info, token, args);
+ if (ret)
+ break;
}
out:
if (!ret && btrfs_test_opt(root, SPACE_CACHE))
--
1.7.7.6
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs"
in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Make space to save default mount options in super block.
Parse saved default mount options first and then parse mount options given
when the file system is mounted.
Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
---
fs/btrfs/ctree.h | 7 ++++++-
fs/btrfs/super.c | 16 ++++++++++++++--
2 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 0d195b5..eea6bd0 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -461,8 +461,11 @@ struct btrfs_super_block {
__le64 cache_generation;
+ /* default mount options */
+ __le64 default_mount_opt;
+
/* future expansion */
- __le64 reserved[31];
+ __le64 reserved[30];
u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE];
struct btrfs_root_backup super_roots[BTRFS_NUM_BACKUP_ROOTS];
} __attribute__ ((__packed__));
@@ -2581,6 +2584,8 @@ BTRFS_SETGET_STACK_FUNCS(super_csum_type, struct
btrfs_super_block,
csum_type, 16);
BTRFS_SETGET_STACK_FUNCS(super_cache_generation, struct btrfs_super_block,
cache_generation, 64);
+BTRFS_SETGET_STACK_FUNCS(super_default_mount_opt, struct btrfs_super_block,
+ default_mount_opt, 64);
static inline int btrfs_super_csum_size(struct btrfs_super_block *s)
{
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index d51aaee..1cadf0e 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -567,13 +567,25 @@ int btrfs_parse_options(struct btrfs_root *root, char
*options)
struct btrfs_fs_info *info = root->fs_info;
substring_t args[MAX_OPT_ARGS];
char *p, *orig = NULL;
- u64 cache_gen;
+ u64 cache_gen, default_opt;
int ret = 0;
- cache_gen = btrfs_super_cache_generation(root->fs_info->super_copy);
+ cache_gen = btrfs_super_cache_generation(info->super_copy);
if (cache_gen)
btrfs_set_opt(info->mount_opt, SPACE_CACHE);
+ default_opt = btrfs_super_default_mount_opt(info->super_copy);
+ if (default_opt) {
+ int token;
+ for (token = 0; token < Opt_err; token++) {
+ if (default_opt & (1ul << token)) {
+ ret = __btrfs_parse_options(info, token, args);
+ if (ret)
+ return ret;
+ }
+ }
+ }
+
if (!options)
goto out;
--
1.7.7.6
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs"
in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Tsutomu Itoh
2012-Oct-12 05:35 UTC
Re: [PATCH v2 1/4] Btrfs-progs: add mount-option command
Hi, Seto-san, (2012/10/12 12:24), Hidetoshi Seto wrote:> This patch adds mount-option command that can set/get/clear default > mount options. > > Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> > --- > Makefile | 4 +- > btrfs-parse-mntopt.c | 109 +++++++++++++++++++++++++++++ > btrfs-parse-mntopt.h | 66 ++++++++++++++++++ > btrfs.c | 1 + > cmds-mount.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++ > commands.h | 2 + > ctree.h | 7 ++- > 7 files changed, 371 insertions(+), 3 deletions(-) > create mode 100644 btrfs-parse-mntopt.c > create mode 100644 btrfs-parse-mntopt.h > create mode 100644 cmds-mount.c > > diff --git a/Makefile b/Makefile > index 4894903..c25d982 100644 > --- a/Makefile > +++ b/Makefile > @@ -5,10 +5,10 @@ objects = ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \ > root-tree.o dir-item.o file-item.o inode-item.o \ > inode-map.o crc32c.o rbtree.o extent-cache.o extent_io.o \ > volumes.o utils.o btrfs-list.o btrfslabel.o repair.o \ > - send-stream.o send-utils.o qgroup.o > + send-stream.o send-utils.o qgroup.o btrfs-parse-mntopt.o > cmds_objects = cmds-subvolume.o cmds-filesystem.o cmds-device.o cmds-scrub.o \ > cmds-inspect.o cmds-balance.o cmds-send.o cmds-receive.o \ > - cmds-quota.o cmds-qgroup.o > + cmds-quota.o cmds-qgroup.o cmds-mount.o > > CHECKFLAGS= -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise \ > -Wuninitialized -Wshadow -Wundef > diff --git a/btrfs-parse-mntopt.c b/btrfs-parse-mntopt.c > new file mode 100644 > index 0000000..66a924d > --- /dev/null > +++ b/btrfs-parse-mntopt.c > @@ -0,0 +1,109 @@ > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > +#include "ctree.h" > +#include "btrfs-parse-mntopt.h" > + > +void btrfs_parse_string2mntopt(u64 *optval, int optnum, char **options) > +{ > + char *p, *opts; > + int i, j; > + u64 newval = *optval; > + char overwrite = 0; > + > + for (i = 0; i < optnum; i++) { > + char *token, *save_ptr; > + char revert = 0; > + u64 orders = 0; > + > + opts = options[i]; > + > + switch (*opts) { > + case ''='': > + if (overwrite) { > + fprintf(stderr, "''='' operator may only be specified once.\n"); > + return; > + } > + if (i) { > + fprintf(stderr, "cannot use operator ''='' with ''+/-''.\n"); > + return; > + } > + if (!*(opts + 1)) { > + fprintf(stderr, "no options after ''=''.\n"); > + return; > + } > + overwrite = 1; > + opts++; > + break; > + case ''-'': > + revert = 1; > + case ''+'': > + if (overwrite) { > + fprintf(stderr, "cannot use operator ''='' with ''+/-''.\n"); > + return; > + } > + if (!*(opts + 1)) { > + fprintf(stderr, "no options after ''%c''.\n", *opts); > + return; > + } > + opts++; > + break; > + default: > + fprintf(stderr, "options must be specified with ''+/-/=''.\n"); > + return; > + } > + > + for (token = strtok_r(opts, ",", &save_ptr); token != NULL; > + token = strtok_r(NULL, ",", &save_ptr)) { > + char *arg; > + > + arg = strchr(token, ''=''); > + if (arg) { > + /* TBD: compress=<type> */ > + fprintf(stderr, "format ''option=arg'' is not supported.\n"); > + return; > + } > + > + for (j = 0; tokens[j].pattern != NULL; j++) { > + if (!strcmp(token, tokens[j].pattern)) { > + orders |= (1 << tokens[j].token); > + break; > + } > + } > + if (!tokens[j].pattern) { > + fprintf(stderr, "unknown option ''%s''.\n", token); > + printf("supported options : "); > + btrfs_parse_mntopt2string(-1); > + return; > + } > + } > + > + if (overwrite) > + newval = orders; > + else if (revert) > + newval &= ~orders; > + else > + newval |= orders; > + } > + > + *optval = newval; > +} > + > +void btrfs_parse_mntopt2string(u64 optval) > +{ > + if (!optval) > + printf("no default options\n"); > + else { > + int i, cont = 0; > + > + for (i = 0; tokens[i].pattern != NULL; i++) { > + if (optval & (1 << tokens[i].token)) { > + if (cont) > + printf(","); > + printf("%s", tokens[i].pattern); > + cont = 1; > + } > + } > + printf("\n"); > + } > +} > diff --git a/btrfs-parse-mntopt.h b/btrfs-parse-mntopt.h > new file mode 100644 > index 0000000..784a942 > --- /dev/null > +++ b/btrfs-parse-mntopt.h > @@ -0,0 +1,66 @@Please add #ifndef _BTRFS_PARSE_MNTOPT_H #define _BTRFS_PARSE_MNTOPT_H> +/* btrfs-parse-mntopt.h */ > + > +struct match_token { > + int token; > + const char *pattern; > +}; > + > +typedef struct match_token match_table_t[]; > + > +/* copy & pasted from super.c */ > +enum { > + Opt_degraded, Opt_subvol, Opt_subvolid, Opt_device, Opt_nodatasum, > + Opt_nodatacow, Opt_max_inline, Opt_alloc_start, Opt_nobarrier, Opt_ssd, > + Opt_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl, Opt_compress, > + Opt_compress_type, Opt_compress_force, Opt_compress_force_type, > + Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard, > + Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed, > + Opt_enospc_debug, Opt_subvolrootid, Opt_defrag, Opt_inode_cache, > + Opt_no_space_cache, Opt_recovery, Opt_skip_balance, > + Opt_check_integrity, Opt_check_integrity_including_extent_data, > + Opt_check_integrity_print_mask, Opt_fatal_errors, > + Opt_err, > +}; > + > +static match_table_t tokens = { > +/* {Opt_degraded, "degraded"}, ... never be default */ > +/* {Opt_subvol, "subvol=%s"}, ... not supported */ > +/* {Opt_subvolid, "subvolid=%d"}, ... not supported */ > +/* {Opt_device, "device=%s"}, ... not supported */ > + {Opt_nodatasum, "nodatasum"}, > + {Opt_nodatacow, "nodatacow"}, > + {Opt_nobarrier, "nobarrier"}, > +/* {Opt_max_inline, "max_inline=%s"}, ... not supported */ > +/* {Opt_alloc_start, "alloc_start=%s"}, ... not supported */ > +/* {Opt_thread_pool, "thread_pool=%d"}, ... not supported */ > + {Opt_compress, "compress"}, > +/* {Opt_compress_type, "compress=%s"}, ... TBD? */ > + {Opt_compress_force, "compress-force"}, > +/* {Opt_compress_force_type, "compress-force=%s"}, ... TBD? */ > + {Opt_ssd, "ssd"}, > + {Opt_ssd_spread, "ssd_spread"}, > + {Opt_nossd, "nossd"}, > + {Opt_noacl, "noacl"}, > + {Opt_notreelog, "notreelog"}, > + {Opt_flushoncommit, "flushoncommit"}, > +/* {Opt_ratio, "metadata_ratio=%d"}, ... not supported */ > + {Opt_discard, "discard"}, > + {Opt_space_cache, "space_cache"}, > + {Opt_clear_cache, "clear_cache"}, > + {Opt_user_subvol_rm_allowed, "user_subvol_rm_allowed"}, > +/* {Opt_enospc_debug, "enospc_debug"}, ... never be default */ > +/* {Opt_subvolrootid, "subvolrootid=%d"}, ... not supported */ > + {Opt_defrag, "autodefrag"}, > + {Opt_inode_cache, "inode_cache"}, > + {Opt_no_space_cache, "nospace_cache"}, > + {Opt_recovery, "recovery"}, > + {Opt_skip_balance, "skip_balance"}, > + {Opt_check_integrity, "check_int"}, > + {Opt_check_integrity_including_extent_data, "check_int_data"}, > +/* {Opt_check_integrity_print_mask, "check_int_print_mask=%d"}, > + {Opt_fatal_errors, "fatal_errors=%s"}, ... not supported */ > + {Opt_err, NULL}, /* must be end */ > +}; > + > +void btrfs_parse_string2mntopt(u64 *optval, int optnum, char **options); > +void btrfs_parse_mntopt2string(u64 optval);#endif /* _BTRFS_PARSE_MNTOPT_H */ Thanks, Tsutomu> diff --git a/btrfs.c b/btrfs.c > index a229cee..608869d 100644 > --- a/btrfs.c > +++ b/btrfs.c > @@ -250,6 +250,7 @@ const struct cmd_group btrfs_cmd_group = { > { "receive", cmd_receive, NULL, &receive_cmd_group, 0 }, > { "quota", cmd_quota, NULL, "a_cmd_group, 0 }, > { "qgroup", cmd_qgroup, NULL, &qgroup_cmd_group, 0 }, > + { "mount-option", cmd_mount, NULL, &mount_cmd_group, 0 }, > { "help", cmd_help, cmd_help_usage, NULL, 0 }, > { "version", cmd_version, cmd_version_usage, NULL, 0 }, > { 0, 0, 0, 0, 0 } > diff --git a/cmds-mount.c b/cmds-mount.c > new file mode 100644 > index 0000000..1752019 > --- /dev/null > +++ b/cmds-mount.c > @@ -0,0 +1,185 @@ > +/* > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public > + * License v2 as published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * General Public License for more details. > + * > + * You should have received a copy of the GNU General Public > + * License along with this program; if not, write to the > + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, > + * Boston, MA 021110-1307, USA. > + */ > + > +#include <stdio.h> > +#include <stdlib.h> > +#include <sys/ioctl.h> > +#include "ioctl.h" > +#include "ctree.h" > +#include "transaction.h" > +#include "commands.h" > +#include "disk-io.h" > +#include "utils.h" > +#include "btrfs-parse-mntopt.h" > + > +static int mount_check_device(char *device) > +{ > + int ret; > + > + ret = check_mounted(device); > + if (ret == 1) { > + fprintf(stderr, "%s is mounted\n", device); > + return 1; > + } > + if (ret < 0) { > + fprintf(stderr, "error checking %s mount status with %d(%s)\n", > + device, ret, strerror(-1*ret)); > + return 1; > + } > + return 0; > +} > + > +static int mount_set_common(char *device, int numopts, char **options) > +{ > + struct btrfs_root *root; > + struct btrfs_trans_handle *trans; > + u64 optval = 0; > + int ret; > + > + root = open_ctree(device, 0, 1); > + if (!root) { > + fprintf(stderr, "error opening ctree of %s\n", device); > + return 1; > + } > + > + if (numopts) { > + optval = btrfs_super_default_mount_opt(&root->fs_info->super_copy); > + btrfs_parse_string2mntopt(&optval, numopts, options); > + } > + > + trans = btrfs_start_transaction(root, 1); > + btrfs_set_super_default_mount_opt(&root->fs_info->super_copy, optval); > + ret = btrfs_commit_transaction(trans, root); > + > + close_ctree(root); > + > + return ret; > +} > + > +static int mount_show_common(char *device) > +{ > + struct btrfs_root *root; > + u64 def_opt; > + > + root = open_ctree(device, 0, 0); > + if (!root) { > + fprintf(stderr, "error opening ctree of %s\n", device); > + return 1; > + } > + > + def_opt = btrfs_super_default_mount_opt(&root->fs_info->super_copy); > + btrfs_parse_mntopt2string(def_opt); > + > + close_ctree(root); > + > + return 0; > +} > + > +static const char * const cmd_set_mntopt_usage[] = { > + "btrfs mount-option set [[+-=]<mount-option>,...] <device>", > + "Set default mount options", > + NULL > +}; > + > +static int cmd_set_mntopt(int argc, char **argv) > +{ > + char *device; > + > + if (check_argc_min(argc, 2)) { > + usage(cmd_set_mntopt_usage); > + return 1; > + } > + > + device = argv[argc - 1]; > + if (mount_check_device(device)) > + return 1; > + > + if (argc == 2) { > + /* get mount option */ > + return mount_show_common(device); > + } > + /* set mount option */ > + /* > + * Note: > + * argv[0] = "btrfs mount-option set" > + * argv[*] = <options> > + * argv[n] = <device> > + */ > + return mount_set_common(device, argc - 2, &argv[1]); > +} > + > +static const char * const cmd_get_mntopt_usage[] = { > + "btrfs mount-option get <device>", > + "Get default mount options", > + NULL > +}; > + > +static int cmd_get_mntopt(int argc, char **argv) > +{ > + char *device; > + > + if (check_argc_exact(argc, 2)) { > + usage(cmd_get_mntopt_usage); > + return 1; > + } > + > + device = argv[argc - 1]; > + if (mount_check_device(device)) > + return 1; > + > + return mount_show_common(device); > +}; > + > +static const char * const cmd_clear_mntopt_usage[] = { > + "btrfs mount-option clear <device>", > + "Clear default mount options", > + NULL > +}; > + > +static int cmd_clear_mntopt(int argc, char **argv) > +{ > + char *device; > + > + if (check_argc_exact(argc, 2)) { > + usage(cmd_clear_mntopt_usage); > + return 1; > + } > + > + device = argv[argc - 1]; > + if (mount_check_device(device)) > + return 1; > + > + return mount_set_common(device, 0, NULL); > +}; > + > +static const char * const mount_cmd_group_usage[] = { > + "btrfs mount-option <command> [<args>]", > + NULL > +}; > + > +const struct cmd_group mount_cmd_group = { > + mount_cmd_group_usage, NULL, { > + { "set", cmd_set_mntopt, cmd_set_mntopt_usage, NULL, 0 }, > + { "get", cmd_get_mntopt, cmd_get_mntopt_usage, NULL, 0 }, > + { "clear", cmd_clear_mntopt, cmd_clear_mntopt_usage, NULL, 0}, > + {0, 0, 0, 0, 0 } > + } > +}; > + > +int cmd_mount(int argc, char **argv) > +{ > + return handle_command_group(&mount_cmd_group, argc, argv); > +} > diff --git a/commands.h b/commands.h > index bb6d2dd..fea30fd 100644 > --- a/commands.h > +++ b/commands.h > @@ -92,6 +92,7 @@ extern const struct cmd_group send_cmd_group; > extern const struct cmd_group receive_cmd_group; > extern const struct cmd_group quota_cmd_group; > extern const struct cmd_group qgroup_cmd_group; > +extern const struct cmd_group mount_cmd_group; > > int cmd_subvolume(int argc, char **argv); > int cmd_filesystem(int argc, char **argv); > @@ -103,6 +104,7 @@ int cmd_send(int argc, char **argv); > int cmd_receive(int argc, char **argv); > int cmd_quota(int argc, char **argv); > int cmd_qgroup(int argc, char **argv); > +int cmd_mount(int argc, char **argv); > > /* subvolume exported functions */ > int test_issubvolume(char *path); > diff --git a/ctree.h b/ctree.h > index 7f55229..363a118 100644 > --- a/ctree.h > +++ b/ctree.h > @@ -402,8 +402,11 @@ struct btrfs_super_block { > > __le64 cache_generation; > > + /* default mount options */ > + __le64 default_mount_opt; > + > /* future expansion */ > - __le64 reserved[31]; > + __le64 reserved[30]; > u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE]; > struct btrfs_root_backup super_roots[BTRFS_NUM_BACKUP_ROOTS]; > } __attribute__ ((__packed__)); > @@ -1820,6 +1823,8 @@ BTRFS_SETGET_STACK_FUNCS(super_csum_type, struct btrfs_super_block, > csum_type, 16); > BTRFS_SETGET_STACK_FUNCS(super_cache_generation, struct btrfs_super_block, > cache_generation, 64); > +BTRFS_SETGET_STACK_FUNCS(super_default_mount_opt, struct btrfs_super_block, > + default_mount_opt, 64); > > static inline int btrfs_super_csum_size(struct btrfs_super_block *s) > { >-- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Tsutomu Itoh
2012-Oct-12 08:21 UTC
Re: [PATCH v2 1/4] Btrfs-progs: add mount-option command
Hi, (2012/10/12 12:24), Hidetoshi Seto wrote:> This patch adds mount-option command that can set/get/clear default > mount options. > > Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> > --- > Makefile | 4 +- > btrfs-parse-mntopt.c | 109 +++++++++++++++++++++++++++++ > btrfs-parse-mntopt.h | 66 ++++++++++++++++++ > btrfs.c | 1 + > cmds-mount.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++ > commands.h | 2 + > ctree.h | 7 ++- > 7 files changed, 371 insertions(+), 3 deletions(-) > create mode 100644 btrfs-parse-mntopt.c > create mode 100644 btrfs-parse-mntopt.h > create mode 100644 cmds-mount.c > > diff --git a/Makefile b/Makefile > index 4894903..c25d982 100644 > --- a/Makefile > +++ b/Makefile > @@ -5,10 +5,10 @@ objects = ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \ > root-tree.o dir-item.o file-item.o inode-item.o \ > inode-map.o crc32c.o rbtree.o extent-cache.o extent_io.o \ > volumes.o utils.o btrfs-list.o btrfslabel.o repair.o \ > - send-stream.o send-utils.o qgroup.o > + send-stream.o send-utils.o qgroup.o btrfs-parse-mntopt.o > cmds_objects = cmds-subvolume.o cmds-filesystem.o cmds-device.o cmds-scrub.o \ > cmds-inspect.o cmds-balance.o cmds-send.o cmds-receive.o \ > - cmds-quota.o cmds-qgroup.o > + cmds-quota.o cmds-qgroup.o cmds-mount.o > > CHECKFLAGS= -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise \ > -Wuninitialized -Wshadow -Wundef > diff --git a/btrfs-parse-mntopt.c b/btrfs-parse-mntopt.c > new file mode 100644 > index 0000000..66a924d > --- /dev/null > +++ b/btrfs-parse-mntopt.c > @@ -0,0 +1,109 @@ > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > +#include "ctree.h" > +#include "btrfs-parse-mntopt.h" > + > +void btrfs_parse_string2mntopt(u64 *optval, int optnum, char **options) > +{ > + char *p, *opts; > + int i, j; > + u64 newval = *optval; > + char overwrite = 0; > + > + for (i = 0; i < optnum; i++) { > + char *token, *save_ptr; > + char revert = 0; > + u64 orders = 0; > + > + opts = options[i]; > + > + switch (*opts) { > + case ''='': > + if (overwrite) { > + fprintf(stderr, "''='' operator may only be specified once.\n"); > + return; > + } > + if (i) { > + fprintf(stderr, "cannot use operator ''='' with ''+/-''.\n"); > + return; > + } > + if (!*(opts + 1)) { > + fprintf(stderr, "no options after ''=''.\n"); > + return; > + } > + overwrite = 1; > + opts++; > + break; > + case ''-'': > + revert = 1; > + case ''+'': > + if (overwrite) { > + fprintf(stderr, "cannot use operator ''='' with ''+/-''.\n"); > + return; > + } > + if (!*(opts + 1)) { > + fprintf(stderr, "no options after ''%c''.\n", *opts); > + return; > + } > + opts++; > + break; > + default: > + fprintf(stderr, "options must be specified with ''+/-/=''.\n"); > + return; > + } > + > + for (token = strtok_r(opts, ",", &save_ptr); token != NULL; > + token = strtok_r(NULL, ",", &save_ptr)) { > + char *arg; > + > + arg = strchr(token, ''=''); > + if (arg) { > + /* TBD: compress=<type> */ > + fprintf(stderr, "format ''option=arg'' is not supported.\n"); > + return; > + } > + > + for (j = 0; tokens[j].pattern != NULL; j++) { > + if (!strcmp(token, tokens[j].pattern)) { > + orders |= (1 << tokens[j].token); > + break; > + } > + } > + if (!tokens[j].pattern) { > + fprintf(stderr, "unknown option ''%s''.\n", token); > + printf("supported options : "); > + btrfs_parse_mntopt2string(-1); > + return; > + } > + } > + > + if (overwrite) > + newval = orders; > + else if (revert) > + newval &= ~orders; > + else > + newval |= orders; > + } > + > + *optval = newval; > +} > + > +void btrfs_parse_mntopt2string(u64 optval) > +{ > + if (!optval) > + printf("no default options\n"); > + else { > + int i, cont = 0; > + > + for (i = 0; tokens[i].pattern != NULL; i++) { > + if (optval & (1 << tokens[i].token)) { > + if (cont) > + printf(","); > + printf("%s", tokens[i].pattern); > + cont = 1; > + } > + } > + printf("\n"); > + } > +} > diff --git a/btrfs-parse-mntopt.h b/btrfs-parse-mntopt.h > new file mode 100644 > index 0000000..784a942 > --- /dev/null > +++ b/btrfs-parse-mntopt.h > @@ -0,0 +1,66 @@ > +/* btrfs-parse-mntopt.h */ > + > +struct match_token { > + int token; > + const char *pattern; > +}; > + > +typedef struct match_token match_table_t[]; > + > +/* copy & pasted from super.c */ > +enum { > + Opt_degraded, Opt_subvol, Opt_subvolid, Opt_device, Opt_nodatasum, > + Opt_nodatacow, Opt_max_inline, Opt_alloc_start, Opt_nobarrier, Opt_ssd, > + Opt_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl, Opt_compress, > + Opt_compress_type, Opt_compress_force, Opt_compress_force_type, > + Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard, > + Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed, > + Opt_enospc_debug, Opt_subvolrootid, Opt_defrag, Opt_inode_cache, > + Opt_no_space_cache, Opt_recovery, Opt_skip_balance, > + Opt_check_integrity, Opt_check_integrity_including_extent_data, > + Opt_check_integrity_print_mask, Opt_fatal_errors, > + Opt_err, > +}; > + > +static match_table_t tokens = { > +/* {Opt_degraded, "degraded"}, ... never be default */ > +/* {Opt_subvol, "subvol=%s"}, ... not supported */ > +/* {Opt_subvolid, "subvolid=%d"}, ... not supported */ > +/* {Opt_device, "device=%s"}, ... not supported */ > + {Opt_nodatasum, "nodatasum"}, > + {Opt_nodatacow, "nodatacow"}, > + {Opt_nobarrier, "nobarrier"}, > +/* {Opt_max_inline, "max_inline=%s"}, ... not supported */ > +/* {Opt_alloc_start, "alloc_start=%s"}, ... not supported */ > +/* {Opt_thread_pool, "thread_pool=%d"}, ... not supported */ > + {Opt_compress, "compress"}, > +/* {Opt_compress_type, "compress=%s"}, ... TBD? */ > + {Opt_compress_force, "compress-force"}, > +/* {Opt_compress_force_type, "compress-force=%s"}, ... TBD? */ > + {Opt_ssd, "ssd"}, > + {Opt_ssd_spread, "ssd_spread"}, > + {Opt_nossd, "nossd"}, > + {Opt_noacl, "noacl"}, > + {Opt_notreelog, "notreelog"}, > + {Opt_flushoncommit, "flushoncommit"}, > +/* {Opt_ratio, "metadata_ratio=%d"}, ... not supported */ > + {Opt_discard, "discard"}, > + {Opt_space_cache, "space_cache"}, > + {Opt_clear_cache, "clear_cache"}, > + {Opt_user_subvol_rm_allowed, "user_subvol_rm_allowed"}, > +/* {Opt_enospc_debug, "enospc_debug"}, ... never be default */ > +/* {Opt_subvolrootid, "subvolrootid=%d"}, ... not supported */ > + {Opt_defrag, "autodefrag"}, > + {Opt_inode_cache, "inode_cache"}, > + {Opt_no_space_cache, "nospace_cache"}, > + {Opt_recovery, "recovery"}, > + {Opt_skip_balance, "skip_balance"}, > + {Opt_check_integrity, "check_int"}, > + {Opt_check_integrity_including_extent_data, "check_int_data"}, > +/* {Opt_check_integrity_print_mask, "check_int_print_mask=%d"}, > + {Opt_fatal_errors, "fatal_errors=%s"}, ... not supported */ > + {Opt_err, NULL}, /* must be end */ > +}; > + > +void btrfs_parse_string2mntopt(u64 *optval, int optnum, char **options); > +void btrfs_parse_mntopt2string(u64 optval); > diff --git a/btrfs.c b/btrfs.c > index a229cee..608869d 100644 > --- a/btrfs.c > +++ b/btrfs.c > @@ -250,6 +250,7 @@ const struct cmd_group btrfs_cmd_group = { > { "receive", cmd_receive, NULL, &receive_cmd_group, 0 }, > { "quota", cmd_quota, NULL, "a_cmd_group, 0 }, > { "qgroup", cmd_qgroup, NULL, &qgroup_cmd_group, 0 }, > + { "mount-option", cmd_mount, NULL, &mount_cmd_group, 0 }, > { "help", cmd_help, cmd_help_usage, NULL, 0 }, > { "version", cmd_version, cmd_version_usage, NULL, 0 }, > { 0, 0, 0, 0, 0 } > diff --git a/cmds-mount.c b/cmds-mount.c > new file mode 100644 > index 0000000..1752019 > --- /dev/null > +++ b/cmds-mount.c > @@ -0,0 +1,185 @@ > +/* > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public > + * License v2 as published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * General Public License for more details. > + * > + * You should have received a copy of the GNU General Public > + * License along with this program; if not, write to the > + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, > + * Boston, MA 021110-1307, USA. > + */ > + > +#include <stdio.h> > +#include <stdlib.h> > +#include <sys/ioctl.h> > +#include "ioctl.h" > +#include "ctree.h" > +#include "transaction.h" > +#include "commands.h" > +#include "disk-io.h" > +#include "utils.h" > +#include "btrfs-parse-mntopt.h" > + > +static int mount_check_device(char *device) > +{ > + int ret; > + > + ret = check_mounted(device); > + if (ret == 1) { > + fprintf(stderr, "%s is mounted\n", device); > + return 1; > + }I think that "btrfs mount-option get <device>" command should not be an error even if the device is mounted. Thanks, Tsutomu> + if (ret < 0) { > + fprintf(stderr, "error checking %s mount status with %d(%s)\n", > + device, ret, strerror(-1*ret)); > + return 1; > + } > + return 0; > +}-- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Goffredo Baroncelli
2012-Oct-14 09:04 UTC
Re: [PATCH v2 2/4] Btrfs-progs: add mount-option command man page
On 2012-10-12 05:24, Hidetoshi Seto wrote:> Add mount-option command man page. > > Signed-off-by: Hidetoshi Seto<seto.hidetoshi@jp.fujitsu.com> > --- > man/btrfs.8.in | 25 +++++++++++++++++++++++++ > 1 files changed, 25 insertions(+), 0 deletions(-) > > diff --git a/man/btrfs.8.in b/man/btrfs.8.in > index 4b0a9f9..85d5030 100644 > --- a/man/btrfs.8.in > +++ b/man/btrfs.8.in > @@ -52,6 +52,12 @@ btrfs \- control a btrfs filesystem > \fBbtrfs\fP \fBinspect-internal logical-resolve\fP > [-Pv] \fI<logical>\fP \fI<path>\fP > .PP > +\fBbtrfs\fP \fBmount-option set\fP \fI[[<+/-/=><option>,...]...]\fP \fI<device>\fP > +.PP > +\fBbtrfs\fP \fBmount-option get\fP \fI<device>\fP > +.PP > +\fBbtrfs\fP \fBmount-option clear\fP \fI<device>\fP > +.PP > \fBbtrfs\fP \fBhelp|\-\-help|\-h \fP\fI\fP > .PP > \fBbtrfs\fP \fB<command> \-\-help \fP\fI\fP > @@ -319,6 +325,25 @@ skip the path resolving and print the inodes instead > .IP -v 5 > verbose mode. print count of returned paths and all ioctl() return values > .RE > +.TP > + > +\fBmount-option set\fP \fI[<+/-/=><option>,...]...]\fP \fI<device>\fP > +With some operators \fB+\fP,\fB-\fP,\fB=\fP and some options, > +set default mount options to the \fI<device>\fP. > +These \fB+\fP,\fB-\fP,\fB=\fP operators mean like \fBchmod\fP operators. > +The operator \fB+\fP causes the selected mount options to be added to existing > +default mount options of the \fI<device>\fP; \fB-\fP causes them to be removed; > +and \fB=\fP causes them to be added and causes unmentioned options to be removed. > +Without options, print default mount options of the \fI<device>\fR. > +.TPPlease list all the available options here; otherwise I suggest to list them in the help of "btrfs mount-option" I think that it would be more simple ...> + > +\fBmount-option get\fP \fI<device>\fP > +Print default mount options of the \fI<device>\fR. > +.TP > + > +\fBmount-option clear\fP \fI<device>\fP > +Clear default mount options of the \fI<device>\fR. > +.TP > > .SH EXIT STATUS > \fBbtrfs\fR returns a zero exist status if it succeeds. Non zero is returned in-- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html