Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ublk: refactor recovery configuration flag helpers

ublk currently supports the following behaviors on ublk server exit:

A: outstanding I/Os get errors, subsequently issued I/Os get errors
B: outstanding I/Os get errors, subsequently issued I/Os queue
C: outstanding I/Os get reissued, subsequently issued I/Os queue

and the following behaviors for recovery of preexisting block devices by
a future incarnation of the ublk server:

1: ublk devices stopped on ublk server exit (no recovery possible)
2: ublk devices are recoverable using start/end_recovery commands

The userspace interface allows selection of combinations of these
behaviors using flags specified at device creation time, namely:

default behavior: A + 1
UBLK_F_USER_RECOVERY: B + 2
UBLK_F_USER_RECOVERY|UBLK_F_USER_RECOVERY_REISSUE: C + 2

We can't easily change the userspace interface to allow independent
selection of one of {A, B, C} and one of {1, 2}, but we can refactor the
internal helpers which test for the flags. Replace the existing helpers
with the following set:

ublk_nosrv_should_reissue_outstanding: tests for behavior C
ublk_nosrv_[dev_]should_queue_io: tests for behavior B
ublk_nosrv_should_stop_dev: tests for behavior 1

Signed-off-by: Uday Shankar <ushankar@purestorage.com>
Reviewed-by: Ming Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20241007182419.3263186-3-ushankar@purestorage.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Uday Shankar and committed by
Jens Axboe
3b939b8f d00c0ea1

