Chapter 6: Device Drivers
*(current->bio_tail) = bio;
bio->bi_next = NULL;
current->bio_tail = &bio->bi_next;
return;
}
do {
current->bio_list = bio->bi_next;
if (bio->bi_next == NULL)
current->bio_tail = ¤t->bio_list;
else
bio->bi_next = NULL;
__generic_make_request(bio);
bio = current->bio_list;
} while (bio);
current->bio_tail = NULL; /* deactivate */
}
The method is simple, yet creative. Figure 6-17 shows how the data structures evolve over time.
bio_list
bio_tail
current
bio_list
bio_tail
Bio 1
(a) (b)
(c) (d)
Bio 1
bio_list
bio_tail
current
bio
bi_next
bi_next bi_next bi_next
Bio 2
bi_next
Bio 3
bi_next
Bio 4
bi_next
Bio 1 Bio 2
bio bio
bio
bi_next
bio_list
bio_tail
Bio 2
bi_next
Bio 1
current
Figure 6-17: BIO lists evolving under recursive calls togeneric_make_request.
current->bio_tailis initialized toNULL, so we can skip the first conditional block. Onebioinstance
is submitted, and the data structures look as in Figure 6-17(a).biopoints to the submitted BIO, while
current->bio_listisNULLandcurrent_bio_tailpoint to the address ofcurrent_bio_tail.Notethat
the following pictures in the figure will always consider the localbiovariable of the first function call to
generic_make_request— not any variables in later stack frames.
Now suppose that__generic_make_requestdoes recursively callgeneric_make_requestto submit
aBIOinstance, which we call BIO 2. How do the data structures look when__generic_make_request
returns? Consider the action of the recursive call: Sincecurrent->bio_tailis not aNULLpointer any-
more, the initialif-block ingeneric_make_requestis processed.current->bio_listthen points to
the second BIO, andcurrent->bio_tailpoints at the address of thebi_nextofBIO2.Thusthedata
structure looks as in Figure 6-17(b) when__generic_make_requestreturns.