Merge tag 'for-linus-5.7-1' of git://github.com/cminyard/linux-ipmi
[linux-block.git] / fs / xattr.c
index 90dd78f0eb279d4729d7f36e0bab3d2816bd002c..e13265e65871f4fc1f09e13bb410c3f44d2d6882 100644 (file)
@@ -817,7 +817,7 @@ struct simple_xattr *simple_xattr_alloc(const void *value, size_t size)
        if (len < sizeof(*new_xattr))
                return NULL;
 
-       new_xattr = kmalloc(len, GFP_KERNEL);
+       new_xattr = kvmalloc(len, GFP_KERNEL);
        if (!new_xattr)
                return NULL;
 
@@ -860,6 +860,7 @@ int simple_xattr_get(struct simple_xattrs *xattrs, const char *name,
  * @value: value of the xattr. If %NULL, will remove the attribute.
  * @size: size of the new xattr
  * @flags: %XATTR_{CREATE|REPLACE}
+ * @removed_size: returns size of the removed xattr, -1 if none removed
  *
  * %XATTR_CREATE is set, the xattr shouldn't exist already; otherwise fails
  * with -EEXIST.  If %XATTR_REPLACE is set, the xattr should exist;
@@ -868,7 +869,8 @@ int simple_xattr_get(struct simple_xattrs *xattrs, const char *name,
  * Returns 0 on success, -errno on failure.
  */
 int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
-                    const void *value, size_t size, int flags)
+                    const void *value, size_t size, int flags,
+                    ssize_t *removed_size)
 {
        struct simple_xattr *xattr;
        struct simple_xattr *new_xattr = NULL;
@@ -882,7 +884,7 @@ int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
 
                new_xattr->name = kstrdup(name, GFP_KERNEL);
                if (!new_xattr->name) {
-                       kfree(new_xattr);
+                       kvfree(new_xattr);
                        return -ENOMEM;
                }
        }
@@ -895,8 +897,12 @@ int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
                                err = -EEXIST;
                        } else if (new_xattr) {
                                list_replace(&xattr->list, &new_xattr->list);
+                               if (removed_size)
+                                       *removed_size = xattr->size;
                        } else {
                                list_del(&xattr->list);
+                               if (removed_size)
+                                       *removed_size = xattr->size;
                        }
                        goto out;
                }
@@ -908,11 +914,14 @@ int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
                list_add(&new_xattr->list, &xattrs->head);
                xattr = NULL;
        }
+
+       if (removed_size)
+               *removed_size = -1;
 out:
        spin_unlock(&xattrs->lock);
        if (xattr) {
                kfree(xattr->name);
-               kfree(xattr);
+               kvfree(xattr);
        }
        return err;