]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
xfs: fix memory allocation failures with ACLs
authorDave Chinner <dchinner@redhat.com>
Mon, 2 Sep 2013 10:52:59 +0000 (20:52 +1000)
committerBen Myers <bpm@sgi.com>
Tue, 10 Sep 2013 18:56:25 +0000 (13:56 -0500)
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>
fs/xfs/xfs_acl.c

index 69518960b2ba17e888d71f75d30e4df57d0cca73..4ea73cc44259030acdc7f66c8af3ff1f2cd88615 100644 (file)
@@ -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.