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

Commit f0f00520 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'blk-end-request' of git://git.kernel.dk/linux-2.6-block

* 'blk-end-request' of git://git.kernel.dk/linux-2.6-block: (30 commits)
  blk_end_request: changing xsysace (take 4)
  blk_end_request: changing ub (take 4)
  blk_end_request: cleanup of request completion (take 4)
  blk_end_request: cleanup 'uptodate' related code (take 4)
  blk_end_request: remove/unexport end_that_request_* (take 4)
  blk_end_request: changing scsi (take 4)
  blk_end_request: add bidi completion interface (take 4)
  blk_end_request: changing ide-cd (take 4)
  blk_end_request: add callback feature (take 4)
  blk_end_request: changing ide normal caller (take 4)
  blk_end_request: changing cpqarray (take 4)
  blk_end_request: changing cciss (take 4)
  blk_end_request: changing ide-scsi (take 4)
  blk_end_request: changing s390 (take 4)
  blk_end_request: changing mmc (take 4)
  blk_end_request: changing i2o_block (take 4)
  blk_end_request: changing viocd (take 4)
  blk_end_request: changing xen-blkfront (take 4)
  blk_end_request: changing viodasd (take 4)
  blk_end_request: changing sx8 (take 4)
  ...
parents 68fbda7d a65b5866
Loading
Loading
Loading
Loading
+6 −10
Original line number Diff line number Diff line
@@ -116,8 +116,8 @@ static void mbox_tx_work(struct work_struct *work)
		}

		spin_lock(q->queue_lock);
		blkdev_dequeue_request(rq);
		end_that_request_last(rq, 0);
		if (__blk_end_request(rq, 0, 0))
			BUG();
		spin_unlock(q->queue_lock);
	}
}
@@ -149,10 +149,8 @@ static void mbox_rx_work(struct work_struct *work)

		msg = (mbox_msg_t) rq->data;

		spin_lock_irqsave(q->queue_lock, flags);
		blkdev_dequeue_request(rq);
		end_that_request_last(rq, 0);
		spin_unlock_irqrestore(q->queue_lock, flags);
		if (blk_end_request(rq, 0, 0))
			BUG();

		mbox->rxq->callback((void *)msg);
	}
@@ -263,10 +261,8 @@ omap_mbox_read(struct device *dev, struct device_attribute *attr, char *buf)

		*p = (mbox_msg_t) rq->data;

		spin_lock_irqsave(q->queue_lock, flags);
		blkdev_dequeue_request(rq);
		end_that_request_last(rq, 0);
		spin_unlock_irqrestore(q->queue_lock, flags);
		if (blk_end_request(rq, 0, 0))
			BUG();

		if (unlikely(mbox_seq_test(mbox, *p))) {
			pr_info("mbox: Illegal seq bit!(%08x) ignored\n", *p);
+4 −12
Original line number Diff line number Diff line
@@ -475,17 +475,9 @@ static void do_ubd_request(struct request_queue * q);
/* Only changed by ubd_init, which is an initcall. */
int thread_fd = -1;

static void ubd_end_request(struct request *req, int bytes, int uptodate)
static void ubd_end_request(struct request *req, int bytes, int error)
{
	if (!end_that_request_first(req, uptodate, bytes >> 9)) {
		struct ubd *dev = req->rq_disk->private_data;
		unsigned long flags;

		add_disk_randomness(req->rq_disk);
		spin_lock_irqsave(&dev->lock, flags);
		end_that_request_last(req, uptodate);
		spin_unlock_irqrestore(&dev->lock, flags);
	}
	blk_end_request(req, error, bytes);
}

/* Callable only from interrupt context - otherwise you need to do
@@ -493,10 +485,10 @@ static void ubd_end_request(struct request *req, int bytes, int uptodate)
static inline void ubd_finish(struct request *req, int bytes)
{
	if(bytes < 0){
		ubd_end_request(req, 0, 0);
		ubd_end_request(req, 0, -EIO);
		return;
	}
	ubd_end_request(req, bytes, 1);
	ubd_end_request(req, bytes, 0);
}

static LIST_HEAD(restart);
+213 −85
Original line number Diff line number Diff line
@@ -347,7 +347,6 @@ unsigned blk_ordered_req_seq(struct request *rq)
void blk_ordered_complete_seq(struct request_queue *q, unsigned seq, int error)
{
	struct request *rq;
	int uptodate;

	if (error && !q->orderr)
		q->orderr = error;
@@ -361,15 +360,11 @@ void blk_ordered_complete_seq(struct request_queue *q, unsigned seq, int error)
	/*
	 * Okay, sequence complete.
	 */
	uptodate = 1;
	if (q->orderr)
		uptodate = q->orderr;

	q->ordseq = 0;
	rq = q->orig_bar_rq;

	end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
	end_that_request_last(rq, uptodate);
	if (__blk_end_request(rq, q->orderr, blk_rq_bytes(rq)))
		BUG();
}

