summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2013-09-02 20:52:59 +1000
committerBen Myers <bpm@sgi.com>2013-09-10 13:56:25 -0500
commit2dc164f2965b92a6efd2edb9e2813271741e96db (patch)
tree2687c83330c2328b0ffc49ff5a414a4d53280b77
parent0a4edc8f0b54cd5f613e7fda7dc8106cb9869bc9 (diff)
xfs: fix memory allocation failures with ACLs
Ever since increasing the number of supported ACLs from 25 to as many as can fit in an xattr, there have been reports of order 4 memory allocations failing in the ACL code. Fix it in the same way we've fixed all the xattr read/write code that has the same problem. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Mark Tinguely <tinguely@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
-rw-r--r--fs/xfs/xfs_acl.c32
1 files changed, 22 insertions, 10 deletions
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 69518960b2ba..4ea73cc44259 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -152,9 +152,12 @@ xfs_get_acl(struct inode *inode, int type)
* go out to the disk.
*/
len = XFS_ACL_MAX_SIZE(ip->i_mount);
- xfs_acl = kzalloc(len, GFP_KERNEL);
- if (!xfs_acl)
- return ERR_PTR(-ENOMEM);
+ xfs_acl = kmem_zalloc(len, KM_SLEEP | KM_MAYFAIL);
+ if (!xfs_acl) {
+ xfs_acl = kmem_zalloc_large(len);
+ if (!xfs_acl)
+ return ERR_PTR(-ENOMEM);
+ }
error = -xfs_attr_get(ip, ea_name, (unsigned char *)xfs_acl,
&len, ATTR_ROOT);
@@ -175,10 +178,13 @@ xfs_get_acl(struct inode *inode, int type)
if (IS_ERR(acl))
goto out;
- out_update_cache:
+out_update_cache:
set_cached_acl(inode, type, acl);
- out:
- kfree(xfs_acl);
+out:
+ if (is_vmalloc_addr(xfs_acl))
+ kmem_free_large(xfs_acl);
+ else
+ kfree(xfs_acl);
return acl;
}
@@ -209,9 +215,12 @@ xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
struct xfs_acl *xfs_acl;
int len = XFS_ACL_MAX_SIZE(ip->i_mount);
- xfs_acl = kzalloc(len, GFP_KERNEL);
- if (!xfs_acl)
- return -ENOMEM;
+ xfs_acl = kmem_zalloc(len, KM_SLEEP | KM_MAYFAIL);
+ if (!xfs_acl) {
+ xfs_acl = kmem_zalloc_large(len);
+ if (!xfs_acl)
+ return -ENOMEM;
+ }
xfs_acl_to_disk(xfs_acl, acl);
@@ -222,7 +231,10 @@ xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
error = -xfs_attr_set(ip, ea_name, (unsigned char *)xfs_acl,
len, ATTR_ROOT);
- kfree(xfs_acl);
+ if (is_vmalloc_addr(xfs_acl))
+ kmem_free_large(xfs_acl);
+ else
+ kfree(xfs_acl);
} else {
/*
* A NULL ACL argument means we want to remove the ACL.