xfs
[Top] [All Lists]

[PATCH 1/2] xfs: fix memory allocation failures with ACLs

To: xfs@xxxxxxxxxxx
Subject: [PATCH 1/2] xfs: fix memory allocation failures with ACLs
From: Dave Chinner <david@xxxxxxxxxxxxx>
Date: Mon, 2 Sep 2013 20:52:59 +1000
Delivered-to: xfs@xxxxxxxxxxx
In-reply-to: <1378119180-31380-1-git-send-email-david@xxxxxxxxxxxxx>
References: <1378119180-31380-1-git-send-email-david@xxxxxxxxxxxxx>
From: Dave Chinner <dchinner@xxxxxxxxxx>

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@xxxxxxxxxx>
---
 fs/xfs/xfs_acl.c | 32 ++++++++++++++++++++++----------
 1 file changed, 22 insertions(+), 10 deletions(-)

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 @@ 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.
-- 
1.8.3.2

<Prev in Thread] Current Thread [Next in Thread>