10 #include <sys/ioctl.h>
12 #include <sys/types.h>
16 #include "libbcache.h"
17 #include "linux/bcache-ioctl.h"
19 #include "tools-util.h"
21 /* This code belongs under show_fs */
28 unsigned has_metadata;
37 /* XXX: dirty != used, it doesn't count metadata */
41 static struct bcache_dev fill_dev(const char *dev_name, unsigned nr, int dir)
43 return (struct bcache_dev) {
47 .has_metadata = read_file_u64(dir, "has_metadata"),
48 .has_data = read_file_u64(dir, "has_data"),
49 .state = read_file_str(dir, "state"),
50 .tier = read_file_u64(dir, "tier"),
52 .bucket_size = read_file_u64(dir, "bucket_size_bytes"),
53 .first_bucket = read_file_u64(dir, "first_bucket"),
54 .nbuckets = read_file_u64(dir, "nbuckets"),
55 .bytes_dirty = read_file_u64(dir, "dirty_bytes"),
59 static void show_dev(struct bcache_dev *dev)
61 u64 capacity = (dev->nbuckets - dev->first_bucket) *
64 * XXX: show fragmentation information, cached/dirty information
67 printf("Device %u (/dev/%s):\n"
68 " Has metadata:\t%u\n"
69 " Has dirty data:\t%u\n"
83 capacity - dev->bytes_dirty,
84 (dev->bytes_dirty * 100) / capacity);
87 int cmd_device_show(int argc, char *argv[])
89 int human_readable = 0;
91 // { int shortoption, char *longoption, char *help, NihOptionGroup, char *argname, void *value, NihOptionSetter}
93 { 'h', "human-readable", N_("print sizes in powers of 1024 (e.g., 1023M)"),
94 NULL, NULL, &human_readable, NULL},
97 char **args = bch_nih_init(argc, argv, opts);
100 die("Please supply a single device");
102 struct bcache_handle fs = bcache_fs_open(argv[1]);
103 struct dirent *entry;
105 struct bcache_dev devices[256];
106 unsigned i, j, nr_devices = 0, nr_active_tiers = 0;
108 unsigned tiers[BCH_TIER_MAX]; /* number of devices in each tier */
109 memset(tiers, 0, sizeof(tiers));
111 while ((entry = readdir(fs.sysfs))) {
115 sscanf(entry->d_name, "cache%u%n", &nr, &pos);
116 if (pos != strlen(entry->d_name))
120 if (readlinkat(dirfd(fs.sysfs), entry->d_name,
121 link, sizeof(link)) < 0)
122 die("readlink error: %s\n", strerror(errno));
124 char *dev_name = basename(dirname(link));
126 int fd = xopenat(dirfd(fs.sysfs), entry->d_name, O_RDONLY);
128 devices[nr_devices] = fill_dev(strdup(dev_name), nr, fd);
129 tiers[devices[nr_devices].tier]++;
135 for (i = 0; i < BCH_TIER_MAX; i++)
139 /* Print out devices sorted by tier: */
142 for (i = 0; i < BCH_TIER_MAX; i++) {
146 if (nr_active_tiers > 1) {
150 printf("Tier %u:\n\n", i);
153 for (j = 0; j < nr_devices; j++) {
154 if (devices[j].tier != i)
160 show_dev(&devices[j]);
168 static void disk_ioctl(const char *fs, const char *dev, int cmd, int flags)
170 struct bch_ioctl_disk i = { .flags = flags, .dev = (__u64) dev, };
172 xioctl(bcache_fs_open(fs).ioctl_fd, cmd, &i);
175 static void device_add_usage(void)
177 puts("bcache device add - add a device to an existing filesystem\n"
178 "Usage: bcache device add [OPTION]... filesystem device\n"
181 " --fs_size=size Size of filesystem on device\n"
182 " --bucket=size Bucket size\n"
183 " --discard Enable discards\n"
184 " -t, --tier=# Higher tier (e.g. 1) indicates slower devices\n"
185 " -f, --force Use device even if it appears to already be formatted\n"
186 " -h, --help Display this help and exit\n"
188 "Report bugs to <linux-bcache@vger.kernel.org>");
191 int cmd_device_add(int argc, char *argv[])
193 static const struct option longopts[] = {
194 { "fs_size", required_argument, NULL, 'S' },
195 { "bucket", required_argument, NULL, 'B' },
196 { "discard", no_argument, NULL, 'D' },
197 { "tier", required_argument, NULL, 't' },
198 { "force", no_argument, NULL, 'f' },
201 struct format_opts format_opts = format_opts_default();
202 struct dev_opts dev_opts = { 0 };
206 while ((opt = getopt_long(argc, argv, "t:fh",
207 longopts, NULL)) != -1)
210 if (bch_strtoull_h(optarg, &dev_opts.size))
211 die("invalid filesystem size");
216 dev_opts.bucket_size =
217 hatoi_validate(optarg, "bucket size");
220 dev_opts.discard = true;
223 if (kstrtouint(optarg, 10, &dev_opts.tier) ||
224 dev_opts.tier >= BCH_TIER_MAX)
235 if (argc - optind != 2)
236 die("Please supply a filesystem and a device to add");
238 struct bcache_handle fs = bcache_fs_open(argv[optind]);
240 dev_opts.path = argv[optind + 1];
241 dev_opts.fd = open_for_format(dev_opts.path, force);
243 format_opts.block_size =
244 read_file_u64(fs.sysfs_fd, "block_size_bytes") >> 9;
245 format_opts.btree_node_size =
246 read_file_u64(fs.sysfs_fd, "btree_node_size_bytes") >> 9;
248 struct bch_sb *sb = bcache_format(format_opts, &dev_opts, 1);
253 struct bch_ioctl_disk i = { .dev = (__u64) dev_opts.path, };
255 xioctl(fs.ioctl_fd, BCH_IOCTL_DISK_ADD, &i);
259 static void device_remove_usage(void)
261 puts("bcache device_remove - remove a device from a filesystem\n"
262 "Usage: bcache device remove filesystem device\n"
265 " -f, --force Force removal, even if some data\n"
266 " couldn't be migrated\n"
267 " --force-metadata Force removal, even if some metadata\n"
268 " couldn't be migrated\n"
269 " -h, --help display this help and exit\n"
270 "Report bugs to <linux-bcache@vger.kernel.org>");
274 int cmd_device_remove(int argc, char *argv[])
276 static const struct option longopts[] = {
277 { "force", 0, NULL, 'f' },
278 { "force-metadata", 0, NULL, 'F' },
279 { "help", 0, NULL, 'h' },
284 while ((opt = getopt_long(argc, argv, "fh", longopts, NULL)) != -1)
287 flags |= BCH_FORCE_IF_DATA_LOST;
290 flags |= BCH_FORCE_IF_METADATA_LOST;
293 device_remove_usage();
296 if (argc - optind != 2)
297 die("Please supply a filesystem and at least one device to remove");
299 disk_ioctl(argv[optind], argv[optind + 1],
300 BCH_IOCTL_DISK_REMOVE, flags);
304 static void device_online_usage(void)
306 puts("bcache device online - readd a device to a running filesystem\n"
307 "Usage: bcache device online [OPTION]... filesystem device\n"
310 " -h, --help Display this help and exit\n"
312 "Report bugs to <linux-bcache@vger.kernel.org>");
315 int cmd_device_online(int argc, char *argv[])
319 while ((opt = getopt(argc, argv, "h")) != -1)
322 device_online_usage();
326 if (argc - optind != 2)
327 die("Please supply a filesystem and a device");
329 disk_ioctl(argv[optind], argv[optind + 1], BCH_IOCTL_DISK_ONLINE, 0);
333 static void device_offline_usage(void)
335 puts("bcache device offline - take a device offline, without removing it\n"
336 "Usage: bcache device offline [OPTION]... filesystem device\n"
339 " -f, --force Force, if data redundancy will be degraded\n"
340 " -h, --help Display this help and exit\n"
342 "Report bugs to <linux-bcache@vger.kernel.org>");
345 int cmd_device_offline(int argc, char *argv[])
347 static const struct option longopts[] = {
348 { "force", 0, NULL, 'f' },
353 while ((opt = getopt_long(argc, argv, "fh",
354 longopts, NULL)) != -1)
357 flags |= BCH_FORCE_IF_DEGRADED;
360 device_offline_usage();
364 if (argc - optind != 2)
365 die("Please supply a filesystem and a device");
367 disk_ioctl(argv[optind], argv[optind + 1],
368 BCH_IOCTL_DISK_OFFLINE, flags);
372 static void device_evacuate_usage(void)
374 puts("bcache device evacuate - move data off of a given device\n"
375 "Usage: bcache device evacuate [OPTION]... filesystem device\n"
378 " -h, --help Display this help and exit\n"
380 "Report bugs to <linux-bcache@vger.kernel.org>");
383 int cmd_device_evacuate(int argc, char *argv[])
387 while ((opt = getopt(argc, argv, "h")) != -1)
390 device_evacuate_usage();
394 if (argc - optind != 2)
395 die("Please supply a filesystem and a device");
397 disk_ioctl(argv[optind], argv[optind + 1], BCH_IOCTL_DISK_EVACUATE, 0);
401 static void device_set_state_usage(void)
403 puts("bcache device set-state\n"
404 "Usage: bcache device set-state filesystem device new-state\n"
407 " -f, --force Force, if data redundancy will be degraded\n"
408 " -h, --help display this help and exit\n"
409 "Report bugs to <linux-bcache@vger.kernel.org>");
413 int cmd_device_set_state(int argc, char *argv[])
415 static const struct option longopts[] = {
416 { "force", 0, NULL, 'f' },
417 { "help", 0, NULL, 'h' },
422 while ((opt = getopt_long(argc, argv, "fh", longopts, NULL)) != -1)
425 flags |= BCH_FORCE_IF_DEGRADED;
428 device_set_state_usage();
431 if (argc - optind != 3)
432 die("Please supply a filesystem, device and state");
434 struct bcache_handle fs = bcache_fs_open(argv[optind]);
436 struct bch_ioctl_disk_set_state i = {
438 .dev = (__u64) argv[optind + 1],
439 .new_state = read_string_list_or_die(argv[optind + 2],
440 bch_dev_state, "device state"),
443 xioctl(fs.ioctl_fd, BCH_IOCTL_DISK_SET_STATE, &i);