2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public
4 * License v2 as published by the Free Software Foundation.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * General Public License for more details.
11 * You should have received a copy of the GNU General Public
12 * License along with this program; if not, write to the
13 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14 * Boston, MA 021110-1307, USA.
22 #include <sys/ioctl.h>
27 #include "kerncompat.h"
32 #include "cmds-fi-usage.h"
36 #include "mkfs/common.h"
38 static const char * const device_cmd_group_usage[] = {
39 "btrfs device <command> [<args>]",
43 static const char * const cmd_device_add_usage[] = {
44 "btrfs device add [options] <device> [<device>...] <path>",
45 "Add a device to a filesystem",
46 "-K|--nodiscard do not perform whole device TRIM",
47 "-f|--force force overwrite existing filesystem on the disk",
51 static int cmd_device_add(int argc, char **argv)
54 int i, fdmnt, ret = 0;
55 DIR *dirstream = NULL;
62 static const struct option long_options[] = {
63 { "nodiscard", optional_argument, NULL, 'K'},
64 { "force", no_argument, NULL, 'f'},
68 c = getopt_long(argc, argv, "Kf", long_options, NULL);
79 usage(cmd_device_add_usage);
83 if (check_argc_min(argc - optind, 2))
84 usage(cmd_device_add_usage);
87 mntpnt = argv[last_dev];
89 fdmnt = btrfs_open_dir(mntpnt, &dirstream, 1);
93 for (i = optind; i < last_dev; i++){
94 struct btrfs_ioctl_vol_args ioctl_args;
96 u64 dev_block_count = 0;
99 res = test_dev_for_mkfs(argv[i], force);
105 devfd = open(argv[i], O_RDWR);
107 error("unable to open device '%s'", argv[i]);
112 res = btrfs_prepare_device(devfd, argv[i], &dev_block_count, 0,
113 PREP_DEVICE_ZERO_END | PREP_DEVICE_VERBOSE |
114 (discard ? PREP_DEVICE_DISCARD : 0));
121 path = canonicalize_path(argv[i]);
123 error("could not canonicalize pathname '%s': %s",
124 argv[i], strerror(errno));
129 memset(&ioctl_args, 0, sizeof(ioctl_args));
130 strncpy_null(ioctl_args.name, path);
131 res = ioctl(fdmnt, BTRFS_IOC_ADD_DEV, &ioctl_args);
133 error("error adding device '%s': %s",
134 path, strerror(errno));
141 close_file_or_dir(fdmnt, dirstream);
145 static int _cmd_device_remove(int argc, char **argv,
146 const char * const *usagestr)
149 int i, fdmnt, ret = 0;
150 DIR *dirstream = NULL;
152 clean_args_no_options(argc, argv, usagestr);
154 if (check_argc_min(argc - optind, 2))
157 mntpnt = argv[argc - 1];
159 fdmnt = btrfs_open_dir(mntpnt, &dirstream, 1);
163 for(i = optind; i < argc - 1; i++) {
164 struct btrfs_ioctl_vol_args arg;
165 struct btrfs_ioctl_vol_args_v2 argv2 = {0};
169 if (string_is_numerical(argv[i])) {
170 argv2.devid = arg_strtou64(argv[i]);
171 argv2.flags = BTRFS_DEVICE_SPEC_BY_ID;
173 } else if (is_block_device(argv[i]) == 1 ||
174 strcmp(argv[i], "missing") == 0) {
175 strncpy_null(argv2.name, argv[i]);
177 error("not a block device: %s", argv[i]);
183 * Positive values are from BTRFS_ERROR_DEV_*,
184 * otherwise it's a generic error, one of errnos
186 res = ioctl(fdmnt, BTRFS_IOC_RM_DEV_V2, &argv2);
189 * If BTRFS_IOC_RM_DEV_V2 is not supported we get ENOTTY and if
190 * argv2.flags includes a flag which kernel doesn't understand then
191 * we shall get EOPNOTSUPP
193 if (res < 0 && (errno == ENOTTY || errno == EOPNOTSUPP)) {
195 error("device delete by id failed: %s",
200 memset(&arg, 0, sizeof(arg));
201 strncpy_null(arg.name, argv[i]);
202 res = ioctl(fdmnt, BTRFS_IOC_RM_DEV, &arg);
209 msg = btrfs_err_str(res);
211 msg = strerror(errno);
213 error("error removing devid %llu: %s",
214 (unsigned long long)argv2.devid, msg);
216 error("error removing device '%s': %s",
223 close_file_or_dir(fdmnt, dirstream);
227 static const char * const cmd_device_remove_usage[] = {
228 "btrfs device remove <device>|<devid> [<device>|<devid>...] <path>",
229 "Remove a device from a filesystem",
233 static int cmd_device_remove(int argc, char **argv)
235 return _cmd_device_remove(argc, argv, cmd_device_remove_usage);
238 static const char * const cmd_device_delete_usage[] = {
239 "btrfs device delete <device>|<devid> [<device>|<devid>...] <path>",
240 "Remove a device from a filesystem",
244 static int cmd_device_delete(int argc, char **argv)
246 return _cmd_device_remove(argc, argv, cmd_device_delete_usage);
249 static const char * const cmd_device_scan_usage[] = {
250 "btrfs device scan [(-d|--all-devices)|<device> [<device>...]]",
251 "Scan devices for a btrfs filesystem",
252 " -d|--all-devices (deprecated)",
256 static int cmd_device_scan(int argc, char **argv)
265 static const struct option long_options[] = {
266 { "all-devices", no_argument, NULL, 'd'},
270 c = getopt_long(argc, argv, "d", long_options, NULL);
278 usage(cmd_device_scan_usage);
283 if (all && check_argc_max(argc - optind, 1))
284 usage(cmd_device_scan_usage);
286 if (all || argc - optind == 0) {
287 printf("Scanning for Btrfs filesystems\n");
288 ret = btrfs_scan_devices();
289 error_on(ret, "error %d while scanning", ret);
290 ret = btrfs_register_all_devices();
291 error_on(ret, "there are %d errors while registering devices", ret);
295 for( i = devstart ; i < argc ; i++ ){
298 if (is_block_device(argv[i]) != 1) {
299 error("not a block device: %s", argv[i]);
303 path = canonicalize_path(argv[i]);
305 error("could not canonicalize path '%s': %s",
306 argv[i], strerror(errno));
310 printf("Scanning for Btrfs filesystems in '%s'\n", path);
311 if (btrfs_register_one_device(path) != 0) {
323 static const char * const cmd_device_ready_usage[] = {
324 "btrfs device ready <device>",
325 "Check device to see if it has all of its devices in cache for mounting",
329 static int cmd_device_ready(int argc, char **argv)
331 struct btrfs_ioctl_vol_args args;
336 clean_args_no_options(argc, argv, cmd_device_ready_usage);
338 if (check_argc_exact(argc - optind, 1))
339 usage(cmd_device_ready_usage);
341 fd = open("/dev/btrfs-control", O_RDWR);
343 perror("failed to open /dev/btrfs-control");
347 path = canonicalize_path(argv[optind]);
349 error("could not canonicalize pathname '%s': %s",
350 argv[optind], strerror(errno));
355 if (is_block_device(path) != 1) {
356 error("not a block device: %s", path);
361 memset(&args, 0, sizeof(args));
362 strncpy_null(args.name, path);
363 ret = ioctl(fd, BTRFS_IOC_DEVICES_READY, &args);
365 error("unable to determine if device '%s' is ready for mount: %s",
366 path, strerror(errno));
376 static const char * const cmd_device_stats_usage[] = {
377 "btrfs device stats [options] <path>|<device>",
378 "Show device IO error statistics",
379 "Show device IO error statistics for all devices of the given filesystem",
380 "identified by PATH or DEVICE. The filesystem must be mounted.",
382 "-c|--check return non-zero if any stat counter is not zero",
383 "-z|--reset show current stats and reset values to zero",
387 static int cmd_device_stats(int argc, char **argv)
390 struct btrfs_ioctl_fs_info_args fi_args;
391 struct btrfs_ioctl_dev_info_args *di_args = NULL;
398 DIR *dirstream = NULL;
402 static const struct option long_options[] = {
403 {"reset", no_argument, NULL, 'z'},
407 c = getopt_long(argc, argv, "cz", long_options, NULL);
416 flags = BTRFS_DEV_STATS_RESET;
420 usage(cmd_device_stats_usage);
424 if (check_argc_exact(argc - optind, 1))
425 usage(cmd_device_stats_usage);
427 dev_path = argv[optind];
429 fdmnt = open_path_or_dev_mnt(dev_path, &dirstream, 1);
433 ret = get_fs_info(dev_path, &fi_args, &di_args);
435 error("getting device info for %s failed: %s", dev_path,
440 if (!fi_args.num_devices) {
441 error("no devices found");
446 for (i = 0; i < fi_args.num_devices; i++) {
447 struct btrfs_ioctl_get_dev_stats args = {0};
448 char path[BTRFS_DEVICE_PATH_NAME_MAX + 1];
450 strncpy(path, (char *)di_args[i].path,
451 BTRFS_DEVICE_PATH_NAME_MAX);
452 path[BTRFS_DEVICE_PATH_NAME_MAX] = 0;
454 args.devid = di_args[i].devid;
455 args.nr_items = BTRFS_DEV_STAT_VALUES_MAX;
458 if (ioctl(fdmnt, BTRFS_IOC_GET_DEV_STATS, &args) < 0) {
459 error("device stats ioctl failed on %s: %s",
460 path, strerror(errno));
463 char *canonical_path;
465 static const struct {
469 { "write_io_errs", BTRFS_DEV_STAT_WRITE_ERRS },
470 { "read_io_errs", BTRFS_DEV_STAT_READ_ERRS },
471 { "flush_io_errs", BTRFS_DEV_STAT_FLUSH_ERRS },
473 BTRFS_DEV_STAT_CORRUPTION_ERRS },
475 BTRFS_DEV_STAT_GENERATION_ERRS },
478 canonical_path = canonicalize_path(path);
480 /* No path when device is missing. */
481 if (!canonical_path) {
482 canonical_path = malloc(32);
483 if (!canonical_path) {
484 error("not enough memory for path buffer");
487 snprintf(canonical_path, 32,
488 "devid:%llu", args.devid);
491 for (j = 0; j < ARRAY_SIZE(dev_stats); j++) {
492 /* We got fewer items than we know */
493 if (args.nr_items < dev_stats[j].num + 1)
495 printf("[%s].%-16s %llu\n", canonical_path,
498 args.values[dev_stats[j].num]);
500 && (args.values[dev_stats[j].num] > 0))
504 free(canonical_path);
510 close_file_or_dir(fdmnt, dirstream);
515 static const char * const cmd_device_usage_usage[] = {
516 "btrfs device usage [options] <path> [<path>..]",
517 "Show detailed information about internal allocations in devices.",
518 HELPINFO_UNITS_SHORT_LONG,
522 static int _cmd_device_usage(int fd, char *path, unsigned unit_mode)
526 struct chunk_info *chunkinfo = NULL;
527 struct device_info *devinfo = NULL;
531 ret = load_chunk_and_device_info(fd, &chunkinfo, &chunkcount, &devinfo,
536 for (i = 0; i < devcount; i++) {
537 printf("%s, ID: %llu\n", devinfo[i].path, devinfo[i].devid);
538 print_device_sizes(&devinfo[i], unit_mode);
539 print_device_chunks(&devinfo[i], chunkinfo, chunkcount,
551 static int cmd_device_usage(int argc, char **argv)
557 unit_mode = get_unit_mode_from_arg(&argc, argv, 1);
559 clean_args_no_options(argc, argv, cmd_device_usage_usage);
561 if (check_argc_min(argc - optind, 1))
562 usage(cmd_device_usage_usage);
564 for (i = optind; i < argc; i++) {
566 DIR *dirstream = NULL;
571 fd = btrfs_open_dir(argv[i], &dirstream, 1);
577 ret = _cmd_device_usage(fd, argv[i], unit_mode);
578 close_file_or_dir(fd, dirstream);
587 static const char device_cmd_group_info[] =
588 "manage and query devices in the filesystem";
590 const struct cmd_group device_cmd_group = {
591 device_cmd_group_usage, device_cmd_group_info, {
592 { "add", cmd_device_add, cmd_device_add_usage, NULL, 0 },
593 { "delete", cmd_device_delete, cmd_device_delete_usage, NULL,
595 { "remove", cmd_device_remove, cmd_device_remove_usage, NULL, 0 },
596 { "scan", cmd_device_scan, cmd_device_scan_usage, NULL, 0 },
597 { "ready", cmd_device_ready, cmd_device_ready_usage, NULL, 0 },
598 { "stats", cmd_device_stats, cmd_device_stats_usage, NULL, 0 },
599 { "usage", cmd_device_usage,
600 cmd_device_usage_usage, NULL, 0 },
605 int cmd_device(int argc, char **argv)
607 return handle_command_group(&device_cmd_group, argc, argv);