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

Commit 7f8635cc 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:
  cciss: fix cciss_revalidate panic
  block: max hardware sectors limit wrapper
  block: Deprecate QUEUE_FLAG_CLUSTER and use queue_limits instead
  blk-throttle: Correct the placement of smp_rmb()
  blk-throttle: Trim/adjust slice_end once a bio has been dispatched
  block: check for proper length of iov entries earlier in blk_rq_map_user_iov()
  drbd: fix for spin_lock_irqsave in endio callback
  drbd: don't recvmsg with zero length
parents 3cb50ddf 0fc13c89
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -201,12 +201,13 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
	for (i = 0; i < iov_count; i++) {
		unsigned long uaddr = (unsigned long)iov[i].iov_base;

		if (!iov[i].iov_len)
			return -EINVAL;

		if (uaddr & queue_dma_alignment(q)) {
			unaligned = 1;
			break;
		}
		if (!iov[i].iov_len)
			return -EINVAL;
	}

	if (unaligned || (q->dma_pad_mask & len) || map_data)
+3 −3
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
		return 0;

	fbio = bio;
	cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
	cluster = blk_queue_cluster(q);
	seg_size = 0;
	nr_phys_segs = 0;
	for_each_bio(bio) {
@@ -87,7 +87,7 @@ EXPORT_SYMBOL(blk_recount_segments);
static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
				   struct bio *nxt)
{
	if (!test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags))
	if (!blk_queue_cluster(q))
		return 0;

	if (bio->bi_seg_back_size + nxt->bi_seg_front_size >
@@ -123,7 +123,7 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
	int nsegs, cluster;

	nsegs = 0;
	cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
	cluster = blk_queue_cluster(q);

	/*
	 * for each bio in rq
+22 −29
Original line number Diff line number Diff line
@@ -126,7 +126,7 @@ void blk_set_default_limits(struct queue_limits *lim)
	lim->alignment_offset = 0;
	lim->io_opt = 0;
	lim->misaligned = 0;
	lim->no_cluster = 0;
	lim->cluster = 1;
}
EXPORT_SYMBOL(blk_set_default_limits);

@@ -229,8 +229,8 @@ void blk_queue_bounce_limit(struct request_queue *q, u64 dma_mask)
EXPORT_SYMBOL(blk_queue_bounce_limit);

/**
 * blk_queue_max_hw_sectors - set max sectors for a request for this queue
 * @q:  the request queue for the device
 * blk_limits_max_hw_sectors - set hard and soft limit of max sectors for request
 * @limits: the queue limits
 * @max_hw_sectors:  max hardware sectors in the usual 512b unit
 *
 * Description:
@@ -244,7 +244,7 @@ EXPORT_SYMBOL(blk_queue_bounce_limit);
 *    per-device basis in /sys/block/<device>/queue/max_sectors_kb.
 *    The soft limit can not exceed max_hw_sectors.
 **/
void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_sectors)
void blk_limits_max_hw_sectors(struct queue_limits *limits, unsigned int max_hw_sectors)
{
	if ((max_hw_sectors << 9) < PAGE_CACHE_SIZE) {
		max_hw_sectors = 1 << (PAGE_CACHE_SHIFT - 9);
@@ -252,10 +252,24 @@ void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_secto
		       __func__, max_hw_sectors);
	}

	q->limits.max_hw_sectors = max_hw_sectors;
	q->limits.max_sectors = min_t(unsigned int, max_hw_sectors,
	limits->max_hw_sectors = max_hw_sectors;
	limits->max_sectors = min_t(unsigned int, max_hw_sectors,
				    BLK_DEF_MAX_SECTORS);
}
EXPORT_SYMBOL(blk_limits_max_hw_sectors);

/**
 * blk_queue_max_hw_sectors - set max sectors for a request for this queue
 * @q:  the request queue for the device
 * @max_hw_sectors:  max hardware sectors in the usual 512b unit
 *
 * Description:
 *    See description for blk_limits_max_hw_sectors().
 **/
void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_sectors)
{
	blk_limits_max_hw_sectors(&q->limits, max_hw_sectors);
}
EXPORT_SYMBOL(blk_queue_max_hw_sectors);

