* [PATCH RFC] Btrfs-progs: allow btrfstune to set persistent mount options
@ 2013-08-06 18:28 Filipe David Borba Manana
0 siblings, 0 replies; only message in thread
From: Filipe David Borba Manana @ 2013-08-06 18:28 UTC (permalink / raw)
To: linux-btrfs; +Cc: Filipe David Borba Manana
This is the complement to the corresponding kernel patch that
adds support for permanent options.
NOTE: Like the corresponding kernel patch, this is a WIP with the
goal o gathering feedback.
Signed-off-by: Filipe David Borba Manana <fdmanana@gmail.com>
---
btrfstune.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
ctree.h | 8 +++++
print-tree.c | 9 +++++
3 files changed, 120 insertions(+), 2 deletions(-)
diff --git a/btrfstune.c b/btrfstune.c
index 4db1767..b3d3e57 100644
--- a/btrfstune.c
+++ b/btrfstune.c
@@ -97,12 +97,100 @@ int enable_skinny_metadata(struct btrfs_root *root)
return 0;
}
+static int set_persistent_mount_options(struct btrfs_root *root,
+ const char *options)
+{
+ int ret;
+ struct btrfs_trans_handle *trans = NULL;
+ struct btrfs_path *path;
+ struct btrfs_key key, location;
+ struct extent_buffer *leaf;
+ struct btrfs_dir_item *dir_item;
+ struct btrfs_disk_key disk_key;
+ struct btrfs_root *tree_root = root->fs_info->tree_root;
+ unsigned long data_ptr;
+ u32 data_size, data_len;
+
+ path = btrfs_alloc_path();
+ if (!path)
+ return -ENOMEM;
+
+ trans = btrfs_start_transaction(root, 1);
+ if (!trans) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ key.objectid = BTRFS_PERSISTENT_OPTIONS_OBJECTID;
+ key.type = 0;
+ key.offset = 0;
+
+ ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1);
+ if (ret < 0)
+ goto out;
+ if (!ret) {
+ char *buf;
+
+ leaf = path->nodes[0];
+ dir_item = btrfs_item_ptr(leaf, path->slots[0],
+ struct btrfs_dir_item);
+ buf = (char *) malloc(btrfs_dir_data_len(leaf, dir_item));
+ if (!buf) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ read_extent_buffer(leaf, buf,
+ (unsigned long)((char *)(dir_item + 1)),
+ btrfs_dir_data_len(leaf, dir_item));
+ printf("Current persistent options: %.*s\n",
+ btrfs_dir_data_len(leaf, dir_item), buf);
+ free(buf);
+ ret = btrfs_del_item(trans, tree_root, path);
+ if (ret)
+ goto out;
+ }
+
+ btrfs_release_path(root, path);
+
+ data_len = strlen(options);
+ data_size = sizeof(*dir_item) + data_len;
+ ret = btrfs_insert_empty_item(trans, tree_root, path, &key, data_size);
+ if (ret)
+ goto out;
+
+ leaf = path->nodes[0];
+ dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item);
+
+ memset(&location, 0, sizeof(location));
+ btrfs_cpu_key_to_disk(&disk_key, &location);
+ btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
+ btrfs_set_dir_type(leaf, dir_item, BTRFS_FT_UNKNOWN);
+ btrfs_set_dir_name_len(leaf, dir_item, 0);
+ btrfs_set_dir_data_len(leaf, dir_item, data_len);
+ data_ptr = (unsigned long)((char *)(dir_item + 1));
+
+ write_extent_buffer(leaf, options, data_ptr, data_len);
+ btrfs_mark_buffer_dirty(leaf);
+
+out:
+ if (!ret && trans)
+ ret = btrfs_commit_transaction(trans, root);
+ else if (trans)
+ btrfs_free_transaction(root, trans);
+ btrfs_free_path(path);
+ if (!ret)
+ printf("New persistent options: %s\n", options);
+
+ return ret;
+}
+
static void print_usage(void)
{
fprintf(stderr, "usage: btrfstune [options] device\n");
fprintf(stderr, "\t-S value\tenable/disable seeding\n");
fprintf(stderr, "\t-r \t\tenable extended inode refs\n");
- fprintf(stderr, "\t-x enable skinny metadata extent refs\n");
+ fprintf(stderr, "\t-x \t\tenable skinny metadata extent refs\n");
+ fprintf(stderr, "\t-o options\tset persistent mount options\n");
}
int main(int argc, char *argv[])
@@ -114,9 +202,10 @@ int main(int argc, char *argv[])
int seeding_value = 0;
int skinny_flag = 0;
int ret;
+ char *options = NULL;
while(1) {
- int c = getopt(argc, argv, "S:rx");
+ int c = getopt(argc, argv, "S:rxo:");
if (c < 0)
break;
switch(c) {
@@ -130,6 +219,9 @@ int main(int argc, char *argv[])
case 'x':
skinny_flag = 1;
break;
+ case 'o':
+ options = optarg;
+ break;
default:
print_usage();
return 1;
@@ -171,6 +263,15 @@ int main(int argc, char *argv[])
success++;
}
+ if (options) {
+ ret = set_persistent_mount_options(root, options);
+ if (ret)
+ fprintf(stderr,
+ "Error setting persistent options: %d\n", ret);
+ else
+ success++;
+ }
+
if (success > 0) {
ret = 0;
} else {
diff --git a/ctree.h b/ctree.h
index 0b0d701..8255661 100644
--- a/ctree.h
+++ b/ctree.h
@@ -102,6 +102,14 @@ struct btrfs_free_space_ctl;
*/
#define BTRFS_FREE_INO_OBJECTID -12ULL
+/*
+ * Item that stores permanent mount options. These options
+ * have effect if they are not specified as well at mount
+ * time (that is, if a permanent option is also specified at
+ * mount time, the later wins).
+ */
+#define BTRFS_PERSISTENT_OPTIONS_OBJECTID -13ULL
+
/* dummy objectid represents multiple objectids */
#define BTRFS_MULTIPLE_OBJECTIDS -255ULL
diff --git a/print-tree.c b/print-tree.c
index aae47a9..4cb7af6 100644
--- a/print-tree.c
+++ b/print-tree.c
@@ -585,6 +585,9 @@ static void print_objectid(u64 objectid, u8 type)
case BTRFS_MULTIPLE_OBJECTIDS:
printf("MULTIPLE");
break;
+ case BTRFS_PERSISTENT_OPTIONS_OBJECTID:
+ printf("PERSISTENT_OPTIONS");
+ break;
case (u64)-1:
printf("-1");
break;
@@ -849,6 +852,12 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
case BTRFS_DEV_STATS_KEY:
printf("\t\tdevice stats\n");
break;
+ case 0:
+ if (objectid == BTRFS_PERSISTENT_OPTIONS_OBJECTID) {
+ di = btrfs_item_ptr(l, i, struct btrfs_dir_item);
+ print_dir_item(l, item, di);
+ }
+ break;
};
fflush(stdout);
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2013-08-06 18:28 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-08-06 18:28 [PATCH RFC] Btrfs-progs: allow btrfstune to set persistent mount options Filipe David Borba Manana
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.