mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-02-22 00:00:03 +03:00
cmd_fsck: Create loopback device for kernel fsck when necessary
fstests generic/648 now passes Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
282331defa
commit
4f9293b045
@ -160,6 +160,45 @@ static bool should_use_kernel_fsck(darray_str devs)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool is_blockdev(const char *path)
|
||||
{
|
||||
struct stat s;
|
||||
if (stat(path, &s))
|
||||
return true;
|
||||
return S_ISBLK(s.st_mode);
|
||||
}
|
||||
|
||||
static void loopdev_free(const char *path)
|
||||
{
|
||||
char *cmd = mprintf("losetup -d %s", path);
|
||||
system(cmd);
|
||||
free(cmd);
|
||||
}
|
||||
|
||||
static char *loopdev_alloc(const char *path)
|
||||
{
|
||||
char *cmd = mprintf("losetup --show -f %s", path);
|
||||
FILE *f = popen(cmd, "r");
|
||||
free(cmd);
|
||||
if (!f) {
|
||||
fprintf(stderr, "error executing losetup: %m\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *line = NULL;
|
||||
size_t n = 0;
|
||||
getline(&line, &n, f);
|
||||
int ret = pclose(f);
|
||||
if (ret) {
|
||||
fprintf(stderr, "error executing losetup: %i\n", ret);
|
||||
free(line);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strim(line);
|
||||
return line;
|
||||
}
|
||||
|
||||
int cmd_fsck(int argc, char *argv[])
|
||||
{
|
||||
static const struct option longopts[] = {
|
||||
@ -243,19 +282,35 @@ int cmd_fsck(int argc, char *argv[])
|
||||
struct printbuf parse_later = PRINTBUF;
|
||||
|
||||
if (kernel_probed) {
|
||||
darray_str loopdevs = {};
|
||||
int fsck_fd = -1;
|
||||
|
||||
printf("Running in-kernel offline fsck\n");
|
||||
struct bch_ioctl_fsck_offline *fsck = calloc(sizeof(*fsck) +
|
||||
sizeof(u64) * devs.nr, 1);
|
||||
struct bch_ioctl_fsck_offline *fsck = calloc(sizeof(*fsck) + sizeof(u64) * devs.nr, 1);
|
||||
|
||||
fsck->opts = (unsigned long)opts_str.buf;
|
||||
darray_for_each(devs, i)
|
||||
fsck->devs[i - devs.data] = (unsigned long) *i;
|
||||
darray_for_each(devs, i) {
|
||||
if (is_blockdev(*i)) {
|
||||
fsck->devs[i - devs.data] = (unsigned long) *i;
|
||||
} else {
|
||||
char *l = loopdev_alloc(*i);
|
||||
if (!l)
|
||||
goto kernel_fsck_err;
|
||||
darray_push(&loopdevs, l);
|
||||
fsck->devs[i - devs.data] = (unsigned long) l;
|
||||
}
|
||||
}
|
||||
fsck->nr_devs = devs.nr;
|
||||
|
||||
int ctl_fd = bcachectl_open();
|
||||
int fsck_fd = ioctl(ctl_fd, BCH_IOCTL_FSCK_OFFLINE, fsck);
|
||||
fsck_fd = ioctl(ctl_fd, BCH_IOCTL_FSCK_OFFLINE, fsck);
|
||||
kernel_fsck_err:
|
||||
free(fsck);
|
||||
|
||||
darray_for_each(loopdevs, i)
|
||||
loopdev_free(*i);
|
||||
darray_exit(&loopdevs);
|
||||
|
||||
if (fsck_fd < 0 && kernel < 0)
|
||||
goto userland_fsck;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user