10 #include <sys/ioctl.h>
12 #include <sys/types.h>
15 #include "bcachefs_ioctl.h"
17 #include "libbcachefs.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: %m\n");
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, };
172 if (!kstrtoull(dev, 10, &i.dev))
173 i.flags |= BCH_BY_INDEX;
177 xioctl(bcache_fs_open(fs).ioctl_fd, cmd, &i);
180 static void device_add_usage(void)
182 puts("bcachefs device add - add a device to an existing filesystem\n"
183 "Usage: bcachefs device add [OPTION]... filesystem device\n"
186 " --fs_size=size Size of filesystem on device\n"
187 " --bucket=size Bucket size\n"
188 " --discard Enable discards\n"
189 " -t, --tier=# Higher tier (e.g. 1) indicates slower devices\n"
190 " -f, --force Use device even if it appears to already be formatted\n"
191 " -h, --help Display this help and exit\n"
193 "Report bugs to <linux-bcache@vger.kernel.org>");
196 int cmd_device_add(int argc, char *argv[])
198 static const struct option longopts[] = {
199 { "fs_size", required_argument, NULL, 'S' },
200 { "bucket", required_argument, NULL, 'B' },
201 { "discard", no_argument, NULL, 'D' },
202 { "tier", required_argument, NULL, 't' },
203 { "force", no_argument, NULL, 'f' },
206 struct format_opts format_opts = format_opts_default();
207 struct dev_opts dev_opts = { 0 };
211 while ((opt = getopt_long(argc, argv, "t:fh",
212 longopts, NULL)) != -1)
215 if (bch2_strtoull_h(optarg, &dev_opts.size))
216 die("invalid filesystem size");
221 dev_opts.bucket_size =
222 hatoi_validate(optarg, "bucket size");
225 dev_opts.discard = true;
228 if (kstrtouint(optarg, 10, &dev_opts.tier) ||
229 dev_opts.tier >= BCH_TIER_MAX)
240 if (argc - optind != 2)
241 die("Please supply a filesystem and a device to add");
243 struct bcache_handle fs = bcache_fs_open(argv[optind]);
245 dev_opts.path = argv[optind + 1];
246 dev_opts.fd = open_for_format(dev_opts.path, force);
248 format_opts.block_size =
249 read_file_u64(fs.sysfs_fd, "block_size") >> 9;
250 format_opts.btree_node_size =
251 read_file_u64(fs.sysfs_fd, "btree_node_size") >> 9;
253 struct bch_sb *sb = bch2_format(format_opts, &dev_opts, 1);
258 struct bch_ioctl_disk i = { .dev = (__u64) dev_opts.path, };
260 xioctl(fs.ioctl_fd, BCH_IOCTL_DISK_ADD, &i);
264 static void device_remove_usage(void)
266 puts("bcachefs device_remove - remove a device from a filesystem\n"
267 "Usage: bcachefs device remove filesystem device\n"
270 " -f, --force Force removal, even if some data\n"
271 " couldn't be migrated\n"
272 " --force-metadata Force removal, even if some metadata\n"
273 " couldn't be migrated\n"
274 " -h, --help display this help and exit\n"
275 "Report bugs to <linux-bcache@vger.kernel.org>");
279 int cmd_device_remove(int argc, char *argv[])
281 static const struct option longopts[] = {
282 { "force", 0, NULL, 'f' },
283 { "force-metadata", 0, NULL, 'F' },
284 { "help", 0, NULL, 'h' },
287 int opt, flags = BCH_FORCE_IF_DEGRADED;
289 while ((opt = getopt_long(argc, argv, "fh", longopts, NULL)) != -1)
292 flags |= BCH_FORCE_IF_DATA_LOST;
295 flags |= BCH_FORCE_IF_METADATA_LOST;
298 device_remove_usage();
301 if (argc - optind != 2)
302 die("Please supply a filesystem and at least one device to remove");
304 disk_ioctl(argv[optind], argv[optind + 1],
305 BCH_IOCTL_DISK_REMOVE, flags);
309 static void device_online_usage(void)
311 puts("bcachefs device online - readd a device to a running filesystem\n"
312 "Usage: bcachefs device online [OPTION]... filesystem device\n"
315 " -h, --help Display this help and exit\n"
317 "Report bugs to <linux-bcache@vger.kernel.org>");
320 int cmd_device_online(int argc, char *argv[])
324 while ((opt = getopt(argc, argv, "h")) != -1)
327 device_online_usage();
331 if (argc - optind != 2)
332 die("Please supply a filesystem and a device");
334 disk_ioctl(argv[optind], argv[optind + 1], BCH_IOCTL_DISK_ONLINE, 0);
338 static void device_offline_usage(void)
340 puts("bcachefs device offline - take a device offline, without removing it\n"
341 "Usage: bcachefs device offline [OPTION]... filesystem device\n"
344 " -f, --force Force, if data redundancy will be degraded\n"
345 " -h, --help Display this help and exit\n"
347 "Report bugs to <linux-bcache@vger.kernel.org>");
350 int cmd_device_offline(int argc, char *argv[])
352 static const struct option longopts[] = {
353 { "force", 0, NULL, 'f' },
358 while ((opt = getopt_long(argc, argv, "fh",
359 longopts, NULL)) != -1)
362 flags |= BCH_FORCE_IF_DEGRADED;
365 device_offline_usage();
369 if (argc - optind != 2)
370 die("Please supply a filesystem and a device");
372 disk_ioctl(argv[optind], argv[optind + 1],
373 BCH_IOCTL_DISK_OFFLINE, flags);
377 static void device_evacuate_usage(void)
379 puts("bcachefs device evacuate - move data off of a given device\n"
380 "Usage: bcachefs device evacuate [OPTION]... filesystem device\n"
383 " -h, --help Display this help and exit\n"
385 "Report bugs to <linux-bcache@vger.kernel.org>");
388 int cmd_device_evacuate(int argc, char *argv[])
392 while ((opt = getopt(argc, argv, "h")) != -1)
395 device_evacuate_usage();
399 if (argc - optind != 2)
400 die("Please supply a filesystem and a device");
402 disk_ioctl(argv[optind], argv[optind + 1], BCH_IOCTL_DISK_EVACUATE, 0);
406 static void device_set_state_usage(void)
408 puts("bcachefs device set-state\n"
409 "Usage: bcachefs device set-state filesystem device new-state\n"
412 " -f, --force Force, if data redundancy will be degraded\n"
413 " -h, --help display this help and exit\n"
414 "Report bugs to <linux-bcache@vger.kernel.org>");
418 int cmd_device_set_state(int argc, char *argv[])
420 static const struct option longopts[] = {
421 { "force", 0, NULL, 'f' },
422 { "help", 0, NULL, 'h' },
427 while ((opt = getopt_long(argc, argv, "fh", longopts, NULL)) != -1)
430 flags |= BCH_FORCE_IF_DEGRADED;
433 device_set_state_usage();
436 if (argc - optind != 3)
437 die("Please supply a filesystem, device and state");
439 struct bcache_handle fs = bcache_fs_open(argv[optind]);
441 struct bch_ioctl_disk_set_state i = {
443 .new_state = read_string_list_or_die(argv[optind + 2],
444 bch2_dev_state, "device state"),
447 const char *dev = argv[optind + 1];
448 if (!kstrtoull(dev, 10, &i.dev))
449 i.flags |= BCH_BY_INDEX;
453 xioctl(fs.ioctl_fd, BCH_IOCTL_DISK_SET_STATE, &i);