diff options
author | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-09-11 12:58:59 -0300 |
---|---|---|
committer | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-09-11 12:58:59 -0300 |
commit | 0520a938e11c34a5ffc422b9316b85e294b0fbb2 (patch) | |
tree | 9e44592eccb90ed2d2b3a893fb602e4ca894f695 /fs/aufs/module.c | |
parent | 273d4428f8c4cc94c9598f8bcc006ec2e8c654ea (diff) |
Linux-libre 4.7.3-gnupck-4.7.3-gnu
Diffstat (limited to 'fs/aufs/module.c')
-rw-r--r-- | fs/aufs/module.c | 60 |
1 files changed, 52 insertions, 8 deletions
diff --git a/fs/aufs/module.c b/fs/aufs/module.c index ede9a232a..5092b4bd6 100644 --- a/fs/aufs/module.c +++ b/fs/aufs/module.c @@ -10,13 +10,57 @@ #include <linux/seq_file.h> #include "aufs.h" -void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp) +/* shrinkable realloc */ +void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink) { - if (new_sz <= nused) - return p; + size_t sz; + int diff; + + sz = 0; + diff = -1; + if (p) { +#if 0 /* unused */ + if (!new_sz) { + au_delayed_kfree(p); + p = NULL; + goto out; + } +#else + AuDebugOn(!new_sz); +#endif + sz = ksize(p); + diff = au_kmidx_sub(sz, new_sz); + } + if (sz && !diff) + goto out; + + if (sz < new_sz) + /* expand or SLOB */ + p = krealloc(p, new_sz, gfp); + else if (new_sz < sz && may_shrink) { + /* shrink */ + void *q; + + q = kmalloc(new_sz, gfp); + if (q) { + if (p) { + memcpy(q, p, new_sz); + au_delayed_kfree(p); + } + p = q; + } else + p = NULL; + } - p = krealloc(p, new_sz, gfp); - if (p) +out: + return p; +} + +void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp, + int may_shrink) +{ + p = au_krealloc(p, new_sz, gfp, may_shrink); + if (p && new_sz > nused) memset(p + nused, 0, new_sz - nused); return p; } @@ -38,9 +82,9 @@ static void au_do_dfree(struct work_struct *work __maybe_unused) head = &au_dfree.cache[AuCache_##idx].llist; \ node = llist_del_all(head); \ for (; node; node = next) { \ - struct au_##name *p = \ - p = llist_entry(node, struct au_##name, \ - lnode); \ + struct au_##name *p \ + = llist_entry(node, struct au_##name, \ + lnode); \ next = llist_next(node); \ au_cache_free_##name(p); \ } \ |