History

mm: allow !GFP_KERNEL allocations for kvmalloc

Support for GFP_NO{FS,IO} and __GFP_NOFAIL has been implemented by previous patches so we can allow the support for kvmalloc. This will allow some external users to simplify or completely remove their helpers. GFP_NOWAIT semantic hasn't been supported so far but it hasn't been explicitly documented so let's add a note about that. ceph_kvmalloc is the first helper to be dropped and changed to kvmalloc.

Michal Hocko committed 4 years ago

Commit a421ef31 parent 30d3f018 files · +15 −50Browse files

Unified · Split

8 files
  1. include/linux/ceph/libceph.h +0 −1
  2. mm/util.c +4 −11
  3. net/ceph/buffer.c +2 −2
  4. net/ceph/ceph_common.c +0 −27
  5. net/ceph/crypto.c +1 −1
  6. net/ceph/messenger.c +1 −1
  7. net/ceph/messenger_v2.c +1 −1
  8. net/ceph/osdmap.c +6 −6
include/linux/ceph/libceph.h+0−1
@@ -295,7 +295,6 @@ extern bool libceph_compatible(void *data); · 294 unmodified lines
295 295
296extern const char *ceph_msg_type_name(int type);296extern const char *ceph_msg_type_name(int type);
297extern int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid);297extern int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid);
298extern void *ceph_kvmalloc(size_t size, gfp_t flags);
299 298
300struct fs_parameter;299struct fs_parameter;
301struct fc_log;300struct fc_log;
mm/util.c+4−11
@@ -549,13 +549,10 @@ EXPORT_SYMBOL(vm_mmap); · 548 unmodified lines
549 * Uses kmalloc to get the memory but if the allocation fails then falls back549 * Uses kmalloc to get the memory but if the allocation fails then falls back
550 * to the vmalloc allocator. Use kvfree for freeing the memory.550 * to the vmalloc allocator. Use kvfree for freeing the memory.
551 *551 *
552 * Reclaim modifiers - __GFP_NORETRY and __GFP_NOFAIL are not supported.552 * GFP_NOWAIT and GFP_ATOMIC are not supported, neither is the __GFP_NORETRY modifier.
553 * __GFP_RETRY_MAYFAIL is supported, and it should be used only if kmalloc is553 * __GFP_RETRY_MAYFAIL is supported, and it should be used only if kmalloc is
554 * preferable to the vmalloc fallback, due to visible performance drawbacks.554 * preferable to the vmalloc fallback, due to visible performance drawbacks.
555 *555 *
556 * Please note that any use of gfp flags outside of GFP_KERNEL is careful to not
557 * fall back to vmalloc.
558 *
559 * Return: pointer to the allocated memory of %NULL in case of failure556 * Return: pointer to the allocated memory of %NULL in case of failure
560 */557 */
561void *kvmalloc_node(size_t size, gfp_t flags, int node)558void *kvmalloc_node(size_t size, gfp_t flags, int node)
@@ -563,13 +560,6 @@ void *kvmalloc_node(size_t size, gfp_t flags, int node) · 1 unmodified line
563 gfp_t kmalloc_flags = flags;560 gfp_t kmalloc_flags = flags;
564 void *ret;561 void *ret;
565 562
566 /*
567 * vmalloc uses GFP_KERNEL for some internal allocations (e.g page tables)
568 * so the given set of flags has to be compatible.
569 */
570 if ((flags & GFP_KERNEL) != GFP_KERNEL)
571 return kmalloc_node(size, flags, node);
572
573 /*563 /*
574 * We want to attempt a large physically contiguous block first because564 * We want to attempt a large physically contiguous block first because
575 * it is less likely to fragment multiple larger blocks and therefore565 * it is less likely to fragment multiple larger blocks and therefore
@@ -582,6 +572,9 @@ void *kvmalloc_node(size_t size, gfp_t flags, int node) · 6 unmodified lines
582 572
583 if (!(kmalloc_flags & __GFP_RETRY_MAYFAIL))573 if (!(kmalloc_flags & __GFP_RETRY_MAYFAIL))
584 kmalloc_flags |= __GFP_NORETRY;574 kmalloc_flags |= __GFP_NORETRY;
575
576 /* nofail semantic is implemented by the vmalloc fallback */
577 kmalloc_flags &= ~__GFP_NOFAIL;
585 }578 }
586 579
587 ret = kmalloc_node(size, kmalloc_flags, node);580 ret = kmalloc_node(size, kmalloc_flags, node);
net/ceph/buffer.c+2−2
@@ -7,7 +7,7 @@ · 6 unmodified lines
7 7
8#include <linux/ceph/buffer.h>8#include <linux/ceph/buffer.h>
9#include <linux/ceph/decode.h>9#include <linux/ceph/decode.h>
10#include <linux/ceph/libceph.h> /* for ceph_kvmalloc */10#include <linux/ceph/libceph.h> /* for kvmalloc */
11 11
12struct ceph_buffer *ceph_buffer_new(size_t len, gfp_t gfp)12struct ceph_buffer *ceph_buffer_new(size_t len, gfp_t gfp)
13{13{
@@ -17,7 +17,7 @@ struct ceph_buffer *ceph_buffer_new(size_t len, gfp_t gfp) · 3 unmodified lines
17 if (!b)17 if (!b)
18 return NULL;18 return NULL;
19 19
20 b->vec.iov_base = ceph_kvmalloc(len, gfp);20 b->vec.iov_base = kvmalloc(len, gfp);
21 if (!b->vec.iov_base) {21 if (!b->vec.iov_base) {
22 kfree(b);22 kfree(b);
23 return NULL;23 return NULL;
net/ceph/ceph_common.c+0−27
@@ -190,33 +190,6 @@ int ceph_compare_options(struct ceph_options *new_opt, · 189 unmodified lines
190}190}
191EXPORT_SYMBOL(ceph_compare_options);191EXPORT_SYMBOL(ceph_compare_options);
192 192
193/*
194 * kvmalloc() doesn't fall back to the vmalloc allocator unless flags are
195 * compatible with (a superset of) GFP_KERNEL. This is because while the
196 * actual pages are allocated with the specified flags, the page table pages
197 * are always allocated with GFP_KERNEL.
198 *
199 * ceph_kvmalloc() may be called with GFP_KERNEL, GFP_NOFS or GFP_NOIO.
200 */
201void *ceph_kvmalloc(size_t size, gfp_t flags)
202{
203 void *p;
204
205 if ((flags & (__GFP_IO | __GFP_FS)) == (__GFP_IO | __GFP_FS)) {
206 p = kvmalloc(size, flags);
207 } else if ((flags & (__GFP_IO | __GFP_FS)) == __GFP_IO) {
208 unsigned int nofs_flag = memalloc_nofs_save();
209 p = kvmalloc(size, GFP_KERNEL);
210 memalloc_nofs_restore(nofs_flag);
211 } else {
212 unsigned int noio_flag = memalloc_noio_save();
213 p = kvmalloc(size, GFP_KERNEL);
214 memalloc_noio_restore(noio_flag);
215 }
216
217 return p;
218}
219
220static int parse_fsid(const char *str, struct ceph_fsid *fsid)193static int parse_fsid(const char *str, struct ceph_fsid *fsid)
221{194{
222 int i = 0;195 int i = 0;
net/ceph/crypto.c+1−1
@@ -147,7 +147,7 @@ void ceph_crypto_key_destroy(struct ceph_crypto_key *key) · 146 unmodified lines
147static const u8 *aes_iv = (u8 *)CEPH_AES_IV;147static const u8 *aes_iv = (u8 *)CEPH_AES_IV;
148 148
149/*149/*
150 * Should be used for buffers allocated with ceph_kvmalloc().150 * Should be used for buffers allocated with kvmalloc().
151 * Currently these are encrypt out-buffer (ceph_buffer) and decrypt151 * Currently these are encrypt out-buffer (ceph_buffer) and decrypt
152 * in-buffer (msg front).152 * in-buffer (msg front).
153 *153 *
net/ceph/messenger.c+1−1
@@ -1920,7 +1920,7 @@ struct ceph_msg *ceph_msg_new2(int type, int front_len, int max_data_items, · 1919 unmodified lines
1920 1920
1921 /* front */1921 /* front */
1922 if (front_len) {1922 if (front_len) {
1923 m->front.iov_base = ceph_kvmalloc(front_len, flags);1923 m->front.iov_base = kvmalloc(front_len, flags);
1924 if (m->front.iov_base == NULL) {1924 if (m->front.iov_base == NULL) {
1925 dout("ceph_msg_new can't allocate %d bytes\n",1925 dout("ceph_msg_new can't allocate %d bytes\n",
1926 front_len);1926 front_len);
net/ceph/messenger_v2.c+1−1
@@ -308,7 +308,7 @@ static void *alloc_conn_buf(struct ceph_connection *con, int len) · 307 unmodified lines
308 if (WARN_ON(con->v2.conn_buf_cnt >= ARRAY_SIZE(con->v2.conn_bufs)))308 if (WARN_ON(con->v2.conn_buf_cnt >= ARRAY_SIZE(con->v2.conn_bufs)))
309 return NULL;309 return NULL;
310 310
311 buf = ceph_kvmalloc(len, GFP_NOIO);311 buf = kvmalloc(len, GFP_NOIO);
312 if (!buf)312 if (!buf)
313 return NULL;313 return NULL;
314 314
net/ceph/osdmap.c+6−6
@@ -980,7 +980,7 @@ static struct crush_work *alloc_workspace(const struct crush_map *c) · 979 unmodified lines
980 work_size = crush_work_size(c, CEPH_PG_MAX_SIZE);980 work_size = crush_work_size(c, CEPH_PG_MAX_SIZE);
981 dout("%s work_size %zu bytes\n", __func__, work_size);981 dout("%s work_size %zu bytes\n", __func__, work_size);
982 982
983 work = ceph_kvmalloc(work_size, GFP_NOIO);983 work = kvmalloc(work_size, GFP_NOIO);
984 if (!work)984 if (!work)
985 return NULL;985 return NULL;
986 986
@@ -1190,9 +1190,9 @@ static int osdmap_set_max_osd(struct ceph_osdmap *map, u32 max) · 203 unmodified lines
1190 if (max == map->max_osd)1190 if (max == map->max_osd)
1191 return 0;1191 return 0;
1192 1192
1193 state = ceph_kvmalloc(array_size(max, sizeof(*state)), GFP_NOFS);1193 state = kvmalloc(array_size(max, sizeof(*state)), GFP_NOFS);
1194 weight = ceph_kvmalloc(array_size(max, sizeof(*weight)), GFP_NOFS);1194 weight = kvmalloc(array_size(max, sizeof(*weight)), GFP_NOFS);
1195 addr = ceph_kvmalloc(array_size(max, sizeof(*addr)), GFP_NOFS);1195 addr = kvmalloc(array_size(max, sizeof(*addr)), GFP_NOFS);
1196 if (!state || !weight || !addr) {1196 if (!state || !weight || !addr) {
1197 kvfree(state);1197 kvfree(state);
1198 kvfree(weight);1198 kvfree(weight);
@@ -1222,7 +1222,7 @@ static int osdmap_set_max_osd(struct ceph_osdmap *map, u32 max) · 23 unmodified lines
1222 if (map->osd_primary_affinity) {1222 if (map->osd_primary_affinity) {
1223 u32 *affinity;1223 u32 *affinity;
1224 1224
1225 affinity = ceph_kvmalloc(array_size(max, sizeof(*affinity)),1225 affinity = kvmalloc(array_size(max, sizeof(*affinity)),
1226 GFP_NOFS);1226 GFP_NOFS);
1227 if (!affinity)1227 if (!affinity)
1228 return -ENOMEM;1228 return -ENOMEM;
@@ -1503,7 +1503,7 @@ static int set_primary_affinity(struct ceph_osdmap *map, int osd, u32 aff) · 274 unmodified lines
1503 if (!map->osd_primary_affinity) {1503 if (!map->osd_primary_affinity) {
1504 int i;1504 int i;
1505 1505
1506 map->osd_primary_affinity = ceph_kvmalloc(1506 map->osd_primary_affinity = kvmalloc(
1507 array_size(map->max_osd, sizeof(*map->osd_primary_affinity)),1507 array_size(map->max_osd, sizeof(*map->osd_primary_affinity)),
1508 GFP_NOFS);1508 GFP_NOFS);
1509 if (!map->osd_primary_affinity)1509 if (!map->osd_primary_affinity)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t