btrfs-progs: check: introduce traversal function for fsck
[platform/upstream/btrfs-progs.git] / btrfstune.c
index dd5626e..ac559fb 100644 (file)
@@ -24,6 +24,7 @@
 #include <unistd.h>
 #include <dirent.h>
 #include <uuid/uuid.h>
+#include <getopt.h>
 
 #include "kerncompat.h"
 #include "ctree.h"
@@ -94,17 +95,12 @@ static int change_header_uuid(struct btrfs_root *root, struct extent_buffer *eb)
        int same_chunk_tree_uuid = 1;
        int ret;
 
-       /* Check for whether we need to change fs/chunk id */
-       if (!fs_info->new_fsid && !fs_info->new_chunk_tree_uuid)
-               return 0;
-       if (fs_info->new_fsid)
-               same_fsid = !memcmp_extent_buffer(eb, fs_info->new_fsid,
-                                         btrfs_header_fsid(), BTRFS_FSID_SIZE);
-       if (fs_info->new_chunk_tree_uuid)
-               same_chunk_tree_uuid =
-                       !memcmp_extent_buffer(eb, fs_info->new_chunk_tree_uuid,
-                                             btrfs_header_chunk_tree_uuid(eb),
-                                             BTRFS_UUID_SIZE);
+       same_fsid = !memcmp_extent_buffer(eb, fs_info->new_fsid,
+                       btrfs_header_fsid(), BTRFS_FSID_SIZE);
+       same_chunk_tree_uuid =
+               !memcmp_extent_buffer(eb, fs_info->new_chunk_tree_uuid,
+                               btrfs_header_chunk_tree_uuid(eb),
+                               BTRFS_UUID_SIZE);
        if (same_fsid && same_chunk_tree_uuid)
                return 0;
        if (!same_fsid)
@@ -126,9 +122,6 @@ static int change_extents_uuid(struct btrfs_fs_info *fs_info)
        struct btrfs_key key = {0, 0, 0};
        int ret = 0;
 
-       if (!fs_info->new_fsid && !fs_info->new_chunk_tree_uuid)
-               return 0;
-
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
@@ -195,16 +188,16 @@ static int change_device_uuid(struct btrfs_root *root, struct extent_buffer *eb,
        int ret = 0;
 
        di = btrfs_item_ptr(eb, slot, struct btrfs_dev_item);
-       if (fs_info->new_fsid) {
-               if (!memcmp_extent_buffer(eb, fs_info->new_fsid,
-                                         (unsigned long)btrfs_device_fsid(di),
-                                         BTRFS_FSID_SIZE))
-                       return ret;
-               write_extent_buffer(eb, fs_info->new_fsid,
-                                   (unsigned long)btrfs_device_fsid(di),
-                                   BTRFS_FSID_SIZE);
-               ret = write_tree_block(NULL, root, eb);
-       }
+       if (!memcmp_extent_buffer(eb, fs_info->new_fsid,
+                                 (unsigned long)btrfs_device_fsid(di),
+                                 BTRFS_FSID_SIZE))
+               return ret;
+
+       write_extent_buffer(eb, fs_info->new_fsid,
+                           (unsigned long)btrfs_device_fsid(di),
+                           BTRFS_FSID_SIZE);
+       ret = write_tree_block(NULL, root, eb);
+
        return ret;
 }
 
@@ -215,12 +208,6 @@ static int change_devices_uuid(struct btrfs_fs_info *fs_info)
        struct btrfs_key key = {0, 0, 0};
        int ret = 0;
 
-       /*
-        * Unlike change_extents_uuid, we only need to change fsid in dev_item
-        */
-       if (!fs_info->new_fsid)
-               return 0;
-
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
@@ -257,11 +244,7 @@ static int change_fsid_prepare(struct btrfs_fs_info *fs_info)
        u64 flags = btrfs_super_flags(fs_info->super_copy);
        int ret = 0;
 
-       if (!fs_info->new_fsid && !fs_info->new_chunk_tree_uuid)
-               return 0;
-
-       if (fs_info->new_fsid)
-               flags |= BTRFS_SUPER_FLAG_CHANGING_FSID;
+       flags |= BTRFS_SUPER_FLAG_CHANGING_FSID;
        btrfs_set_super_flags(fs_info->super_copy, flags);
 
        memcpy(fs_info->super_copy->fsid, fs_info->new_fsid, BTRFS_FSID_SIZE);
