Skip to content

Commit

Permalink
pktcdvd: use BIO list management functions
Browse files Browse the repository at this point in the history
Now that the bio list management stuff is generic, convert pktcdvd to
use bio lists instead of its own private bio list implementation.

Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Acked-by: Peter Osterlund <petero2@telia.com>
Cc: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
  • Loading branch information
Akinobu Mita authored and Jens Axboe committed Feb 24, 2010
1 parent bddd87c commit c5ecc48
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 74 deletions.
89 changes: 21 additions & 68 deletions drivers/block/pktcdvd.c
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,7 @@ static struct packet_data *pkt_alloc_packet_data(int frames)
}

spin_lock_init(&pkt->lock);
bio_list_init(&pkt->orig_bios);

for (i = 0; i < frames; i++) {
struct bio *bio = pkt_bio_alloc(1);
Expand Down Expand Up @@ -720,43 +721,6 @@ static void pkt_rbtree_insert(struct pktcdvd_device *pd, struct pkt_rb_node *nod
pd->bio_queue_size++;
}

/*
* Add a bio to a single linked list defined by its head and tail pointers.
*/
static void pkt_add_list_last(struct bio *bio, struct bio **list_head, struct bio **list_tail)
{
bio->bi_next = NULL;
if (*list_tail) {
BUG_ON((*list_head) == NULL);
(*list_tail)->bi_next = bio;
(*list_tail) = bio;
} else {
BUG_ON((*list_head) != NULL);
(*list_head) = bio;
(*list_tail) = bio;
}
}

/*
* Remove and return the first bio from a single linked list defined by its
* head and tail pointers.
*/
static inline struct bio *pkt_get_list_first(struct bio **list_head, struct bio **list_tail)
{
struct bio *bio;

if (*list_head == NULL)
return NULL;

bio = *list_head;
*list_head = bio->bi_next;
if (*list_head == NULL)
*list_tail = NULL;

bio->bi_next = NULL;
return bio;
}

/*
* Send a packet_command to the underlying block device and
* wait for completion.
Expand Down Expand Up @@ -876,13 +840,10 @@ static noinline_for_stack int pkt_set_speed(struct pktcdvd_device *pd,
static void pkt_queue_bio(struct pktcdvd_device *pd, struct bio *bio)
{
spin_lock(&pd->iosched.lock);
if (bio_data_dir(bio) == READ) {
pkt_add_list_last(bio, &pd->iosched.read_queue,
&pd->iosched.read_queue_tail);
} else {
pkt_add_list_last(bio, &pd->iosched.write_queue,
&pd->iosched.write_queue_tail);
}
if (bio_data_dir(bio) == READ)
bio_list_add(&pd->iosched.read_queue, bio);
else
bio_list_add(&pd->iosched.write_queue, bio);
spin_unlock(&pd->iosched.lock);

atomic_set(&pd->iosched.attention, 1);
Expand Down Expand Up @@ -917,8 +878,8 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
int reads_queued, writes_queued;

spin_lock(&pd->iosched.lock);
reads_queued = (pd->iosched.read_queue != NULL);
writes_queued = (pd->iosched.write_queue != NULL);
reads_queued = !bio_list_empty(&pd->iosched.read_queue);
writes_queued = !bio_list_empty(&pd->iosched.write_queue);
spin_unlock(&pd->iosched.lock);

if (!reads_queued && !writes_queued)
Expand All @@ -927,7 +888,7 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
if (pd->iosched.writing) {
int need_write_seek = 1;
spin_lock(&pd->iosched.lock);
bio = pd->iosched.write_queue;
bio = bio_list_peek(&pd->iosched.write_queue);
spin_unlock(&pd->iosched.lock);
if (bio && (bio->bi_sector == pd->iosched.last_write))
need_write_seek = 0;
Expand All @@ -950,13 +911,10 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
}

spin_lock(&pd->iosched.lock);
if (pd->iosched.writing) {
bio = pkt_get_list_first(&pd->iosched.write_queue,
&pd->iosched.write_queue_tail);
} else {
bio = pkt_get_list_first(&pd->iosched.read_queue,
&pd->iosched.read_queue_tail);
}
if (pd->iosched.writing)
bio = bio_list_pop(&pd->iosched.write_queue);
else
bio = bio_list_pop(&pd->iosched.read_queue);
spin_unlock(&pd->iosched.lock);

if (!bio)
Expand Down Expand Up @@ -1114,7 +1072,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
int f;
char written[PACKET_MAX_SIZE];

BUG_ON(!pkt->orig_bios);
BUG_ON(bio_list_empty(&pkt->orig_bios));

atomic_set(&pkt->io_wait, 0);
atomic_set(&pkt->io_errors, 0);
Expand All @@ -1124,7 +1082,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
*/
memset(written, 0, sizeof(written));
spin_lock(&pkt->lock);
for (bio = pkt->orig_bios; bio; bio = bio->bi_next) {
bio_list_for_each(bio, &pkt->orig_bios) {
int first_frame = (bio->bi_sector - pkt->sector) / (CD_FRAMESIZE >> 9);
int num_frames = bio->bi_size / CD_FRAMESIZE;
pd->stats.secs_w += num_frames * (CD_FRAMESIZE >> 9);
Expand Down Expand Up @@ -1363,7 +1321,7 @@ static int pkt_handle_queue(struct pktcdvd_device *pd)
break;
pkt_rbtree_erase(pd, node);
spin_lock(&pkt->lock);
pkt_add_list_last(bio, &pkt->orig_bios, &pkt->orig_bios_tail);
bio_list_add(&pkt->orig_bios, bio);
pkt->write_size += bio->bi_size / CD_FRAMESIZE;
spin_unlock(&pkt->lock);
}
Expand Down Expand Up @@ -1409,7 +1367,7 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
*/
frames_write = 0;
spin_lock(&pkt->lock);
for (bio = pkt->orig_bios; bio; bio = bio->bi_next) {
bio_list_for_each(bio, &pkt->orig_bios) {
int segment = bio->bi_idx;
int src_offs = 0;
int first_frame = (bio->bi_sector - pkt->sector) / (CD_FRAMESIZE >> 9);
Expand Down Expand Up @@ -1472,20 +1430,14 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)

static void pkt_finish_packet(struct packet_data *pkt, int uptodate)
{
struct bio *bio, *next;
struct bio *bio;

if (!uptodate)
pkt->cache_valid = 0;

/* Finish all bios corresponding to this packet */
bio = pkt->orig_bios;
while (bio) {
next = bio->bi_next;
bio->bi_next = NULL;
while ((bio = bio_list_pop(&pkt->orig_bios)))
bio_endio(bio, uptodate ? 0 : -EIO);
bio = next;
}
pkt->orig_bios = pkt->orig_bios_tail = NULL;
}

static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data *pkt)
Expand Down Expand Up @@ -2567,8 +2519,7 @@ static int pkt_make_request(struct request_queue *q, struct bio *bio)
spin_lock(&pkt->lock);
if ((pkt->state == PACKET_WAITING_STATE) ||
(pkt->state == PACKET_READ_WAIT_STATE)) {
pkt_add_list_last(bio, &pkt->orig_bios,
&pkt->orig_bios_tail);
bio_list_add(&pkt->orig_bios, bio);
pkt->write_size += bio->bi_size / CD_FRAMESIZE;
if ((pkt->write_size >= pkt->frames) &&
(pkt->state == PACKET_WAITING_STATE)) {
Expand Down Expand Up @@ -2898,6 +2849,8 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev)

spin_lock_init(&pd->lock);
spin_lock_init(&pd->iosched.lock);
bio_list_init(&pd->iosched.read_queue);
bio_list_init(&pd->iosched.write_queue);
sprintf(pd->name, DRIVER_NAME"%d", idx);
init_waitqueue_head(&pd->wqueue);
pd->bio_queue = RB_ROOT;
Expand Down
10 changes: 4 additions & 6 deletions include/linux/pktcdvd.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,8 @@ struct packet_iosched
atomic_t attention; /* Set to non-zero when queue processing is needed */
int writing; /* Non-zero when writing, zero when reading */
spinlock_t lock; /* Protecting read/write queue manipulations */
struct bio *read_queue;
struct bio *read_queue_tail;
struct bio *write_queue;
struct bio *write_queue_tail;
struct bio_list read_queue;
struct bio_list write_queue;
sector_t last_write; /* The sector where the last write ended */
int successive_reads;
};
Expand Down Expand Up @@ -206,8 +204,8 @@ struct packet_data
spinlock_t lock; /* Lock protecting state transitions and */
/* orig_bios list */

struct bio *orig_bios; /* Original bios passed to pkt_make_request */
struct bio *orig_bios_tail;/* that will be handled by this packet */
struct bio_list orig_bios; /* Original bios passed to pkt_make_request */
/* that will be handled by this packet */
int write_size; /* Total size of all bios in the orig_bios */
/* list, measured in number of frames */

Expand Down

0 comments on commit c5ecc48

Please sign in to comment.