Commit a421ef30 authored by Michal Hocko's avatar Michal Hocko Committed by Linus Torvalds
Browse files

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.

Link: https://lkml.kernel.org/r/20211122153233.9924-5-mhocko@kernel.org


Signed-off-by: default avatarMichal Hocko <mhocko@suse.com>
Reviewed-by: default avatarUladzislau Rezki (Sony) <urezki@gmail.com>
Acked-by: default avatarVlastimil Babka <vbabka@suse.cz>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Ilya Dryomov <idryomov@gmail.com>
Cc: Jeff Layton <jlayton@kernel.org>
Cc: Neil Brown <neilb@suse.de>
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 30d3f011
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -295,7 +295,6 @@ extern bool libceph_compatible(void *data);

extern const char *ceph_msg_type_name(int type);
extern int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid);
extern void *ceph_kvmalloc(size_t size, gfp_t flags);

struct fs_parameter;
struct fc_log;
+4 −11
Original line number Diff line number Diff line
@@ -549,13 +549,10 @@ EXPORT_SYMBOL(vm_mmap);
 * Uses kmalloc to get the memory but if the allocation fails then falls back
 * to the vmalloc allocator. Use kvfree for freeing the memory.
 *
 * Reclaim modifiers - __GFP_NORETRY and __GFP_NOFAIL are not supported.
 * GFP_NOWAIT and GFP_ATOMIC are not supported, neither is the __GFP_NORETRY modifier.
 * __GFP_RETRY_MAYFAIL is supported, and it should be used only if kmalloc is
 * preferable to the vmalloc fallback, due to visible performance drawbacks.
 *
 * Please note that any use of gfp flags outside of GFP_KERNEL is careful to not
 * fall back to vmalloc.
 *
 * Return: pointer to the allocated memory of %NULL in case of failure
 */
void *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)
	gfp_t kmalloc_flags = flags;
	void *ret;

	/*
	 * vmalloc uses GFP_KERNEL for some internal allocations (e.g page tables)
	 * so the given set of flags has to be compatible.
	 */
	if ((flags & GFP_KERNEL) != GFP_KERNEL)
		return kmalloc_node(size, flags, node);

	/*
	 * We want to attempt a large physically contiguous block first because
	 * 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)

		if (!(kmalloc_flags & __GFP_RETRY_MAYFAIL))
			kmalloc_flags |= __GFP_NORETRY;

		/* nofail semantic is implemented by the vmalloc fallback */
		kmalloc_flags &= ~__GFP_NOFAIL;
	}

	ret = kmalloc_node(size, kmalloc_flags, node);
+2 −2
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@

#include <linux/ceph/buffer.h>
#include <linux/ceph/decode.h>
#include <linux/ceph/libceph.h> /* for ceph_kvmalloc */
#include <linux/ceph/libceph.h> /* for kvmalloc */

struct ceph_buffer *ceph_buffer_new(size_t len, gfp_t gfp)
{
@@ -17,7 +17,7 @@ struct ceph_buffer *ceph_buffer_new(size_t len, gfp_t gfp)
	if (!b)
		return NULL;

	b->vec.iov_base = ceph_kvmalloc(len, gfp);
	b->vec.iov_base = kvmalloc(len, gfp);
	if (!b->vec.iov_base) {
		kfree(b);
		return NULL;
+0 −27
Original line number Diff line number Diff line
@@ -190,33 +190,6 @@ int ceph_compare_options(struct ceph_options *new_opt,
}
EXPORT_SYMBOL(ceph_compare_options);

/*
 * kvmalloc() doesn't fall back to the vmalloc allocator unless flags are
 * compatible with (a superset of) GFP_KERNEL.  This is because while the
 * actual pages are allocated with the specified flags, the page table pages
 * are always allocated with GFP_KERNEL.
 *
 * ceph_kvmalloc() may be called with GFP_KERNEL, GFP_NOFS or GFP_NOIO.
 */
void *ceph_kvmalloc(size_t size, gfp_t flags)
{
	void *p;

	if ((flags & (__GFP_IO | __GFP_FS)) == (__GFP_IO | __GFP_FS)) {
		p = kvmalloc(size, flags);
	} else if ((flags & (__GFP_IO | __GFP_FS)) == __GFP_IO) {
		unsigned int nofs_flag = memalloc_nofs_save();
		p = kvmalloc(size, GFP_KERNEL);
		memalloc_nofs_restore(nofs_flag);
	} else {
		unsigned int noio_flag = memalloc_noio_save();
		p = kvmalloc(size, GFP_KERNEL);
		memalloc_noio_restore(noio_flag);
	}

	return p;
}

static int parse_fsid(const char *str, struct ceph_fsid *fsid)
{
	int i = 0;
+1 −1
Original line number Diff line number Diff line
@@ -147,7 +147,7 @@ void ceph_crypto_key_destroy(struct ceph_crypto_key *key)
static const u8 *aes_iv = (u8 *)CEPH_AES_IV;

/*
 * Should be used for buffers allocated with ceph_kvmalloc().
 * Should be used for buffers allocated with kvmalloc().
 * Currently these are encrypt out-buffer (ceph_buffer) and decrypt
 * in-buffer (msg front).
 *
Loading