X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=btrfstune.c;h=808466f97ae5cb932ba61667e9835616cacab049;hb=7ab0bdd7125c098670a6c2bb9d6bb95c1aaa78ed;hp=47830c5a94189452b6958e97fc17f605737ba90c;hpb=4d1d3a59d6debe80ce1e2da60e82233ab8f1f886;p=platform%2Fupstream%2Fbtrfs-progs.git diff --git a/btrfstune.c b/btrfstune.c index 47830c5..808466f 100644 --- a/btrfstune.c +++ b/btrfstune.c @@ -16,8 +16,6 @@ * Boston, MA 021110-1307, USA. */ -#define _XOPEN_SOURCE 500 -#define _GNU_SOURCE 1 #include #include #include @@ -30,22 +28,24 @@ #include "disk-io.h" #include "transaction.h" #include "utils.h" -#include "version.h" static char *device; +static int force = 0; -int update_seeding_flag(struct btrfs_root *root, int set_flag) +static int update_seeding_flag(struct btrfs_root *root, int set_flag) { struct btrfs_trans_handle *trans; struct btrfs_super_block *disk_super; u64 super_flags; - disk_super = &root->fs_info->super_copy; + disk_super = root->fs_info->super_copy; super_flags = btrfs_super_flags(disk_super); if (set_flag) { if (super_flags & BTRFS_SUPER_FLAG_SEEDING) { - fprintf(stderr, "seeding flag is already set on %s\n", - device); + if (force) + return 0; + else + fprintf(stderr, "seeding flag is already set on %s\n", device); return 1; } super_flags |= BTRFS_SUPER_FLAG_SEEDING; @@ -56,6 +56,7 @@ int update_seeding_flag(struct btrfs_root *root, int set_flag) return 1; } super_flags &= ~BTRFS_SUPER_FLAG_SEEDING; + fprintf(stderr, "Warning: Seeding flag cleared.\n"); } trans = btrfs_start_transaction(root, 1); @@ -65,28 +66,76 @@ int update_seeding_flag(struct btrfs_root *root, int set_flag) return 0; } +static int enable_extrefs_flag(struct btrfs_root *root) +{ + struct btrfs_trans_handle *trans; + struct btrfs_super_block *disk_super; + u64 super_flags; + + disk_super = root->fs_info->super_copy; + super_flags = btrfs_super_incompat_flags(disk_super); + super_flags |= BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF; + trans = btrfs_start_transaction(root, 1); + btrfs_set_super_incompat_flags(disk_super, super_flags); + btrfs_commit_transaction(trans, root); + + return 0; +} + +static int enable_skinny_metadata(struct btrfs_root *root) +{ + struct btrfs_trans_handle *trans; + struct btrfs_super_block *disk_super; + u64 super_flags; + + disk_super = root->fs_info->super_copy; + super_flags = btrfs_super_incompat_flags(disk_super); + super_flags |= BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA; + trans = btrfs_start_transaction(root, 1); + btrfs_set_super_incompat_flags(disk_super, super_flags); + btrfs_commit_transaction(trans, root); + + return 0; +} + static void print_usage(void) { fprintf(stderr, "usage: btrfstune [options] device\n"); - fprintf(stderr, "\t-S value\tenable/disable seeding\n"); + fprintf(stderr, "\t-S value\tpositive value will enable seeding, zero to disable, negative is not allowed\n"); + fprintf(stderr, "\t-r \t\tenable extended inode refs\n"); + fprintf(stderr, "\t-x \t\tenable skinny metadata extent refs\n"); + fprintf(stderr, "\t-f \t\tforce to set or clear flags, make sure that you are aware of the dangers\n"); } int main(int argc, char *argv[]) { struct btrfs_root *root; int success = 0; + int total = 0; + int extrefs_flag = 0; int seeding_flag = 0; - int seeding_value = 0; + u64 seeding_value = 0; + int skinny_flag = 0; int ret; + optind = 1; while(1) { - int c = getopt(argc, argv, "S:"); + int c = getopt(argc, argv, "S:rxf"); if (c < 0) break; switch(c) { case 'S': seeding_flag = 1; - seeding_value = atoi(optarg); + seeding_value = arg_strtou64(optarg); + break; + case 'r': + extrefs_flag = 1; + break; + case 'x': + skinny_flag = 1; + break; + case 'f': + force = 1; break; default: print_usage(); @@ -94,31 +143,72 @@ int main(int argc, char *argv[]) } } + set_argv0(argv); argc = argc - optind; device = argv[optind]; - if (argc != 1) { + if (check_argc_exact(argc, 1)) { + print_usage(); + return 1; + } + + if (!(seeding_flag + extrefs_flag + skinny_flag)) { + fprintf(stderr, + "ERROR: At least one option should be assigned.\n"); print_usage(); return 1; } - if (check_mounted(device)) { + ret = check_mounted(device); + if (ret < 0) { + fprintf(stderr, "Could not check mount status: %s\n", + strerror(-ret)); + return 1; + } else if (ret) { fprintf(stderr, "%s is mounted\n", device); return 1; } - root = open_ctree(device, 0, 1); + root = open_ctree(device, 0, OPEN_CTREE_WRITES); + + if (!root) { + fprintf(stderr, "Open ctree failed\n"); + return 1; + } if (seeding_flag) { + if (!seeding_value && !force) { + fprintf(stderr, "Warning: This is dangerous, clearing the seeding flag may cause the derived device not to be mountable!\n"); + ret = ask_user("We are going to clear the seeding flag, are you sure?"); + if (!ret) { + fprintf(stderr, "Clear seeding flag canceled\n"); + return 1; + } + } + ret = update_seeding_flag(root, seeding_value); if (!ret) success++; + total++; + } + + if (extrefs_flag) { + enable_extrefs_flag(root); + success++; + total++; + } + + if (skinny_flag) { + enable_skinny_metadata(root); + success++; + total++; } - if (success > 0) { + if (success == total) { ret = 0; } else { root->fs_info->readonly = 1; ret = 1; + fprintf(stderr, "btrfstune failed\n"); } close_ctree(root);