All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 4/7] dm: introduce dm_kvmalloc
@ 2015-07-03 20:59 Mikulas Patocka
  2015-07-06 12:42 ` Vivek Goyal
  2015-07-06 13:47 ` Mike Snitzer
  0 siblings, 2 replies; 8+ messages in thread
From: Mikulas Patocka @ 2015-07-03 20:59 UTC (permalink / raw)
  To: Mike Snitzer, Alasdair G. Kergon, Edward Thornber; +Cc: dm-devel

Introduce the functions dm_kvmalloc and dm_kvmalloc_node. These functions
attempt to do allocation with kmalloc and if it fails, use vmalloc. Memory
allocated with these functions should be freed with kvfree (that function
is already present in the Linux kernel).

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>

---
 drivers/md/dm-ioctl.c         |   26 +++++---------------------
 drivers/md/dm-table.c         |   37 +++++++++++++++++++++++++++++++++++++
 include/linux/device-mapper.h |    2 ++
 3 files changed, 44 insertions(+), 21 deletions(-)

Index: linux-4.1/drivers/md/dm-ioctl.c
===================================================================
--- linux-4.1.orig/drivers/md/dm-ioctl.c	2015-07-02 19:21:15.000000000 +0200
+++ linux-4.1/drivers/md/dm-ioctl.c	2015-07-02 19:21:21.000000000 +0200
@@ -1676,12 +1676,8 @@ static void free_params(struct dm_ioctl 
 	if (param_flags & DM_WIPE_BUFFER)
 		memset(param, 0, param_size);
 
-	if (param_flags & DM_PARAMS_ALLOC) {
-		if (is_vmalloc_addr(param))
-			vfree(param);
-		else
-			kfree(param);
-	}
+	if (param_flags & DM_PARAMS_ALLOC)
+		kvfree(param);
 }
 
 static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kernel,
@@ -1712,21 +1708,7 @@ static int copy_params(struct dm_ioctl _
 	 * Try to avoid low memory issues when a device is suspended.
 	 * Use kmalloc() rather than vmalloc() when we can.
 	 */
-	dmi = NULL;
-	if (param_kernel->data_size <= KMALLOC_MAX_SIZE) {
-		dmi = kmalloc(param_kernel->data_size, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
-		if (dmi)
-			*param_flags |= DM_PARAMS_ALLOC;
-	}
-
-	if (!dmi) {
-		unsigned noio_flag;
-		noio_flag = memalloc_noio_save();
-		dmi = __vmalloc(param_kernel->data_size, GFP_NOIO | __GFP_REPEAT | __GFP_HIGH | __GFP_HIGHMEM, PAGE_KERNEL);
-		memalloc_noio_restore(noio_flag);
-		if (dmi)
-			*param_flags |= DM_PARAMS_ALLOC;
-	}
+	dmi = dm_kvmalloc(param_kernel->data_size, GFP_NOIO);
 
 	if (!dmi) {
 		if (secure_data && clear_user(user, param_kernel->data_size))
@@ -1734,6 +1716,8 @@ static int copy_params(struct dm_ioctl _
 		return -ENOMEM;
 	}
 
+	*param_flags |= DM_PARAMS_ALLOC;
+
 	if (copy_from_user(dmi, user, param_kernel->data_size))
 		goto bad;
 
Index: linux-4.1/include/linux/device-mapper.h
===================================================================
--- linux-4.1.orig/include/linux/device-mapper.h	2015-07-02 19:21:16.000000000 +0200
+++ linux-4.1/include/linux/device-mapper.h	2015-07-02 19:21:21.000000000 +0200
@@ -475,6 +475,8 @@ struct dm_table *dm_swap_table(struct ma
 /*
  * A wrapper around vmalloc.
  */
+void *dm_kvmalloc_node(size_t size, gfp_t gfp, int node);
+void *dm_kvmalloc(size_t size, gfp_t gfp);
 void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size);
 
 /*-----------------------------------------------------------------
Index: linux-4.1/drivers/md/dm-table.c
===================================================================
--- linux-4.1.orig/drivers/md/dm-table.c	2015-07-02 19:21:16.000000000 +0200
+++ linux-4.1/drivers/md/dm-table.c	2015-07-02 19:28:18.000000000 +0200
@@ -131,6 +131,43 @@ static int setup_btree_index(unsigned in
 	return 0;
 }
 
+void *dm_kvmalloc_node(size_t size, gfp_t gfp, int node)
+{
+	void *p;
+	unsigned uninitialized_var(noio_flag);
+
+	/* vmalloc doesn't support no-wait allocations */
+	WARN_ON(!(gfp & __GFP_WAIT));
+
+	if (likely(size <= KMALLOC_MAX_SIZE)) {
+		p = kmalloc_node(size, gfp | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN, node);
+		if (likely(p != NULL))
+			return p;
+	}
+	if ((gfp & (__GFP_IO | __GFP_FS)) != (__GFP_IO | __GFP_FS)) {
+		/*
+		 * vmalloc allocates page tables with GFP_KERNEL, regardless
+		 * of GFP flags passed to it. If we are no GFP_NOIO context,
+		 * we call memalloc_noio_save, so that all allocations are
+		 * implicitly done with GFP_NOIO.
+		 */
+		noio_flag = memalloc_noio_save();
+		gfp |= __GFP_HIGH;
+	}
+	p = __vmalloc_node_flags(size, node, gfp | __GFP_REPEAT | __GFP_HIGHMEM);
+	if ((gfp & (__GFP_IO | __GFP_FS)) != (__GFP_IO | __GFP_FS)) {
+		memalloc_noio_restore(noio_flag);
+	}
+	return p;
+}
+EXPORT_SYMBOL(dm_kvmalloc_node);
+
+void *dm_kvmalloc(size_t size, gfp_t gfp)
+{
+	return dm_kvmalloc_node(size, gfp, NUMA_NO_NODE);
+}
+EXPORT_SYMBOL(dm_kvmalloc);
+
 void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size)
 {
 	unsigned long size;

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2015-07-07 13:25 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-07-03 20:59 [PATCH 4/7] dm: introduce dm_kvmalloc Mikulas Patocka
2015-07-06 12:42 ` Vivek Goyal
2015-07-06 13:04   ` Mikulas Patocka
2015-07-06 13:07     ` Vivek Goyal
2015-07-07 12:52       ` Mikulas Patocka
2015-07-06 13:47 ` Mike Snitzer
2015-07-07 12:50   ` Mikulas Patocka
2015-07-07 13:25     ` Mike Snitzer

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.