/**
@@ -464,15 +478,6 @@ EXPORT_SYMBOL(blk_queue_io_opt);
void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b)
{
	blk_stack_limits(&t->limits, &b->limits, 0);

	if (!t->queue_lock)
		WARN_ON_ONCE(1);
	else if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) {
		unsigned long flags;
		spin_lock_irqsave(t->queue_lock, flags);
		queue_flag_clear(QUEUE_FLAG_CLUSTER, t);
		spin_unlock_irqrestore(t->queue_lock, flags);
	}
}
EXPORT_SYMBOL(blk_queue_stack_limits);

@@ -545,7 +550,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
	t->io_min = max(t->io_min, b->io_min);
	t->io_opt = lcm(t->io_opt, b->io_opt);

	t->no_cluster |= b->no_cluster;
	t->cluster &= b->cluster;
	t->discard_zeroes_data &= b->discard_zeroes_data;

	/* Physical block size a multiple of the logical block size? */
@@ -641,7 +646,6 @@ void disk_stack_limits(struct gendisk *disk, struct block_device *bdev,
		       sector_t offset)
{
	struct request_queue *t = disk->queue;
	struct request_queue *b = bdev_get_queue(bdev);

	if (bdev_stack_limits(&t->limits, bdev, offset >> 9) < 0) {
		char top[BDEVNAME_SIZE], bottom[BDEVNAME_SIZE];
@@ -652,17 +656,6 @@ void disk_stack_limits(struct gendisk *disk, struct block_device *bdev,
		printk(KERN_NOTICE "%s: Warning: Device %s is misaligned\n",
		       top, bottom);
	}

	if (!t->queue_lock)
		WARN_ON_ONCE(1);
	else if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) {
		unsigned long flags;

		spin_lock_irqsave(t->queue_lock, flags);
		if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags))
			queue_flag_clear(QUEUE_FLAG_CLUSTER, t);
		spin_unlock_irqrestore(t->queue_lock, flags);
	}
}
EXPORT_SYMBOL(disk_stack_limits);

+1 −1
Original line number Diff line number Diff line
@@ -119,7 +119,7 @@ static ssize_t queue_max_integrity_segments_show(struct request_queue *q, char *

static ssize_t queue_max_segment_size_show(struct request_queue *q, char *page)
{
	if (test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags))
	if (blk_queue_cluster(q))
		return queue_var_show(queue_max_segment_size(q), (page));

	return queue_var_show(PAGE_CACHE_SIZE, (page));
+25 −14
Original line number Diff line number Diff line
@@ -355,6 +355,12 @@ throtl_start_new_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw)
			tg->slice_end[rw], jiffies);
}

static inline void throtl_set_slice_end(struct throtl_data *td,
		struct throtl_grp *tg, bool rw, unsigned long jiffy_end)
{
	tg->slice_end[rw] = roundup(jiffy_end, throtl_slice);
}

static inline void throtl_extend_slice(struct throtl_data *td,
		struct throtl_grp *tg, bool rw, unsigned long jiffy_end)
{
@@ -391,6 +397,16 @@ throtl_trim_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw)
	if (throtl_slice_used(td, tg, rw))
		return;

	/*
	 * A bio has been dispatched. Also adjust slice_end. It might happen
	 * that initially cgroup limit was very low resulting in high
	 * slice_end, but later limit was bumped up and bio was dispached
	 * sooner, then we need to reduce slice_end. A high bogus slice_end
	 * is bad because it does not allow new slice to start.
	 */

	throtl_set_slice_end(td, tg, rw, jiffies + throtl_slice);

	time_elapsed = jiffies - tg->slice_start[rw];

	nr_slices = time_elapsed / throtl_slice;
@@ -709,26 +725,21 @@ static void throtl_process_limit_change(struct throtl_data *td)
	struct throtl_grp *tg;
	struct hlist_node *pos, *n;

	/*
	 * Make sure atomic_inc() effects from
	 * throtl_update_blkio_group_read_bps(), group of functions are
	 * visible.
	 * Is this required or smp_mb__after_atomic_inc() was suffcient
	 * after the atomic_inc().
	 */
	smp_rmb();
	if (!atomic_read(&td->limits_changed))
		return;

	throtl_log(td, "limit changed =%d", atomic_read(&td->limits_changed));

	hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {
	/*
		 * Do I need an smp_rmb() here to make sure tg->limits_changed
		 * update is visible. I am relying on smp_rmb() at the
		 * beginning of function and not putting a new one here.
	 * Make sure updates from throtl_update_blkio_group_read_bps() group
	 * of functions to tg->limits_changed are visible. We do not
	 * want update td->limits_changed to be visible but update to
	 * tg->limits_changed not being visible yet on this cpu. Hence
	 * the read barrier.
	 */
	smp_rmb();

	hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {
		if (throtl_tg_on_rr(tg) && tg->limits_changed) {
			throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu"
				" riops=%u wiops=%u", tg->bps[READ],
Loading