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

Commit f50efd2f authored by Jens Axboe's avatar Jens Axboe
Browse files

Merge branch 'bcache-for-upstream' of...

Merge branch 'bcache-for-upstream' of http://evilpiepirate.org/git/linux-bcache into for-3.10/drivers

Kent writes:

Hey Jens, this is everything I've got ready for 3.10 - there's _still_
one more bug I'm trying to track down.

Andrew - I've got patches that rip out the pkey() and pbtree() macros,
but they're somewhat tied up with some other nontrivial refactorings so
I think I'm going to wait a bit on those.
parents 0821e904 ee668506
Loading
Loading
Loading
Loading
+49 −23
Original line number Original line Diff line number Diff line
@@ -243,13 +243,22 @@ static void invalidate_buckets_lru(struct cache *ca)
	ca->heap.used = 0;
	ca->heap.used = 0;


	for_each_bucket(b, ca) {
	for_each_bucket(b, ca) {
		/*
		 * If we fill up the unused list, if we then return before
		 * adding anything to the free_inc list we'll skip writing
		 * prios/gens and just go back to allocating from the unused
		 * list:
		 */
		if (fifo_full(&ca->unused))
			return;

		if (!can_invalidate_bucket(ca, b))
		if (!can_invalidate_bucket(ca, b))
			continue;
			continue;


		if (!GC_SECTORS_USED(b)) {
		if (!GC_SECTORS_USED(b) &&
			if (!bch_bucket_add_unused(ca, b))
		    bch_bucket_add_unused(ca, b))
				return;
			continue;
		} else {

		if (!heap_full(&ca->heap))
		if (!heap_full(&ca->heap))
			heap_add(&ca->heap, b, bucket_max_cmp);
			heap_add(&ca->heap, b, bucket_max_cmp);
		else if (bucket_max_cmp(b, heap_peek(&ca->heap))) {
		else if (bucket_max_cmp(b, heap_peek(&ca->heap))) {
@@ -257,17 +266,14 @@ static void invalidate_buckets_lru(struct cache *ca)
			heap_sift(&ca->heap, 0, bucket_max_cmp);
			heap_sift(&ca->heap, 0, bucket_max_cmp);
		}
		}
	}
	}
	}

	if (ca->heap.used * 2 < ca->heap.size)
		bch_queue_gc(ca->set);


	for (i = ca->heap.used / 2 - 1; i >= 0; --i)
	for (i = ca->heap.used / 2 - 1; i >= 0; --i)
		heap_sift(&ca->heap, i, bucket_min_cmp);
		heap_sift(&ca->heap, i, bucket_min_cmp);


	while (!fifo_full(&ca->free_inc)) {
	while (!fifo_full(&ca->free_inc)) {
		if (!heap_pop(&ca->heap, b, bucket_min_cmp)) {
		if (!heap_pop(&ca->heap, b, bucket_min_cmp)) {
			/* We don't want to be calling invalidate_buckets()
			/*
			 * We don't want to be calling invalidate_buckets()
			 * multiple times when it can't do anything
			 * multiple times when it can't do anything
			 */
			 */
			ca->invalidate_needs_gc = 1;
			ca->invalidate_needs_gc = 1;
@@ -343,15 +349,22 @@ static void invalidate_buckets(struct cache *ca)
		invalidate_buckets_random(ca);
		invalidate_buckets_random(ca);
		break;
		break;
	}
	}

	pr_debug("free %zu/%zu free_inc %zu/%zu unused %zu/%zu",
		 fifo_used(&ca->free), ca->free.size,
		 fifo_used(&ca->free_inc), ca->free_inc.size,
		 fifo_used(&ca->unused), ca->unused.size);
}
}


