Commit fdd3ccee authored by Dave Chinner's avatar Dave Chinner Committed by Ben Myers

xfs: factor all the kmalloc-or-vmalloc fallback allocations

We have quite a few places now where we do:

	x = kmem_zalloc(large size)
	if (!x)
		x = kmem_zalloc_large(large size)

and do a similar dance when freeing the memory. kmem_free() already
does the correct freeing dance, and kmem_zalloc_large() is only ever
called in these constructs, so just factor it all into
kmem_zalloc_large() and kmem_free().
Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarMark Tinguely <tinguely@sgi.com>
Signed-off-by: default avatarBen Myers <bpm@sgi.com>
parent 2dc164f2
...@@ -27,8 +27,6 @@ ...@@ -27,8 +27,6 @@
/* /*
* Greedy allocation. May fail and may return vmalloced memory. * Greedy allocation. May fail and may return vmalloced memory.
*
* Must be freed using kmem_free_large.
*/ */
void * void *
kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize) kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize)
...@@ -36,7 +34,7 @@ kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize) ...@@ -36,7 +34,7 @@ kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize)
void *ptr; void *ptr;
size_t kmsize = maxsize; size_t kmsize = maxsize;
while (!(ptr = kmem_zalloc_large(kmsize))) { while (!(ptr = vzalloc(kmsize))) {
if ((kmsize >>= 1) <= minsize) if ((kmsize >>= 1) <= minsize)
kmsize = minsize; kmsize = minsize;
} }
...@@ -75,6 +73,17 @@ kmem_zalloc(size_t size, xfs_km_flags_t flags) ...@@ -75,6 +73,17 @@ kmem_zalloc(size_t size, xfs_km_flags_t flags)
return ptr; return ptr;
} }
void *
kmem_zalloc_large(size_t size, xfs_km_flags_t flags)
{
void *ptr;
ptr = kmem_zalloc(size, flags | KM_MAYFAIL);
if (ptr)
return ptr;
return vzalloc(size);
}
void void
kmem_free(const void *ptr) kmem_free(const void *ptr)
{ {
......
...@@ -57,17 +57,10 @@ kmem_flags_convert(xfs_km_flags_t flags) ...@@ -57,17 +57,10 @@ kmem_flags_convert(xfs_km_flags_t flags)
extern void *kmem_alloc(size_t, xfs_km_flags_t); extern void *kmem_alloc(size_t, xfs_km_flags_t);
extern void *kmem_zalloc(size_t, xfs_km_flags_t); extern void *kmem_zalloc(size_t, xfs_km_flags_t);
extern void *kmem_zalloc_large(size_t size, xfs_km_flags_t);
extern void *kmem_realloc(const void *, size_t, size_t, xfs_km_flags_t); extern void *kmem_realloc(const void *, size_t, size_t, xfs_km_flags_t);
extern void kmem_free(const void *); extern void kmem_free(const void *);
static inline void *kmem_zalloc_large(size_t size)
{
return vzalloc(size);
}
static inline void kmem_free_large(void *ptr)
{
vfree(ptr);
}
extern void *kmem_zalloc_greedy(size_t *, size_t, size_t); extern void *kmem_zalloc_greedy(size_t *, size_t, size_t);
......
...@@ -152,12 +152,9 @@ xfs_get_acl(struct inode *inode, int type) ...@@ -152,12 +152,9 @@ xfs_get_acl(struct inode *inode, int type)
* go out to the disk. * go out to the disk.
*/ */
len = XFS_ACL_MAX_SIZE(ip->i_mount); len = XFS_ACL_MAX_SIZE(ip->i_mount);
xfs_acl = kmem_zalloc(len, KM_SLEEP | KM_MAYFAIL); xfs_acl = kmem_zalloc_large(len, KM_SLEEP);
if (!xfs_acl) { if (!xfs_acl)
xfs_acl = kmem_zalloc_large(len); return ERR_PTR(-ENOMEM);
if (!xfs_acl)
return ERR_PTR(-ENOMEM);
}
error = -xfs_attr_get(ip, ea_name, (unsigned char *)xfs_acl, error = -xfs_attr_get(ip, ea_name, (unsigned char *)xfs_acl,
&len, ATTR_ROOT); &len, ATTR_ROOT);
...@@ -181,10 +178,7 @@ xfs_get_acl(struct inode *inode, int type) ...@@ -181,10 +178,7 @@ xfs_get_acl(struct inode *inode, int type)
out_update_cache: out_update_cache:
set_cached_acl(inode, type, acl); set_cached_acl(inode, type, acl);
out: out:
if (is_vmalloc_addr(xfs_acl)) kmem_free(xfs_acl);
kmem_free_large(xfs_acl);
else
kfree(xfs_acl);
return acl; return acl;
} }
...@@ -215,12 +209,9 @@ xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) ...@@ -215,12 +209,9 @@ xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
struct xfs_acl *xfs_acl; struct xfs_acl *xfs_acl;
int len = XFS_ACL_MAX_SIZE(ip->i_mount); int len = XFS_ACL_MAX_SIZE(ip->i_mount);
xfs_acl = kmem_zalloc(len, KM_SLEEP | KM_MAYFAIL); xfs_acl = kmem_zalloc_large(len, KM_SLEEP);
if (!xfs_acl) { if (!xfs_acl)
xfs_acl = kmem_zalloc_large(len); return -ENOMEM;
if (!xfs_acl)
return -ENOMEM;
}
xfs_acl_to_disk(xfs_acl, acl); xfs_acl_to_disk(xfs_acl, acl);
...@@ -231,10 +222,7 @@ xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) ...@@ -231,10 +222,7 @@ xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
error = -xfs_attr_set(ip, ea_name, (unsigned char *)xfs_acl, error = -xfs_attr_set(ip, ea_name, (unsigned char *)xfs_acl,
len, ATTR_ROOT); len, ATTR_ROOT);
if (is_vmalloc_addr(xfs_acl)) kmem_free(xfs_acl);
kmem_free_large(xfs_acl);
else
kfree(xfs_acl);
} else { } else {
/* /*
* A NULL ACL argument means we want to remove the ACL. * A NULL ACL argument means we want to remove the ACL.
......
...@@ -612,13 +612,9 @@ xfs_getbmap( ...@@ -612,13 +612,9 @@ xfs_getbmap(
if (bmv->bmv_count > ULONG_MAX / sizeof(struct getbmapx)) if (bmv->bmv_count > ULONG_MAX / sizeof(struct getbmapx))
return XFS_ERROR(ENOMEM); return XFS_ERROR(ENOMEM);
out = kmem_zalloc(bmv->bmv_count * sizeof(struct getbmapx), KM_MAYFAIL); out = kmem_zalloc_large(bmv->bmv_count * sizeof(struct getbmapx), 0);
if (!out) { if (!out)
out = kmem_zalloc_large(bmv->bmv_count * return XFS_ERROR(ENOMEM);
sizeof(struct getbmapx));
if (!out)
return XFS_ERROR(ENOMEM);
}
xfs_ilock(ip, XFS_IOLOCK_SHARED); xfs_ilock(ip, XFS_IOLOCK_SHARED);
if (whichfork == XFS_DATA_FORK && !(iflags & BMV_IF_DELALLOC)) { if (whichfork == XFS_DATA_FORK && !(iflags & BMV_IF_DELALLOC)) {
...@@ -754,10 +750,7 @@ xfs_getbmap( ...@@ -754,10 +750,7 @@ xfs_getbmap(
break; break;
} }
if (is_vmalloc_addr(out)) kmem_free(out);
kmem_free_large(out);
else
kmem_free(out);
return error; return error;
} }
......
...@@ -456,12 +456,9 @@ xfs_attrlist_by_handle( ...@@ -456,12 +456,9 @@ xfs_attrlist_by_handle(
if (IS_ERR(dentry)) if (IS_ERR(dentry))
return PTR_ERR(dentry); return PTR_ERR(dentry);
kbuf = kmem_zalloc(al_hreq.buflen, KM_SLEEP | KM_MAYFAIL); kbuf = kmem_zalloc_large(al_hreq.buflen, KM_SLEEP);
if (!kbuf) { if (!kbuf)
kbuf = kmem_zalloc_large(al_hreq.buflen); goto out_dput;
if (!kbuf)
goto out_dput;
}
cursor = (attrlist_cursor_kern_t *)&al_hreq.pos; cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
error = -xfs_attr_list(XFS_I(dentry->d_inode), kbuf, al_hreq.buflen, error = -xfs_attr_list(XFS_I(dentry->d_inode), kbuf, al_hreq.buflen,
...@@ -472,12 +469,9 @@ xfs_attrlist_by_handle( ...@@ -472,12 +469,9 @@ xfs_attrlist_by_handle(
if (copy_to_user(al_hreq.buffer, kbuf, al_hreq.buflen)) if (copy_to_user(al_hreq.buffer, kbuf, al_hreq.buflen))
error = -EFAULT; error = -EFAULT;
out_kfree: out_kfree:
if (is_vmalloc_addr(kbuf)) kmem_free(kbuf);
kmem_free_large(kbuf); out_dput:
else
kmem_free(kbuf);
out_dput:
dput(dentry); dput(dentry);
return error; return error;
} }
...@@ -495,12 +489,9 @@ xfs_attrmulti_attr_get( ...@@ -495,12 +489,9 @@ xfs_attrmulti_attr_get(
if (*len > XATTR_SIZE_MAX) if (*len > XATTR_SIZE_MAX)
return EINVAL; return EINVAL;
kbuf = kmem_zalloc(*len, KM_SLEEP | KM_MAYFAIL); kbuf = kmem_zalloc_large(*len, KM_SLEEP);
if (!kbuf) { if (!kbuf)
kbuf = kmem_zalloc_large(*len); return ENOMEM;
if (!kbuf)
return ENOMEM;
}
error = xfs_attr_get(XFS_I(inode), name, kbuf, (int *)len, flags); error = xfs_attr_get(XFS_I(inode), name, kbuf, (int *)len, flags);
if (error) if (error)
...@@ -509,11 +500,8 @@ xfs_attrmulti_attr_get( ...@@ -509,11 +500,8 @@ xfs_attrmulti_attr_get(
if (copy_to_user(ubuf, kbuf, *len)) if (copy_to_user(ubuf, kbuf, *len))
error = EFAULT; error = EFAULT;
out_kfree: out_kfree:
if (is_vmalloc_addr(kbuf)) kmem_free(kbuf);
kmem_free_large(kbuf);
else
kmem_free(kbuf);
return error; return error;
} }
......
...@@ -371,12 +371,9 @@ xfs_compat_attrlist_by_handle( ...@@ -371,12 +371,9 @@ xfs_compat_attrlist_by_handle(
return PTR_ERR(dentry); return PTR_ERR(dentry);
error = -ENOMEM; error = -ENOMEM;
kbuf = kmem_zalloc(al_hreq.buflen, KM_SLEEP | KM_MAYFAIL); kbuf = kmem_zalloc_large(al_hreq.buflen, KM_SLEEP);
if (!kbuf) { if (!kbuf)
kbuf = kmem_zalloc_large(al_hreq.buflen); goto out_dput;
if (!kbuf)
goto out_dput;
}
cursor = (attrlist_cursor_kern_t *)&al_hreq.pos; cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
error = -xfs_attr_list(XFS_I(dentry->d_inode), kbuf, al_hreq.buflen, error = -xfs_attr_list(XFS_I(dentry->d_inode), kbuf, al_hreq.buflen,
...@@ -387,12 +384,9 @@ xfs_compat_attrlist_by_handle( ...@@ -387,12 +384,9 @@ xfs_compat_attrlist_by_handle(
if (copy_to_user(compat_ptr(al_hreq.buffer), kbuf, al_hreq.buflen)) if (copy_to_user(compat_ptr(al_hreq.buffer), kbuf, al_hreq.buflen))
error = -EFAULT; error = -EFAULT;
out_kfree: out_kfree:
if (is_vmalloc_addr(kbuf)) kmem_free(kbuf);
kmem_free_large(kbuf); out_dput:
else
kmem_free(kbuf);
out_dput:
dput(dentry); dput(dentry);
return error; return error;
} }
......
...@@ -495,7 +495,7 @@ xfs_bulkstat( ...@@ -495,7 +495,7 @@ xfs_bulkstat(
/* /*
* Done, we're either out of filesystem or space to put the data. * Done, we're either out of filesystem or space to put the data.
*/ */
kmem_free_large(irbuf); kmem_free(irbuf);
*ubcountp = ubelem; *ubcountp = ubelem;
/* /*
* Found some inodes, return them now and return the error next time. * Found some inodes, return them now and return the error next time.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment