X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=cmds-device.c;h=4337eb27203748d4c534be095eed1666f6a638c4;hb=c0f7e291274df28e83554fe2c38cb5e5cebddd7c;hp=f69d02489a3f970d757d9714f57b925f8a999ccc;hpb=633dc6f80f201afdf5b8524ae377187d58f0ef3b;p=platform%2Fupstream%2Fbtrfs-progs.git diff --git a/cmds-device.c b/cmds-device.c index f69d024..4337eb2 100644 --- a/cmds-device.c +++ b/cmds-device.c @@ -32,6 +32,8 @@ #include "cmds-fi-usage.h" #include "commands.h" +#include "help.h" +#include "mkfs/common.h" static const char * const device_cmd_group_usage[] = { "btrfs device []", @@ -107,8 +109,9 @@ static int cmd_device_add(int argc, char **argv) continue; } - res = btrfs_prepare_device(devfd, argv[i], 1, &dev_block_count, - 0, 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++; @@ -146,7 +149,9 @@ static int _cmd_device_remove(int argc, char **argv, 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]; @@ -155,18 +160,48 @@ 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 && strcmp(argv[i], "missing")) { + 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); + + /* + * 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; @@ -174,8 +209,13 @@ static int _cmd_device_remove(int argc, char **argv, msg = btrfs_err_str(res); else msg = strerror(errno); - error("error removing device '%s': %s", - argv[i], msg); + 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++; } } @@ -185,7 +225,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 }; @@ -196,7 +236,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 }; @@ -216,11 +256,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[] = { @@ -239,16 +278,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(); + ret = btrfs_scan_devices(); error_on(ret, "error %d while scanning", ret); ret = btrfs_register_all_devices(); - error_on(ret, "error %d while registering devices", ret); + error_on(ret, "there are %d errors while registering devices", ret); goto out; } @@ -293,7 +333,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); @@ -302,10 +344,10 @@ static int cmd_device_ready(int argc, char **argv) return 1; } - path = canonicalize_path(argv[argc - 1]); + path = canonicalize_path(argv[optind]); if (!path) { error("could not canonicalize pathname '%s': %s", - argv[argc - 1], strerror(errno)); + argv[optind], strerror(errno)); ret = 1; goto out; } @@ -332,10 +374,13 @@ out: } static const char * const cmd_device_stats_usage[] = { - "btrfs device stats [-z] |", - "Show current device IO stats.", + "btrfs device stats [options] |", + "Show device IO error statistics", + "Show device IO error statistics for all devices of the given filesystem", + "identified by PATH or DEVICE. The filesystem must be mounted.", "", - "-z show current stats and reset values to zero", + "-c|--check return non-zero if any stat counter is not zero", + "-z|--reset show current stats and reset values to zero", NULL }; @@ -347,14 +392,27 @@ static int cmd_device_stats(int argc, char **argv) int ret; int fdmnt; int i; - int c; int err = 0; + int check = 0; __u64 flags = 0; DIR *dirstream = NULL; - optind = 1; - while ((c = getopt(argc, argv, "z")) != -1) { + while (1) { + int c; + static const struct option long_options[] = { + {"check", no_argument, NULL, 'c'}, + {"reset", no_argument, NULL, 'z'}, + {NULL, 0, NULL, 0} + }; + + c = getopt_long(argc, argv, "cz", long_options, NULL); + if (c < 0) + break; + switch (c) { + case 'c': + check = 1; + break; case 'z': flags = BTRFS_DEV_STATS_RESET; break; @@ -364,8 +422,7 @@ 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]; @@ -376,7 +433,7 @@ static int cmd_device_stats(int argc, char **argv) ret = get_fs_info(dev_path, &fi_args, &di_args); if (ret) { - error("getting dev info for devstats failed: %s", + error("getting device info for %s failed: %s", dev_path, strerror(-ret)); err = 1; goto out; @@ -389,50 +446,61 @@ static int cmd_device_stats(int argc, char **argv) for (i = 0; i < fi_args.num_devices; i++) { struct btrfs_ioctl_get_dev_stats args = {0}; - __u8 path[BTRFS_DEVICE_PATH_NAME_MAX + 1]; + char path[BTRFS_DEVICE_PATH_NAME_MAX + 1]; - strncpy((char *)path, (char *)di_args[i].path, + strncpy(path, (char *)di_args[i].path, BTRFS_DEVICE_PATH_NAME_MAX); - path[BTRFS_DEVICE_PATH_NAME_MAX] = '\0'; + path[BTRFS_DEVICE_PATH_NAME_MAX] = 0; args.devid = di_args[i].devid; args.nr_items = BTRFS_DEV_STAT_VALUES_MAX; args.flags = flags; if (ioctl(fdmnt, BTRFS_IOC_GET_DEV_STATS, &args) < 0) { - error("DEV_STATS ioctl failed on %s: %s", + error("device stats ioctl failed on %s: %s", path, strerror(errno)); - err = 1; + err |= 1; } else { char *canonical_path; - - canonical_path = canonicalize_path((char *)path); - - if (args.nr_items >= BTRFS_DEV_STAT_WRITE_ERRS + 1) - printf("[%s].write_io_errs %llu\n", - canonical_path, - (unsigned long long) args.values[ - BTRFS_DEV_STAT_WRITE_ERRS]); - if (args.nr_items >= BTRFS_DEV_STAT_READ_ERRS + 1) - printf("[%s].read_io_errs %llu\n", - canonical_path, - (unsigned long long) args.values[ - BTRFS_DEV_STAT_READ_ERRS]); - if (args.nr_items >= BTRFS_DEV_STAT_FLUSH_ERRS + 1) - printf("[%s].flush_io_errs %llu\n", - canonical_path, - (unsigned long long) args.values[ - BTRFS_DEV_STAT_FLUSH_ERRS]); - if (args.nr_items >= BTRFS_DEV_STAT_CORRUPTION_ERRS + 1) - printf("[%s].corruption_errs %llu\n", - canonical_path, - (unsigned long long) args.values[ - BTRFS_DEV_STAT_CORRUPTION_ERRS]); - if (args.nr_items >= BTRFS_DEV_STAT_GENERATION_ERRS + 1) - printf("[%s].generation_errs %llu\n", - canonical_path, - (unsigned long long) args.values[ - BTRFS_DEV_STAT_GENERATION_ERRS]); + int j; + static const struct { + const char name[32]; + u64 num; + } dev_stats[] = { + { "write_io_errs", BTRFS_DEV_STAT_WRITE_ERRS }, + { "read_io_errs", BTRFS_DEV_STAT_READ_ERRS }, + { "flush_io_errs", BTRFS_DEV_STAT_FLUSH_ERRS }, + { "corruption_errs", + BTRFS_DEV_STAT_CORRUPTION_ERRS }, + { "generation_errs", + BTRFS_DEV_STAT_GENERATION_ERRS }, + }; + + canonical_path = canonicalize_path(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); + } + + for (j = 0; j < ARRAY_SIZE(dev_stats); j++) { + /* We got fewer items than we know */ + if (args.nr_items < dev_stats[j].num + 1) + continue; + printf("[%s].%-16s %llu\n", canonical_path, + dev_stats[j].name, + (unsigned long long) + args.values[dev_stats[j].num]); + if ((check == 1) + && (args.values[dev_stats[j].num] > 0)) + err |= 64; + } free(canonical_path); } @@ -468,8 +536,8 @@ static int _cmd_device_usage(int fd, char *path, unsigned unit_mode) for (i = 0; i < devcount; i++) { printf("%s, ID: %llu\n", devinfo[i].path, devinfo[i].devid); - print_device_sizes(fd, &devinfo[i], unit_mode); - print_device_chunks(fd, &devinfo[i], chunkinfo, chunkcount, + print_device_sizes(&devinfo[i], unit_mode); + print_device_chunks(&devinfo[i], chunkinfo, chunkcount, unit_mode); printf("\n"); } @@ -489,10 +557,12 @@ static int cmd_device_usage(int argc, char **argv) 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;