Skip to contentSkip to conversation

mv sg.c features to the block layer

PATCH In review Mike Christie 1 participant 1 message Feb 9, 2007

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

PATCH 1/2 mv sg.c features to the block layer

This patch moves the reserve buffer, large segment allocations, and mmap to the block layer. This patches also converts bsg, tgt, cdrom, and scsi_ioctl.c to the change in the blk_rq_map_user api. A side affect of coverting tgt to the new api, is that I killed the scsi_cmnd->offset field which was supposed to be removed before merging but snuck in. It also kills the tgt bio layer violations.

The mmap code and reserve buffer code is very simple. It should behave and work like sg where we have one command using the reserve buffer at a time. If it does not and will affect users, let me know and I will fix. The bsg and scsi_ioctl code does not use the reserve buffer or mmap code, and that should behave like it did before, except for the copy path we allocated multiple pages at a time so we can get very large IOs.

The patches have been lightly tested. I ran sg utils over a block device. I did not test cdrom, tgt or bsg.

If you guys want me to try and break up the patches to make it easier to review I will. Then I can resend them in a git bisect friendly way.

block/bsg.c +3 -2
index e97e3ec..0bc819d 100644
@@ -321,7 +321,7 @@ bsg_map_hdr(struct bsg_device *bd, struc
 		dxfer_len = 0;
 
 	if (dxfer_len) {
-		ret = blk_rq_map_user(q, rq, dxferp, dxfer_len);
+		ret = blk_rq_init_transfer(q, rq, dxferp, dxfer_len);
 		if (ret) {
 			dprintk("failed map at %d\n", ret);
 			blk_put_request(rq);
@@ -460,7 +460,8 @@ static int blk_complete_sgv4_hdr_rq(stru
 			ret = -EFAULT;
 	}
 
-	blk_rq_unmap_user(bio);
+	blk_rq_complete_transfer(rq->q, bio, (void __user *)hdr->din_xferp,
+				 hdr->din_xfer_len);
 	blk_put_request(rq);
 
 	return ret;
block/ll_rw_blk.c +420 -89

595 lines not on this page · raw message

block/scsi_ioctl.c +2 -2
index 18e935f..33c54a0 100644
@@ -244,7 +244,7 @@ EXPORT_SYMBOL_GPL(blk_fill_sghdr_rq);
  */
 int blk_unmap_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr)
 {
-	blk_rq_unmap_user(rq->bio);
+	blk_rq_complete_transfer(rq->q, rq->bio, hdr->dxferp, hdr->dxfer_len);
 	blk_put_request(rq);
 	return 0;
 }
@@ -348,7 +348,7 @@ static int sg_io(struct file *file, requ
 					  hdr->dxfer_len);
 		kfree(iov);
 	} else if (hdr->dxfer_len)
-		ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len);
+		ret = blk_rq_init_transfer(q, rq, hdr->dxferp, hdr->dxfer_len);
 
 	if (ret)
 		goto out;
drivers/cdrom/cdrom.c +2 -2
index 3105ddd..0ea8374 100644
@@ -2118,7 +2118,7 @@ static int cdrom_read_cdda_bpc(struct cd
 
 		len = nr * CD_FRAMESIZE_RAW;
 
-		ret = blk_rq_map_user(q, rq, ubuf, len);
+		ret = blk_rq_init_transfer(q, rq, ubuf, len);
 		if (ret)
 			break;
 
@@ -2145,7 +2145,7 @@ static int cdrom_read_cdda_bpc(struct cd
 			cdi->last_sense = s->sense_key;
 		}
 
-		if (blk_rq_unmap_user(bio))
+		if (blk_rq_complete_transfer(q, bio, ubuf, len))
 			ret = -EFAULT;
 
 		if (ret)
drivers/scsi/scsi_tgt_lib.c +21 -84

170 lines not on this page · raw message

fs/bio.c +207 -65

367 lines not on this page · raw message

include/linux/bio.h +8 -4
index 08daf32..f3160a4 100644
@@ -125,6 +125,7 @@ #define BIO_CLONED	4	/* doesn't own data
 #define BIO_BOUNCED	5	/* bio is a bounce bio */
 #define BIO_USER_MAPPED 6	/* contains user pages */
 #define BIO_EOPNOTSUPP	7	/* not supported */
+#define BIO_USED_RESERVE 8	/* using reserve buffer */
 #define bio_flagged(bio, flag)	((bio)->bi_flags & (1 << (flag)))
 
 /*
@@ -298,8 +299,8 @@ extern int bio_add_page(struct bio *, st
 extern int bio_add_pc_page(struct request_queue *, struct bio *, struct page *,
 			   unsigned int, unsigned int);
 extern int bio_get_nr_vecs(struct block_device *);
-extern struct bio *bio_map_user(struct request_queue *, struct block_device *,
-				unsigned long, unsigned int, int);
+extern struct bio *bio_map_user(struct request_queue *, unsigned long,
+				unsigned int, int, int);
 struct sg_iovec;
 extern struct bio *bio_map_user_iov(struct request_queue *,
 				    struct block_device *,
@@ -310,8 +311,11 @@ extern struct bio *bio_map_kern(struct r
 extern void bio_set_pages_dirty(struct bio *bio);
 extern void bio_check_pages_dirty(struct bio *bio);
 extern void bio_release_pages(struct bio *bio);
-extern struct bio *bio_copy_user(struct request_queue *, unsigned long, unsigned int, int);
-extern int bio_uncopy_user(struct bio *);
+extern struct bio *bio_copy_user(struct request_queue *, unsigned long, unsigned int, int, int);
+extern int bio_uncopy_user(struct bio *, void __user *, unsigned long, int *);
+extern unsigned int bio_estimate_max_segment_size(struct request_queue *);
+extern struct page *bio_alloc_pages(struct request_queue *, unsigned int,
+				    int *);
 void zero_fill_bio(struct bio *bio);
 
 #ifdef CONFIG_HIGHMEM
include/linux/blkdev.h +26 -2
index 9c55749..0b76c1d 100644
@@ -359,6 +359,13 @@ struct blk_queue_tag {
 	atomic_t refcnt;		/* map can be shared */
 };
 
