public inbox for linux-xfs@vger.kernel.org
 help / color / mirror / Atom feed
* xfs: replace KM_LARGE with explicit vmalloc use
@ 2010-01-20 21:55 Christoph Hellwig
  2010-01-21 19:06 ` Alex Elder
  0 siblings, 1 reply; 2+ messages in thread
From: Christoph Hellwig @ 2010-01-20 21:55 UTC (permalink / raw)
  To: xfs

We use the KM_LARGE flag to make kmem_alloc and friends use vmalloc if
nessecary.  As we only need this for a few boot/mount time allocations
just switch to explicit vmalloc calls there.

Signed-off-by: Christoph Hellwig <hch@lst.de>

Index: xfs/fs/xfs/linux-2.6/kmem.c
===================================================================
--- xfs.orig/fs/xfs/linux-2.6/kmem.c	2010-01-17 13:33:52.749254562 +0100
+++ xfs/fs/xfs/linux-2.6/kmem.c	2010-01-17 21:07:10.919003863 +0100
@@ -16,7 +16,6 @@
  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 #include <linux/mm.h>
-#include <linux/vmalloc.h>
 #include <linux/highmem.h>
 #include <linux/swap.h>
 #include <linux/blkdev.h>
@@ -24,8 +23,25 @@
 #include "time.h"
 #include "kmem.h"
 
-#define MAX_VMALLOCS	6
-#define MAX_SLAB_SIZE	0x20000
+/*
+ * Greedy allocation.  May fail and may return vmalloced memory.
+ *
+ * Must be freed using kmem_free_large.
+ */
+void *
+kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize)
+{
+	void		*ptr;
+	size_t		kmsize = maxsize;
+
+	while (!(ptr = kmem_zalloc_large(kmsize))) {
+		if ((kmsize >>= 1) <= minsize)
+			kmsize = minsize;
+	}
+	if (ptr)
+		*size = kmsize;
+	return ptr;
+}
 
 void *
 kmem_alloc(size_t size, unsigned int __nocast flags)
@@ -34,19 +50,8 @@ kmem_alloc(size_t size, unsigned int __n
 	gfp_t	lflags = kmem_flags_convert(flags);
 	void	*ptr;
 
-#ifdef DEBUG
-	if (unlikely(!(flags & KM_LARGE) && (size > PAGE_SIZE))) {
-		printk(KERN_WARNING "Large %s attempt, size=%ld\n",
-			__func__, (long)size);
-		dump_stack();
-	}
-#endif
-
 	do {
-		if (size < MAX_SLAB_SIZE || retries > MAX_VMALLOCS)
-			ptr = kmalloc(size, lflags);
-		else
-			ptr = __vmalloc(size, lflags, PAGE_KERNEL);
+		ptr = kmalloc(size, lflags);
 		if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP)))
 			return ptr;
 		if (!(++retries % 100))
@@ -68,27 +73,6 @@ kmem_zalloc(size_t size, unsigned int __
 	return ptr;
 }
 
-void *
-kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize,
-		   unsigned int __nocast flags)
-{
-	void		*ptr;
-	size_t		kmsize = maxsize;
-	unsigned int	kmflags = (flags & ~KM_SLEEP) | KM_NOSLEEP;
-
-	while (!(ptr = kmem_zalloc(kmsize, kmflags))) {
-		if ((kmsize <= minsize) && (flags & KM_NOSLEEP))
-			break;
-		if ((kmsize >>= 1) <= minsize) {
-			kmsize = minsize;
-			kmflags = flags;
-		}
-	}
-	if (ptr)
-		*size = kmsize;
-	return ptr;
-}
-
 void
 kmem_free(const void *ptr)
 {
Index: xfs/fs/xfs/linux-2.6/kmem.h
===================================================================
--- xfs.orig/fs/xfs/linux-2.6/kmem.h	2010-01-17 13:33:52.755254557 +0100
+++ xfs/fs/xfs/linux-2.6/kmem.h	2010-01-17 21:07:10.919003863 +0100
@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/vmalloc.h>
 
 /*
  * General memory allocation interfaces
@@ -30,7 +31,6 @@
 #define KM_NOSLEEP	0x0002u
 #define KM_NOFS		0x0004u
 #define KM_MAYFAIL	0x0008u
-#define KM_LARGE	0x0010u
 
 /*
  * We use a special process flag to avoid recursive callbacks into
@@ -42,7 +42,7 @@ kmem_flags_convert(unsigned int __nocast
 {
 	gfp_t	lflags;
 
-	BUG_ON(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL|KM_LARGE));
+	BUG_ON(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL));
 
 	if (flags & KM_NOSLEEP) {
 		lflags = GFP_ATOMIC | __GFP_NOWARN;
@@ -56,10 +56,25 @@ kmem_flags_convert(unsigned int __nocast
 
 extern void *kmem_alloc(size_t, unsigned int __nocast);
 extern void *kmem_zalloc(size_t, unsigned int __nocast);
-extern void *kmem_zalloc_greedy(size_t *, size_t, size_t, unsigned int __nocast);
 extern void *kmem_realloc(const void *, size_t, size_t, unsigned int __nocast);
 extern void  kmem_free(const void *);
 
+static inline void *kmem_zalloc_large(size_t size)
+{
+	void *ptr;
+
+	ptr = vmalloc(size);
+	if (ptr)
+		memset(ptr, 0, size);
+	return ptr;
+}
+static inline void kmem_free_large(void *ptr)
+{
+	vfree(ptr);
+}
+
+extern void *kmem_zalloc_greedy(size_t *, size_t, size_t);
+
 /*
  * Zone interfaces
  */
Index: xfs/fs/xfs/quota/xfs_qm.c
===================================================================
--- xfs.orig/fs/xfs/quota/xfs_qm.c	2010-01-17 13:33:52.767254546 +0100
+++ xfs/fs/xfs/quota/xfs_qm.c	2010-01-17 21:07:10.921003908 +0100
@@ -118,9 +118,14 @@ xfs_Gqm_init(void)
 	 */
 	udqhash = kmem_zalloc_greedy(&hsize,
 				     XFS_QM_HASHSIZE_LOW * sizeof(xfs_dqhash_t),
-				     XFS_QM_HASHSIZE_HIGH * sizeof(xfs_dqhash_t),
-				     KM_SLEEP | KM_MAYFAIL | KM_LARGE);
-	gdqhash = kmem_zalloc(hsize, KM_SLEEP | KM_LARGE);
+				     XFS_QM_HASHSIZE_HIGH * sizeof(xfs_dqhash_t));
+	if (!udqhash)
+		goto out;
+
+	gdqhash = kmem_zalloc_large(hsize);
+	if (!udqhash)
+		goto out_free_udqhash;
+
 	hsize /= sizeof(xfs_dqhash_t);
 	ndquot = hsize << 8;
 
@@ -170,6 +175,11 @@ xfs_Gqm_init(void)
 	mutex_init(&qcheck_lock);
 #endif
 	return xqm;
+
+ out_free_udqhash:
+	kmem_free_large(udqhash);
+ out:
+	return NULL;
 }
 
 /*
@@ -189,8 +199,8 @@ xfs_qm_destroy(
 		xfs_qm_list_destroy(&(xqm->qm_usr_dqhtable[i]));
 		xfs_qm_list_destroy(&(xqm->qm_grp_dqhtable[i]));
 	}
-	kmem_free(xqm->qm_usr_dqhtable);
-	kmem_free(xqm->qm_grp_dqhtable);
+	kmem_free_large(xqm->qm_usr_dqhtable);
+	kmem_free_large(xqm->qm_grp_dqhtable);
 	xqm->qm_usr_dqhtable = NULL;
 	xqm->qm_grp_dqhtable = NULL;
 	xqm->qm_dqhashmask = 0;
@@ -219,8 +229,12 @@ xfs_qm_hold_quotafs_ref(
 	 */
 	mutex_lock(&xfs_Gqm_lock);
 
-	if (xfs_Gqm == NULL)
+	if (!xfs_Gqm) {
 		xfs_Gqm = xfs_Gqm_init();
+		if (!xfs_Gqm)
+			return ENOMEM;
+	}
+
 	/*
 	 * We can keep a list of all filesystems with quotas mounted for
 	 * debugging and statistical purposes, but ...
Index: xfs/fs/xfs/xfs_itable.c
===================================================================
--- xfs.orig/fs/xfs/xfs_itable.c	2010-01-17 13:33:52.778254478 +0100
+++ xfs/fs/xfs/xfs_itable.c	2010-01-17 21:07:10.922012487 +0100
@@ -408,8 +408,10 @@ xfs_bulkstat(
 		(XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog);
 	nimask = ~(nicluster - 1);
 	nbcluster = nicluster >> mp->m_sb.sb_inopblog;
-	irbuf = kmem_zalloc_greedy(&irbsize, PAGE_SIZE, PAGE_SIZE * 4,
-				   KM_SLEEP | KM_MAYFAIL | KM_LARGE);
+	irbuf = kmem_zalloc_greedy(&irbsize, PAGE_SIZE, PAGE_SIZE * 4);
+	if (!irbuf)
+		return ENOMEM;
+
 	nirbuf = irbsize / sizeof(*irbuf);
 
 	/*
@@ -727,7 +729,7 @@ xfs_bulkstat(
 	/*
 	 * Done, we're either out of filesystem or space to put the data.
 	 */
-	kmem_free(irbuf);
+	kmem_free_large(irbuf);
 	*ubcountp = ubelem;
 	/*
 	 * Found some inodes, return them now and return the error next time.
Index: xfs/fs/xfs/linux-2.6/xfs_buf.c
===================================================================
--- xfs.orig/fs/xfs/linux-2.6/xfs_buf.c	2010-01-17 15:06:01.607003933 +0100
+++ xfs/fs/xfs/linux-2.6/xfs_buf.c	2010-01-17 21:07:10.924003662 +0100
@@ -1525,8 +1525,8 @@ xfs_alloc_bufhash(
 
 	btp->bt_hashshift = external ? 3 : 8;	/* 8 or 256 buckets */
 	btp->bt_hashmask = (1 << btp->bt_hashshift) - 1;
-	btp->bt_hash = kmem_zalloc((1 << btp->bt_hashshift) *
-					sizeof(xfs_bufhash_t), KM_SLEEP | KM_LARGE);
+	btp->bt_hash = kmem_zalloc_large((1 << btp->bt_hashshift) *
+					 sizeof(xfs_bufhash_t));
 	for (i = 0; i < (1 << btp->bt_hashshift); i++) {
 		spin_lock_init(&btp->bt_hash[i].bh_lock);
 		INIT_LIST_HEAD(&btp->bt_hash[i].bh_list);
@@ -1537,7 +1537,7 @@ STATIC void
 xfs_free_bufhash(
 	xfs_buftarg_t		*btp)
 {
-	kmem_free(btp->bt_hash);
+	kmem_free_large(btp->bt_hash);
 	btp->bt_hash = NULL;
 }
 

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* RE: replace KM_LARGE with explicit vmalloc use
  2010-01-20 21:55 xfs: replace KM_LARGE with explicit vmalloc use Christoph Hellwig
@ 2010-01-21 19:06 ` Alex Elder
  0 siblings, 0 replies; 2+ messages in thread