static void pre_flush_end_io(struct request *rq, int error)
@@ -486,9 +481,9 @@ int blk_do_ordered(struct request_queue *q, struct request **rqp)
			 * ORDERED_NONE while this request is on it.
			 */
			blkdev_dequeue_request(rq);
			end_that_request_first(rq, -EOPNOTSUPP,
					       rq->hard_nr_sectors);
			end_that_request_last(rq, -EOPNOTSUPP);
			if (__blk_end_request(rq, -EOPNOTSUPP,
					      blk_rq_bytes(rq)))
				BUG();
			*rqp = NULL;
			return 0;
		}
@@ -3437,21 +3432,28 @@ static void blk_recalc_rq_sectors(struct request *rq, int nsect)
	}
}

static int __end_that_request_first(struct request *req, int uptodate,
/**
 * __end_that_request_first - end I/O on a request
 * @req:      the request being processed
 * @error:    0 for success, < 0 for error
 * @nr_bytes: number of bytes to complete
 *
 * Description:
 *     Ends I/O on a number of bytes attached to @req, and sets it up
 *     for the next range of segments (if any) in the cluster.
 *
 * Return:
 *     0 - we are done with this request, call end_that_request_last()
 *     1 - still buffers pending for this request
 **/
static int __end_that_request_first(struct request *req, int error,
				    int nr_bytes)
{
	int total_bytes, bio_nbytes, error, next_idx = 0;
	int total_bytes, bio_nbytes, next_idx = 0;
	struct bio *bio;

	blk_add_trace_rq(req->q, req, BLK_TA_COMPLETE);

	/*
	 * extend uptodate bool to allow < 0 value to be direct io error
	 */
	error = 0;
	if (end_io_error(uptodate))
		error = !uptodate ? -EIO : uptodate;

	/*
	 * for a REQ_BLOCK_PC request, we want to carry any eventual
	 * sense key with us all the way through
@@ -3459,7 +3461,7 @@ static int __end_that_request_first(struct request *req, int uptodate,
	if (!blk_pc_request(req))
		req->errors = 0;

	if (!uptodate) {
	if (error) {
		if (blk_fs_request(req) && !(req->cmd_flags & REQ_QUIET))
			printk("end_request: I/O error, dev %s, sector %llu\n",
				req->rq_disk ? req->rq_disk->disk_name : "?",
@@ -3553,49 +3555,6 @@ static int __end_that_request_first(struct request *req, int uptodate,
	return 1;
}

/**
 * end_that_request_first - end I/O on a request
 * @req:      the request being processed
 * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error
 * @nr_sectors: number of sectors to end I/O on
 *
 * Description:
 *     Ends I/O on a number of sectors attached to @req, and sets it up
 *     for the next range of segments (if any) in the cluster.
 *
 * Return:
 *     0 - we are done with this request, call end_that_request_last()
 *     1 - still buffers pending for this request
 **/
int end_that_request_first(struct request *req, int uptodate, int nr_sectors)
{
	return __end_that_request_first(req, uptodate, nr_sectors << 9);
}

EXPORT_SYMBOL(end_that_request_first);

/**
 * end_that_request_chunk - end I/O on a request
 * @req:      the request being processed
 * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error
 * @nr_bytes: number of bytes to complete
 *
 * Description:
 *     Ends I/O on a number of bytes attached to @req, and sets it up
 *     for the next range of segments (if any). Like end_that_request_first(),
 *     but deals with bytes instead of sectors.
 *
 * Return:
 *     0 - we are done with this request, call end_that_request_last()
 *     1 - still buffers pending for this request
 **/
int end_that_request_chunk(struct request *req, int uptodate, int nr_bytes)
{
	return __end_that_request_first(req, uptodate, nr_bytes);
}

EXPORT_SYMBOL(end_that_request_chunk);

/*
 * splice the completion data to a local structure and hand off to
 * process_completion_queue() to complete the requests
@@ -3675,17 +3634,15 @@ EXPORT_SYMBOL(blk_complete_request);
/*
 * queue lock must be held
 */
void end_that_request_last(struct request *req, int uptodate)
static void end_that_request_last(struct request *req, int error)
{
	struct gendisk *disk = req->rq_disk;
	int error;

	/*
	 * extend uptodate bool to allow < 0 value to be direct io error
	 */
	error = 0;
	if (end_io_error(uptodate))
		error = !uptodate ? -EIO : uptodate;
	if (blk_rq_tagged(req))
		blk_queue_end_tag(req->q, req);

	if (blk_queued_rq(req))
		blkdev_dequeue_request(req);

	if (unlikely(laptop_mode) && blk_fs_request(req))
		laptop_io_completion();
@@ -3704,32 +3661,54 @@ void end_that_request_last(struct request *req, int uptodate)
		disk_round_stats(disk);
		disk->in_flight--;
	}

	if (req->end_io)
		req->end_io(req, error);
	else
	else {
		if (blk_bidi_rq(req))
			__blk_put_request(req->next_rq->q, req->next_rq);

		__blk_put_request(req->q, req);
	}

EXPORT_SYMBOL(end_that_request_last);
}

static inline void __end_request(struct request *rq, int uptodate,
				 unsigned int nr_bytes, int dequeue)
				 unsigned int nr_bytes)
{
	if (!end_that_request_chunk(rq, uptodate, nr_bytes)) {
		if (dequeue)
			blkdev_dequeue_request(rq);
		add_disk_randomness(rq->rq_disk);
		end_that_request_last(rq, uptodate);
	}
	int error = 0;

	if (uptodate <= 0)
		error = uptodate ? uptodate : -EIO;

	__blk_end_request(rq, error, nr_bytes);
}

