zvol_disk_open() may spin on CPU

`zvol_disk_open()` waits for up to `zfs_vdev_open_timeout_ms` (1 second by
default) (e.g. if the block device does not exist).  While in this loop,
it calls `schedule_timeout()`.

The problem is that `schedule_timeout()` may not actually cause the
thread to go off-CPU.  Per the "documentation" (comment in the source
code):
```
 * The function behavior depends on the current task state:
 * %TASK_RUNNING - the scheduler is called, but the task does not sleep
 * at all. That happens because sched_submit_work() does nothing for
 * tasks in %TASK_RUNNING state.
```

In my experience, `schedule_timeout()` never sleeps from this code path.
This is especially noticeable if `zfs_vdev_open_timeout_ms` has been
increased from its default.

This commit uses `msleep()` to actually sleep.  Note that this is how it
was before https://github.com/openzfs/zfs/pull/7629.

Signed-off-by: Matthew Ahrens <mahrens@delphix.com>
This commit is contained in:
Matthew Ahrens 2023-12-08 17:08:18 -08:00
parent 2a27fd4111
commit 7fc38a82d4
2 changed files with 3 additions and 3 deletions

View File

@ -364,10 +364,10 @@ vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
if (v->vdev_removed)
break;
schedule_timeout(MSEC_TO_TICK(10));
msleep(10);
} else if (unlikely(PTR_ERR(bdev) == -ERESTARTSYS)) {
timeout = MSEC2NSEC(zfs_vdev_open_timeout_ms * 10);
continue;
msleep(10);
} else if (IS_ERR(bdev)) {
break;
}

View File

@ -769,7 +769,7 @@ retry:
if ((gethrtime() - start) > timeout)
return (SET_ERROR(-ERESTARTSYS));
schedule_timeout(MSEC_TO_TICK(10));
msleep(10);
goto retry;
#endif
} else {