11 #include <sys/ioctl.h>
13 #include <sys/types.h>
17 #include <uuid/uuid.h>
19 #include "ccan/crc/crc.h"
21 #include "bcachefs_ioctl.h"
22 #include "linux/sort.h"
23 #include "tools-util.h"
28 struct units_buf __pr_units(u64 v, enum units units)
34 snprintf(ret.b, sizeof(ret.b), "%llu", v << 9);
37 snprintf(ret.b, sizeof(ret.b), "%llu", v);
43 int exp = log(v) / log(1024);
44 snprintf(ret.b, sizeof(ret.b), "%.1f%c",
48 snprintf(ret.b, sizeof(ret.b), "%llu", v);
57 /* Argument parsing stuff: */
59 /* File parsing (i.e. sysfs) */
61 char *read_file_str(int dirfd, const char *path)
63 int fd = xopenat(dirfd, path, O_RDONLY);
64 ssize_t len = xfstat(fd).st_size;
66 char *buf = xmalloc(len + 1);
68 len = read(fd, buf, len);
70 die("read error: %s", strerror(errno));
73 if (len && buf[len - 1] == '\n')
81 u64 read_file_u64(int dirfd, const char *path)
83 char *buf = read_file_str(dirfd, path);
85 if (kstrtou64(buf, 10, &v))
86 die("read_file_u64: error parsing %s (got %s)", path, buf);
91 /* String list options: */
93 ssize_t read_string_list_or_die(const char *opt, const char * const list[],
96 ssize_t v = bch2_read_string_list(opt, list);
98 die("Bad %s %s", msg, opt);
103 /* Returns size of file or block device: */
104 u64 get_size(const char *path, int fd)
106 struct stat statbuf = xfstat(fd);
108 if (!S_ISBLK(statbuf.st_mode))
109 return statbuf.st_size;
112 xioctl(fd, BLKGETSIZE64, &ret);
116 /* Returns blocksize in units of 512 byte sectors: */
117 unsigned get_blocksize(const char *path, int fd)
119 struct stat statbuf = xfstat(fd);
121 if (!S_ISBLK(statbuf.st_mode))
122 return statbuf.st_blksize >> 9;
125 xioctl(fd, BLKPBSZGET, &ret);
129 /* Open a block device, do magic blkid stuff to probe for existing filesystems: */
130 int open_for_format(const char *dev, bool force)
133 const char *fs_type = NULL, *fs_label = NULL;
134 size_t fs_type_len, fs_label_len;
136 int fd = xopen(dev, O_RDWR|O_EXCL);
141 if (!(pr = blkid_new_probe()))
142 die("blkid error 1");
143 if (blkid_probe_set_device(pr, fd, 0, 0))
144 die("blkid error 2");
145 if (blkid_probe_enable_partitions(pr, true))
146 die("blkid error 3");
147 if (blkid_do_fullprobe(pr) < 0)
148 die("blkid error 4");
150 blkid_probe_lookup_value(pr, "TYPE", &fs_type, &fs_type_len);
151 blkid_probe_lookup_value(pr, "LABEL", &fs_label, &fs_label_len);
155 printf("%s contains a %s filesystem labelled '%s'\n",
156 dev, fs_type, fs_label);
158 printf("%s contains a %s filesystem\n",
160 fputs("Proceed anyway?", stdout);
165 blkid_free_probe(pr);
169 /* Global control device: */
170 int bcachectl_open(void)
172 return xopen("/dev/bcachefs-ctl", O_RDWR);
175 /* Filesystem handles (ioctl, sysfs dir): */
177 #define SYSFS_BASE "/sys/fs/bcachefs/"
179 struct bcache_handle bcache_fs_open(const char *path)
181 struct bcache_handle ret;
184 if (!uuid_parse(path, tmp)) {
185 /* It's a UUID, look it up in sysfs: */
186 char *sysfs = mprintf("%s%s", SYSFS_BASE, path);
187 ret.sysfs_fd = xopen(sysfs, O_RDONLY);
189 char *minor = read_file_str(ret.sysfs_fd, "minor");
190 char *ctl = mprintf("/dev/bcachefs%s-ctl", minor);
191 ret.ioctl_fd = xopen(ctl, O_RDWR);
198 ret.ioctl_fd = xopen(path, O_RDONLY);
200 struct bch_ioctl_query_uuid uuid;
201 xioctl(ret.ioctl_fd, BCH_IOCTL_QUERY_UUID, &uuid);
204 uuid_unparse(uuid.uuid.b, uuid_str);
206 char *sysfs = mprintf("%s%s", SYSFS_BASE, uuid_str);
207 ret.sysfs_fd = xopen(sysfs, O_RDONLY);
216 const char *short_yes = "yY";
221 fputs(" (y,n) ", stdout);
224 if (getline(&buf, &buflen, stdin) < 0)
225 die("error reading from standard input");
227 ret = strchr(short_yes, buf[0]);
232 static int range_cmp(const void *_l, const void *_r)
234 const struct range *l = _l, *r = _r;
236 if (l->start < r->start)
238 if (l->start > r->start)
243 void ranges_sort_merge(ranges *r)
246 ranges tmp = { NULL };
248 sort(&darray_item(*r, 0), darray_size(*r),
249 sizeof(darray_item(*r, 0)), range_cmp, NULL);
251 /* Merge contiguous ranges: */
252 darray_foreach(i, *r) {
253 t = tmp.size ? &tmp.item[tmp.size - 1] : NULL;
255 if (t && t->end >= i->start)
256 t->end = max(t->end, i->end);
258 darray_append(tmp, *i);
265 void ranges_roundup(ranges *r, unsigned block_size)
269 darray_foreach(i, *r) {
270 i->start = round_down(i->start, block_size);
271 i->end = round_up(i->end, block_size);
275 void ranges_rounddown(ranges *r, unsigned block_size)
279 darray_foreach(i, *r) {
280 i->start = round_up(i->start, block_size);
281 i->end = round_down(i->end, block_size);
282 i->end = max(i->end, i->start);
286 struct fiemap_extent fiemap_iter_next(struct fiemap_iter *iter)
288 struct fiemap_extent e;
290 BUG_ON(iter->idx > iter->f.fm_mapped_extents);
292 if (iter->idx == iter->f.fm_mapped_extents) {
293 xioctl(iter->fd, FS_IOC_FIEMAP, &iter->f);
295 if (!iter->f.fm_mapped_extents)
296 return (struct fiemap_extent) { .fe_length = 0 };
301 e = iter->f.fm_extents[iter->idx++];
302 BUG_ON(!e.fe_length);
304 iter->f.fm_start = e.fe_logical + e.fe_length;
309 const char *strcmp_prefix(const char *a, const char *a_prefix)
311 while (*a_prefix && *a == *a_prefix) {
315 return *a_prefix ? NULL : a;
318 unsigned hatoi_validate(const char *s, const char *msg)
322 if (bch2_strtoull_h(s, &v))
323 die("bad %s %s", msg, s);
326 die("%s must be a power of two", msg);
331 die("%s too large\n", msg);
334 die("%s too small\n", msg);