static unsigned int rq_byte_size(struct request *rq)
/**
 * blk_rq_bytes - Returns bytes left to complete in the entire request
 **/
unsigned int blk_rq_bytes(struct request *rq)
{
	if (blk_fs_request(rq))
		return rq->hard_nr_sectors << 9;

	return rq->data_len;
}
EXPORT_SYMBOL_GPL(blk_rq_bytes);

/**
 * blk_rq_cur_bytes - Returns bytes left to complete in the current segment
 **/
unsigned int blk_rq_cur_bytes(struct request *rq)
{
	if (blk_fs_request(rq))
		return rq->current_nr_sectors << 9;

	if (rq->bio)
		return rq->bio->bi_size;

	return rq->data_len;
}
EXPORT_SYMBOL_GPL(blk_rq_cur_bytes);

/**
 * end_queued_request - end all I/O on a queued request
@@ -3744,7 +3723,7 @@ static unsigned int rq_byte_size(struct request *rq)
 **/
void end_queued_request(struct request *rq, int uptodate)
{
	__end_request(rq, uptodate, rq_byte_size(rq), 1);
	__end_request(rq, uptodate, blk_rq_bytes(rq));
}
EXPORT_SYMBOL(end_queued_request);

@@ -3761,7 +3740,7 @@ EXPORT_SYMBOL(end_queued_request);
 **/
void end_dequeued_request(struct request *rq, int uptodate)
{
	__end_request(rq, uptodate, rq_byte_size(rq), 0);
	__end_request(rq, uptodate, blk_rq_bytes(rq));
}
EXPORT_SYMBOL(end_dequeued_request);

