diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2016-12-18 12:56:47 -0900 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2017-01-18 21:41:29 -0900 |
commit | 78580ee57b79e6de2f85fa497445c344a74a2b7d (patch) | |
tree | 9d5d67c3d6553c63cd3cb1c309996b1953be14a6 | |
parent | e69ab7fc6c99362ed763d1a166009b26da2befc9 (diff) |
bcache: fall back to vmalloc() for allocating entries in journal replay
-rw-r--r-- | drivers/md/bcache/journal.c | 11 | ||||
-rw-r--r-- | drivers/md/bcache/journal.h | 1 | ||||
-rw-r--r-- | drivers/md/bcache/super.c | 9 | ||||
-rw-r--r-- | drivers/md/bcache/util.h | 18 |
4 files changed, 20 insertions, 19 deletions
diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c index 4734caec178d..a6ec23ebfc3f 100644 --- a/drivers/md/bcache/journal.c +++ b/drivers/md/bcache/journal.c @@ -436,7 +436,7 @@ static enum { where = jlist->head; add: - i = kmalloc(offsetof(struct journal_replay, j) + bytes, GFP_KERNEL); + i = kvmalloc(offsetof(struct journal_replay, j) + bytes, GFP_KERNEL); if (!i) { ret = JOURNAL_ENTRY_ADD_ERROR; goto out; @@ -863,15 +863,14 @@ search_done: #undef read_bucket } -static void journal_entries_free(struct journal *j, - struct list_head *list) +void bch_journal_entries_free(struct list_head *list) { while (!list_empty(list)) { struct journal_replay *i = list_first_entry(list, struct journal_replay, list); list_del(&i->list); - kfree(i); + kvfree(i); } } @@ -928,7 +927,7 @@ const char *bch_journal_read(struct cache_set *c, struct list_head *list) closure_sync(&jlist.cl); if (jlist.ret) { - journal_entries_free(&c->journal, list); + bch_journal_entries_free(list); return jlist.ret == -ENOMEM ? "cannot allocate memory for journal" @@ -1456,7 +1455,7 @@ err: if (ret) bch_err(c, "journal replay error: %d", ret); - journal_entries_free(j, list); + bch_journal_entries_free(list); return ret; } diff --git a/drivers/md/bcache/journal.h b/drivers/md/bcache/journal.h index 6fe7014ecd76..c8c6639666d3 100644 --- a/drivers/md/bcache/journal.h +++ b/drivers/md/bcache/journal.h @@ -339,6 +339,7 @@ static inline bool journal_flushes_device(struct cache *ca) void bch_journal_start(struct cache_set *); void bch_journal_mark(struct cache_set *, struct list_head *); +void bch_journal_entries_free(struct list_head *); const char *bch_journal_read(struct cache_set *, struct list_head *); int bch_journal_replay(struct cache_set *, struct list_head *); diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index 93a97114a10e..aa96931d3db9 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -1485,14 +1485,7 @@ static const char *run_cache_set(struct cache_set *c) BUG_ON(!list_empty(&journal)); return NULL; err: - while (!list_empty(&journal)) { - struct journal_replay *r = - list_first_entry(&journal, struct journal_replay, list); - - list_del(&r->list); - kfree(r); - } - + bch_journal_entries_free(&journal); set_bit(CACHE_SET_ERROR, &c->flags); bch_cache_set_unregister(c); closure_put(&c->caching); diff --git a/drivers/md/bcache/util.h b/drivers/md/bcache/util.h index 129ecb638ae5..115188f5c23b 100644 --- a/drivers/md/bcache/util.h +++ b/drivers/md/bcache/util.h @@ -77,6 +77,18 @@ do { \ (__builtin_types_compatible_p(typeof(_val), _type) || \ __builtin_types_compatible_p(typeof(_val), const _type)) +static inline void *kvmalloc(size_t bytes, gfp_t gfp) +{ + if (bytes <= PAGE_SIZE || + !(gfp & GFP_KERNEL)) + return kmalloc(bytes, gfp); + + return ((bytes <= KMALLOC_MAX_SIZE) + ? kmalloc(bytes, gfp|__GFP_NOWARN) + : NULL) ?: + vmalloc(bytes); +} + #define DECLARE_HEAP(type, name) \ struct { \ size_t size, used; \ @@ -89,11 +101,7 @@ do { \ (heap)->used = 0; \ (heap)->size = (_size); \ _bytes = (heap)->size * sizeof(*(heap)->data); \ - (heap)->data = NULL; \ - if (_bytes < KMALLOC_MAX_SIZE) \ - (heap)->data = kmalloc(_bytes, (gfp)); \ - if ((!(heap)->data) && ((gfp) & GFP_KERNEL)) \ - (heap)->data = vmalloc(_bytes); \ + (heap)->data = kvmalloc(_bytes, (gfp)); \ (heap)->data; \ }) |