Commit eeb0bed5 authored by Ilya Dryomov's avatar Ilya Dryomov
Browse files

libceph: add ceph_kv{malloc,free}() and switch to them



Encapsulate kmalloc vs vmalloc memory allocation and freeing logic into
two helpers, ceph_kvmalloc() and ceph_kvfree(), and switch to them.

ceph_kvmalloc() kmalloc()'s a maximum of 8 pages, anything bigger is
vmalloc()'ed with __GFP_HIGHMEM set.  This changes the existing
behaviour:

- for buffers (ceph_buffer_new()), from trying to kmalloc() everything
  and using vmalloc() just as a fallback

- for messages (ceph_msg_new()), from going to vmalloc() for anything
  bigger than a page

- for messages (ceph_msg_new()), from disallowing vmalloc() to use high
  memory

Signed-off-by: default avatarIlya Dryomov <ilya.dryomov@inktank.com>
Reviewed-by: default avatarSage Weil <sage@inktank.com>
parent 80213a84
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@ struct ceph_buffer {
	struct kref kref;
	struct kvec vec;
	size_t alloc_len;
	bool is_vmalloc;
};

extern struct ceph_buffer *ceph_buffer_new(size_t len, gfp_t gfp);
+7 −4
Original line number Diff line number Diff line
@@ -173,15 +173,18 @@ static inline int calc_pages_for(u64 off, u64 len)
		(off >> PAGE_CACHE_SHIFT);
}

extern struct kmem_cache *ceph_inode_cachep;
extern struct kmem_cache *ceph_cap_cachep;
extern struct kmem_cache *ceph_dentry_cachep;
extern struct kmem_cache *ceph_file_cachep;

/* ceph_common.c */
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 struct kmem_cache *ceph_inode_cachep;
extern struct kmem_cache *ceph_cap_cachep;
extern struct kmem_cache *ceph_dentry_cachep;
extern struct kmem_cache *ceph_file_cachep;
extern void *ceph_kvmalloc(size_t size, gfp_t flags);
extern void ceph_kvfree(const void *ptr);

extern struct ceph_options *ceph_parse_options(char *options,
			      const char *dev_name, const char *dev_name_end,
+0 −1
Original line number Diff line number Diff line
@@ -154,7 +154,6 @@ struct ceph_msg {
	struct list_head list_head;	/* links for connection lists */

	struct kref kref;
	bool front_is_vmalloc;
	bool more_to_follow;
	bool needs_out_seq;
	int front_alloc_len;
+6 −16
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@

#include <linux/ceph/buffer.h>
#include <linux/ceph/decode.h>
#include <linux/ceph/libceph.h> /* for ceph_kv{malloc,free} */

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

	b->vec.iov_base = kmalloc(len, gfp | __GFP_NOWARN);
	if (b->vec.iov_base) {
		b->is_vmalloc = false;
	} else {
		b->vec.iov_base = __vmalloc(len, gfp | __GFP_HIGHMEM, PAGE_KERNEL);
	b->vec.iov_base = ceph_kvmalloc(len, gfp);
	if (!b->vec.iov_base) {
		kfree(b);
		return NULL;
	}
		b->is_vmalloc = true;
	}

	kref_init(&b->kref);
	b->alloc_len = len;
@@ -40,12 +35,7 @@ void ceph_buffer_release(struct kref *kref)
	struct ceph_buffer *b = container_of(kref, struct ceph_buffer, kref);

	dout("buffer_release %p\n", b);
	if (b->vec.iov_base) {
		if (b->is_vmalloc)
			vfree(b->vec.iov_base);
		else
			kfree(b->vec.iov_base);
	}
	ceph_kvfree(b->vec.iov_base);
	kfree(b);
}
EXPORT_SYMBOL(ceph_buffer_release);
+20 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/statfs.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
#include <linux/nsproxy.h>
#include <net/net_namespace.h>

@@ -170,6 +171,25 @@ int ceph_compare_options(struct ceph_options *new_opt,
}
EXPORT_SYMBOL(ceph_compare_options);

void *ceph_kvmalloc(size_t size, gfp_t flags)
{
	if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
		void *ptr = kmalloc(size, flags | __GFP_NOWARN);
		if (ptr)
			return ptr;
	}

	return __vmalloc(size, flags | __GFP_HIGHMEM, PAGE_KERNEL);
}

void ceph_kvfree(const void *ptr)
{
	if (is_vmalloc_addr(ptr))
		vfree(ptr);
	else
		kfree(ptr);
}


static int parse_fsid(const char *str, struct ceph_fsid *fsid)
{
Loading