@@ -3787,10 +3766,159 @@ EXPORT_SYMBOL(end_dequeued_request);
 **/
void end_request(struct request *req, int uptodate)
{
	__end_request(req, uptodate, req->hard_cur_sectors << 9, 1);
	__end_request(req, uptodate, req->hard_cur_sectors << 9);
}
EXPORT_SYMBOL(end_request);

/**
 * blk_end_io - Generic end_io function to complete a request.
 * @rq:           the request being processed
 * @error:        0 for success, < 0 for error
 * @nr_bytes:     number of bytes to complete @rq
 * @bidi_bytes:   number of bytes to complete @rq->next_rq
 * @drv_callback: function called between completion of bios in the request
 *                and completion of the request.
 *                If the callback returns non 0, this helper returns without
 *                completion of the request.
 *
 * Description:
 *     Ends I/O on a number of bytes attached to @rq and @rq->next_rq.
 *     If @rq has leftover, sets it up for the next range of segments.
 *
 * Return:
 *     0 - we are done with this request
 *     1 - this request is not freed yet, it still has pending buffers.
 **/
static int blk_end_io(struct request *rq, int error, int nr_bytes,
		      int bidi_bytes, int (drv_callback)(struct request *))
{
	struct request_queue *q = rq->q;
	unsigned long flags = 0UL;

	if (blk_fs_request(rq) || blk_pc_request(rq)) {
		if (__end_that_request_first(rq, error, nr_bytes))
			return 1;

		/* Bidi request must be completed as a whole */
		if (blk_bidi_rq(rq) &&
		    __end_that_request_first(rq->next_rq, error, bidi_bytes))
			return 1;
	}

	/* Special feature for tricky drivers */
	if (drv_callback && drv_callback(rq))
		return 1;

	add_disk_randomness(rq->rq_disk);

	spin_lock_irqsave(q->queue_lock, flags);
	end_that_request_last(rq, error);
	spin_unlock_irqrestore(q->queue_lock, flags);

	return 0;
}

/**
 * blk_end_request - Helper function for drivers to complete the request.
 * @rq:       the request being processed
 * @error:    0 for success, < 0 for error
 * @nr_bytes: number of bytes to complete
 *
 * Description:
 *     Ends I/O on a number of bytes attached to @rq.
 *     If @rq has leftover, sets it up for the next range of segments.
 *
 * Return:
 *     0 - we are done with this request
 *     1 - still buffers pending for this request
 **/
int blk_end_request(struct request *rq, int error, int nr_bytes)
{
	return blk_end_io(rq, error, nr_bytes, 0, NULL);
}
EXPORT_SYMBOL_GPL(blk_end_request);

/**
 * __blk_end_request - Helper function for drivers to complete the request.
 * @rq:       the request being processed
 * @error:    0 for success, < 0 for error
 * @nr_bytes: number of bytes to complete
 *
 * Description:
 *     Must be called with queue lock held unlike blk_end_request().
 *
 * Return:
 *     0 - we are done with this request
 *     1 - still buffers pending for this request
 **/
int __blk_end_request(struct request *rq, int error, int nr_bytes)
{
	if (blk_fs_request(rq) || blk_pc_request(rq)) {
		if (__end_that_request_first(rq, error, nr_bytes))
			return 1;
	}

	add_disk_randomness(rq->rq_disk);

	end_that_request_last(rq, error);

	return 0;
}
EXPORT_SYMBOL_GPL(__blk_end_request);

/**
 * blk_end_bidi_request - Helper function for drivers to complete bidi request.
 * @rq:         the bidi request being processed
 * @error:      0 for success, < 0 for error
 * @nr_bytes:   number of bytes to complete @rq
 * @bidi_bytes: number of bytes to complete @rq->next_rq
 *
 * Description:
 *     Ends I/O on a number of bytes attached to @rq and @rq->next_rq.
 *
 * Return:
 *     0 - we are done with this request
 *     1 - still buffers pending for this request
 **/
