forked from Mirrors/btrfs-progs
Btrfs-progs: detect when scrub is started twice
Check whether any involved device is already busy running a scrub. This would cause damaged status messages and the state "aborted" without the explanation that a scrub was already running. Therefore check it first, prevent it and give some feedback to the user if scrub is already running. Note that if scrub is started with a block device as the parameter, only that particular block device is checked. It is a normal mode of operation to start scrub on multiple single devices, there is no reason to prevent this. Here is an example: /mnt2 is the mountpoint of a filesystem. /dev/sdk and /dev/sdl are the block devices for that filesystem. case 1: btrfs scrub start /mnt2 btrfs scrub start /mnt2 -> complain case 1: btrfs scrub start /dev/sdk btrfs scrub start /dev/sdk -> complain case 3: btrfs scrub start /dev/sdk btrfs scrub start /dev/sdl -> don't complain case 4: btrfs scrub start /dev/sdk btrfs scrub start /mnt2 -> complain case 5: btrfs scrub start /mnt2 btrfs scrub start /dev/sdk -> complain if the scrub on /dev/sdk is still running. -> don't complain if the scrub on /dev/sdk is finished, the status messages will be fine. Reported-by: David Sterba <dsterba@suse.cz> Signed-off-by: Stefan Behrens <sbehrens@giantdisaster.de> Signed-off-by: David Sterba <dsterba@suse.cz> Signed-off-by: Chris Mason <chris.mason@fusionio.com>master
parent
f6e4a423eb
commit
9681f82853
42
cmds-scrub.c
42
cmds-scrub.c
|
@ -1025,6 +1025,27 @@ int mkdir_p(char *path)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int is_scrub_running_on_fs(struct btrfs_ioctl_fs_info_args *fi_args,
|
||||
struct btrfs_ioctl_dev_info_args *di_args,
|
||||
struct scrub_file_record **past_scrubs)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!fi_args || !di_args || !past_scrubs)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < fi_args->num_devices; i++) {
|
||||
struct scrub_file_record *sfr =
|
||||
last_dev_scrub(past_scrubs, di_args[i].devid);
|
||||
|
||||
if (!sfr)
|
||||
continue;
|
||||
if (!(sfr->stats.finished || sfr->stats.canceled))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char * const cmd_scrub_start_usage[];
|
||||
static const char * const cmd_scrub_resume_usage[];
|
||||
|
||||
|
@ -1162,6 +1183,27 @@ static int scrub_start(int argc, char **argv, int resume)
|
|||
close(fdres);
|
||||
}
|
||||
|
||||
/*
|
||||
* check whether any involved device is already busy running a
|
||||
* scrub. This would cause damaged status messages and the state
|
||||
* "aborted" without the explanation that a scrub was already
|
||||
* running. Therefore check it first, prevent it and give some
|
||||
* feedback to the user if scrub is already running.
|
||||
* Note that if scrub is started with a block device as the
|
||||
* parameter, only that particular block device is checked. It
|
||||
* is a normal mode of operation to start scrub on multiple
|
||||
* single devices, there is no reason to prevent this.
|
||||
*/
|
||||
if (is_scrub_running_on_fs(&fi_args, di_args, past_scrubs)) {
|
||||
ERR(!do_quiet,
|
||||
"ERROR: scrub is already running.\n"
|
||||
"To cancel use 'btrfs scrub cancel %s'.\n"
|
||||
"To see the status use 'btrfs scrub status [-d] %s'.\n",
|
||||
path, path);
|
||||
err = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
t_devs = malloc(fi_args.num_devices * sizeof(*t_devs));
|
||||
sp = calloc(fi_args.num_devices, sizeof(*sp));
|
||||
spc.progress = calloc(fi_args.num_devices * 2, sizeof(*spc.progress));
|
||||
|
|
Loading…
Reference in New Issue