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;
|
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[])
|
int cmd_fsck(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
static const struct option longopts[] = {
|
static const struct option longopts[] = {
|
||||||
@ -243,19 +282,35 @@ int cmd_fsck(int argc, char *argv[])
|
|||||||
struct printbuf parse_later = PRINTBUF;
|
struct printbuf parse_later = PRINTBUF;
|
||||||
|
|
||||||
if (kernel_probed) {
|
if (kernel_probed) {
|
||||||
|
darray_str loopdevs = {};
|
||||||
|
int fsck_fd = -1;
|
||||||
|
|
||||||
printf("Running in-kernel offline fsck\n");
|
printf("Running in-kernel offline fsck\n");
|
||||||
struct bch_ioctl_fsck_offline *fsck = calloc(sizeof(*fsck) +
|
struct bch_ioctl_fsck_offline *fsck = calloc(sizeof(*fsck) + sizeof(u64) * devs.nr, 1);
|
||||||
sizeof(u64) * devs.nr, 1);
|
|
||||||
|
|
||||||
fsck->opts = (unsigned long)opts_str.buf;
|
fsck->opts = (unsigned long)opts_str.buf;
|
||||||
darray_for_each(devs, i)
|
darray_for_each(devs, i) {
|
||||||
fsck->devs[i - devs.data] = (unsigned long) *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;
|
fsck->nr_devs = devs.nr;
|
||||||
|
|
||||||
int ctl_fd = bcachectl_open();
|
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);
|
free(fsck);
|
||||||
|
|
||||||
|
darray_for_each(loopdevs, i)
|
||||||
|
loopdev_free(*i);
|
||||||
|
darray_exit(&loopdevs);
|
||||||
|
|
||||||
if (fsck_fd < 0 && kernel < 0)
|
if (fsck_fd < 0 && kernel < 0)
|
||||||
goto userland_fsck;
|
goto userland_fsck;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user