12 #include <sys/ioctl.h>
14 #include <sys/types.h>
17 #include <uuid/uuid.h>
19 #include "ccan/crc/crc.h"
21 #include "linux/bcache-ioctl.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 = openat(dirfd, path, O_RDONLY);
65 die("Unable to open %s\n", path);
68 if (fstat(fd, &statbuf) < 0)
71 char *buf = malloc(statbuf.st_size + 1);
73 int len = read(fd, buf, statbuf.st_size);
75 die("read error while reading from file %s\n", path);
78 if (len && buf[len - 1] == '\n')
86 u64 read_file_u64(int dirfd, const char *path)
88 char *buf = read_file_str(dirfd, path);
89 u64 ret = strtoll(buf, NULL, 10);
95 /* String list options: */
97 ssize_t read_string_list_or_die(const char *opt, const char * const list[],
100 ssize_t v = bch_read_string_list(opt, list);
102 die("Bad %s %s", msg, opt);
107 /* Returns size of file or block device, in units of 512 byte sectors: */
108 u64 get_size(const char *path, int fd)
111 if (fstat(fd, &statbuf))
112 die("Error statting %s: %s", path, strerror(errno));
114 if (!S_ISBLK(statbuf.st_mode))
115 return statbuf.st_size >> 9;
118 if (ioctl(fd, BLKGETSIZE64, &ret))
119 die("Error getting block device size on %s: %s\n",
120 path, strerror(errno));
125 /* Returns blocksize in units of 512 byte sectors: */
126 unsigned get_blocksize(const char *path, int fd)
129 if (fstat(fd, &statbuf))
130 die("Error statting %s: %s", path, strerror(errno));
132 if (!S_ISBLK(statbuf.st_mode))
133 return statbuf.st_blksize >> 9;
136 if (ioctl(fd, BLKPBSZGET, &ret))
137 die("Error getting blocksize on %s: %s\n",
138 path, strerror(errno));
143 /* Global control device: */
144 int bcachectl_open(void)
146 int fd = open("/dev/bcache-ctl", O_RDWR);
148 die("Can't open bcache device: %s", strerror(errno));
153 /* Filesystem handles (ioctl, sysfs dir): */
155 #define SYSFS_BASE "/sys/fs/bcache/"
157 struct bcache_handle bcache_fs_open(const char *path)
159 struct bcache_handle ret;
162 if (!uuid_parse(path, tmp)) {
163 /* It's a UUID, look it up in sysfs: */
165 char *sysfs = alloca(strlen(SYSFS_BASE) + strlen(path) + 1);
166 sprintf(sysfs, "%s%s", SYSFS_BASE, path);
168 ret.sysfs_fd = open(sysfs, O_RDONLY);
170 die("Unable to open %s\n", path);
172 char *minor = read_file_str(ret.sysfs_fd, "minor");
173 char *ctl = alloca(20 + strlen(minor));
175 sprintf(ctl, "/dev/bcache%s-ctl", minor);
178 ret.ioctl_fd = open(ctl, O_RDWR);
179 if (ret.ioctl_fd < 0)
180 die("Error opening control device: %s\n",
185 ret.ioctl_fd = open(path, O_RDONLY);
186 if (ret.ioctl_fd < 0)
187 die("Error opening %s: %s\n",
188 path, strerror(errno));
190 struct bch_ioctl_query_uuid uuid;
191 if (ioctl(ret.ioctl_fd, BCH_IOCTL_QUERY_UUID, &uuid))
192 die("ioctl error (not a bcache fs?): %s\n",
196 uuid_unparse(uuid.uuid.b, uuid_str);
198 char *sysfs = alloca(strlen(SYSFS_BASE) + strlen(uuid_str) + 1);
199 sprintf(sysfs, "%s%s", SYSFS_BASE, uuid_str);
201 ret.sysfs_fd = open(sysfs, O_RDONLY);
202 if (ret.sysfs_fd < 0)
203 die("Unable to open sysfs dir %s: %s\n",
204 sysfs, strerror(errno));
212 const char *short_yes = "yY";
217 fputs(" (y,n) ", stdout);
220 if (getline(&buf, &buflen, stdin) < 0)
221 die("error reading from standard input");
223 ret = strchr(short_yes, buf[0]);