mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-26 03:09:34 +03:00
Fix set block scheduler warnings
There were two cases when attempting to set the vdev block device scheduler which would causes console warnings. The first case was when the vdev used a loop, ram, dm, or other such device which doesn't support a configurable scheduler. In these cases attempting to set a scheduler is pointless and can be safely skipped. The secord case is slightly more troubling. We were seeing transient cases where setting the elevator would return -EFAULT. On retry everything is fine so there appears to be a small window where this is possible. To handle that case we silently retry up to three times before reporting the warning. In all of the above cases the warning is harmless and at worse you may see slightly different performance characteristics from one or more of your vdevs.
This commit is contained in:
parent
4c0d8e50b9
commit
fdcd952b4d
@ -119,24 +119,42 @@ vdev_disk_error(zio_t *zio)
|
||||
* open time from the kernel.
|
||||
*/
|
||||
static int
|
||||
vdev_elevator_switch(vdev_t *v, char *elevator, char *device)
|
||||
vdev_elevator_switch(vdev_t *v, char *elevator)
|
||||
{
|
||||
vdev_disk_t *vd = v->vdev_tsd;
|
||||
struct block_device *bdev = vd->vd_bdev;
|
||||
struct request_queue *q = bdev_get_queue(bdev);
|
||||
char *device = bdev->bd_disk->disk_name;
|
||||
char sh_path[] = "/bin/sh";
|
||||
char sh_cmd[128];
|
||||
char *argv[] = { sh_path, "-c", sh_cmd };
|
||||
char *envp[] = { NULL };
|
||||
int error;
|
||||
int count = 0, error;
|
||||
|
||||
/* Skip devices without schedulers (loop, ram, dm, etc) */
|
||||
if (!q->elevator || !blk_queue_stackable(q))
|
||||
return (0);
|
||||
|
||||
/* Leave existing scheduler when set to "none" */
|
||||
if (!strncmp(elevator, "none", 4) && (strlen(elevator) == 4))
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Set the desired scheduler with a three attempt retry for
|
||||
* -EFAULT which has been observed to occur spuriously.
|
||||
*/
|
||||
sprintf(sh_cmd, "%s \"%s\" >/sys/block/%s/queue/scheduler",
|
||||
"/bin/echo", elevator, device);
|
||||
|
||||
error = call_usermodehelper(sh_path, argv, envp, 1);
|
||||
while (++count <= 3) {
|
||||
error = call_usermodehelper(sh_path, argv, envp, 1);
|
||||
if ((error == 0) || (error != -EFAULT))
|
||||
break;
|
||||
}
|
||||
|
||||
if (error)
|
||||
printk("ZFS: Unable to set \"%s\" scheduler for %s (%s): %d\n",
|
||||
elevator, v->vdev_path, device, error);
|
||||
elevator, v->vdev_path, device, error);
|
||||
|
||||
return (error);
|
||||
}
|
||||
@ -207,8 +225,7 @@ vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *ashift)
|
||||
*ashift = highbit(MAX(block_size, SPA_MINBLOCKSIZE)) - 1;
|
||||
|
||||
/* Try to set the io scheduler elevator algorithm */
|
||||
(void) vdev_elevator_switch(v, zfs_vdev_scheduler,
|
||||
bdev->bd_disk->disk_name);
|
||||
(void) vdev_elevator_switch(v, zfs_vdev_scheduler);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user