int blk_end_bidi_request(struct request *rq, int error, int nr_bytes,
			 int bidi_bytes)
{
	return blk_end_io(rq, error, nr_bytes, bidi_bytes, NULL);
}
EXPORT_SYMBOL_GPL(blk_end_bidi_request);

/**
 * blk_end_request_callback - Special helper function for tricky drivers
 * @rq:           the request being processed
 * @error:        0 for success, < 0 for error
 * @nr_bytes:     number of bytes to complete
 * @drv_callback: function called between completion of bios in the request
 *                and completion of the request.
 *                If the callback returns non 0, this helper returns without
 *                completion of the request.
 *
 * Description:
 *     Ends I/O on a number of bytes attached to @rq.
 *     If @rq has leftover, sets it up for the next range of segments.
 *
 *     This special helper function is used only for existing tricky drivers.
 *     (e.g. cdrom_newpc_intr() of ide-cd)
 *     This interface will be removed when such drivers are rewritten.
 *     Don't use this interface in other places anymore.
 *
 * Return:
 *     0 - we are done with this request
 *     1 - this request is not freed yet.
 *         this request still has pending buffers or
 *         the driver doesn't want to finish this request yet.
 **/
int blk_end_request_callback(struct request *rq, int error, int nr_bytes,
			     int (drv_callback)(struct request *))
{
	return blk_end_io(rq, error, nr_bytes, 0, drv_callback);
}
EXPORT_SYMBOL_GPL(blk_end_request_callback);

static void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
			    struct bio *bio)
{
+2 −9
Original line number Diff line number Diff line
@@ -3455,19 +3455,12 @@ static inline bool DAC960_ProcessCompletedRequest(DAC960_Command_T *Command,
						 bool SuccessfulIO)
{
	struct request *Request = Command->Request;
	int UpToDate;

	UpToDate = 0;
	if (SuccessfulIO)
		UpToDate = 1;
	int Error = SuccessfulIO ? 0 : -EIO;

	pci_unmap_sg(Command->Controller->PCIDevice, Command->cmd_sglist,
		Command->SegmentCount, Command->DmaDirection);

	 if (!end_that_request_first(Request, UpToDate, Command->BlockCount)) {
		add_disk_randomness(Request->rq_disk);
 	 	end_that_request_last(Request, UpToDate);

	 if (!__blk_end_request(Request, Error, Command->BlockCount << 9)) {
		if (Command->Completion) {
			complete(Command->Completion);
			Command->Completion = NULL;
+3 −22
Original line number Diff line number Diff line
@@ -1187,17 +1187,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
	}
}

static inline void complete_buffers(struct bio *bio, int status)
{
	while (bio) {
		struct bio *xbh = bio->bi_next;

		bio->bi_next = NULL;
		bio_endio(bio, status ? 0 : -EIO);
		bio = xbh;
	}
}

static void cciss_check_queues(ctlr_info_t *h)
{
	int start_queue = h->next_to_run;
@@ -1263,21 +1252,14 @@ static void cciss_softirq_done(struct request *rq)
		pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
	}

	complete_buffers(rq->bio, (rq->errors == 0));

	if (blk_fs_request(rq)) {
		const int rw = rq_data_dir(rq);

		disk_stat_add(rq->rq_disk, sectors[rw], rq->nr_sectors);
	}

#ifdef CCISS_DEBUG
	printk("Done with %p\n", rq);
#endif				/* CCISS_DEBUG */

	add_disk_randomness(rq->rq_disk);
	if (blk_end_request(rq, (rq->errors == 0) ? 0 : -EIO, blk_rq_bytes(rq)))
		BUG();

	spin_lock_irqsave(&h->lock, flags);
	end_that_request_last(rq, (rq->errors == 0));
	cmd_free(h, cmd, 1);
	cciss_check_queues(h);
	spin_unlock_irqrestore(&h->lock, flags);
@@ -2544,7 +2526,6 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
	}
	cmd->rq->data_len = 0;
	cmd->rq->completion_data = cmd;
	blk_add_trace_rq(cmd->rq->q, cmd->rq, BLK_TA_COMPLETE);
	blk_complete_request(cmd->rq);
}

Loading