11 #include <sys/ioctl.h>
13 #include <sys/types.h>
16 #include <uuid/uuid.h>
18 #include "ccan/crc/crc.h"
20 #include "linux/bcache-ioctl.h"
21 #include "linux/sort.h"
22 #include "tools-util.h"
27 struct units_buf __pr_units(u64 v, enum units units)
33 snprintf(ret.b, sizeof(ret.b), "%llu", v << 9);
36 snprintf(ret.b, sizeof(ret.b), "%llu", v);
42 int exp = log(v) / log(1024);
43 snprintf(ret.b, sizeof(ret.b), "%.1f%c",
47 snprintf(ret.b, sizeof(ret.b), "%llu", v);
56 /* Argument parsing stuff: */
58 /* File parsing (i.e. sysfs) */
60 char *read_file_str(int dirfd, const char *path)
62 int fd = xopenat(dirfd, path, O_RDONLY);
63 size_t len = xfstat(fd).st_size;
65 char *buf = malloc(len + 1);
67 xpread(fd, buf, len, 0);
70 if (len && buf[len - 1] == '\n')
78 u64 read_file_u64(int dirfd, const char *path)
80 char *buf = read_file_str(dirfd, path);
81 u64 ret = strtoll(buf, NULL, 10);
87 /* String list options: */
89 ssize_t read_string_list_or_die(const char *opt, const char * const list[],
92 ssize_t v = bch_read_string_list(opt, list);
94 die("Bad %s %s", msg, opt);
99 /* Returns size of file or block device: */
100 u64 get_size(const char *path, int fd)
102 struct stat statbuf = xfstat(fd);
104 if (!S_ISBLK(statbuf.st_mode))
105 return statbuf.st_size;
108 xioctl(fd, BLKGETSIZE64, &ret);
112 /* Returns blocksize in units of 512 byte sectors: */
113 unsigned get_blocksize(const char *path, int fd)
115 struct stat statbuf = xfstat(fd);
117 if (!S_ISBLK(statbuf.st_mode))
118 return statbuf.st_blksize >> 9;
121 xioctl(fd, BLKPBSZGET, &ret);
125 /* Global control device: */
126 int bcachectl_open(void)
128 return xopen("/dev/bcache-ctl", O_RDWR);
131 /* Filesystem handles (ioctl, sysfs dir): */
133 #define SYSFS_BASE "/sys/fs/bcache/"
135 struct bcache_handle bcache_fs_open(const char *path)
137 struct bcache_handle ret;
140 if (!uuid_parse(path, tmp)) {
141 /* It's a UUID, look it up in sysfs: */
142 char *sysfs = mprintf("%s%s", SYSFS_BASE, path);
143 ret.sysfs_fd = xopen(sysfs, O_RDONLY);
145 char *minor = read_file_str(ret.sysfs_fd, "minor");
146 char *ctl = mprintf("/dev/bcache%s-ctl", minor);
147 ret.ioctl_fd = xopen(ctl, O_RDWR);
154 ret.ioctl_fd = xopen(path, O_RDONLY);
156 struct bch_ioctl_query_uuid uuid;
157 xioctl(ret.ioctl_fd, BCH_IOCTL_QUERY_UUID, &uuid);
160 uuid_unparse(uuid.uuid.b, uuid_str);
162 char *sysfs = mprintf("%s%s", SYSFS_BASE, uuid_str);
163 ret.sysfs_fd = xopen(sysfs, O_RDONLY);
172 const char *short_yes = "yY";
177 fputs(" (y,n) ", stdout);
180 if (getline(&buf, &buflen, stdin) < 0)
181 die("error reading from standard input");
183 ret = strchr(short_yes, buf[0]);
188 static int range_cmp(const void *_l, const void *_r)
190 const struct range *l = _l, *r = _r;
192 if (l->start < r->start)
194 if (l->start > r->start)
199 void ranges_sort_merge(ranges *r)
202 ranges tmp = { NULL };
204 sort(&darray_item(*r, 0), darray_size(*r),
205 sizeof(darray_item(*r, 0)), range_cmp, NULL);
207 /* Merge contiguous ranges: */
208 darray_foreach(i, *r) {
209 t = tmp.size ? &tmp.item[tmp.size - 1] : NULL;
211 if (t && t->end >= i->start)
212 t->end = max(t->end, i->end);
214 darray_append(tmp, *i);
221 void ranges_roundup(ranges *r, unsigned block_size)
225 darray_foreach(i, *r) {
226 i->start = round_down(i->start, block_size);
227 i->end = round_up(i->end, block_size);
231 void ranges_rounddown(ranges *r, unsigned block_size)
235 darray_foreach(i, *r) {
236 i->start = round_up(i->start, block_size);
237 i->end = round_down(i->end, block_size);
238 i->end = max(i->end, i->start);
242 struct fiemap_extent fiemap_iter_next(struct fiemap_iter *iter)
244 struct fiemap_extent e;
246 BUG_ON(iter->idx > iter->f.fm_mapped_extents);
248 if (iter->idx == iter->f.fm_mapped_extents) {
249 xioctl(iter->fd, FS_IOC_FIEMAP, &iter->f);
251 if (!iter->f.fm_mapped_extents)
252 return (struct fiemap_extent) { .fe_length = 0 };
257 e = iter->f.fm_extents[iter->idx++];
258 BUG_ON(!e.fe_length);
260 iter->f.fm_start = e.fe_logical + e.fe_length;
265 const char *strcmp_prefix(const char *a, const char *a_prefix)
267 while (*a_prefix && *a == *a_prefix) {
271 return *a_prefix ? NULL : a;