| @@ -19,6 +19,7 @@ · 18 unmodified lines |
| 19 | 19 | #include <linux/errno.h> |
| 20 | 20 | #include <linux/major.h> |
| 21 | 21 | #include <linux/wait.h> |
| 22 | +#include <linux/wait_bit.h> |
| 22 | 23 | #include <linux/blkdev.h> |
| 23 | 24 | #include <linux/init.h> |
| 24 | 25 | #include <linux/swap.h> |
| @@ -26,7 +27,6 @@ · 1 unmodified line |
| 26 | 27 | #include <linux/compat.h> |
| 27 | 28 | #include <linux/mutex.h> |
| 28 | 29 | #include <linux/writeback.h> |
| 29 | | −#include <linux/completion.h> |
| 30 | 30 | #include <linux/highmem.h> |
| 31 | 31 | #include <linux/sysfs.h> |
| 32 | 32 | #include <linux/miscdevice.h> |
| @@ -327,7 +327,6 @@ struct ublk_device { · 294 unmodified lines |
| 327 | 327 | |
| 328 | 328 | struct ublk_params params; |
| 329 | 329 | |
| 330 | | − struct completion completion; |
| 331 | 330 | u32 nr_queue_ready; |
| 332 | 331 | bool unprivileged_daemons; |
| 333 | 332 | struct mutex cancel_mutex; |
| @@ -3054,12 +3053,12 @@ static void ublk_mark_io_ready(struct ublk_device *ub, u16 q_id, · 2720 unmodified lines |
| 3054 | 3053 | if (ublk_dev_ready(ub)) { |
| 3055 | 3054 | /* |
| 3056 | 3055 | * All queues ready - clear device-level canceling flag |
| 3057 | | − * and complete the recovery/initialization. |
| 3056 | + * and wake ublk_dev_ready() waiters. |
| 3058 | 3057 | */ |
| 3059 | 3058 | mutex_lock(&ub->cancel_mutex); |
| 3060 | 3059 | ub->canceling = false; |
| 3061 | 3060 | mutex_unlock(&ub->cancel_mutex); |
| 3062 | | − complete_all(&ub->completion); |
| 3061 | + wake_up_var(&ub->nr_queue_ready); |
| 3063 | 3062 | } |
| 3064 | 3063 | } |
| 3065 | 3064 | |
| @@ -4273,7 +4272,6 @@ static int ublk_init_queues(struct ublk_device *ub) · 1207 unmodified lines |
| 4273 | 4272 | goto fail; |
| 4274 | 4273 | } |
| 4275 | 4274 | |
| 4276 | | − init_completion(&ub->completion); |
| 4277 | 4275 | return 0; |
| 4278 | 4276 | |
| 4279 | 4277 | fail: |
| @@ -4417,6 +4415,26 @@ static bool ublk_validate_user_pid(struct ublk_device *ub, pid_t ublksrv_pid) · 137 unmodified lines |
| 4417 | 4415 | return ub->ublksrv_tgid == ublksrv_pid; |
| 4418 | 4416 | } |
| 4419 | 4417 | |
| 4418 | +/* |
| 4419 | + * Wait until all queues have fetched their I/O commands, and return with |
| 4420 | + * ub->mutex held and readiness guaranteed: then every queue's ->canceling |
| 4421 | + * is cleared. Ready may regress between wakeup and mutex_lock() (F_BATCH |
| 4422 | + * UNPREP, daemon death), so re-check it under the mutex and wait again. |
| 4423 | + */ |
| 4424 | +static int ublk_wait_dev_ready_and_lock(struct ublk_device *ub) |
| 4425 | +{ |
| 4426 | + while (true) { |
| 4427 | + if (wait_var_event_interruptible(&ub->nr_queue_ready, |
| 4428 | + ublk_dev_ready(ub))) |
| 4429 | + return -EINTR; |
| 4430 | + |
| 4431 | + mutex_lock(&ub->mutex); |
| 4432 | + if (ublk_dev_ready(ub)) |
| 4433 | + return 0; |
| 4434 | + mutex_unlock(&ub->mutex); |
| 4435 | + } |
| 4436 | +} |
| 4437 | + |
| 4420 | 4438 | static int ublk_ctrl_start_dev(struct ublk_device *ub, |
| 4421 | 4439 | const struct ublksrv_ctrl_cmd *header) |
| 4422 | 4440 | { |
| @@ -4499,15 +4517,10 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub, · 76 unmodified lines |
| 4499 | 4517 | }; |
| 4500 | 4518 | } |
| 4501 | 4519 | |
| 4502 | | − if (wait_for_completion_interruptible(&ub->completion) != 0) |
| 4520 | + if (ublk_wait_dev_ready_and_lock(ub)) |
| 4503 | 4521 | return -EINTR; |
| 4504 | 4522 | |
| 4505 | | − if (!ublk_validate_user_pid(ub, ublksrv_pid)) |
| 4506 | | − return -EINVAL; |
| 4507 | | − |
| 4508 | | − mutex_lock(&ub->mutex); |
| 4509 | | − /* device may become not ready in case of F_BATCH */ |
| 4510 | | − if (!ublk_dev_ready(ub)) { |
| 4523 | + if (!ublk_validate_user_pid(ub, ublksrv_pid)) { |
| 4511 | 4524 | ret = -EINVAL; |
| 4512 | 4525 | goto out_unlock; |
| 4513 | 4526 | } |
| @@ -5071,7 +5084,6 @@ static int ublk_ctrl_start_recovery(struct ublk_device *ub) · 557 unmodified lines |
| 5071 | 5084 | goto out_unlock; |
| 5072 | 5085 | } |
| 5073 | 5086 | pr_devel("%s: start recovery for dev id %d\n", __func__, ub->ub_number); |
| 5074 | | − init_completion(&ub->completion); |
| 5075 | 5087 | ret = 0; |
| 5076 | 5088 | out_unlock: |
| 5077 | 5089 | mutex_unlock(&ub->mutex); |
| @@ -5087,16 +5099,17 @@ static int ublk_ctrl_end_recovery(struct ublk_device *ub, · 9 unmodified lines |
| 5087 | 5099 | pr_devel("%s: Waiting for all FETCH_REQs, dev id %d...\n", __func__, |
| 5088 | 5100 | header->dev_id); |
| 5089 | 5101 | |
| 5090 | | − if (wait_for_completion_interruptible(&ub->completion)) |
| 5102 | + if (ublk_wait_dev_ready_and_lock(ub)) |
| 5091 | 5103 | return -EINTR; |
| 5092 | 5104 | |
| 5093 | 5105 | pr_devel("%s: All FETCH_REQs received, dev id %d\n", __func__, |
| 5094 | 5106 | header->dev_id); |
| 5095 | 5107 | |
| 5096 | | − if (!ublk_validate_user_pid(ub, ublksrv_pid)) |
| 5097 | | − return -EINVAL; |
| 5108 | + if (!ublk_validate_user_pid(ub, ublksrv_pid)) { |
| 5109 | + ret = -EINVAL; |
| 5110 | + goto out_unlock; |
| 5111 | + } |
| 5098 | 5112 | |
| 5099 | | − mutex_lock(&ub->mutex); |
| 5100 | 5113 | if (ublk_nosrv_should_stop_dev(ub)) |
| 5101 | 5114 | goto out_unlock; |
| 5102 | 5115 | |