+struct blk_reserve_buf {
+	struct scatterlist *sg;		/* sg to hold pages */
+	unsigned buf_size;		/* size of reserve buffer */
+	int sg_count;			/* number of sg entries in use */
+	int sg_index;			/* index pf sg in list */
+};
+
 struct request_queue
 {
 	/*
@@ -454,6 +461,7 @@ struct request_queue
 	/*
 	 * sg stuff
 	 */
+	struct blk_reserve_buf *reserve_buf;
 	unsigned int		sg_timeout;
 	unsigned int		sg_reserved_size;
 	int			node;
@@ -481,6 +489,7 @@ #define QUEUE_FLAG_DEAD		5	/* queue bein
 #define QUEUE_FLAG_REENTER	6	/* Re-entrancy avoidance */
 #define QUEUE_FLAG_PLUGGED	7	/* queue is plugged */
 #define QUEUE_FLAG_ELVSWITCH	8	/* don't use elevator, just do FIFO */
+#define QUEUE_FLAG_RESERVE_USED 9	/* sg reserve buffer in use */
 
 enum {
 	/*
@@ -526,6 +535,7 @@ #define blk_queue_plugged(q)	test_bit(QU
 #define blk_queue_tagged(q)	test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags)
 #define blk_queue_stopped(q)	test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags)
 #define blk_queue_flushing(q)	((q)->ordseq)
+#define blk_queue_reserve_in_use(q) test_bit(QUEUE_FLAG_RESERVE_USED, &(q)->queue_flags)
 
 #define blk_fs_request(rq)	((rq)->cmd_type == REQ_TYPE_FS)
 #define blk_pc_request(rq)	((rq)->cmd_type == REQ_TYPE_BLOCK_PC)
@@ -678,8 +688,22 @@ extern void blk_sync_queue(struct reques
 extern void __blk_stop_queue(request_queue_t *q);
 extern void blk_run_queue(request_queue_t *);
 extern void blk_start_queueing(request_queue_t *);
-extern int blk_rq_map_user(request_queue_t *, struct request *, void __user *, unsigned long);
-extern int blk_rq_unmap_user(struct bio *);
+extern struct page *blk_rq_vma_nopage(struct request_queue *, struct request *,
+				      struct vm_area_struct *, unsigned long,
+				      int *);
+extern int blk_rq_mmap(struct request_queue *, struct request *,
+			struct vm_area_struct *);
+extern int blk_queue_free_reserve_buf(struct request_queue *);
+extern int blk_queue_alloc_reserve_buf(struct request_queue *, unsigned long);
+extern struct page *blk_get_reserve_seg(struct request_queue *, unsigned int *);
+extern void blk_put_reserve_seg(request_queue_t *);
+extern int blk_rq_init_transfer(request_queue_t *, struct request *, void __user *, unsigned long);
+extern int blk_rq_map_user(request_queue_t *, struct request *,
+			   void __user *, unsigned long, int);
+extern int blk_rq_copy_user(request_queue_t *, struct request *,
+			    void __user *, unsigned long, int);
+extern int blk_rq_complete_transfer(struct request_queue *, struct bio *,
+				    void __user *, unsigned long);
 extern int blk_rq_map_kern(request_queue_t *, struct request *, void *, unsigned int, gfp_t);
 extern int blk_rq_map_user_iov(request_queue_t *, struct request *,
 			       struct sg_iovec *, int, unsigned int);
include/scsi/scsi_cmnd.h +0 -3
index d6948d0..a2e0c10 100644
@@ -73,9 +73,6 @@ #define MAX_COMMAND_SIZE	16
 	unsigned short use_sg;	/* Number of pieces of scatter-gather */
 	unsigned short sglist_len;	/* size of malloc'd scatter-gather list */
 
-	/* offset in cmd we are at (for multi-transfer tgt cmds) */
-	unsigned offset;
-
 	unsigned underflow;	/* Return error if less than
 				   this amount is transferred */
 
Signature · 1 line
1.4.1.1