X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=cmds-device.c;h=a939c56f05b522efd711b5516a6bf7369c6a6f51;hb=dad817d3bad44619c355d11e39512b413da6939c;hp=5f2b952ac16f579cb472868455ac7c9d636a2bfe;hpb=54fdddfdc14fa6e9ddf6960cb22d668d83cdf65e;p=platform%2Fupstream%2Fbtrfs-progs.git diff --git a/cmds-device.c b/cmds-device.c index 5f2b952..a939c56 100644 --- a/cmds-device.c +++ b/cmds-device.c @@ -49,10 +49,11 @@ static const char * const cmd_device_add_usage[] = { static int cmd_device_add(int argc, char **argv) { char *mntpnt; - int i, fdmnt, ret=0, e; + int i, fdmnt, ret = 0; DIR *dirstream = NULL; int discard = 1; int force = 0; + int last_dev; while (1) { int c; @@ -77,22 +78,20 @@ static int cmd_device_add(int argc, char **argv) } } - argc = argc - optind; - - if (check_argc_min(argc, 2)) + if (check_argc_min(argc - optind, 2)) usage(cmd_device_add_usage); - mntpnt = argv[optind + argc - 1]; + last_dev = argc - 1; + mntpnt = argv[last_dev]; fdmnt = btrfs_open_dir(mntpnt, &dirstream, 1); if (fdmnt < 0) return 1; - for (i = optind; i < optind + argc - 1; i++){ + for (i = optind; i < last_dev; i++){ struct btrfs_ioctl_vol_args ioctl_args; int devfd, res; u64 dev_block_count = 0; - int mixed = 0; char *path; res = test_dev_for_mkfs(argv[i], force); @@ -103,13 +102,14 @@ static int cmd_device_add(int argc, char **argv) devfd = open(argv[i], O_RDWR); if (devfd < 0) { - fprintf(stderr, "ERROR: Unable to open device '%s'\n", argv[i]); + error("unable to open device '%s'", argv[i]); ret++; continue; } - res = btrfs_prepare_device(devfd, argv[i], 1, &dev_block_count, - 0, &mixed, discard); + res = btrfs_prepare_device(devfd, argv[i], &dev_block_count, 0, + PREP_DEVICE_ZERO_END | PREP_DEVICE_VERBOSE | + (discard ? PREP_DEVICE_DISCARD : 0)); close(devfd); if (res) { ret++; @@ -118,8 +118,7 @@ static int cmd_device_add(int argc, char **argv) path = canonicalize_path(argv[i]); if (!path) { - fprintf(stderr, - "ERROR: Could not canonicalize pathname '%s': %s\n", + error("could not canonicalize pathname '%s': %s", argv[i], strerror(errno)); ret++; goto error_out; @@ -128,10 +127,9 @@ static int cmd_device_add(int argc, char **argv) memset(&ioctl_args, 0, sizeof(ioctl_args)); strncpy_null(ioctl_args.name, path); res = ioctl(fdmnt, BTRFS_IOC_ADD_DEV, &ioctl_args); - e = errno; if (res < 0) { - fprintf(stderr, "ERROR: error adding the device '%s' - %s\n", - path, strerror(e)); + error("error adding device '%s': %s", + path, strerror(errno)); ret++; } free(path); @@ -139,7 +137,6 @@ static int cmd_device_add(int argc, char **argv) error_out: close_file_or_dir(fdmnt, dirstream); - btrfs_close_all_devices(); return !!ret; } @@ -147,10 +144,12 @@ static int _cmd_device_remove(int argc, char **argv, const char * const *usagestr) { char *mntpnt; - int i, fdmnt, ret=0, e; + int i, fdmnt, ret = 0; DIR *dirstream = NULL; - if (check_argc_min(argc, 3)) + clean_args_no_options(argc, argv, usagestr); + + if (check_argc_min(argc - optind, 2)) usage(usagestr); mntpnt = argv[argc - 1]; @@ -159,30 +158,62 @@ static int _cmd_device_remove(int argc, char **argv, if (fdmnt < 0) return 1; - for(i=1 ; i < argc - 1; i++ ){ + for(i = optind; i < argc - 1; i++) { struct btrfs_ioctl_vol_args arg; + struct btrfs_ioctl_vol_args_v2 argv2 = {0}; + int is_devid = 0; int res; - if (is_block_device(argv[i]) != 1) { - fprintf(stderr, - "ERROR: %s is not a block device\n", argv[i]); + if (string_is_numerical(argv[i])) { + argv2.devid = arg_strtou64(argv[i]); + argv2.flags = BTRFS_DEVICE_SPEC_BY_ID; + is_devid = 1; + } else if (is_block_device(argv[i]) == 1 || + strcmp(argv[i], "missing") == 0) { + strncpy_null(argv2.name, argv[i]); + } else { + error("not a block device: %s", argv[i]); ret++; continue; } - memset(&arg, 0, sizeof(arg)); - strncpy_null(arg.name, argv[i]); - res = ioctl(fdmnt, BTRFS_IOC_RM_DEV, &arg); - e = errno; + + /* + * Positive values are from BTRFS_ERROR_DEV_*, + * otherwise it's a generic error, one of errnos + */ + res = ioctl(fdmnt, BTRFS_IOC_RM_DEV_V2, &argv2); + + /* + * If BTRFS_IOC_RM_DEV_V2 is not supported we get ENOTTY and if + * argv2.flags includes a flag which kernel doesn't understand then + * we shall get EOPNOTSUPP + */ + if (res < 0 && (errno == ENOTTY || errno == EOPNOTSUPP)) { + if (is_devid) { + error("device delete by id failed: %s", + strerror(errno)); + ret++; + continue; + } + memset(&arg, 0, sizeof(arg)); + strncpy_null(arg.name, argv[i]); + res = ioctl(fdmnt, BTRFS_IOC_RM_DEV, &arg); + } + if (res) { const char *msg; if (res > 0) msg = btrfs_err_str(res); else - msg = strerror(e); - fprintf(stderr, - "ERROR: error removing the device '%s' - %s\n", - argv[i], msg); + msg = strerror(errno); + if (is_devid) { + error("error removing devid %llu: %s", + (unsigned long long)argv2.devid, msg); + } else { + error("error removing device '%s': %s", + argv[i], msg); + } ret++; } } @@ -192,7 +223,7 @@ static int _cmd_device_remove(int argc, char **argv, } static const char * const cmd_device_remove_usage[] = { - "btrfs device remove [...] ", + "btrfs device remove | [|...] ", "Remove a device from a filesystem", NULL }; @@ -203,7 +234,7 @@ static int cmd_device_remove(int argc, char **argv) } static const char * const cmd_device_delete_usage[] = { - "btrfs device delete [...] ", + "btrfs device delete | [|...] ", "Remove a device from a filesystem", NULL }; @@ -223,11 +254,10 @@ static const char * const cmd_device_scan_usage[] = { static int cmd_device_scan(int argc, char **argv) { int i; - int devstart = 1; + int devstart; int all = 0; int ret = 0; - optind = 1; while (1) { int c; static const struct option long_options[] = { @@ -246,18 +276,17 @@ static int cmd_device_scan(int argc, char **argv) usage(cmd_device_scan_usage); } } + devstart = optind; - if (all && check_argc_max(argc, 2)) + if (all && check_argc_max(argc - optind, 1)) usage(cmd_device_scan_usage); - if (all || argc == 1) { + if (all || argc - optind == 0) { printf("Scanning for Btrfs filesystems\n"); ret = btrfs_scan_lblkid(); - if (ret) - fprintf(stderr, "ERROR: error %d while scanning\n", ret); + error_on(ret, "error %d while scanning", ret); ret = btrfs_register_all_devices(); - if (ret) - fprintf(stderr, "ERROR: error %d while registering\n", ret); + error_on(ret, "there are %d errors while registering devices", ret); goto out; } @@ -265,15 +294,13 @@ static int cmd_device_scan(int argc, char **argv) char *path; if (is_block_device(argv[i]) != 1) { - fprintf(stderr, - "ERROR: %s is not a block device\n", argv[i]); + error("not a block device: %s", argv[i]); ret = 1; goto out; } path = canonicalize_path(argv[i]); if (!path) { - fprintf(stderr, - "ERROR: Could not canonicalize path '%s': %s\n", + error("could not canonicalize path '%s': %s", argv[i], strerror(errno)); ret = 1; goto out; @@ -288,7 +315,6 @@ static int cmd_device_scan(int argc, char **argv) } out: - btrfs_close_all_devices(); return !!ret; } @@ -305,7 +331,9 @@ static int cmd_device_ready(int argc, char **argv) int ret; char *path; - if (check_argc_min(argc, 2)) + clean_args_no_options(argc, argv, cmd_device_ready_usage); + + if (check_argc_exact(argc - optind, 1)) usage(cmd_device_ready_usage); fd = open("/dev/btrfs-control", O_RDWR); @@ -314,18 +342,16 @@ static int cmd_device_ready(int argc, char **argv) return 1; } - path = canonicalize_path(argv[argc - 1]); + path = canonicalize_path(argv[optind]); if (!path) { - fprintf(stderr, - "ERROR: Could not canonicalize pathname '%s': %s\n", - argv[argc - 1], strerror(errno)); + error("could not canonicalize pathname '%s': %s", + argv[optind], strerror(errno)); ret = 1; goto out; } if (is_block_device(path) != 1) { - fprintf(stderr, - "ERROR: %s is not a block device\n", path); + error("not a block device: %s", path); ret = 1; goto out; } @@ -334,9 +360,8 @@ static int cmd_device_ready(int argc, char **argv) strncpy_null(args.name, path); ret = ioctl(fd, BTRFS_IOC_DEVICES_READY, &args); if (ret < 0) { - fprintf(stderr, "ERROR: unable to determine if the device '%s'" - " is ready for mounting - %s\n", path, - strerror(errno)); + error("unable to determine if device '%s' is ready for mount: %s", + path, strerror(errno)); ret = 1; } @@ -367,7 +392,6 @@ static int cmd_device_stats(int argc, char **argv) __u64 flags = 0; DIR *dirstream = NULL; - optind = 1; while ((c = getopt(argc, argv, "z")) != -1) { switch (c) { case 'z': @@ -379,34 +403,24 @@ static int cmd_device_stats(int argc, char **argv) } } - argc = argc - optind; - if (check_argc_exact(argc, 1)) + if (check_argc_exact(argc - optind, 1)) usage(cmd_device_stats_usage); dev_path = argv[optind]; - fdmnt = open_path_or_dev_mnt(dev_path, &dirstream); - - if (fdmnt < 0) { - if (errno == EINVAL) - fprintf(stderr, - "ERROR: '%s' is not a mounted btrfs device\n", - dev_path); - else - fprintf(stderr, "ERROR: can't access '%s': %s\n", - dev_path, strerror(errno)); + fdmnt = open_path_or_dev_mnt(dev_path, &dirstream, 1); + if (fdmnt < 0) return 1; - } ret = get_fs_info(dev_path, &fi_args, &di_args); if (ret) { - fprintf(stderr, "ERROR: getting dev info for devstats failed: " - "%s\n", strerror(-ret)); + error("getting dev info for devstats failed: %s", + strerror(-ret)); err = 1; goto out; } if (!fi_args.num_devices) { - fprintf(stderr, "ERROR: no devices found\n"); + error("no devices found"); err = 1; goto out; } @@ -424,15 +438,25 @@ static int cmd_device_stats(int argc, char **argv) args.flags = flags; if (ioctl(fdmnt, BTRFS_IOC_GET_DEV_STATS, &args) < 0) { - fprintf(stderr, - "ERROR: ioctl(BTRFS_IOC_GET_DEV_STATS) on %s failed: %s\n", - path, strerror(errno)); + error("DEV_STATS ioctl failed on %s: %s", + path, strerror(errno)); err = 1; } else { char *canonical_path; canonical_path = canonicalize_path((char *)path); + /* No path when device is missing. */ + if (!canonical_path) { + canonical_path = malloc(32); + if (!canonical_path) { + error("not enough memory for path buffer"); + goto out; + } + snprintf(canonical_path, 32, + "devid:%llu", args.devid); + } + if (args.nr_items >= BTRFS_DEV_STAT_WRITE_ERRS + 1) printf("[%s].write_io_errs %llu\n", canonical_path, @@ -466,7 +490,6 @@ static int cmd_device_stats(int argc, char **argv) out: free(di_args); close_file_or_dir(fdmnt, dirstream); - btrfs_close_all_devices(); return err; } @@ -474,7 +497,7 @@ out: static const char * const cmd_device_usage_usage[] = { "btrfs device usage [options] [..]", "Show detailed information about internal allocations in devices.", - HELPINFO_OUTPUT_UNIT_DF, + HELPINFO_UNITS_SHORT_LONG, NULL }; @@ -511,35 +534,35 @@ static int cmd_device_usage(int argc, char **argv) { unsigned unit_mode; int ret = 0; - int more_than_one = 0; int i; unit_mode = get_unit_mode_from_arg(&argc, argv, 1); - if (check_argc_min(argc, 2) || argv[1][0] == '-') + clean_args_no_options(argc, argv, cmd_device_usage_usage); + + if (check_argc_min(argc - optind, 1)) usage(cmd_device_usage_usage); - for (i = 1; i < argc; i++) { + for (i = optind; i < argc; i++) { int fd; DIR *dirstream = NULL; - if (more_than_one) + if (i > 1) printf("\n"); fd = btrfs_open_dir(argv[i], &dirstream, 1); if (fd < 0) { ret = 1; - goto out; + break; } ret = _cmd_device_usage(fd, argv[i], unit_mode); close_file_or_dir(fd, dirstream); if (ret) - goto out; - more_than_one = 1; + break; } -out: + return !!ret; }