Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eea9befa authored by NeilBrown's avatar NeilBrown Committed by Jens Axboe
Browse files

Fix various abuse of bio fields in umem.c



umem.c:
  advances bi_idx and bi_sector to track where it is up to.
   But it is only ever doing this on one bio, so the updated
   fields can easily be kept elsewhere (current_*).
  updates bi_size, but never uses the updated values, so
   this isn't needed.
  reuses bi_phys_segments to count how many iovecs have been
   completely.  As the completion happens sequentiually, we
   can store this information outside the bio too.

Signed-off-by: default avatarNeil Brown <neilb@suse.de>

diff .prev/drivers/block/umem.c ./drivers/block/umem.c
Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
parent 5705f702
Loading
Loading
Loading
Loading
+25 −13
Original line number Diff line number Diff line
@@ -113,6 +113,8 @@ struct cardinfo {
				    * have been written
				    */
	struct bio	*bio, *currentbio, **biotail;
	int		current_idx;
	sector_t	current_sector;

	struct request_queue *queue;

@@ -121,6 +123,7 @@ struct cardinfo {
		struct mm_dma_desc	*desc;
		int	 		cnt, headcnt;
		struct bio		*bio, **biotail;
		int			idx;
	} mm_pages[2];
#define DESC_PER_PAGE ((PAGE_SIZE*2)/sizeof(struct mm_dma_desc))

@@ -380,12 +383,16 @@ static int add_bio(struct cardinfo *card)
	dma_addr_t dma_handle;
	int offset;
	struct bio *bio;
	struct bio_vec *vec;
	int idx;
	int rw;
	int len;

	bio = card->currentbio;
	if (!bio && card->bio) {
		card->currentbio = card->bio;
		card->current_idx = card->bio->bi_idx;
		card->current_sector = card->bio->bi_sector;
		card->bio = card->bio->bi_next;
		if (card->bio == NULL)
			card->biotail = &card->bio;
@@ -394,15 +401,17 @@ static int add_bio(struct cardinfo *card)
	}
	if (!bio)
		return 0;
	idx = card->current_idx;

	rw = bio_rw(bio);
	if (card->mm_pages[card->Ready].cnt >= DESC_PER_PAGE)
		return 0;

	len = bio_iovec(bio)->bv_len;
	vec = bio_iovec_idx(bio, idx);
	len = vec->bv_len;
	dma_handle = pci_map_page(card->dev,
				  bio_page(bio),
				  bio_offset(bio),
				  vec->bv_page,
				  vec->bv_offset,
				  len,
				  (rw==READ) ?
				  PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
@@ -410,6 +419,8 @@ static int add_bio(struct cardinfo *card)
	p = &card->mm_pages[card->Ready];
	desc = &p->desc[p->cnt];
	p->cnt++;
	if (p->bio == NULL)
		p->idx = idx;
	if ((p->biotail) != &bio->bi_next) {
		*(p->biotail) = bio;
		p->biotail = &(bio->bi_next);
@@ -419,7 +430,7 @@ static int add_bio(struct cardinfo *card)
	desc->data_dma_handle = dma_handle;

	desc->pci_addr = cpu_to_le64((u64)desc->data_dma_handle);
	desc->local_addr= cpu_to_le64(bio->bi_sector << 9);
	desc->local_addr = cpu_to_le64(card->current_sector << 9);
	desc->transfer_size = cpu_to_le32(len);
	offset = ( ((char*)&desc->sem_control_bits) - ((char*)p->desc));
	desc->sem_addr = cpu_to_le64((u64)(p->page_dma+offset));
@@ -435,10 +446,10 @@ static int add_bio(struct cardinfo *card)
		desc->control_bits |= cpu_to_le32(DMASCR_TRANSFER_READ);
	desc->sem_control_bits = desc->control_bits;

	bio->bi_sector += (len>>9);
	bio->bi_size -= len;
	bio->bi_idx++;
	if (bio->bi_idx >= bio->bi_vcnt) 
	card->current_sector += (len >> 9);
	idx++;
	card->current_idx = idx;
	if (idx >= bio->bi_vcnt)
		card->currentbio = NULL;

	return 1;
@@ -474,10 +485,12 @@ static void process_page(unsigned long data)
			last=1; 
		}
		page->headcnt++;
		idx = bio->bi_phys_segments;
		bio->bi_phys_segments++;
		if (bio->bi_phys_segments >= bio->bi_vcnt)
		idx = page->idx;
		page->idx++;
		if (page->idx >= bio->bi_vcnt) {
			page->bio = bio->bi_next;
			page->idx = page->bio->bi_idx;
		}

		pci_unmap_page(card->dev, desc->data_dma_handle, 
			       bio_iovec_idx(bio,idx)->bv_len,
@@ -547,7 +560,6 @@ static int mm_make_request(struct request_queue *q, struct bio *bio)
	pr_debug("mm_make_request %llu %u\n",
		 (unsigned long long)bio->bi_sector, bio->bi_size);

	bio->bi_phys_segments = bio->bi_idx; /* count of completed segments*/
	spin_lock_irq(&card->lock);
	*card->biotail = bio;
	bio->bi_next = NULL;