Skip to content

Commit 40f0fa7

Browse files
ps-ushankarkawasaki
authored andcommitted
ublk: introduce and use ublk_set_canceling helper
For performance reasons (minimizing the number of cache lines accessed in the hot path), we store the "canceling" state redundantly - there is one flag in the device, which can be considered the source of truth, and per-queue copies of that flag. This redundancy can cause confusion, and opens the door to bugs where the state is set inconsistently. Try to guard against these bugs by introducing a ublk_set_canceling helper which is the sole mutator of both the per-device and per-queue canceling state. This helper always sets the state consistently. Use the helper in all places where we need to modify the canceling state. No functional changes are expected. Signed-off-by: Uday Shankar <[email protected]> Reviewed-by: Ming Lei <[email protected]>
1 parent 971ba9e commit 40f0fa7

1 file changed

Lines changed: 34 additions & 20 deletions

File tree

drivers/block/ublk_drv.c

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1552,6 +1552,27 @@ static void ublk_put_disk(struct gendisk *disk)
15521552
put_device(disk_to_dev(disk));
15531553
}
15541554

1555+
/*
1556+
* Use this function to ensure that ->canceling is consistently set for
1557+
* the device and all queues. Do not set these flags directly.
1558+
*
1559+
* Caller must ensure that:
1560+
* - cancel_mutex is held. This ensures that there is no concurrent
1561+
* access to ub->canceling and no concurrent writes to ubq->canceling.
1562+
* - there are no concurrent reads of ubq->canceling from the queue_rq
1563+
* path. This can be done by quiescing the queue, or through other
1564+
* means.
1565+
*/
1566+
static void ublk_set_canceling(struct ublk_device *ub, bool canceling)
1567+
__must_hold(&ub->cancel_mutex)
1568+
{
1569+
int i;
1570+
1571+
ub->canceling = canceling;
1572+
for (i = 0; i < ub->dev_info.nr_hw_queues; i++)
1573+
ublk_get_queue(ub, i)->canceling = canceling;
1574+
}
1575+
15551576
static int ublk_ch_release(struct inode *inode, struct file *filp)
15561577
{
15571578
struct ublk_device *ub = filp->private_data;
@@ -1580,13 +1601,11 @@ static int ublk_ch_release(struct inode *inode, struct file *filp)
15801601
* All requests may be inflight, so ->canceling may not be set, set
15811602
* it now.
15821603
*/
1583-
ub->canceling = true;
1584-
for (i = 0; i < ub->dev_info.nr_hw_queues; i++) {
1585-
struct ublk_queue *ubq = ublk_get_queue(ub, i);
1586-
1587-
ubq->canceling = true;
1588-
ublk_abort_queue(ub, ubq);
1589-
}
1604+
mutex_lock(&ub->cancel_mutex);
1605+
ublk_set_canceling(ub, true);
1606+
for (i = 0; i < ub->dev_info.nr_hw_queues; i++)
1607+
ublk_abort_queue(ub, ublk_get_queue(ub, i));
1608+
mutex_unlock(&ub->cancel_mutex);
15901609
blk_mq_kick_requeue_list(disk->queue);
15911610

15921611
/*
@@ -1712,7 +1731,6 @@ static void ublk_abort_queue(struct ublk_device *ub, struct ublk_queue *ubq)
17121731
static void ublk_start_cancel(struct ublk_device *ub)
17131732
{
17141733
struct gendisk *disk = ublk_get_disk(ub);
1715-
int i;
17161734

17171735
/* Our disk has been dead */
17181736
if (!disk)
@@ -1729,9 +1747,7 @@ static void ublk_start_cancel(struct ublk_device *ub)
17291747
* touch completed uring_cmd
17301748
*/
17311749
blk_mq_quiesce_queue(disk->queue);
1732-
ub->canceling = true;
1733-
for (i = 0; i < ub->dev_info.nr_hw_queues; i++)
1734-
ublk_get_queue(ub, i)->canceling = true;
1750+
ublk_set_canceling(ub, true);
17351751
blk_mq_unquiesce_queue(disk->queue);
17361752
out:
17371753
mutex_unlock(&ub->cancel_mutex);
@@ -1931,10 +1947,11 @@ static void ublk_reset_io_flags(struct ublk_device *ub)
19311947
for (j = 0; j < ubq->q_depth; j++)
19321948
ubq->ios[j].flags &= ~UBLK_IO_FLAG_CANCELED;
19331949
spin_unlock(&ubq->cancel_lock);
1934-
ubq->canceling = false;
19351950
ubq->fail_io = false;
19361951
}
1937-
ub->canceling = false;
1952+
mutex_lock(&ub->cancel_mutex);
1953+
ublk_set_canceling(ub, false);
1954+
mutex_unlock(&ub->cancel_mutex);
19381955
}
19391956

19401957
/* device can only be started after all IOs are ready */
@@ -3345,7 +3362,7 @@ static int ublk_ctrl_quiesce_dev(struct ublk_device *ub,
33453362
/* zero means wait forever */
33463363
u64 timeout_ms = header->data[0];
33473364
struct gendisk *disk;
3348-
int i, ret = -ENODEV;
3365+
int ret = -ENODEV;
33493366

33503367
if (!(ub->dev_info.flags & UBLK_F_QUIESCE))
33513368
return -EOPNOTSUPP;
@@ -3363,14 +3380,11 @@ static int ublk_ctrl_quiesce_dev(struct ublk_device *ub,
33633380
goto put_disk;
33643381

33653382
/* Mark the device as canceling */
3383+
mutex_lock(&ub->cancel_mutex);
33663384
blk_mq_quiesce_queue(disk->queue);
3367-
ub->canceling = true;
3368-
for (i = 0; i < ub->dev_info.nr_hw_queues; i++) {
3369-
struct ublk_queue *ubq = ublk_get_queue(ub, i);
3370-
3371-
ubq->canceling = true;
3372-
}
3385+
ublk_set_canceling(ub, true);
33733386
blk_mq_unquiesce_queue(disk->queue);
3387+
mutex_unlock(&ub->cancel_mutex);
33743388

33753389
if (!timeout_ms)
33763390
timeout_ms = UINT_MAX;

0 commit comments

Comments
 (0)