#define allocator_wait(ca, cond)					\
#define allocator_wait(ca, cond)					\
do {									\
do {									\
	DEFINE_WAIT(__wait);						\
	DEFINE_WAIT(__wait);						\
									\
									\
	while (!(cond)) {						\
	while (1) {							\
		prepare_to_wait(&ca->set->alloc_wait,			\
		prepare_to_wait(&ca->set->alloc_wait,			\
				&__wait, TASK_INTERRUPTIBLE);		\
				&__wait, TASK_INTERRUPTIBLE);		\
		if (cond)						\
			break;						\
									\
									\
		mutex_unlock(&(ca)->set->bucket_lock);			\
		mutex_unlock(&(ca)->set->bucket_lock);			\
		if (test_bit(CACHE_SET_STOPPING_2, &ca->set->flags)) {	\
		if (test_bit(CACHE_SET_STOPPING_2, &ca->set->flags)) {	\
@@ -360,7 +373,6 @@ do { \
		}							\
		}							\
									\
									\
		schedule();						\
		schedule();						\
		__set_current_state(TASK_RUNNING);			\
		mutex_lock(&(ca)->set->bucket_lock);			\
		mutex_lock(&(ca)->set->bucket_lock);			\
	}								\
	}								\
									\
									\
@@ -374,6 +386,11 @@ void bch_allocator_thread(struct closure *cl)
	mutex_lock(&ca->set->bucket_lock);
	mutex_lock(&ca->set->bucket_lock);


	while (1) {
	while (1) {
		/*
		 * First, we pull buckets off of the unused and free_inc lists,
		 * possibly issue discards to them, then we add the bucket to
		 * the free list:
		 */
		while (1) {
		while (1) {
			long bucket;
			long bucket;


@@ -398,19 +415,28 @@ void bch_allocator_thread(struct closure *cl)
			}
			}
		}
		}


		allocator_wait(ca, ca->set->gc_mark_valid);
		/*
		invalidate_buckets(ca);
		 * We've run out of free buckets, we need to find some buckets
		 * we can invalidate. First, invalidate them in memory and add
		 * them to the free_inc list:
		 */


		allocator_wait(ca, !atomic_read(&ca->set->prio_blocked) ||
		allocator_wait(ca, ca->set->gc_mark_valid &&
			       !CACHE_SYNC(&ca->set->sb));
			       (ca->need_save_prio > 64 ||
				!ca->invalidate_needs_gc));
		invalidate_buckets(ca);


		/*
		 * Now, we write their new gens to disk so we can start writing
		 * new stuff to them:
		 */
		allocator_wait(ca, !atomic_read(&ca->set->prio_blocked));
		if (CACHE_SYNC(&ca->set->sb) &&
		if (CACHE_SYNC(&ca->set->sb) &&
		    (!fifo_empty(&ca->free_inc) ||
		    (!fifo_empty(&ca->free_inc) ||
		     ca->need_save_prio > 64)) {
		     ca->need_save_prio > 64))
			bch_prio_write(ca);
			bch_prio_write(ca);
	}
	}
}
}
}


long bch_bucket_alloc(struct cache *ca, unsigned watermark, struct closure *cl)
long bch_bucket_alloc(struct cache *ca, unsigned watermark, struct closure *cl)
{
{
@@ -475,7 +501,7 @@ void bch_bucket_free(struct cache_set *c, struct bkey *k)
	for (i = 0; i < KEY_PTRS(k); i++) {
	for (i = 0; i < KEY_PTRS(k); i++) {
		struct bucket *b = PTR_BUCKET(c, k, i);
		struct bucket *b = PTR_BUCKET(c, k, i);


		SET_GC_MARK(b, 0);
		SET_GC_MARK(b, GC_MARK_RECLAIMABLE);
		SET_GC_SECTORS_USED(b, 0);
		SET_GC_SECTORS_USED(b, 0);
		bch_bucket_add_unused(PTR_CACHE(c, k, i), b);
		bch_bucket_add_unused(PTR_CACHE(c, k, i), b);
	}
	}
+37 −10
Original line number Original line Diff line number Diff line
@@ -223,11 +223,17 @@ struct bkey {
#define BKEY_PADDED(key)					\
#define BKEY_PADDED(key)					\
	union { struct bkey key; uint64_t key ## _pad[BKEY_PAD]; }
	union { struct bkey key; uint64_t key ## _pad[BKEY_PAD]; }


/* Version 1: Backing device
/* Version 0: Cache device
 * Version 1: Backing device
 * Version 2: Seed pointer into btree node checksum
 * Version 2: Seed pointer into btree node checksum
 * Version 3: New UUID format
 * Version 3: Cache device with new UUID format
 * Version 4: Backing device with data offset
 */
 */
#define BCACHE_SB_VERSION	3
#define BCACHE_SB_VERSION_CDEV			0
#define BCACHE_SB_VERSION_BDEV			1
#define BCACHE_SB_VERSION_CDEV_WITH_UUID	3
#define BCACHE_SB_VERSION_BDEV_WITH_OFFSET	4
#define BCACHE_SB_MAX_VERSION			4


#define SB_SECTOR		8
#define SB_SECTOR		8
#define SB_SIZE			4096
#define SB_SIZE			4096
@@ -236,13 +242,12 @@ struct bkey {
/* SB_JOURNAL_BUCKETS must be divisible by BITS_PER_LONG */
/* SB_JOURNAL_BUCKETS must be divisible by BITS_PER_LONG */
#define MAX_CACHES_PER_SET	8
#define MAX_CACHES_PER_SET	8


#define BDEV_DATA_START		16	/* sectors */
#define BDEV_DATA_START_DEFAULT	16	/* sectors */


struct cache_sb {
struct cache_sb {
	uint64_t		csum;
	uint64_t		csum;
	uint64_t		offset;	/* sector where this sb was written */
	uint64_t		offset;	/* sector where this sb was written */
	uint64_t		version;
	uint64_t		version;
#define CACHE_BACKING_DEV	1


	uint8_t			magic[16];
	uint8_t			magic[16];


@@ -257,12 +262,28 @@ struct cache_sb {
	uint64_t		seq;
	uint64_t		seq;
	uint64_t		pad[8];
	uint64_t		pad[8];


	union {
	struct {
		/* Cache devices */
		uint64_t	nbuckets;	/* device size */
		uint64_t	nbuckets;	/* device size */

		uint16_t	block_size;	/* sectors */
		uint16_t	block_size;	/* sectors */
		uint16_t	bucket_size;	/* sectors */
		uint16_t	bucket_size;	/* sectors */


		uint16_t	nr_in_set;
		uint16_t	nr_in_set;
		uint16_t	nr_this_dev;
		uint16_t	nr_this_dev;
	};
	struct {
		/* Backing devices */
		uint64_t	data_offset;

		/*
		 * block_size from the cache device section is still used by
		 * backing devices, so don't add anything here until we fix
		 * things to not need it for backing devices anymore
		 */
	};
	};


	uint32_t		last_mount;	/* time_t */
	uint32_t		last_mount;	/* time_t */


@@ -861,6 +882,12 @@ static inline bool key_merging_disabled(struct cache_set *c)
#endif
#endif
}
}


static inline bool SB_IS_BDEV(const struct cache_sb *sb)
{
	return sb->version == BCACHE_SB_VERSION_BDEV
		|| sb->version == BCACHE_SB_VERSION_BDEV_WITH_OFFSET;
}

struct bbio {
struct bbio {
	unsigned		submit_time_us;
	unsigned		submit_time_us;
	union {
	union {
+1 −2
Original line number Original line Diff line number Diff line
@@ -984,7 +984,7 @@ static void btree_node_free(struct btree *b, struct btree_op *op)


	if (b->prio_blocked &&
	if (b->prio_blocked &&
	    !atomic_sub_return(b->prio_blocked, &b->c->prio_blocked))
	    !atomic_sub_return(b->prio_blocked, &b->c->prio_blocked))
		closure_wake_up(&b->c->bucket_wait);
		wake_up(&b->c->alloc_wait);


	b->prio_blocked = 0;
	b->prio_blocked = 0;


@@ -1548,7 +1548,6 @@ static void bch_btree_gc(struct closure *cl)


	trace_bcache_gc_end(c->sb.set_uuid);
	trace_bcache_gc_end(c->sb.set_uuid);
	wake_up(&c->alloc_wait);
	wake_up(&c->alloc_wait);
	closure_wake_up(&c->bucket_wait);


	continue_at(cl, bch_moving_gc, bch_gc_wq);
	continue_at(cl, bch_moving_gc, bch_gc_wq);
}
}
+21 −14
Original line number Original line Diff line number Diff line
@@ -38,6 +38,15 @@ static void bch_generic_make_request_hack(struct bio *bio)
		bio = clone;
		bio = clone;
	}
	}


	/*
	 * Hack, since drivers that clone bios clone up to bi_max_vecs, but our
	 * bios might have had more than that (before we split them per device
	 * limitations).
	 *
	 * To be taken out once immutable bvec stuff is in.
	 */
	bio->bi_max_vecs = bio->bi_vcnt;

	generic_make_request(bio);
	generic_make_request(bio);
}
}


@@ -149,34 +158,32 @@ static unsigned bch_bio_max_sectors(struct bio *bio)
{
{
	unsigned ret = bio_sectors(bio);
	unsigned ret = bio_sectors(bio);
	struct request_queue *q = bdev_get_queue(bio->bi_bdev);
	struct request_queue *q = bdev_get_queue(bio->bi_bdev);
	unsigned max_segments = min_t(unsigned, BIO_MAX_PAGES,
				      queue_max_segments(q));
	struct bio_vec *bv, *end = bio_iovec(bio) +
	struct bio_vec *bv, *end = bio_iovec(bio) +
		min_t(int, bio_segments(bio), queue_max_segments(q));
		min_t(int, bio_segments(bio), max_segments);

	struct bvec_merge_data bvm = {
		.bi_bdev	= bio->bi_bdev,
		.bi_sector	= bio->bi_sector,
		.bi_size	= 0,
		.bi_rw		= bio->bi_rw,
	};


	if (bio->bi_rw & REQ_DISCARD)
	if (bio->bi_rw & REQ_DISCARD)
		return min(ret, q->limits.max_discard_sectors);
		return min(ret, q->limits.max_discard_sectors);


	if (bio_segments(bio) > queue_max_segments(q) ||
	if (bio_segments(bio) > max_segments ||
	    q->merge_bvec_fn) {
	    q->merge_bvec_fn) {
		ret = 0;
		ret = 0;


		for (bv = bio_iovec(bio); bv < end; bv++) {
		for (bv = bio_iovec(bio); bv < end; bv++) {
			struct bvec_merge_data bvm = {
				.bi_bdev	= bio->bi_bdev,
				.bi_sector	= bio->bi_sector,
				.bi_size	= ret << 9,
				.bi_rw		= bio->bi_rw,
			};

			if (q->merge_bvec_fn &&
			if (q->merge_bvec_fn &&
			    q->merge_bvec_fn(q, &bvm, bv) < (int) bv->bv_len)
			    q->merge_bvec_fn(q, &bvm, bv) < (int) bv->bv_len)
				break;
				break;


			ret += bv->bv_len >> 9;
			ret += bv->bv_len >> 9;
			bvm.bi_size	+= bv->bv_len;
		}
		}

		if (ret >= (BIO_MAX_PAGES * PAGE_SIZE) >> 9)
			return (BIO_MAX_PAGES * PAGE_SIZE) >> 9;
	}
	}


	ret = min(ret, queue_max_sectors(q));
	ret = min(ret, queue_max_sectors(q));
+1 −1
Original line number Original line Diff line number Diff line
@@ -1220,7 +1220,7 @@ static void cached_dev_make_request(struct request_queue *q, struct bio *bio)
	part_stat_unlock();
	part_stat_unlock();


	bio->bi_bdev = dc->bdev;
	bio->bi_bdev = dc->bdev;
	bio->bi_sector += BDEV_DATA_START;
	bio->bi_sector += dc->sb.data_offset;


	if (cached_dev_get(dc)) {
	if (cached_dev_get(dc)) {
		s = search_alloc(bio, d);
		s = search_alloc(bio, d);
Loading