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

Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block

* 'for-linus' of git://git.kernel.dk/linux-2.6-block:
  cfq-iosched: Allow RT requests to pre-empt ongoing BE timeslice
  block: add sysfs file for controlling io stats accounting
  Mark mandatory elevator functions in the biodoc.txt
  include/linux: Add bsg.h to the Kernel exported headers
  block: silently error an unsupported barrier bio
  block: Fix documentation for blkdev_issue_flush()
  block: add bio_rw_flagged() for testing bio->bi_rw
  block: seperate bio/request unplug and sync bits
  block: export SSD/non-rotational queue flag through sysfs
  Fix small typo in bio.h's documentation
  block: get rid of the manual directory counting in blktrace
  block: Allow empty integrity profile
  block: Remove obsolete BUG_ON
  block: Don't verify integrity metadata on read error
parents dbeb1701 3a9a3f6c
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -954,14 +954,14 @@ elevator_allow_merge_fn called whenever the block layer determines
				results in some sort of conflict internally,
				this hook allows it to do that.

elevator_dispatch_fn		fills the dispatch queue with ready requests.
elevator_dispatch_fn*		fills the dispatch queue with ready requests.
				I/O schedulers are free to postpone requests by
				not filling the dispatch queue unless @force
				is non-zero.  Once dispatched, I/O schedulers
				are not allowed to manipulate the requests -
				they belong to generic dispatch queue.

elevator_add_req_fn		called to add a new request into the scheduler
elevator_add_req_fn*		called to add a new request into the scheduler

elevator_queue_empty_fn		returns true if the merge queue is empty.
				Drivers shouldn't use this, but rather check
@@ -991,7 +991,7 @@ elevator_activate_req_fn Called when device driver first sees a request.
elevator_deactivate_req_fn	Called when device driver decides to delay
				a request by requeueing it.

elevator_init_fn
elevator_init_fn*
elevator_exit_fn		Allocate and free any elevator specific storage
				for a queue.

+1 −1
Original line number Diff line number Diff line
@@ -302,7 +302,7 @@ static void bio_end_empty_barrier(struct bio *bio, int err)
 * Description:
 *    Issue a flush for the block device in question. Caller can supply
 *    room for storing the error offset in case of a flush error, if they
 *    wish to.  Caller must run wait_for_completion() on its own.
 *    wish to.
 */
int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector)
{
+63 −37
Original line number Diff line number Diff line
@@ -64,11 +64,12 @@ static struct workqueue_struct *kblockd_workqueue;

static void drive_stat_acct(struct request *rq, int new_io)
{
	struct gendisk *disk = rq->rq_disk;
	struct hd_struct *part;
	int rw = rq_data_dir(rq);
	int cpu;

	if (!blk_fs_request(rq) || !rq->rq_disk)
	if (!blk_fs_request(rq) || !disk || !blk_queue_io_stat(disk->queue))
		return;

	cpu = part_stat_lock();
@@ -599,8 +600,7 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
	q->request_fn		= rfn;
	q->prep_rq_fn		= NULL;
	q->unplug_fn		= generic_unplug_device;
	q->queue_flags		= (1 << QUEUE_FLAG_CLUSTER |
				   1 << QUEUE_FLAG_STACKABLE);
	q->queue_flags		= QUEUE_FLAG_DEFAULT;
	q->queue_lock		= lock;

	blk_queue_segment_boundary(q, BLK_SEG_BOUNDARY_MASK);
@@ -1125,6 +1125,8 @@ void init_request_from_bio(struct request *req, struct bio *bio)

	if (bio_sync(bio))
		req->cmd_flags |= REQ_RW_SYNC;
	if (bio_unplug(bio))
		req->cmd_flags |= REQ_UNPLUG;
	if (bio_rw_meta(bio))
		req->cmd_flags |= REQ_RW_META;

@@ -1141,6 +1143,7 @@ static int __make_request(struct request_queue *q, struct bio *bio)
	int el_ret, nr_sectors;
	const unsigned short prio = bio_prio(bio);
	const int sync = bio_sync(bio);
	const int unplug = bio_unplug(bio);
	int rw_flags;

	nr_sectors = bio_sectors(bio);
@@ -1244,7 +1247,7 @@ get_rq:
		blk_plug_device(q);
	add_request(q, req);
out:
	if (sync || blk_queue_nonrot(q))
	if (unplug || blk_queue_nonrot(q))
		__generic_unplug_device(q);
	spin_unlock_irq(q->queue_lock);
	return 0;
@@ -1448,6 +1451,11 @@ static inline void __generic_make_request(struct bio *bio)
			err = -EOPNOTSUPP;
			goto end_io;
		}
		if (bio_barrier(bio) && bio_has_data(bio) &&
		    (q->next_ordered == QUEUE_ORDERED_NONE)) {
			err = -EOPNOTSUPP;
			goto end_io;
		}

		ret = q->make_request_fn(q, bio);
	} while (ret);