@@ -280,11 +263,7 @@ static int change_fsid_done(struct btrfs_fs_info *fs_info)
 {
        u64 flags = btrfs_super_flags(fs_info->super_copy);
 
-       if (!fs_info->new_fsid && !fs_info->new_chunk_tree_uuid)
-               return 0;
-
-       if (fs_info->new_fsid)
-               flags &= ~BTRFS_SUPER_FLAG_CHANGING_FSID;
+       flags &= ~BTRFS_SUPER_FLAG_CHANGING_FSID;
        btrfs_set_super_flags(fs_info->super_copy, flags);
 
        return write_all_supers(fs_info->tree_root);
@@ -321,6 +300,7 @@ static int change_uuid(struct btrfs_fs_info *fs_info, const char *new_fsid_str)
 {
        uuid_t new_fsid;
        uuid_t new_chunk_id;
+       uuid_t old_fsid;
        char uuid_buf[BTRFS_UUID_UNPARSED_SIZE];
        int ret = 0;
 
@@ -347,14 +327,20 @@ static int change_uuid(struct btrfs_fs_info *fs_info, const char *new_fsid_str)
        fs_info->new_fsid = new_fsid;
        fs_info->new_chunk_tree_uuid = new_chunk_id;
 
-       uuid_unparse_upper(new_fsid, uuid_buf);
-       printf("Changing fsid to %s\n", uuid_buf);
+       memcpy(old_fsid, (const char*)fs_info->fsid, BTRFS_UUID_SIZE);
+       uuid_unparse(old_fsid, uuid_buf);
+       printf("Current fsid: %s\n", uuid_buf);
+
+       uuid_unparse(new_fsid, uuid_buf);
+       printf("New fsid: %s\n", uuid_buf);
        /* Now we can begin fsid change */
+       printf("Set superblock flag CHANGING_FSID\n");
        ret = change_fsid_prepare(fs_info);
        if (ret < 0)
                goto out;
 
        /* Change extents first */
+       printf("Change fsid in extents\n");
        ret = change_extents_uuid(fs_info);
        if (ret < 0) {
                fprintf(stderr, "Failed to change UUID of metadata\n");
@@ -362,6 +348,7 @@ static int change_uuid(struct btrfs_fs_info *fs_info, const char *new_fsid_str)
        }
 
        /* Then devices */
+       printf("Change fsid on devices\n");
        ret = change_devices_uuid(fs_info);
        if (ret < 0) {
                fprintf(stderr, "Failed to change UUID of devices\n");
@@ -378,10 +365,11 @@ static int change_uuid(struct btrfs_fs_info *fs_info, const char *new_fsid_str)
                goto out;
 
        /* Now fsid change is done */
+       printf("Clear superblock flag CHANGING_FSID\n");
        ret = change_fsid_done(fs_info);
        fs_info->new_fsid = NULL;
        fs_info->new_chunk_tree_uuid = NULL;
-       printf("Fsid changed to %s\n", uuid_buf);
+       printf("Fsid change finished\n");
 out:
        return ret;
 }
@@ -411,9 +399,13 @@ int main(int argc, char *argv[])
        int ret;
        u64 super_flags = 0;
 
-       optind = 1;
        while(1) {
-               int c = getopt(argc, argv, "S:rxfuU:n");
+               static const struct option long_options[] = {
+                       { "help", no_argument, NULL, GETOPT_VAL_HELP},
+                       { NULL, 0, NULL, 0 }
+               };
+               int c = getopt_long(argc, argv, "S:rxfuU:n", long_options, NULL);
+
                if (c < 0)
                        break;
                switch(c) {
@@ -441,16 +433,16 @@ int main(int argc, char *argv[])
                        ctree_flags |= OPEN_CTREE_IGNORE_FSID_MISMATCH;
                        random_fsid = 1;
                        break;
+               case GETOPT_VAL_HELP:
                default:
                        print_usage();
-                       return 1;
+                       return c != GETOPT_VAL_HELP;
                }
        }
 
        set_argv0(argv);
-       argc = argc - optind;
        device = argv[optind];
-       if (check_argc_exact(argc, 1)) {
+       if (check_argc_exact(argc - optind, 1)) {
                print_usage();
                return 1;
        }
@@ -554,6 +546,7 @@ int main(int argc, char *argv[])
        }
 out:
        close_ctree(root);
+       btrfs_close_all_devices();
 
        return ret;
 }