Skip to content

Commit 566acf2

Browse files
Christoph Hellwigaxboe
authored andcommitted
block: refator submit_bio_noacct
Split out a __submit_bio_noacct helper for the actual de-recursion algorithm, and simplify the loop by using a continue when we can't enter the queue for a bio. Signed-off-by: Christoph Hellwig <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent ed00aab commit 566acf2

File tree

1 file changed

+75
-68
lines changed

1 file changed

+75
-68
lines changed

block/blk-core.c

Lines changed: 75 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,6 +1084,74 @@ static blk_qc_t __submit_bio(struct bio *bio)
10841084
return ret;
10851085
}
10861086

1087+
/*
1088+
* The loop in this function may be a bit non-obvious, and so deserves some
1089+
* explanation:
1090+
*
1091+
* - Before entering the loop, bio->bi_next is NULL (as all callers ensure
1092+
* that), so we have a list with a single bio.
1093+
* - We pretend that we have just taken it off a longer list, so we assign
1094+
* bio_list to a pointer to the bio_list_on_stack, thus initialising the
1095+
* bio_list of new bios to be added. ->submit_bio() may indeed add some more
1096+
* bios through a recursive call to submit_bio_noacct. If it did, we find a
1097+
* non-NULL value in bio_list and re-enter the loop from the top.
1098+
* - In this case we really did just take the bio of the top of the list (no
1099+
* pretending) and so remove it from bio_list, and call into ->submit_bio()
1100+
* again.
1101+
*
1102+
* bio_list_on_stack[0] contains bios submitted by the current ->submit_bio.
1103+
* bio_list_on_stack[1] contains bios that were submitted before the current
1104+
* ->submit_bio_bio, but that haven't been processed yet.
1105+
*/
1106+
static blk_qc_t __submit_bio_noacct(struct bio *bio)
1107+
{
1108+
struct bio_list bio_list_on_stack[2];
1109+
blk_qc_t ret = BLK_QC_T_NONE;
1110+
1111+
BUG_ON(bio->bi_next);
1112+
1113+
bio_list_init(&bio_list_on_stack[0]);
1114+
current->bio_list = bio_list_on_stack;
1115+
1116+
do {
1117+
struct request_queue *q = bio->bi_disk->queue;
1118+
struct bio_list lower, same;
1119+
1120+
if (unlikely(bio_queue_enter(bio) != 0))
1121+
continue;
1122+
1123+
/*
1124+
* Create a fresh bio_list for all subordinate requests.
1125+
*/
1126+
bio_list_on_stack[1] = bio_list_on_stack[0];
1127+
bio_list_init(&bio_list_on_stack[0]);
1128+
1129+
ret = __submit_bio(bio);
1130+
1131+
/*
1132+
* Sort new bios into those for a lower level and those for the
1133+
* same level.
1134+
*/
1135+
bio_list_init(&lower);
1136+
bio_list_init(&same);
1137+
while ((bio = bio_list_pop(&bio_list_on_stack[0])) != NULL)
1138+
if (q == bio->bi_disk->queue)
1139+
bio_list_add(&same, bio);
1140+
else
1141+
bio_list_add(&lower, bio);
1142+
1143+
/*
1144+
* Now assemble so we handle the lowest level first.
1145+
*/
1146+
bio_list_merge(&bio_list_on_stack[0], &lower);
1147+
bio_list_merge(&bio_list_on_stack[0], &same);
1148+
bio_list_merge(&bio_list_on_stack[0], &bio_list_on_stack[1]);
1149+
} while ((bio = bio_list_pop(&bio_list_on_stack[0])));
1150+
1151+
current->bio_list = NULL;
1152+
return ret;
1153+
}
1154+
10871155
/**
10881156
* submit_bio_noacct - re-submit a bio to the block device layer for I/O
10891157
* @bio: The bio describing the location in memory and on the device.
@@ -1095,82 +1163,21 @@ static blk_qc_t __submit_bio(struct bio *bio)
10951163
*/
10961164
blk_qc_t submit_bio_noacct(struct bio *bio)
10971165
{
1098-
/*
1099-
* bio_list_on_stack[0] contains bios submitted by the current
1100-
* ->submit_bio.
1101-
* bio_list_on_stack[1] contains bios that were submitted before the
1102-
* current ->submit_bio_bio, but that haven't been processed yet.
1103-
*/
1104-
struct bio_list bio_list_on_stack[2];
1105-
blk_qc_t ret = BLK_QC_T_NONE;
1106-
11071166
if (!submit_bio_checks(bio))
1108-
goto out;
1167+
return BLK_QC_T_NONE;
11091168

11101169
/*
1111-
* We only want one ->submit_bio to be active at a time, else
1112-
* stack usage with stacked devices could be a problem. So use
1113-
* current->bio_list to keep a list of requests submited by a
1114-
* ->submit_bio method. current->bio_list is also used as a
1115-
* flag to say if submit_bio_noacct is currently active in this
1116-
* task or not. If it is NULL, then no make_request is active. If
1117-
* it is non-NULL, then a make_request is active, and new requests
1118-
* should be added at the tail
1170+
* We only want one ->submit_bio to be active at a time, else stack
1171+
* usage with stacked devices could be a problem. Use current->bio_list
1172+
* to collect a list of requests submited by a ->submit_bio method while
1173+
* it is active, and then process them after it returned.
11191174
*/
11201175
if (current->bio_list) {
11211176
bio_list_add(&current->bio_list[0], bio);
1122-
goto out;
1177+
return BLK_QC_T_NONE;
11231178
}
11241179

1125-
/* following loop may be a bit non-obvious, and so deserves some
1126-
* explanation.
1127-
* Before entering the loop, bio->bi_next is NULL (as all callers
1128-
* ensure that) so we have a list with a single bio.
1129-
* We pretend that we have just taken it off a longer list, so
1130-
* we assign bio_list to a pointer to the bio_list_on_stack,
1131-
* thus initialising the bio_list of new bios to be
1132-
* added. ->submit_bio() may indeed add some more bios
1133-
* through a recursive call to submit_bio_noacct. If it
1134-
* did, we find a non-NULL value in bio_list and re-enter the loop
1135-
* from the top. In this case we really did just take the bio
1136-
* of the top of the list (no pretending) and so remove it from
1137-
* bio_list, and call into ->submit_bio() again.
1138-
*/
1139-
BUG_ON(bio->bi_next);
1140-
bio_list_init(&bio_list_on_stack[0]);
1141-
current->bio_list = bio_list_on_stack;
1142-
do {
1143-
struct request_queue *q = bio->bi_disk->queue;
1144-
1145-
if (likely(bio_queue_enter(bio) == 0)) {
1146-
struct bio_list lower, same;
1147-
1148-
/* Create a fresh bio_list for all subordinate requests */
1149-
bio_list_on_stack[1] = bio_list_on_stack[0];
1150-
bio_list_init(&bio_list_on_stack[0]);
1151-
ret = __submit_bio(bio);
1152-
1153-
/* sort new bios into those for a lower level
1154-
* and those for the same level
1155-
*/
1156-
bio_list_init(&lower);
1157-
bio_list_init(&same);
1158-
while ((bio = bio_list_pop(&bio_list_on_stack[0])) != NULL)
1159-
if (q == bio->bi_disk->queue)
1160-
bio_list_add(&same, bio);
1161-
else
1162-
bio_list_add(&lower, bio);
1163-
/* now assemble so we handle the lowest level first */
1164-
bio_list_merge(&bio_list_on_stack[0], &lower);
1165-
bio_list_merge(&bio_list_on_stack[0], &same);
1166-
bio_list_merge(&bio_list_on_stack[0], &bio_list_on_stack[1]);
1167-
}
1168-
bio = bio_list_pop(&bio_list_on_stack[0]);
1169-
} while (bio);
1170-
current->bio_list = NULL; /* deactivate */
1171-
1172-
out:
1173-
return ret;
1180+
return __submit_bio_noacct(bio);
11741181
}
11751182
EXPORT_SYMBOL(submit_bio_noacct);
11761183

0 commit comments

Comments
 (0)