Skip to content

Commit

Permalink
fs/xattr.c:listxattr(): fall back to vmalloc() if kmalloc() failed
Browse files Browse the repository at this point in the history
This allocation can be as large as 64k.  As David points out, "falling
back to vmalloc here is much better solution than failing to retreive
the attribute - it will work no matter how fragmented memory gets.  That
means we don't get incomplete backups occurring after days or months of
uptime and successful backups".

Cc: Dave Chinner <[email protected]>
Cc: Dave Jones <[email protected]>
Cc: David Rientjes <[email protected]>
Cc: Al Viro <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
akpm00 authored and torvalds committed Apr 5, 2012
1 parent 703bf2d commit 0d08d7b
Showing 1 changed file with 13 additions and 4 deletions.
17 changes: 13 additions & 4 deletions fs/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
#include <linux/export.h>
#include <linux/fsnotify.h>
#include <linux/audit.h>
#include <asm/uaccess.h>
#include <linux/vmalloc.h>

#include <asm/uaccess.h>

/*
* Check permissions for extended attribute access. This is a bit complicated
Expand Down Expand Up @@ -492,13 +493,18 @@ listxattr(struct dentry *d, char __user *list, size_t size)
{
ssize_t error;
char *klist = NULL;
char *vlist = NULL; /* If non-NULL, we used vmalloc() */

if (size) {
if (size > XATTR_LIST_MAX)
size = XATTR_LIST_MAX;
klist = kmalloc(size, __GFP_NOWARN | GFP_KERNEL);
if (!klist)
return -ENOMEM;
if (!klist) {
vlist = vmalloc(size);
if (!vlist)
return -ENOMEM;
klist = vlist;
}
}

error = vfs_listxattr(d, klist, size);
Expand All @@ -510,7 +516,10 @@ listxattr(struct dentry *d, char __user *list, size_t size)
than XATTR_LIST_MAX bytes. Not possible. */
error = -E2BIG;
}
kfree(klist);
if (vlist)
vfree(vlist);
else
kfree(klist);
return error;
}

Expand Down

0 comments on commit 0d08d7b

Please sign in to comment.