X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=cmds-subvolume.c;h=dc626a6495e59969ed36b796c7a63c44c8dc9660;hb=4a5b95abb620175ca6eb356ff8a7d698891fa8ab;hp=8b24de37e77fc61b2315169eaa23c30749fe258d;hpb=75716f6a8fba11ba04aaca550bb3913a58ccb817;p=platform%2Fupstream%2Fbtrfs-progs.git diff --git a/cmds-subvolume.c b/cmds-subvolume.c index 8b24de3..dc626a6 100644 --- a/cmds-subvolume.c +++ b/cmds-subvolume.c @@ -263,6 +263,9 @@ static int cmd_subvol_delete(int argc, char **argv) DIR *dirstream = NULL; int verbose = 0; int commit_mode = 0; + u8 fsid[BTRFS_FSID_SIZE]; + char uuidbuf[BTRFS_UUID_UNPARSED_SIZE]; + struct seen_fsid *seen_fsid_hash[SEEN_FSID_HASH_SIZE] = { NULL, }; enum { COMMIT_AFTER = 1, COMMIT_EACH = 2 }; while (1) { @@ -358,31 +361,74 @@ again: path, strerror(errno)); ret = 1; } + } else if (commit_mode == COMMIT_AFTER) { + res = get_fsid(dname, fsid, 0); + if (res < 0) { + error("unable to get fsid for '%s': %s", + path, strerror(-res)); + error( + "delete suceeded but commit may not be done in the end"); + ret = 1; + goto out; + } + + if (add_seen_fsid(fsid, seen_fsid_hash, fd, dirstream) == 0) { + if (verbose > 0) { + uuid_unparse(fsid, uuidbuf); + printf(" new fs is found for '%s', fsid: %s\n", + path, uuidbuf); + } + /* + * This is the first time a subvolume on this + * filesystem is deleted, keep fd in order to issue + * SYNC ioctl in the end + */ + goto keep_fd; + } } out: + close_file_or_dir(fd, dirstream); +keep_fd: + fd = -1; + dirstream = NULL; free(dupdname); free(dupvname); dupdname = NULL; dupvname = NULL; cnt++; - if (cnt < argc) { - close_file_or_dir(fd, dirstream); - /* avoid double free */ - fd = -1; - dirstream = NULL; + if (cnt < argc) goto again; - } - if (commit_mode == COMMIT_AFTER && fd != -1) { - res = wait_for_commit(fd); - if (res < 0) { - error("unable to do final sync after deletion: %s", - strerror(errno)); - ret = 1; + if (commit_mode == COMMIT_AFTER) { + int slot; + + /* + * Traverse seen_fsid_hash and issue SYNC ioctl on each + * filesystem + */ + for (slot = 0; slot < SEEN_FSID_HASH_SIZE; slot++) { + struct seen_fsid *seen = seen_fsid_hash[slot]; + + while (seen) { + res = wait_for_commit(seen->fd); + if (res < 0) { + uuid_unparse(seen->fsid, uuidbuf); + error( + "unable to do final sync after deletion: %s, fsid: %s", + strerror(errno), uuidbuf); + ret = 1; + } else if (verbose > 0) { + uuid_unparse(seen->fsid, uuidbuf); + printf("final sync is done for fsid: %s\n", + uuidbuf); + } + seen = seen->next; + } } + /* fd will also be closed in free_seen_fsid */ + free_seen_fsid(seen_fsid_hash); } - close_file_or_dir(fd, dirstream); return ret; } @@ -393,24 +439,32 @@ out: * - lowercase for enabling specific items in the output */ static const char * const cmd_subvol_list_usage[] = { - "btrfs subvolume list [options] [-G [+|-]value] [-C [+|-]value] " - "[--sort=gen,ogen,rootid,path] ", - "List subvolumes (and snapshots)", + "btrfs subvolume list [options] ", + "List subvolumes and snapshots in the filesystem.", "", - "-p print parent ID", + "Path filtering:", + "-o print only subvolumes below specified path", "-a print all the subvolumes in the filesystem and", " distinguish absolute and relative path with respect", " to the given ", + "", + "Field selection:", + "-p print parent ID", "-c print the ogeneration of the subvolume", "-g print the generation of the subvolume", - "-o print only subvolumes below specified path", "-u print the uuid of subvolumes (and snapshots)", "-q print the parent uuid of the snapshots", "-R print the uuid of the received snapshots", - "-t print the result as a table", - "-s list snapshots only in the filesystem", + "", + "Type filtering:", + "-s list only snapshots", "-r list readonly subvolumes (including snapshots)", "-d list deleted subvolumes that are not yet cleaned", + "", + "Other:", + "-t print the result as a table", + "", + "Sorting:", "-G [+|-]value", " filter the subvolumes by generation", " (+value: >= value; -value: <= value; value: = value)", @@ -804,8 +858,11 @@ out: } static const char * const cmd_subvol_set_default_usage[] = { + "btrfs subvolume set-default \n" "btrfs subvolume set-default ", - "Set the default subvolume of a filesystem", + "Set the default subvolume of the filesystem mounted as default.", + "The subvolume can be specified by its path,", + "or the pair of subvolume id and path to the filesystem.", NULL }; @@ -819,17 +876,43 @@ static int cmd_subvol_set_default(int argc, char **argv) clean_args_no_options(argc, argv, cmd_subvol_set_default_usage); - if (check_argc_exact(argc - optind, 2)) + if (check_argc_min(argc - optind, 1) || + check_argc_max(argc - optind, 2)) usage(cmd_subvol_set_default_usage); - subvolid = argv[optind]; - path = argv[optind + 1]; + if (argc - optind == 1) { + /* path to the subvolume is specified */ + path = argv[optind]; - objectid = arg_strtou64(subvolid); + ret = test_issubvolume(path); + if (ret < 0) { + error("stat error: %s", strerror(-ret)); + return 1; + } else if (!ret) { + error("'%s' is not a subvolume", path); + return 1; + } - fd = btrfs_open_dir(path, &dirstream, 1); - if (fd < 0) - return 1; + fd = btrfs_open_dir(path, &dirstream, 1); + if (fd < 0) + return 1; + + ret = lookup_path_rootid(fd, &objectid); + if (ret) { + error("unable to get subvol id: %s", strerror(-ret)); + close_file_or_dir(fd, dirstream); + return 1; + } + } else { + /* subvol id and path to the filesystem are specified */ + subvolid = argv[optind]; + path = argv[optind + 1]; + objectid = arg_strtou64(subvolid); + + fd = btrfs_open_dir(path, &dirstream, 1); + if (fd < 0) + return 1; + } ret = ioctl(fd, BTRFS_IOC_DEFAULT_SUBVOL, &objectid); e = errno;