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

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 Original line 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,
				results in some sort of conflict internally,
				this hook allows it to do that.
				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
				I/O schedulers are free to postpone requests by
				not filling the dispatch queue unless @force
				not filling the dispatch queue unless @force
				is non-zero.  Once dispatched, I/O schedulers
				is non-zero.  Once dispatched, I/O schedulers
				are not allowed to manipulate the requests -
				are not allowed to manipulate the requests -
				they belong to generic dispatch queue.
				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.
elevator_queue_empty_fn		returns true if the merge queue is empty.
				Drivers shouldn't use this, but rather check
				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
elevator_deactivate_req_fn	Called when device driver decides to delay
				a request by requeueing it.
				a request by requeueing it.


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


+1 −1
Original line number Original line Diff line number Diff line
@@ -302,7 +302,7 @@ static void bio_end_empty_barrier(struct bio *bio, int err)
 * Description:
 * Description:
 *    Issue a flush for the block device in question. Caller can supply
 *    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
 *    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)
int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector)
{
{
+63 −37
Original line number Original line 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)
static void drive_stat_acct(struct request *rq, int new_io)
{
{
	struct gendisk *disk = rq->rq_disk;
	struct hd_struct *part;
	struct hd_struct *part;
	int rw = rq_data_dir(rq);
	int rw = rq_data_dir(rq);
	int cpu;
	int cpu;


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


	cpu = part_stat_lock();
	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->request_fn		= rfn;
	q->prep_rq_fn		= NULL;
	q->prep_rq_fn		= NULL;
	q->unplug_fn		= generic_unplug_device;
	q->unplug_fn		= generic_unplug_device;
	q->queue_flags		= (1 << QUEUE_FLAG_CLUSTER |
	q->queue_flags		= QUEUE_FLAG_DEFAULT;
				   1 << QUEUE_FLAG_STACKABLE);
	q->queue_lock		= lock;
	q->queue_lock		= lock;


	blk_queue_segment_boundary(q, BLK_SEG_BOUNDARY_MASK);
	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))
	if (bio_sync(bio))
		req->cmd_flags |= REQ_RW_SYNC;
		req->cmd_flags |= REQ_RW_SYNC;
	if (bio_unplug(bio))
		req->cmd_flags |= REQ_UNPLUG;
	if (bio_rw_meta(bio))
	if (bio_rw_meta(bio))
		req->cmd_flags |= REQ_RW_META;
		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;
	int el_ret, nr_sectors;
	const unsigned short prio = bio_prio(bio);
	const unsigned short prio = bio_prio(bio);
	const int sync = bio_sync(bio);
	const int sync = bio_sync(bio);
	const int unplug = bio_unplug(bio);
	int rw_flags;
	int rw_flags;


	nr_sectors = bio_sectors(bio);
	nr_sectors = bio_sectors(bio);
@@ -1244,7 +1247,7 @@ static int __make_request(struct request_queue *q, struct bio *bio)
		blk_plug_device(q);
		blk_plug_device(q);
	add_request(q, req);
	add_request(q, req);
out:
out:
	if (sync || blk_queue_nonrot(q))
	if (unplug || blk_queue_nonrot(q))
		__generic_unplug_device(q);
		__generic_unplug_device(q);
	spin_unlock_irq(q->queue_lock);
	spin_unlock_irq(q->queue_lock);
	return 0;
	return 0;
@@ -1448,6 +1451,11 @@ static inline void __generic_make_request(struct bio *bio)
			err = -EOPNOTSUPP;
			err = -EOPNOTSUPP;
			goto end_io;
			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);
		ret = q->make_request_fn(q, bio);
	} while (ret);
	} while (ret);
@@ -1655,6 +1663,55 @@ void blkdev_dequeue_request(struct request *req)
}
}
EXPORT_SYMBOL(blkdev_dequeue_request);
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
 * __end_that_request_first - end I/O on a request
 * @req:      the request being processed
 * @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);
				(unsigned long long)req->sector);
	}
	}


	if (blk_fs_request(req) && req->rq_disk) {
	blk_account_io_completion(req, nr_bytes);
		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();
	}


	total_bytes = bio_nbytes = 0;
	total_bytes = bio_nbytes = 0;
	while ((bio = req->bio) != NULL) {
	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)
