mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-11-17 18:11:00 +03:00
Fix spurious -EFAULT when setting I/O scheduler
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
This commit is contained in:
parent
6a8f9b6bf0
commit
e2448b0e62
@ -118,6 +118,12 @@ vdev_disk_error(zio_t *zio)
|
|||||||
* automatically imported on module load so we must do this at device
|
* automatically imported on module load so we must do this at device
|
||||||
* open time from the kernel.
|
* 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
|
static int
|
||||||
vdev_elevator_switch(vdev_t *v, char *elevator)
|
vdev_elevator_switch(vdev_t *v, char *elevator)
|
||||||
{
|
{
|
||||||
@ -125,11 +131,9 @@ vdev_elevator_switch(vdev_t *v, char *elevator)
|
|||||||
struct block_device *bdev = vd->vd_bdev;
|
struct block_device *bdev = vd->vd_bdev;
|
||||||
struct request_queue *q = bdev_get_queue(bdev);
|
struct request_queue *q = bdev_get_queue(bdev);
|
||||||
char *device = bdev->bd_disk->disk_name;
|
char *device = bdev->bd_disk->disk_name;
|
||||||
char sh_path[] = "/bin/sh";
|
char *argv[] = { "/bin/sh", "-c", NULL, NULL };
|
||||||
char sh_cmd[128];
|
|
||||||
char *argv[] = { sh_path, "-c", sh_cmd };
|
|
||||||
char *envp[] = { NULL };
|
char *envp[] = { NULL };
|
||||||
int count = 0, error;
|
int error;
|
||||||
|
|
||||||
/* Skip devices which are not whole disks (partitions) */
|
/* Skip devices which are not whole disks (partitions) */
|
||||||
if (!v->vdev_wholedisk)
|
if (!v->vdev_wholedisk)
|
||||||
@ -143,23 +147,14 @@ vdev_elevator_switch(vdev_t *v, char *elevator)
|
|||||||
if (!strncmp(elevator, "none", 4) && (strlen(elevator) == 4))
|
if (!strncmp(elevator, "none", 4) && (strlen(elevator) == 4))
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
/*
|
argv[2] = kmem_asprintf(SET_SCHEDULER_CMD, device, elevator);
|
||||||
* Set the desired scheduler with a three attempt retry for
|
error = call_usermodehelper(argv[0], argv, envp, 1);
|
||||||
* -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)
|
if (error)
|
||||||
printk("ZFS: Unable to set \"%s\" scheduler for %s (%s): %d\n",
|
printk("ZFS: Unable to set \"%s\" scheduler for %s (%s): %d\n",
|
||||||
elevator, v->vdev_path, device, error);
|
elevator, v->vdev_path, device, error);
|
||||||
|
|
||||||
|
strfree(argv[2]);
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user