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:
Brian Behlendorf 2011-02-25 11:26:41 -08:00
parent 4c0d8e50b9
commit fdcd952b4d

View File

@ -119,21 +119,39 @@ 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);
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);
@ -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;
}