Skip to content

Commit

Permalink
Fix spurious -EFAULT when setting I/O scheduler
Browse files Browse the repository at this point in the history
Occasionally we would see an -EFAULT returned when setting the
I/O scheduler on a vdev.  This was caused an improperly formatted
user mode helper command.

This commit restructures the command to something simpler, allocates
space for it dynamically to save stack, and removes the retry logic
which is no longer needed.

Closes #169
  • Loading branch information
behlendorf committed Apr 22, 2011
1 parent 6a8f9b6 commit e2448b0
Showing 1 changed file with 12 additions and 17 deletions.
29 changes: 12 additions & 17 deletions module/zfs/vdev_disk.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,18 +118,22 @@ vdev_disk_error(zio_t *zio)
* automatically imported on module load so we must do this at device
* open time from the kernel.
*/
#define SET_SCHEDULER_CMD \
"exec 0</dev/null " \
" 1>/sys/block/%s/queue/scheduler " \
" 2>/dev/null; " \
"echo %s"

static int
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 *argv[] = { "/bin/sh", "-c", NULL, NULL };
char *envp[] = { NULL };
int count = 0, error;
int error;

/* Skip devices which are not whole disks (partitions) */
if (!v->vdev_wholedisk)
Expand All @@ -143,23 +147,14 @@ vdev_elevator_switch(vdev_t *v, char *elevator)
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;
}

argv[2] = kmem_asprintf(SET_SCHEDULER_CMD, device, elevator);
error = call_usermodehelper(argv[0], argv, envp, 1);
if (error)
printk("ZFS: Unable to set \"%s\" scheduler for %s (%s): %d\n",
elevator, v->vdev_path, device, error);

strfree(argv[2]);

return (error);
}

Expand Down

0 comments on commit e2448b0

Please sign in to comment.