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>
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 6951896..4ea73cc 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -152,9 +152,12 @@
* 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 @@
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 @@
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 @@
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.