+42 -20
+42 -20
drivers/block/ublk_drv.c
··· 675 675 PAGE_SIZE); 676 676 } 677 677 678 - static inline bool ublk_queue_can_use_recovery_reissue( 679 - struct ublk_queue *ubq) 678 + /* 679 + * Should I/O outstanding to the ublk server when it exits be reissued? 680 + * If not, outstanding I/O will get errors. 681 + */ 682 + static inline bool ublk_nosrv_should_reissue_outstanding(struct ublk_device *ub) 680 683 { 681 - return (ubq->flags & UBLK_F_USER_RECOVERY) && 682 - (ubq->flags & UBLK_F_USER_RECOVERY_REISSUE); 684 + return (ub->dev_info.flags & UBLK_F_USER_RECOVERY) && 685 + (ub->dev_info.flags & UBLK_F_USER_RECOVERY_REISSUE); 683 686 } 684 687 685 - static inline bool ublk_queue_can_use_recovery( 686 - struct ublk_queue *ubq) 688 + /* 689 + * Should I/O issued while there is no ublk server queue? If not, I/O 690 + * issued while there is no ublk server will get errors. 691 + */ 692 + static inline bool ublk_nosrv_dev_should_queue_io(struct ublk_device *ub) 693 + { 694 + return ub->dev_info.flags & UBLK_F_USER_RECOVERY; 695 + } 696 + 697 + /* 698 + * Same as ublk_nosrv_dev_should_queue_io, but uses a queue-local copy 699 + * of the device flags for smaller cache footprint - better for fast 700 + * paths. 701 + */ 702 + static inline bool ublk_nosrv_should_queue_io(struct ublk_queue *ubq) 687 703 { 688 704 return ubq->flags & UBLK_F_USER_RECOVERY; 689 705 } 690 706 691 - static inline bool ublk_can_use_recovery(struct ublk_device *ub) 707 + /* 708 + * Should ublk devices be stopped (i.e. no recovery possible) when the 709 + * ublk server exits? If not, devices can be used again by a future 710 + * incarnation of a ublk server via the start_recovery/end_recovery 711 + * commands. 712 + */ 713 + static inline bool ublk_nosrv_should_stop_dev(struct ublk_device *ub) 692 714 { 693 - return ub->dev_info.flags & UBLK_F_USER_RECOVERY; 715 + return !(ub->dev_info.flags & UBLK_F_USER_RECOVERY); 694 716 } 695 717 696 718 static void ublk_free_disk(struct gendisk *disk) ··· 1088 1066 { 1089 1067 WARN_ON_ONCE(io->flags & UBLK_IO_FLAG_ACTIVE); 1090 1068 1091 - if (ublk_queue_can_use_recovery_reissue(ubq)) 1069 + if (ublk_nosrv_should_reissue_outstanding(ubq->dev)) 1092 1070 blk_mq_requeue_request(req, false); 1093 1071 else 1094 1072 ublk_put_req_ref(ubq, req); ··· 1116 1094 struct request *rq) 1117 1095 { 1118 1096 /* We cannot process this rq so just requeue it. */ 1119 - if (ublk_queue_can_use_recovery(ubq)) 1097 + if (ublk_nosrv_dev_should_queue_io(ubq->dev)) 1120 1098 blk_mq_requeue_request(rq, false); 1121 1099 else 1122 1100 blk_mq_end_request(rq, BLK_STS_IOERR); ··· 1261 1239 struct ublk_device *ub = ubq->dev; 1262 1240 1263 1241 if (ublk_abort_requests(ub, ubq)) { 1264 - if (ublk_can_use_recovery(ub)) 1265 - schedule_work(&ub->quiesce_work); 1266 - else 1242 + if (ublk_nosrv_should_stop_dev(ub)) 1267 1243 schedule_work(&ub->stop_work); 1244 + else 1245 + schedule_work(&ub->quiesce_work); 1268 1246 } 1269 1247 return BLK_EH_DONE; 1270 1248 } ··· 1293 1271 * Note: force_abort is guaranteed to be seen because it is set 1294 1272 * before request queue is unqiuesced. 1295 1273 */ 1296 - if (ublk_queue_can_use_recovery(ubq) && unlikely(ubq->force_abort)) 1274 + if (ublk_nosrv_should_queue_io(ubq) && unlikely(ubq->force_abort)) 1297 1275 return BLK_STS_IOERR; 1298 1276 1299 1277 if (unlikely(ubq->canceling)) { ··· 1514 1492 ublk_cancel_cmd(ubq, io, issue_flags); 1515 1493 1516 1494 if (need_schedule) { 1517 - if (ublk_can_use_recovery(ub)) 1518 - schedule_work(&ub->quiesce_work); 1519 - else 1495 + if (ublk_nosrv_should_stop_dev(ub)) 1520 1496 schedule_work(&ub->stop_work); 1497 + else 1498 + schedule_work(&ub->quiesce_work); 1521 1499 } 1522 1500 } 1523 1501 ··· 1622 1600 mutex_lock(&ub->mutex); 1623 1601 if (ub->dev_info.state == UBLK_S_DEV_DEAD) 1624 1602 goto unlock; 1625 - if (ublk_can_use_recovery(ub)) { 1603 + if (ublk_nosrv_dev_should_queue_io(ub)) { 1626 1604 if (ub->dev_info.state == UBLK_S_DEV_LIVE) 1627 1605 __ublk_quiesce_dev(ub); 1628 1606 ublk_unquiesce_dev(ub); ··· 2732 2710 int i; 2733 2711 2734 2712 mutex_lock(&ub->mutex); 2735 - if (!ublk_can_use_recovery(ub)) 2713 + if (ublk_nosrv_should_stop_dev(ub)) 2736 2714 goto out_unlock; 2737 2715 if (!ub->nr_queues_ready) 2738 2716 goto out_unlock; ··· 2785 2763 __func__, ub->dev_info.nr_hw_queues, header->dev_id); 2786 2764 2787 2765 mutex_lock(&ub->mutex); 2788 - if (!ublk_can_use_recovery(ub)) 2766 + if (ublk_nosrv_should_stop_dev(ub)) 2789 2767 goto out_unlock; 2790 2768 2791 2769 if (ub->dev_info.state != UBLK_S_DEV_QUIESCED) {