@@ -1655,6 +1663,55 @@ void blkdev_dequeue_request(struct request *req)
}
EXPORT_SYMBOL(blkdev_dequeue_request);

static void blk_account_io_completion(struct request *req, unsigned int bytes)
{
	struct gendisk *disk = req->rq_disk;

	if (!disk || !blk_queue_io_stat(disk->queue))
		return;

	if (blk_fs_request(req)) {
		const int rw = rq_data_dir(req);
		struct hd_struct *part;
		int cpu;

		cpu = part_stat_lock();
		part = disk_map_sector_rcu(req->rq_disk, req->sector);
		part_stat_add(cpu, part, sectors[rw], bytes >> 9);
		part_stat_unlock();
	}
}

static void blk_account_io_done(struct request *req)
{
	struct gendisk *disk = req->rq_disk;

	if (!disk || !blk_queue_io_stat(disk->queue))
		return;

	/*
	 * Account IO completion.  bar_rq isn't accounted as a normal
	 * IO on queueing nor completion.  Accounting the containing
	 * request is enough.
	 */
	if (blk_fs_request(req) && req != &req->q->bar_rq) {
		unsigned long duration = jiffies - req->start_time;
		const int rw = rq_data_dir(req);
		struct hd_struct *part;
		int cpu;

		cpu = part_stat_lock();
		part = disk_map_sector_rcu(disk, req->sector);

		part_stat_inc(cpu, part, ios[rw]);
		part_stat_add(cpu, part, ticks[rw], duration);
		part_round_stats(cpu, part);
		part_dec_in_flight(part);

		part_stat_unlock();
	}
}

/**
 * __end_that_request_first - end I/O on a request
 * @req:      the request being processed
@@ -1690,16 +1747,7 @@ static int __end_that_request_first(struct request *req, int error,
				(unsigned long long)req->sector);
	}

	if (blk_fs_request(req) && req->rq_disk) {
		const int rw = rq_data_dir(req);
		struct hd_struct *part;
		int cpu;

		cpu = part_stat_lock();
		part = disk_map_sector_rcu(req->rq_disk, req->sector);
		part_stat_add(cpu, part, sectors[rw], nr_bytes >> 9);
		part_stat_unlock();
	}
	blk_account_io_completion(req, nr_bytes);

	total_bytes = bio_nbytes = 0;
	while ((bio = req->bio) != NULL) {
@@ -1779,8 +1827,6 @@ static int __end_that_request_first(struct request *req, int error,
 */
