diff options
| -rw-r--r-- | drivers/md/bcache/alloc.c | 140 | ||||
| -rw-r--r-- | drivers/md/bcache/bcache.h | 28 | ||||
| -rw-r--r-- | drivers/md/bcache/btree.c | 41 | ||||
| -rw-r--r-- | drivers/md/bcache/btree.h | 2 | ||||
| -rw-r--r-- | drivers/md/bcache/super.c | 24 | ||||
| -rw-r--r-- | include/trace/events/bcache.h | 6 |
6 files changed, 112 insertions, 129 deletions
diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c index a59ef6147fc7..443d03fbac47 100644 --- a/drivers/md/bcache/alloc.c +++ b/drivers/md/bcache/alloc.c | |||
| @@ -78,12 +78,6 @@ uint8_t bch_inc_gen(struct cache *ca, struct bucket *b) | |||
| 78 | ca->set->need_gc = max(ca->set->need_gc, bucket_gc_gen(b)); | 78 | ca->set->need_gc = max(ca->set->need_gc, bucket_gc_gen(b)); |
| 79 | WARN_ON_ONCE(ca->set->need_gc > BUCKET_GC_GEN_MAX); | 79 | WARN_ON_ONCE(ca->set->need_gc > BUCKET_GC_GEN_MAX); |
| 80 | 80 | ||
| 81 | if (CACHE_SYNC(&ca->set->sb)) { | ||
| 82 | ca->need_save_prio = max(ca->need_save_prio, | ||
| 83 | bucket_disk_gen(b)); | ||
| 84 | WARN_ON_ONCE(ca->need_save_prio > BUCKET_DISK_GEN_MAX); | ||
| 85 | } | ||
| 86 | |||
| 87 | return ret; | 81 | return ret; |
| 88 | } | 82 | } |
| 89 | 83 | ||
| @@ -120,58 +114,46 @@ void bch_rescale_priorities(struct cache_set *c, int sectors) | |||
| 120 | mutex_unlock(&c->bucket_lock); | 114 | mutex_unlock(&c->bucket_lock); |
| 121 | } | 115 | } |
| 122 | 116 | ||
| 123 | /* Allocation */ | 117 | /* |
| 118 | * Background allocation thread: scans for buckets to be invalidated, | ||
| 119 | * invalidates them, rewrites prios/gens (marking them as invalidated on disk), | ||
| 120 | * then optionally issues discard commands to the newly free buckets, then puts | ||
| 121 | * them on the various freelists. | ||
| 122 | */ | ||
| 124 | 123 | ||
| 125 | static inline bool can_inc_bucket_gen(struct bucket *b) | 124 | static inline bool can_inc_bucket_gen(struct bucket *b) |
| 126 | { | 125 | { |
| 127 | return bucket_gc_gen(b) < BUCKET_GC_GEN_MAX && | 126 | return bucket_gc_gen(b) < BUCKET_GC_GEN_MAX; |
| 128 | bucket_disk_gen(b) < BUCKET_DISK_GEN_MAX; | ||
| 129 | } | 127 | } |
| 130 | 128 | ||
| 131 | bool bch_bucket_add_unused(struct cache *ca, struct bucket *b) | 129 | bool bch_can_invalidate_bucket(struct cache *ca, struct bucket *b) |
| 132 | { | 130 | { |
| 133 | BUG_ON(GC_MARK(b) || GC_SECTORS_USED(b)); | 131 | BUG_ON(!ca->set->gc_mark_valid); |
| 134 | 132 | ||
| 135 | if (CACHE_REPLACEMENT(&ca->sb) == CACHE_REPLACEMENT_FIFO) { | ||
| 136 | unsigned i; | ||
| 137 | |||
| 138 | for (i = 0; i < RESERVE_NONE; i++) | ||
| 139 | if (!fifo_full(&ca->free[i])) | ||
| 140 | goto add; | ||
| 141 | |||
| 142 | return false; | ||
| 143 | } | ||
| 144 | add: | ||
| 145 | b->prio = 0; | ||
| 146 | |||
| 147 | if (can_inc_bucket_gen(b) && | ||
| 148 | fifo_push(&ca->unused, b - ca->buckets)) { | ||
| 149 | atomic_inc(&b->pin); | ||
| 150 | return true; | ||
| 151 | } | ||
| 152 | |||
| 153 | return false; | ||
| 154 | } | ||
| 155 | |||
| 156 | static bool can_invalidate_bucket(struct cache *ca, struct bucket *b) | ||
| 157 | { | ||
| 158 | return (!GC_MARK(b) || | 133 | return (!GC_MARK(b) || |
| 159 | GC_MARK(b) == GC_MARK_RECLAIMABLE) && | 134 | GC_MARK(b) == GC_MARK_RECLAIMABLE) && |
| 160 | !atomic_read(&b->pin) && | 135 | !atomic_read(&b->pin) && |
| 161 | can_inc_bucket_gen(b); | 136 | can_inc_bucket_gen(b); |
| 162 | } | 137 | } |
| 163 | 138 | ||
| 164 | static void invalidate_one_bucket(struct cache *ca, struct bucket *b) | 139 | void __bch_invalidate_one_bucket(struct cache *ca, struct bucket *b) |
| 165 | { | 140 | { |
| 166 | size_t bucket = b - ca->buckets; | 141 | lockdep_assert_held(&ca->set->bucket_lock); |
| 142 | BUG_ON(GC_MARK(b) && GC_MARK(b) != GC_MARK_RECLAIMABLE); | ||
| 167 | 143 | ||
| 168 | if (GC_SECTORS_USED(b)) | 144 | if (GC_SECTORS_USED(b)) |
| 169 | trace_bcache_invalidate(ca, bucket); | 145 | trace_bcache_invalidate(ca, b - ca->buckets); |
| 170 | 146 | ||
| 171 | bch_inc_gen(ca, b); | 147 | bch_inc_gen(ca, b); |
| 172 | b->prio = INITIAL_PRIO; | 148 | b->prio = INITIAL_PRIO; |
| 173 | atomic_inc(&b->pin); | 149 | atomic_inc(&b->pin); |
| 174 | fifo_push(&ca->free_inc, bucket); | 150 | } |
| 151 | |||
| 152 | static void bch_invalidate_one_bucket(struct cache *ca, struct bucket *b) | ||
| 153 | { | ||
| 154 | __bch_invalidate_one_bucket(ca, b); | ||
| 155 | |||
| 156 | fifo_push(&ca->free_inc, b - ca->buckets); | ||
| 175 | } | 157 | } |
| 176 | 158 | ||
| 177 | /* | 159 | /* |
| @@ -201,20 +183,7 @@ static void invalidate_buckets_lru(struct cache *ca) | |||
| 201 | ca->heap.used = 0; | 183 | ca->heap.used = 0; |
| 202 | 184 | ||
| 203 | for_each_bucket(b, ca) { | 185 | for_each_bucket(b, ca) { |
| 204 | /* | 186 | if (!bch_can_invalidate_bucket(ca, b)) |
| 205 | * If we fill up the unused list, if we then return before | ||
| 206 | * adding anything to the free_inc list we'll skip writing | ||
| 207 | * prios/gens and just go back to allocating from the unused | ||
| 208 | * list: | ||
| 209 | */ | ||
| 210 | if (fifo_full(&ca->unused)) | ||
| 211 | return; | ||
| 212 | |||
| 213 | if (!can_invalidate_bucket(ca, b)) | ||
| 214 | continue; | ||
| 215 | |||
| 216 | if (!GC_SECTORS_USED(b) && | ||
| 217 | bch_bucket_add_unused(ca, b)) | ||
| 218 | continue; | 187 | continue; |
| 219 | 188 | ||
| 220 | if (!heap_full(&ca->heap)) | 189 | if (!heap_full(&ca->heap)) |
| @@ -239,7 +208,7 @@ static void invalidate_buckets_lru(struct cache *ca) | |||
| 239 | return; | 208 | return; |
| 240 | } | 209 | } |
| 241 | 210 | ||
| 242 | invalidate_one_bucket(ca, b); | 211 | bch_invalidate_one_bucket(ca, b); |
| 243 | } | 212 | } |
| 244 | } | 213 | } |
| 245 | 214 | ||
| @@ -255,8 +224,8 @@ static void invalidate_buckets_fifo(struct cache *ca) | |||
| 255 | 224 | ||
| 256 | b = ca->buckets + ca->fifo_last_bucket++; | 225 | b = ca->buckets + ca->fifo_last_bucket++; |
| 257 | 226 | ||
| 258 | if (can_invalidate_bucket(ca, b)) | 227 | if (bch_can_invalidate_bucket(ca, b)) |
| 259 | invalidate_one_bucket(ca, b); | 228 | bch_invalidate_one_bucket(ca, b); |
| 260 | 229 | ||
| 261 | if (++checked >= ca->sb.nbuckets) { | 230 | if (++checked >= ca->sb.nbuckets) { |
| 262 | ca->invalidate_needs_gc = 1; | 231 | ca->invalidate_needs_gc = 1; |
| @@ -280,8 +249,8 @@ static void invalidate_buckets_random(struct cache *ca) | |||
| 280 | 249 | ||
| 281 | b = ca->buckets + n; | 250 | b = ca->buckets + n; |
| 282 | 251 | ||
| 283 | if (can_invalidate_bucket(ca, b)) | 252 | if (bch_can_invalidate_bucket(ca, b)) |
| 284 | invalidate_one_bucket(ca, b); | 253 | bch_invalidate_one_bucket(ca, b); |
| 285 | 254 | ||
| 286 | if (++checked >= ca->sb.nbuckets / 2) { | 255 | if (++checked >= ca->sb.nbuckets / 2) { |
| 287 | ca->invalidate_needs_gc = 1; | 256 | ca->invalidate_needs_gc = 1; |
| @@ -293,8 +262,7 @@ static void invalidate_buckets_random(struct cache *ca) | |||
| 293 | 262 | ||
| 294 | static void invalidate_buckets(struct cache *ca) | 263 | static void invalidate_buckets(struct cache *ca) |
| 295 | { | 264 | { |
| 296 | if (ca->invalidate_needs_gc) | 265 | BUG_ON(ca->invalidate_needs_gc); |
| 297 | return; | ||
| 298 | 266 | ||
| 299 | switch (CACHE_REPLACEMENT(&ca->sb)) { | 267 | switch (CACHE_REPLACEMENT(&ca->sb)) { |
| 300 | case CACHE_REPLACEMENT_LRU: | 268 | case CACHE_REPLACEMENT_LRU: |
| @@ -354,17 +322,10 @@ static int bch_allocator_thread(void *arg) | |||
| 354 | * possibly issue discards to them, then we add the bucket to | 322 | * possibly issue discards to them, then we add the bucket to |
| 355 | * the free list: | 323 | * the free list: |
| 356 | */ | 324 | */ |
| 357 | while (1) { | 325 | while (!fifo_empty(&ca->free_inc)) { |
| 358 | long bucket; | 326 | long bucket; |
| 359 | 327 | ||
| 360 | if ((!atomic_read(&ca->set->prio_blocked) || | 328 | fifo_pop(&ca->free_inc, bucket); |
| 361 | !CACHE_SYNC(&ca->set->sb)) && | ||
| 362 | !fifo_empty(&ca->unused)) | ||
| 363 | fifo_pop(&ca->unused, bucket); | ||
| 364 | else if (!fifo_empty(&ca->free_inc)) | ||
| 365 | fifo_pop(&ca->free_inc, bucket); | ||
| 366 | else | ||
| 367 | break; | ||
| 368 | 329 | ||
| 369 | if (ca->discard) { | 330 | if (ca->discard) { |
| 370 | mutex_unlock(&ca->set->bucket_lock); | 331 | mutex_unlock(&ca->set->bucket_lock); |
| @@ -385,9 +346,9 @@ static int bch_allocator_thread(void *arg) | |||
| 385 | * them to the free_inc list: | 346 | * them to the free_inc list: |
| 386 | */ | 347 | */ |
| 387 | 348 | ||
| 349 | retry_invalidate: | ||
| 388 | allocator_wait(ca, ca->set->gc_mark_valid && | 350 | allocator_wait(ca, ca->set->gc_mark_valid && |
| 389 | (ca->need_save_prio > 64 || | 351 | !ca->invalidate_needs_gc); |
| 390 | !ca->invalidate_needs_gc)); | ||
| 391 | invalidate_buckets(ca); | 352 | invalidate_buckets(ca); |
| 392 | 353 | ||
| 393 | /* | 354 | /* |
| @@ -395,13 +356,28 @@ static int bch_allocator_thread(void *arg) | |||
| 395 | * new stuff to them: | 356 | * new stuff to them: |
| 396 | */ | 357 | */ |
| 397 | allocator_wait(ca, !atomic_read(&ca->set->prio_blocked)); | 358 | allocator_wait(ca, !atomic_read(&ca->set->prio_blocked)); |
| 398 | if (CACHE_SYNC(&ca->set->sb) && | 359 | if (CACHE_SYNC(&ca->set->sb)) { |
| 399 | (!fifo_empty(&ca->free_inc) || | 360 | /* |
| 400 | ca->need_save_prio > 64)) | 361 | * This could deadlock if an allocation with a btree |
| 362 | * node locked ever blocked - having the btree node | ||
| 363 | * locked would block garbage collection, but here we're | ||
| 364 | * waiting on garbage collection before we invalidate | ||
| 365 | * and free anything. | ||
| 366 | * | ||
| 367 | * But this should be safe since the btree code always | ||
| 368 | * uses btree_check_reserve() before allocating now, and | ||
| 369 | * if it fails it blocks without btree nodes locked. | ||
| 370 | */ | ||
| 371 | if (!fifo_full(&ca->free_inc)) | ||
| 372 | goto retry_invalidate; | ||
| 373 | |||
| 401 | bch_prio_write(ca); | 374 | bch_prio_write(ca); |
| 375 | } | ||
| 402 | } | 376 | } |
| 403 | } | 377 | } |
| 404 | 378 | ||
| 379 | /* Allocation */ | ||
| 380 | |||
| 405 | long bch_bucket_alloc(struct cache *ca, unsigned reserve, bool wait) | 381 | long bch_bucket_alloc(struct cache *ca, unsigned reserve, bool wait) |
| 406 | { | 382 | { |
| 407 | DEFINE_WAIT(w); | 383 | DEFINE_WAIT(w); |
| @@ -447,8 +423,6 @@ out: | |||
| 447 | BUG_ON(i == r); | 423 | BUG_ON(i == r); |
| 448 | fifo_for_each(i, &ca->free_inc, iter) | 424 | fifo_for_each(i, &ca->free_inc, iter) |
| 449 | BUG_ON(i == r); | 425 | BUG_ON(i == r); |
| 450 | fifo_for_each(i, &ca->unused, iter) | ||
| 451 | BUG_ON(i == r); | ||
| 452 | } | 426 | } |
| 453 | 427 | ||
| 454 | b = ca->buckets + r; | 428 | b = ca->buckets + r; |
| @@ -470,17 +444,19 @@ out: | |||
| 470 | return r; | 444 | return r; |
| 471 | } | 445 | } |
| 472 | 446 | ||
| 447 | void __bch_bucket_free(struct cache *ca, struct bucket *b) | ||
| 448 | { | ||
| 449 | SET_GC_MARK(b, 0); | ||
| 450 | SET_GC_SECTORS_USED(b, 0); | ||
| 451 | } | ||
| 452 | |||
| 473 | void bch_bucket_free(struct cache_set *c, struct bkey *k) | 453 | void bch_bucket_free(struct cache_set *c, struct bkey *k) |
| 474 | { | 454 | { |
| 475 | unsigned i; | 455 | unsigned i; |
| 476 | 456 | ||
| 477 | for (i = 0; i < KEY_PTRS(k); i++) { | 457 | for (i = 0; i < KEY_PTRS(k); i++) |
| 478 | struct bucket *b = PTR_BUCKET(c, k, i); | 458 | __bch_bucket_free(PTR_CACHE(c, k, i), |
| 479 | 459 | PTR_BUCKET(c, k, i)); | |
| 480 | SET_GC_MARK(b, 0); | ||
| 481 | SET_GC_SECTORS_USED(b, 0); | ||
| 482 | bch_bucket_add_unused(PTR_CACHE(c, k, i), b); | ||
| 483 | } | ||
| 484 | } | 460 | } |
| 485 | 461 | ||
| 486 | int __bch_bucket_alloc_set(struct cache_set *c, unsigned reserve, | 462 | int __bch_bucket_alloc_set(struct cache_set *c, unsigned reserve, |
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h index 171cda89cb6b..200efc1b5cf8 100644 --- a/drivers/md/bcache/bcache.h +++ b/drivers/md/bcache/bcache.h | |||
| @@ -195,7 +195,6 @@ struct bucket { | |||
| 195 | atomic_t pin; | 195 | atomic_t pin; |
| 196 | uint16_t prio; | 196 | uint16_t prio; |
| 197 | uint8_t gen; | 197 | uint8_t gen; |
| 198 | uint8_t disk_gen; | ||
| 199 | uint8_t last_gc; /* Most out of date gen in the btree */ | 198 | uint8_t last_gc; /* Most out of date gen in the btree */ |
| 200 | uint8_t gc_gen; | 199 | uint8_t gc_gen; |
| 201 | uint16_t gc_mark; /* Bitfield used by GC. See below for field */ | 200 | uint16_t gc_mark; /* Bitfield used by GC. See below for field */ |
| @@ -426,14 +425,9 @@ struct cache { | |||
| 426 | * their new gen to disk. After prio_write() finishes writing the new | 425 | * their new gen to disk. After prio_write() finishes writing the new |
| 427 | * gens/prios, they'll be moved to the free list (and possibly discarded | 426 | * gens/prios, they'll be moved to the free list (and possibly discarded |
| 428 | * in the process) | 427 | * in the process) |
| 429 | * | ||
| 430 | * unused: GC found nothing pointing into these buckets (possibly | ||
| 431 | * because all the data they contained was overwritten), so we only | ||
| 432 | * need to discard them before they can be moved to the free list. | ||
| 433 | */ | 428 | */ |
| 434 | DECLARE_FIFO(long, free)[RESERVE_NR]; | 429 | DECLARE_FIFO(long, free)[RESERVE_NR]; |
| 435 | DECLARE_FIFO(long, free_inc); | 430 | DECLARE_FIFO(long, free_inc); |
| 436 | DECLARE_FIFO(long, unused); | ||
| 437 | 431 | ||
| 438 | size_t fifo_last_bucket; | 432 | size_t fifo_last_bucket; |
| 439 | 433 | ||
| @@ -443,12 +437,6 @@ struct cache { | |||
| 443 | DECLARE_HEAP(struct bucket *, heap); | 437 | DECLARE_HEAP(struct bucket *, heap); |
| 444 | 438 | ||
| 445 | /* | 439 | /* |
| 446 | * max(gen - disk_gen) for all buckets. When it gets too big we have to | ||
| 447 | * call prio_write() to keep gens from wrapping. | ||
| 448 | */ | ||
| 449 | uint8_t need_save_prio; | ||
| 450 | |||
| 451 | /* | ||
| 452 | * If nonzero, we know we aren't going to find any buckets to invalidate | 440 | * If nonzero, we know we aren't going to find any buckets to invalidate |
| 453 | * until a gc finishes - otherwise we could pointlessly burn a ton of | 441 | * until a gc finishes - otherwise we could pointlessly burn a ton of |
| 454 | * cpu | 442 | * cpu |
| @@ -848,9 +836,6 @@ static inline bool cached_dev_get(struct cached_dev *dc) | |||
| 848 | /* | 836 | /* |
| 849 | * bucket_gc_gen() returns the difference between the bucket's current gen and | 837 | * bucket_gc_gen() returns the difference between the bucket's current gen and |
| 850 | * the oldest gen of any pointer into that bucket in the btree (last_gc). | 838 | * the oldest gen of any pointer into that bucket in the btree (last_gc). |
| 851 | * | ||
| 852 | * bucket_disk_gen() returns the difference between the current gen and the gen | ||
| 853 | * on disk; they're both used to make sure gens don't wrap around. | ||
| 854 | */ | 839 | */ |
| 855 | 840 | ||
| 856 | static inline uint8_t bucket_gc_gen(struct bucket *b) | 841 | static inline uint8_t bucket_gc_gen(struct bucket *b) |
| @@ -858,13 +843,7 @@ static inline uint8_t bucket_gc_gen(struct bucket *b) | |||
| 858 | return b->gen - b->last_gc; | 843 | return b->gen - b->last_gc; |
| 859 | } | 844 | } |
| 860 | 845 | ||
| 861 | static inline uint8_t bucket_disk_gen(struct bucket *b) | ||
| 862 | { | ||
| 863 | return b->gen - b->disk_gen; | ||
| 864 | } | ||
| 865 | |||
| 866 | #define BUCKET_GC_GEN_MAX 96U | 846 | #define BUCKET_GC_GEN_MAX 96U |
| 867 | #define BUCKET_DISK_GEN_MAX 64U | ||
| 868 | 847 | ||
| 869 | #define kobj_attribute_write(n, fn) \ | 848 | #define kobj_attribute_write(n, fn) \ |
| 870 | static struct kobj_attribute ksysfs_##n = __ATTR(n, S_IWUSR, NULL, fn) | 849 | static struct kobj_attribute ksysfs_##n = __ATTR(n, S_IWUSR, NULL, fn) |
| @@ -897,11 +876,14 @@ void bch_submit_bbio(struct bio *, struct cache_set *, struct bkey *, unsigned); | |||
| 897 | 876 | ||
| 898 | uint8_t bch_inc_gen(struct cache *, struct bucket *); | 877 | uint8_t bch_inc_gen(struct cache *, struct bucket *); |
| 899 | void bch_rescale_priorities(struct cache_set *, int); | 878 | void bch_rescale_priorities(struct cache_set *, int); |
| 900 | bool bch_bucket_add_unused(struct cache *, struct bucket *); | ||
| 901 | 879 | ||
| 902 | long bch_bucket_alloc(struct cache *, unsigned, bool); | 880 | bool bch_can_invalidate_bucket(struct cache *, struct bucket *); |
| 881 | void __bch_invalidate_one_bucket(struct cache *, struct bucket *); | ||
| 882 | |||
| 883 | void __bch_bucket_free(struct cache *, struct bucket *); | ||
| 903 | void bch_bucket_free(struct cache_set *, struct bkey *); | 884 | void bch_bucket_free(struct cache_set *, struct bkey *); |
| 904 | 885 | ||
| 886 | long bch_bucket_alloc(struct cache *, unsigned, bool); | ||
| 905 | int __bch_bucket_alloc_set(struct cache_set *, unsigned, | 887 | int __bch_bucket_alloc_set(struct cache_set *, unsigned, |
| 906 | struct bkey *, int, bool); | 888 | struct bkey *, int, bool); |
| 907 | int bch_bucket_alloc_set(struct cache_set *, unsigned, | 889 | int bch_bucket_alloc_set(struct cache_set *, unsigned, |
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c index be90596a9e2a..4c340c85b122 100644 --- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c | |||
| @@ -1641,7 +1641,7 @@ static void btree_gc_start(struct cache_set *c) | |||
| 1641 | mutex_unlock(&c->bucket_lock); | 1641 | mutex_unlock(&c->bucket_lock); |
| 1642 | } | 1642 | } |
| 1643 | 1643 | ||
| 1644 | size_t bch_btree_gc_finish(struct cache_set *c) | 1644 | static size_t bch_btree_gc_finish(struct cache_set *c) |
| 1645 | { | 1645 | { |
| 1646 | size_t available = 0; | 1646 | size_t available = 0; |
| 1647 | struct bucket *b; | 1647 | struct bucket *b; |
| @@ -1703,9 +1703,6 @@ size_t bch_btree_gc_finish(struct cache_set *c) | |||
| 1703 | 1703 | ||
| 1704 | if (!GC_MARK(b) || GC_MARK(b) == GC_MARK_RECLAIMABLE) | 1704 | if (!GC_MARK(b) || GC_MARK(b) == GC_MARK_RECLAIMABLE) |
| 1705 | available++; | 1705 | available++; |
| 1706 | |||
| 1707 | if (!GC_MARK(b)) | ||
| 1708 | bch_bucket_add_unused(ca, b); | ||
| 1709 | } | 1706 | } |
| 1710 | } | 1707 | } |
| 1711 | 1708 | ||
| @@ -1836,6 +1833,42 @@ int bch_btree_check(struct cache_set *c) | |||
| 1836 | return btree_root(check_recurse, c, &op); | 1833 | return btree_root(check_recurse, c, &op); |
| 1837 | } | 1834 | } |
| 1838 | 1835 | ||
| 1836 | void bch_initial_gc_finish(struct cache_set *c) | ||
| 1837 | { | ||
| 1838 | struct cache *ca; | ||
| 1839 | struct bucket *b; | ||
| 1840 | unsigned i; | ||
| 1841 | |||
| 1842 | bch_btree_gc_finish(c); | ||
| 1843 | |||
| 1844 | mutex_lock(&c->bucket_lock); | ||
| 1845 | |||
| 1846 | /* | ||
| 1847 | * We need to put some unused buckets directly on the prio freelist in | ||
| 1848 | * order to get the allocator thread started - it needs freed buckets in | ||
| 1849 | * order to rewrite the prios and gens, and it needs to rewrite prios | ||
| 1850 | * and gens in order to free buckets. | ||
| 1851 | * | ||
| 1852 | * This is only safe for buckets that have no live data in them, which | ||
| 1853 | * there should always be some of. | ||
| 1854 | */ | ||
| 1855 | for_each_cache(ca, c, i) { | ||
| 1856 | for_each_bucket(b, ca) { | ||
| 1857 | if (fifo_full(&ca->free[RESERVE_PRIO])) | ||
| 1858 | break; | ||
| 1859 | |||
| 1860 | if (bch_can_invalidate_bucket(ca, b) && | ||
| 1861 | !GC_MARK(b)) { | ||
| 1862 | __bch_invalidate_one_bucket(ca, b); | ||
| 1863 | fifo_push(&ca->free[RESERVE_PRIO], | ||
| 1864 | b - ca->buckets); | ||
| 1865 | } | ||
| 1866 | } | ||
| 1867 | } | ||
| 1868 | |||
| 1869 | mutex_unlock(&c->bucket_lock); | ||
| 1870 | } | ||
| 1871 | |||
| 1839 | /* Btree insertion */ | 1872 | /* Btree insertion */ |
| 1840 | 1873 | ||
| 1841 | static bool btree_insert_key(struct btree *b, struct bkey *k, | 1874 | static bool btree_insert_key(struct btree *b, struct bkey *k, |
diff --git a/drivers/md/bcache/btree.h b/drivers/md/bcache/btree.h index 3ce371fa7f98..91dfa5e69685 100644 --- a/drivers/md/bcache/btree.h +++ b/drivers/md/bcache/btree.h | |||
| @@ -252,7 +252,7 @@ int bch_btree_insert(struct cache_set *, struct keylist *, | |||
| 252 | atomic_t *, struct bkey *); | 252 | atomic_t *, struct bkey *); |
| 253 | 253 | ||
| 254 | int bch_gc_thread_start(struct cache_set *); | 254 | int bch_gc_thread_start(struct cache_set *); |
| 255 | size_t bch_btree_gc_finish(struct cache_set *); | 255 | void bch_initial_gc_finish(struct cache_set *); |
| 256 | void bch_moving_gc(struct cache_set *); | 256 | void bch_moving_gc(struct cache_set *); |
| 257 | int bch_btree_check(struct cache_set *); | 257 | int bch_btree_check(struct cache_set *); |
| 258 | void bch_initial_mark_key(struct cache_set *, int, struct bkey *); | 258 | void bch_initial_mark_key(struct cache_set *, int, struct bkey *); |
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index 2d4a56219ec7..a8c57d59a726 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c | |||
| @@ -541,9 +541,6 @@ static void prio_io(struct cache *ca, uint64_t bucket, unsigned long rw) | |||
| 541 | closure_sync(cl); | 541 | closure_sync(cl); |
| 542 | } | 542 | } |
| 543 | 543 | ||
| 544 | #define buckets_free(c) "free %zu, free_inc %zu, unused %zu", \ | ||
| 545 | fifo_used(&c->free), fifo_used(&c->free_inc), fifo_used(&c->unused) | ||
| 546 | |||
| 547 | void bch_prio_write(struct cache *ca) | 544 | void bch_prio_write(struct cache *ca) |
| 548 | { | 545 | { |
| 549 | int i; | 546 | int i; |
| @@ -554,10 +551,6 @@ void bch_prio_write(struct cache *ca) | |||
| 554 | 551 | ||
| 555 | lockdep_assert_held(&ca->set->bucket_lock); | 552 | lockdep_assert_held(&ca->set->bucket_lock); |
| 556 | 553 | ||
| 557 | for (b = ca->buckets; | ||
| 558 | b < ca->buckets + ca->sb.nbuckets; b++) | ||
| 559 | b->disk_gen = b->gen; | ||
| 560 | |||
| 561 | ca->disk_buckets->seq++; | 554 | ca->disk_buckets->seq++; |
| 562 | 555 | ||
| 563 | atomic_long_add(ca->sb.bucket_size * prio_buckets(ca), | 556 | atomic_long_add(ca->sb.bucket_size * prio_buckets(ca), |
| @@ -601,14 +594,17 @@ void bch_prio_write(struct cache *ca) | |||
| 601 | 594 | ||
| 602 | mutex_lock(&ca->set->bucket_lock); | 595 | mutex_lock(&ca->set->bucket_lock); |
| 603 | 596 | ||
| 604 | ca->need_save_prio = 0; | ||
| 605 | |||
| 606 | /* | 597 | /* |
| 607 | * Don't want the old priorities to get garbage collected until after we | 598 | * Don't want the old priorities to get garbage collected until after we |
| 608 | * finish writing the new ones, and they're journalled | 599 | * finish writing the new ones, and they're journalled |
| 609 | */ | 600 | */ |
| 610 | for (i = 0; i < prio_buckets(ca); i++) | 601 | for (i = 0; i < prio_buckets(ca); i++) { |
| 602 | if (ca->prio_last_buckets[i]) | ||
| 603 | __bch_bucket_free(ca, | ||
| 604 | &ca->buckets[ca->prio_last_buckets[i]]); | ||
| 605 | |||
| 611 | ca->prio_last_buckets[i] = ca->prio_buckets[i]; | 606 | ca->prio_last_buckets[i] = ca->prio_buckets[i]; |
| 607 | } | ||
| 612 | } | 608 | } |
| 613 | 609 | ||
| 614 | static void prio_read(struct cache *ca, uint64_t bucket) | 610 | static void prio_read(struct cache *ca, uint64_t bucket) |
| @@ -639,7 +635,7 @@ static void prio_read(struct cache *ca, uint64_t bucket) | |||
| 639 | } | 635 | } |
| 640 | 636 | ||
| 641 | b->prio = le16_to_cpu(d->prio); | 637 | b->prio = le16_to_cpu(d->prio); |
| 642 | b->gen = b->disk_gen = b->last_gc = b->gc_gen = d->gen; | 638 | b->gen = b->last_gc = b->gc_gen = d->gen; |
| 643 | } | 639 | } |
| 644 | } | 640 | } |
| 645 | 641 | ||
| @@ -1606,7 +1602,7 @@ static void run_cache_set(struct cache_set *c) | |||
| 1606 | goto err; | 1602 | goto err; |
| 1607 | 1603 | ||
| 1608 | bch_journal_mark(c, &journal); | 1604 | bch_journal_mark(c, &journal); |
| 1609 | bch_btree_gc_finish(c); | 1605 | bch_initial_gc_finish(c); |
| 1610 | pr_debug("btree_check() done"); | 1606 | pr_debug("btree_check() done"); |
| 1611 | 1607 | ||
| 1612 | /* | 1608 | /* |
| @@ -1648,7 +1644,7 @@ static void run_cache_set(struct cache_set *c) | |||
| 1648 | ca->sb.d[j] = ca->sb.first_bucket + j; | 1644 | ca->sb.d[j] = ca->sb.first_bucket + j; |
| 1649 | } | 1645 | } |
| 1650 | 1646 | ||
| 1651 | bch_btree_gc_finish(c); | 1647 | bch_initial_gc_finish(c); |
| 1652 | 1648 | ||
| 1653 | err = "error starting allocator thread"; | 1649 | err = "error starting allocator thread"; |
| 1654 | for_each_cache(ca, c, i) | 1650 | for_each_cache(ca, c, i) |
| @@ -1794,7 +1790,6 @@ void bch_cache_release(struct kobject *kobj) | |||
| 1794 | vfree(ca->buckets); | 1790 | vfree(ca->buckets); |
| 1795 | 1791 | ||
| 1796 | free_heap(&ca->heap); | 1792 | free_heap(&ca->heap); |
| 1797 | free_fifo(&ca->unused); | ||
| 1798 | free_fifo(&ca->free_inc); | 1793 | free_fifo(&ca->free_inc); |
| 1799 | 1794 | ||
| 1800 | for (i = 0; i < RESERVE_NR; i++) | 1795 | for (i = 0; i < RESERVE_NR; i++) |
| @@ -1831,7 +1826,6 @@ static int cache_alloc(struct cache_sb *sb, struct cache *ca) | |||
| 1831 | !init_fifo(&ca->free[RESERVE_MOVINGGC], free, GFP_KERNEL) || | 1826 | !init_fifo(&ca->free[RESERVE_MOVINGGC], free, GFP_KERNEL) || |
| 1832 | !init_fifo(&ca->free[RESERVE_NONE], free, GFP_KERNEL) || | 1827 | !init_fifo(&ca->free[RESERVE_NONE], free, GFP_KERNEL) || |
| 1833 | !init_fifo(&ca->free_inc, free << 2, GFP_KERNEL) || | 1828 | !init_fifo(&ca->free_inc, free << 2, GFP_KERNEL) || |
| 1834 | !init_fifo(&ca->unused, free << 2, GFP_KERNEL) || | ||
| 1835 | !init_heap(&ca->heap, free << 3, GFP_KERNEL) || | 1829 | !init_heap(&ca->heap, free << 3, GFP_KERNEL) || |
| 1836 | !(ca->buckets = vzalloc(sizeof(struct bucket) * | 1830 | !(ca->buckets = vzalloc(sizeof(struct bucket) * |
| 1837 | ca->sb.nbuckets)) || | 1831 | ca->sb.nbuckets)) || |
diff --git a/include/trace/events/bcache.h b/include/trace/events/bcache.h index 8fc2a7134d3c..c9c3c044b32f 100644 --- a/include/trace/events/bcache.h +++ b/include/trace/events/bcache.h | |||
| @@ -446,7 +446,6 @@ TRACE_EVENT(bcache_alloc_fail, | |||
| 446 | __field(dev_t, dev ) | 446 | __field(dev_t, dev ) |
| 447 | __field(unsigned, free ) | 447 | __field(unsigned, free ) |
| 448 | __field(unsigned, free_inc ) | 448 | __field(unsigned, free_inc ) |
| 449 | __field(unsigned, unused ) | ||
| 450 | __field(unsigned, blocked ) | 449 | __field(unsigned, blocked ) |
| 451 | ), | 450 | ), |
| 452 | 451 | ||
| @@ -454,13 +453,12 @@ TRACE_EVENT(bcache_alloc_fail, | |||
| 454 | __entry->dev = ca->bdev->bd_dev; | 453 | __entry->dev = ca->bdev->bd_dev; |
| 455 | __entry->free = fifo_used(&ca->free[reserve]); | 454 | __entry->free = fifo_used(&ca->free[reserve]); |
| 456 | __entry->free_inc = fifo_used(&ca->free_inc); | 455 | __entry->free_inc = fifo_used(&ca->free_inc); |
| 457 | __entry->unused = fifo_used(&ca->unused); | ||
| 458 | __entry->blocked = atomic_read(&ca->set->prio_blocked); | 456 | __entry->blocked = atomic_read(&ca->set->prio_blocked); |
| 459 | ), | 457 | ), |
| 460 | 458 | ||
| 461 | TP_printk("alloc fail %d,%d free %u free_inc %u unused %u blocked %u", | 459 | TP_printk("alloc fail %d,%d free %u free_inc %u blocked %u", |
| 462 | MAJOR(__entry->dev), MINOR(__entry->dev), __entry->free, | 460 | MAJOR(__entry->dev), MINOR(__entry->dev), __entry->free, |
| 463 | __entry->free_inc, __entry->unused, __entry->blocked) | 461 | __entry->free_inc, __entry->blocked) |
| 464 | ); | 462 | ); |
| 465 | 463 | ||
| 466 | /* Background writeback */ | 464 | /* Background writeback */ |