From: Alex Elder @ 2010-01-21 19:06 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: xfs

Christoph Hellwig wrote:
> We use the KM_LARGE flag to make kmem_alloc and friends use vmalloc if
> nessecary.  As we only need this for a few boot/mount time allocations
> just switch to explicit vmalloc calls there.

I like this.  Simplifies kmalloc for everybody...

> Signed-off-by: Christoph Hellwig <hch@lst.de>

Reviewed-by: Alex Elder <aelder@sgi.com>


> Index: xfs/fs/xfs/linux-2.6/kmem.c
> ===================================================================
> --- xfs.orig/fs/xfs/linux-2.6/kmem.c	2010-01-17 13:33:52.749254562 +0100
> +++ xfs/fs/xfs/linux-2.6/kmem.c	2010-01-17 21:07:10.919003863 +0100
> @@ -16,7 +16,6 @@
>   * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
>   */
>  #include <linux/mm.h>
> -#include <linux/vmalloc.h>
>  #include <linux/highmem.h>
>  #include <linux/swap.h>
>  #include <linux/blkdev.h>
> @@ -24,8 +23,25 @@
>  #include "time.h"
>  #include "kmem.h"
> 
> -#define MAX_VMALLOCS	6
> -#define MAX_SLAB_SIZE	0x20000
> +/*
> + * Greedy allocation.  May fail and may return vmalloced memory.
> + *
> + * Must be freed using kmem_free_large.
> + */
> +void *
> +kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize)
> +{
> +	void		*ptr;
> +	size_t		kmsize = maxsize;
> +
> +	while (!(ptr = kmem_zalloc_large(kmsize))) {
> +		if ((kmsize >>= 1) <= minsize)
> +			kmsize = minsize;
> +	}
> +	if (ptr)
> +		*size = kmsize;
> +	return ptr;
> +}
> 
>  void *
>  kmem_alloc(size_t size, unsigned int __nocast flags)
> @@ -34,19 +50,8 @@ kmem_alloc(size_t size, unsigned int __n
>  	gfp_t	lflags = kmem_flags_convert(flags);
>  	void	*ptr;
> 
> -#ifdef DEBUG
> -	if (unlikely(!(flags & KM_LARGE) && (size > PAGE_SIZE))) {
> -		printk(KERN_WARNING "Large %s attempt, size=%ld\n",
> -			__func__, (long)size);
> -		dump_stack();
> -	}
> -#endif
> -
>  	do {
> -		if (size < MAX_SLAB_SIZE || retries > MAX_VMALLOCS)
> -			ptr = kmalloc(size, lflags);
> -		else
> -			ptr = __vmalloc(size, lflags, PAGE_KERNEL);
> +		ptr = kmalloc(size, lflags);
>  		if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP)))
>  			return ptr;
>  		if (!(++retries % 100))
> @@ -68,27 +73,6 @@ kmem_zalloc(size_t size, unsigned int __
>  	return ptr;
>  }
> 
> -void *
> -kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize,
> -		   unsigned int __nocast flags)
> -{
> -	void		*ptr;
> -	size_t		kmsize = maxsize;
> -	unsigned int	kmflags = (flags & ~KM_SLEEP) | KM_NOSLEEP;
> -
> -	while (!(ptr = kmem_zalloc(kmsize, kmflags))) {
> -		if ((kmsize <= minsize) && (flags & KM_NOSLEEP))
> -			break;
> -		if ((kmsize >>= 1) <= minsize) {
> -			kmsize = minsize;
> -			kmflags = flags;
> -		}
> -	}
> -	if (ptr)
> -		*size = kmsize;
> -	return ptr;
> -}
> -
>  void
>  kmem_free(const void *ptr)
>  {
> Index: xfs/fs/xfs/linux-2.6/kmem.h
> ===================================================================
> --- xfs.orig/fs/xfs/linux-2.6/kmem.h	2010-01-17 13:33:52.755254557 +0100
> +++ xfs/fs/xfs/linux-2.6/kmem.h	2010-01-17 21:07:10.919003863 +0100
> @@ -21,6 +21,7 @@
>  #include <linux/slab.h>
>  #include <linux/sched.h>
>  #include <linux/mm.h>
> +#include <linux/vmalloc.h>
> 
>  /*
>   * General memory allocation interfaces
> @@ -30,7 +31,6 @@
>  #define KM_NOSLEEP	0x0002u
>  #define KM_NOFS		0x0004u
>  #define KM_MAYFAIL	0x0008u
> -#define KM_LARGE	0x0010u
> 
>  /*
>   * We use a special process flag to avoid recursive callbacks into
> @@ -42,7 +42,7 @@ kmem_flags_convert(unsigned int __nocast
>  {
>  	gfp_t	lflags;
> 
> -	BUG_ON(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL|KM_LARGE));
> +	BUG_ON(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL));
> 
>  	if (flags & KM_NOSLEEP) {
>  		lflags = GFP_ATOMIC | __GFP_NOWARN;
> @@ -56,10 +56,25 @@ kmem_flags_convert(unsigned int __nocast
> 
>  extern void *kmem_alloc(size_t, unsigned int __nocast);
>  extern void *kmem_zalloc(size_t, unsigned int __nocast);
> -extern void *kmem_zalloc_greedy(size_t *, size_t, size_t, unsigned int __nocast);
>  extern void *kmem_realloc(const void *, size_t, size_t, unsigned int __nocast);
>  extern void  kmem_free(const void *);
> 
> +static inline void *kmem_zalloc_large(size_t size)
> +{
> +	void *ptr;
> +
> +	ptr = vmalloc(size);
> +	if (ptr)
> +		memset(ptr, 0, size);
> +	return ptr;
> +}
> +static inline void kmem_free_large(void *ptr)
> +{
> +	vfree(ptr);
> +}
> +
> +extern void *kmem_zalloc_greedy(size_t *, size_t, size_t);
> +
>  /*
>   * Zone interfaces
>   */
> Index: xfs/fs/xfs/quota/xfs_qm.c
> ===================================================================
> --- xfs.orig/fs/xfs/quota/xfs_qm.c	2010-01-17 13:33:52.767254546 +0100
> +++ xfs/fs/xfs/quota/xfs_qm.c	2010-01-17 21:07:10.921003908 +0100
> @@ -118,9 +118,14 @@ xfs_Gqm_init(void)
>  	 */
>  	udqhash = kmem_zalloc_greedy(&hsize,
>  				     XFS_QM_HASHSIZE_LOW * sizeof(xfs_dqhash_t),
> -				     XFS_QM_HASHSIZE_HIGH * sizeof(xfs_dqhash_t),
> -				     KM_SLEEP | KM_MAYFAIL | KM_LARGE);
> -	gdqhash = kmem_zalloc(hsize, KM_SLEEP | KM_LARGE);
> +				     XFS_QM_HASHSIZE_HIGH * sizeof(xfs_dqhash_t));
> +	if (!udqhash)
> +		goto out;
> +
> +	gdqhash = kmem_zalloc_large(hsize);
> +	if (!udqhash)
> +		goto out_free_udqhash;
> +
>  	hsize /= sizeof(xfs_dqhash_t);
>  	ndquot = hsize << 8;
> 
> @@ -170,6 +175,11 @@ xfs_Gqm_init(void)
>  	mutex_init(&qcheck_lock);
>  #endif
>  	return xqm;
> +
> + out_free_udqhash:
> +	kmem_free_large(udqhash);
> + out:
> +	return NULL;
>  }
> 
>  /*
> @@ -189,8 +199,8 @@ xfs_qm_destroy(
>  		xfs_qm_list_destroy(&(xqm->qm_usr_dqhtable[i]));
>  		xfs_qm_list_destroy(&(xqm->qm_grp_dqhtable[i]));
>  	}
> -	kmem_free(xqm->qm_usr_dqhtable);
> -	kmem_free(xqm->qm_grp_dqhtable);
> +	kmem_free_large(xqm->qm_usr_dqhtable);
> +	kmem_free_large(xqm->qm_grp_dqhtable);
>  	xqm->qm_usr_dqhtable = NULL;
>  	xqm->qm_grp_dqhtable = NULL;
>  	xqm->qm_dqhashmask = 0;
> @@ -219,8 +229,12 @@ xfs_qm_hold_quotafs_ref(
>  	 */
>  	mutex_lock(&xfs_Gqm_lock);
> 
> -	if (xfs_Gqm == NULL)
> +	if (!xfs_Gqm) {
>  		xfs_Gqm = xfs_Gqm_init();
> +		if (!xfs_Gqm)
> +			return ENOMEM;
> +	}
> +
>  	/*
>  	 * We can keep a list of all filesystems with quotas mounted for
>  	 * debugging and statistical purposes, but ...
> Index: xfs/fs/xfs/xfs_itable.c
> ===================================================================
> --- xfs.orig/fs/xfs/xfs_itable.c	2010-01-17 13:33:52.778254478 +0100
> +++ xfs/fs/xfs/xfs_itable.c	2010-01-17 21:07:10.922012487 +0100
> @@ -408,8 +408,10 @@ xfs_bulkstat(
>  		(XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog);
>  	nimask = ~(nicluster - 1);
>  	nbcluster = nicluster >> mp->m_sb.sb_inopblog;
> -	irbuf = kmem_zalloc_greedy(&irbsize, PAGE_SIZE, PAGE_SIZE * 4,
> -				   KM_SLEEP | KM_MAYFAIL | KM_LARGE);
> +	irbuf = kmem_zalloc_greedy(&irbsize, PAGE_SIZE, PAGE_SIZE * 4);
> +	if (!irbuf)
> +		return ENOMEM;
> +
>  	nirbuf = irbsize / sizeof(*irbuf);
> 
>  	/*
> @@ -727,7 +729,7 @@ xfs_bulkstat(
>  	/*
>  	 * Done, we're either out of filesystem or space to put the data.
>  	 */
> -	kmem_free(irbuf);
> +	kmem_free_large(irbuf);
>  	*ubcountp = ubelem;
>  	/*
>  	 * Found some inodes, return them now and return the error next time.
> Index: xfs/fs/xfs/linux-2.6/xfs_buf.c
> ===================================================================
> --- xfs.orig/fs/xfs/linux-2.6/xfs_buf.c	2010-01-17 15:06:01.607003933 +0100
> +++ xfs/fs/xfs/linux-2.6/xfs_buf.c	2010-01-17 21:07:10.924003662 +0100
> @@ -1525,8 +1525,8 @@ xfs_alloc_bufhash(
> 
>  	btp->bt_hashshift = external ? 3 : 8;	/* 8 or 256 buckets */
>  	btp->bt_hashmask = (1 << btp->bt_hashshift) - 1;
> -	btp->bt_hash = kmem_zalloc((1 << btp->bt_hashshift) *
> -					sizeof(xfs_bufhash_t), KM_SLEEP | KM_LARGE);
> +	btp->bt_hash = kmem_zalloc_large((1 << btp->bt_hashshift) *
> +					 sizeof(xfs_bufhash_t));
>  	for (i = 0; i < (1 << btp->bt_hashshift); i++) {
>  		spin_lock_init(&btp->bt_hash[i].bh_lock);
>  		INIT_LIST_HEAD(&btp->bt_hash[i].bh_list);
> @@ -1537,7 +1537,7 @@ STATIC void
>  xfs_free_bufhash(
>  	xfs_buftarg_t		*btp)
>  {
> -	kmem_free(btp->bt_hash);
> +	kmem_free_large(btp->bt_hash);
>  	btp->bt_hash = NULL;
>  }
> 
> 
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

end of thread, other threads:[~2010-01-21 19:05 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-01-20 21:55 xfs: replace KM_LARGE with explicit vmalloc use Christoph Hellwig
2010-01-21 19:06 ` Alex Elder

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox