Skip to content

Commit

Permalink
Merge branch 'bcache-for-upstream' of http://evilpiepirate.org/git/li…
Browse files Browse the repository at this point in the history
…nux-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.
  • Loading branch information
Jens Axboe committed May 1, 2013
2 parents 0821e90 + ee66850 commit f50efd2
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 112 deletions.
72 changes: 49 additions & 23 deletions drivers/md/bcache/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,31 +243,37 @@ static void invalidate_buckets_lru(struct cache *ca)
ca->heap.used = 0;

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))
continue;

if (!GC_SECTORS_USED(b)) {
if (!bch_bucket_add_unused(ca, b))
return;
} else {
if (!heap_full(&ca->heap))
heap_add(&ca->heap, b, bucket_max_cmp);
else if (bucket_max_cmp(b, heap_peek(&ca->heap))) {
ca->heap.data[0] = b;
heap_sift(&ca->heap, 0, bucket_max_cmp);
}
if (!GC_SECTORS_USED(b) &&
bch_bucket_add_unused(ca, b))
continue;

if (!heap_full(&ca->heap))
heap_add(&ca->heap, b, bucket_max_cmp);
else if (bucket_max_cmp(b, heap_peek(&ca->heap))) {
ca->heap.data[0] = b;
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)
heap_sift(&ca->heap, i, bucket_min_cmp);

while (!fifo_full(&ca->free_inc)) {
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
*/
ca->invalidate_needs_gc = 1;
Expand Down Expand Up @@ -343,15 +349,22 @@ static void invalidate_buckets(struct cache *ca)
invalidate_buckets_random(ca);
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) \
do { \
DEFINE_WAIT(__wait); \
\
while (!(cond)) { \
while (1) { \
prepare_to_wait(&ca->set->alloc_wait, \
&__wait, TASK_INTERRUPTIBLE); \
if (cond) \
break; \
\
mutex_unlock(&(ca)->set->bucket_lock); \
if (test_bit(CACHE_SET_STOPPING_2, &ca->set->flags)) { \
Expand All @@ -360,7 +373,6 @@ do { \
} \
\
schedule(); \
__set_current_state(TASK_RUNNING); \
mutex_lock(&(ca)->set->bucket_lock); \
} \
\
Expand All @@ -374,6 +386,11 @@ void bch_allocator_thread(struct closure *cl)
mutex_lock(&ca->set->bucket_lock);

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) {
long bucket;

Expand All @@ -398,17 +415,26 @@ 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) ||
!CACHE_SYNC(&ca->set->sb));
allocator_wait(ca, ca->set->gc_mark_valid &&
(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) &&
(!fifo_empty(&ca->free_inc) ||
ca->need_save_prio > 64)) {
ca->need_save_prio > 64))
bch_prio_write(ca);
}
}
}

Expand Down Expand Up @@ -475,7 +501,7 @@ void bch_bucket_free(struct cache_set *c, struct bkey *k)
for (i = 0; i < KEY_PTRS(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);
bch_bucket_add_unused(PTR_CACHE(c, k, i), b);
}
Expand Down
47 changes: 37 additions & 10 deletions drivers/md/bcache/bcache.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,11 +223,17 @@ struct bkey {
#define BKEY_PADDED(key) \
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 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_SIZE 4096
Expand All @@ -236,13 +242,12 @@ struct bkey {
/* SB_JOURNAL_BUCKETS must be divisible by BITS_PER_LONG */
#define MAX_CACHES_PER_SET 8

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

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

uint8_t magic[16];

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

uint64_t nbuckets; /* device size */
uint16_t block_size; /* sectors */
uint16_t bucket_size; /* sectors */
union {
struct {
/* Cache devices */
uint64_t nbuckets; /* device size */

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

uint16_t nr_in_set;
uint16_t nr_this_dev;
uint16_t nr_in_set;
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 */

Expand Down Expand Up @@ -861,6 +882,12 @@ static inline bool key_merging_disabled(struct cache_set *c)
#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 {
unsigned submit_time_us;
union {
Expand Down
3 changes: 1 addition & 2 deletions drivers/md/bcache/btree.c
Original file line number Diff line number Diff line change
Expand Up @@ -984,7 +984,7 @@ static void btree_node_free(struct btree *b, struct btree_op *op)

if (b->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;

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

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

continue_at(cl, bch_moving_gc, bch_gc_wq);
}
Expand Down
35 changes: 21 additions & 14 deletions drivers/md/bcache/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ static void bch_generic_make_request_hack(struct bio *bio)
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);
}

Expand Down Expand Up @@ -149,34 +158,32 @@ static unsigned bch_bio_max_sectors(struct bio *bio)
{
unsigned ret = bio_sectors(bio);
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) +
min_t(int, bio_segments(bio), queue_max_segments(q));

struct bvec_merge_data bvm = {
.bi_bdev = bio->bi_bdev,
.bi_sector = bio->bi_sector,
.bi_size = 0,
.bi_rw = bio->bi_rw,
};
min_t(int, bio_segments(bio), max_segments);

if (bio->bi_rw & REQ_DISCARD)
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) {
ret = 0;

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 &&
q->merge_bvec_fn(q, &bvm, bv) < (int) bv->bv_len)
break;

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

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

ret = min(ret, queue_max_sectors(q));
Expand Down
2 changes: 1 addition & 1 deletion drivers/md/bcache/request.c
Original file line number Diff line number Diff line change
Expand Up @@ -1220,7 +1220,7 @@ static void cached_dev_make_request(struct request_queue *q, struct bio *bio)
part_stat_unlock();

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

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

0 comments on commit f50efd2

Please sign in to comment.