static void end_that_request_last(struct request *req, int error)
{
{
	struct gendisk *disk = req->rq_disk;

	if (blk_rq_tagged(req))
	if (blk_rq_tagged(req))
		blk_queue_end_tag(req->q, 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);
	blk_delete_timer(req);


	/*
	blk_account_io_done(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();
	}


	if (req->end_io)
	if (req->end_io)
		req->end_io(req, error);
		req->end_io(req, error);
+14 −11
Original line number Original line 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
 * blk_integrity_register - Register a gendisk as being integrity-capable
 * @disk:	struct gendisk pointer to make integrity-aware
 * @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
 * Description: When a device needs to advertise itself as being able
 * to send/receive integrity metadata it must use this function to
 * to send/receive integrity metadata it must use this function to
 * register the capability with the block layer.  The template is a
 * register the capability with the block layer.  The template is a
 * blk_integrity struct with values appropriate for the underlying
 * 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)
int blk_integrity_register(struct gendisk *disk, struct blk_integrity *template)
{
{
	struct blk_integrity *bi;
	struct blk_integrity *bi;


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


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


	/* Use the provided profile as template */
	/* Use the provided profile as template */
	if (template != NULL) {
		bi->name = template->name;
		bi->name = template->name;
		bi->generate_fn = template->generate_fn;
		bi->generate_fn = template->generate_fn;
		bi->verify_fn = template->verify_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->set_tag_fn = template->set_tag_fn;
		bi->get_tag_fn = template->get_tag_fn;
		bi->get_tag_fn = template->get_tag_fn;
		bi->tag_size = template->tag_size;
		bi->tag_size = template->tag_size;
	} else
		bi->name = "unsupported";


	return 0;
	return 0;
}
}
+57 −1
Original line number Original line 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));
	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)
static ssize_t queue_nomerges_show(struct request_queue *q, char *page)
{
{
	return queue_var_show(blk_queue_nomerges(q), 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);
		queue_flag_set(QUEUE_FLAG_NOMERGES, q);
	else
	else
		queue_flag_clear(QUEUE_FLAG_NOMERGES, q);
		queue_flag_clear(QUEUE_FLAG_NOMERGES, q);

	spin_unlock_irq(q->queue_lock);
	spin_unlock_irq(q->queue_lock);

	return ret;
	return ret;
}
}


@@ -176,6 +197,27 @@ queue_rq_affinity_store(struct request_queue *q, const char *page, size_t count)
	return ret;
	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 = {
static struct queue_sysfs_entry queue_requests_entry = {
	.attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
	.attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
	.show = queue_requests_show,
	.show = queue_requests_show,
@@ -210,6 +252,12 @@ static struct queue_sysfs_entry queue_hw_sector_size_entry = {
	.show = queue_hw_sector_size_show,
	.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 = {
static struct queue_sysfs_entry queue_nomerges_entry = {
	.attr = {.name = "nomerges", .mode = S_IRUGO | S_IWUSR },
	.attr = {.name = "nomerges", .mode = S_IRUGO | S_IWUSR },
	.show = queue_nomerges_show,
	.show = queue_nomerges_show,
@@ -222,6 +270,12 @@ static struct queue_sysfs_entry queue_rq_affinity_entry = {
	.store = queue_rq_affinity_store,
	.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[] = {
static struct attribute *default_attrs[] = {
	&queue_requests_entry.attr,
	&queue_requests_entry.attr,
	&queue_ra_entry.attr,
	&queue_ra_entry.attr,
@@ -229,8 +283,10 @@ static struct attribute *default_attrs[] = {
	&queue_max_sectors_entry.attr,
	&queue_max_sectors_entry.attr,
	&queue_iosched_entry.attr,
	&queue_iosched_entry.attr,
	&queue_hw_sector_size_entry.attr,
	&queue_hw_sector_size_entry.attr,
	&queue_nonrot_entry.attr,
	&queue_nomerges_entry.attr,
	&queue_nomerges_entry.attr,
	&queue_rq_affinity_entry.attr,
	&queue_rq_affinity_entry.attr,
	&queue_iostats_entry.attr,
	NULL,
	NULL,
};
};


Loading