static void end_that_request_last(struct request *req, int error)
{
	struct gendisk *disk = req->rq_disk;

	if (blk_rq_tagged(req))
		blk_queue_end_tag(req->q, req);

@@ -1792,27 +1838,7 @@ static void end_that_request_last(struct request *req, int error)

	blk_delete_timer(req);

	/*
	 * Account IO completion.  bar_rq isn't accounted as a normal
	 * IO on queueing nor completion.  Accounting the containing
	 * request is enough.
	 */
	if (disk && blk_fs_request(req) && req != &req->q->bar_rq) {
		unsigned long duration = jiffies - req->start_time;
		const int rw = rq_data_dir(req);
		struct hd_struct *part;
		int cpu;

		cpu = part_stat_lock();
		part = disk_map_sector_rcu(disk, req->sector);

		part_stat_inc(cpu, part, ios[rw]);
		part_stat_add(cpu, part, ticks[rw], duration);
		part_round_stats(cpu, part);
		part_dec_in_flight(part);

		part_stat_unlock();
	}
	blk_account_io_done(req);

	if (req->end_io)
		req->end_io(req, error);
+14 −11
Original line number Diff line number Diff line
@@ -309,20 +309,20 @@ static struct kobj_type integrity_ktype = {
/**
 * blk_integrity_register - Register a gendisk as being integrity-capable
 * @disk:	struct gendisk pointer to make integrity-aware
 * @template:	integrity profile
 * @template:	optional integrity profile to register
 *
 * Description: When a device needs to advertise itself as being able
 * to send/receive integrity metadata it must use this function to
 * register the capability with the block layer.  The template is a
 * blk_integrity struct with values appropriate for the underlying
 * hardware.  See Documentation/block/data-integrity.txt.
 * hardware.  If template is NULL the new profile is allocated but
 * not filled out. See Documentation/block/data-integrity.txt.
 */
int blk_integrity_register(struct gendisk *disk, struct blk_integrity *template)
{
	struct blk_integrity *bi;

	BUG_ON(disk == NULL);
	BUG_ON(template == NULL);

	if (disk->integrity == NULL) {
		bi = kmem_cache_alloc(integrity_cachep,
@@ -346,6 +346,7 @@ int blk_integrity_register(struct gendisk *disk, struct blk_integrity *template)
		bi = disk->integrity;

	/* Use the provided profile as template */
	if (template != NULL) {
		bi->name = template->name;
		bi->generate_fn = template->generate_fn;
		bi->verify_fn = template->verify_fn;
@@ -353,6 +354,8 @@ int blk_integrity_register(struct gendisk *disk, struct blk_integrity *template)
		bi->set_tag_fn = template->set_tag_fn;
		bi->get_tag_fn = template->get_tag_fn;
		bi->tag_size = template->tag_size;
	} else
		bi->name = "unsupported";

	return 0;
}
+57 −1
Original line number Diff line number Diff line
@@ -130,6 +130,27 @@ static ssize_t queue_max_hw_sectors_show(struct request_queue *q, char *page)
	return queue_var_show(max_hw_sectors_kb, (page));
}

static ssize_t queue_nonrot_show(struct request_queue *q, char *page)
{
	return queue_var_show(!blk_queue_nonrot(q), page);
}

static ssize_t queue_nonrot_store(struct request_queue *q, const char *page,
				  size_t count)
{
	unsigned long nm;
	ssize_t ret = queue_var_store(&nm, page, count);

	spin_lock_irq(q->queue_lock);
	if (nm)
		queue_flag_clear(QUEUE_FLAG_NONROT, q);
	else
		queue_flag_set(QUEUE_FLAG_NONROT, q);
	spin_unlock_irq(q->queue_lock);

	return ret;
}

static ssize_t queue_nomerges_show(struct request_queue *q, char *page)
{
	return queue_var_show(blk_queue_nomerges(q), page);
@@ -146,8 +167,8 @@ static ssize_t queue_nomerges_store(struct request_queue *q, const char *page,
		queue_flag_set(QUEUE_FLAG_NOMERGES, q);
	else
		queue_flag_clear(QUEUE_FLAG_NOMERGES, q);

	spin_unlock_irq(q->queue_lock);

	return ret;
}

@@ -176,6 +197,27 @@ queue_rq_affinity_store(struct request_queue *q, const char *page, size_t count)
	return ret;
}

static ssize_t queue_iostats_show(struct request_queue *q, char *page)
{
	return queue_var_show(blk_queue_io_stat(q), page);
}

static ssize_t queue_iostats_store(struct request_queue *q, const char *page,
				   size_t count)
{
	unsigned long stats;
	ssize_t ret = queue_var_store(&stats, page, count);

	spin_lock_irq(q->queue_lock);
	if (stats)
		queue_flag_set(QUEUE_FLAG_IO_STAT, q);
	else
		queue_flag_clear(QUEUE_FLAG_IO_STAT, q);
	spin_unlock_irq(q->queue_lock);

	return ret;
}

static struct queue_sysfs_entry queue_requests_entry = {
	.attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
	.show = queue_requests_show,
@@ -210,6 +252,12 @@ static struct queue_sysfs_entry queue_hw_sector_size_entry = {
	.show = queue_hw_sector_size_show,
};

static struct queue_sysfs_entry queue_nonrot_entry = {
	.attr = {.name = "rotational", .mode = S_IRUGO | S_IWUSR },
	.show = queue_nonrot_show,
	.store = queue_nonrot_store,
};

static struct queue_sysfs_entry queue_nomerges_entry = {
	.attr = {.name = "nomerges", .mode = S_IRUGO | S_IWUSR },
	.show = queue_nomerges_show,
@@ -222,6 +270,12 @@ static struct queue_sysfs_entry queue_rq_affinity_entry = {
	.store = queue_rq_affinity_store,
};

static struct queue_sysfs_entry queue_iostats_entry = {
	.attr = {.name = "iostats", .mode = S_IRUGO | S_IWUSR },
	.show = queue_iostats_show,
	.store = queue_iostats_store,
};

static struct attribute *default_attrs[] = {
	&queue_requests_entry.attr,
	&queue_ra_entry.attr,
@@ -229,8 +283,10 @@ static struct attribute *default_attrs[] = {
	&queue_max_sectors_entry.attr,
	&queue_iosched_entry.attr,
	&queue_hw_sector_size_entry.attr,
	&queue_nonrot_entry.attr,
	&queue_nomerges_entry.attr,
	&queue_rq_affinity_entry.attr,
	&queue_iostats_entry.attr,
	NULL,
};

Loading