aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/richacl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/richacl.c')
-rw-r--r--fs/ext4/richacl.c86
1 files changed, 49 insertions, 37 deletions
diff --git a/fs/ext4/richacl.c b/fs/ext4/richacl.c
index 2581117..2115385 100644
--- a/fs/ext4/richacl.c
+++ b/fs/ext4/richacl.c
@@ -1,7 +1,8 @@
/*
* Copyright IBM Corporation, 2010
* Copyright (C) 2015 Red Hat, Inc.
- * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
+ * Author: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>,
+ * Andreas Gruenbacher <agruenba@redhat.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2.1 of the GNU Lesser General Public License
@@ -28,7 +29,7 @@ ext4_get_richacl(struct inode *inode)
{
const int name_index = EXT4_XATTR_INDEX_RICHACL;
void *value = NULL;
- struct richacl *acl;
+ struct richacl *acl = NULL;
int retval;
retval = ext4_xattr_get(inode, name_index, "", NULL, 0);
@@ -42,9 +43,7 @@ ext4_get_richacl(struct inode *inode)
acl = richacl_from_xattr(&init_user_ns, value, retval);
if (acl == ERR_PTR(-EINVAL))
acl = ERR_PTR(-EIO);
- } else if (retval == -ENODATA || retval == -ENOSYS)
- acl = NULL;
- else
+ } else if (retval != -ENODATA && retval != -ENOSYS)
acl = ERR_PTR(retval);
kfree(value);
@@ -55,46 +54,55 @@ ext4_get_richacl(struct inode *inode)
}
static int
+__ext4_remove_richacl(handle_t *handle, struct inode *inode)
+{
+ const int name_index = EXT4_XATTR_INDEX_RICHACL;
+ int retval;
+
+ retval = ext4_xattr_set_handle(handle, inode, name_index, "",
+ NULL, 0, 0);
+ if (!retval)
+ set_cached_richacl(inode, NULL);
+ return retval;
+}
+
+static int
__ext4_set_richacl(handle_t *handle, struct inode *inode, struct richacl *acl)
{
const int name_index = EXT4_XATTR_INDEX_RICHACL;
umode_t mode = inode->i_mode;
- int retval;
+ int retval, size;
+ void *value;
- if (acl) {
- /* Don't allow acls with unmapped identifiers. */
- if (richacl_has_unmapped_identifiers(acl))
- return -EINVAL;
-
- if (richacl_equiv_mode(acl, &mode) == 0) {
- inode->i_ctime = ext4_current_time(inode);
- inode->i_mode = mode;
- ext4_mark_inode_dirty(handle, inode);
- acl = NULL;
- }
+ /* Don't allow acls with unmapped identifiers. */
+ if (richacl_has_unmapped_identifiers(acl))
+ return -EINVAL;
+
+ if (richacl_equiv_mode(acl, &mode) == 0) {
+ inode->i_ctime = ext4_current_time(inode);
+ inode->i_mode = mode;
+ ext4_mark_inode_dirty(handle, inode);
+ return __ext4_remove_richacl(handle, inode);
}
- if (acl) {
- void *value;
- size_t size = richacl_xattr_size(acl);
- mode &= ~S_IRWXUGO;
- mode |= richacl_masks_to_mode(acl);
+ mode &= ~S_IRWXUGO;
+ mode |= richacl_masks_to_mode(acl);
+
+ size = richacl_xattr_size(acl);
+ value = kmalloc(size, GFP_NOFS);
+ if (!value)
+ return -ENOMEM;
+ richacl_to_xattr(&init_user_ns, acl, value, size);
+ inode->i_mode = mode;
+ retval = ext4_xattr_set_handle(handle, inode, name_index, "",
+ value, size, 0);
+ kfree(value);
+ if (retval)
+ return retval;
- value = kmalloc(size, GFP_NOFS);
- if (!value)
- return -ENOMEM;
- richacl_to_xattr(&init_user_ns, acl, value, size);
- inode->i_mode = mode;
- retval = ext4_xattr_set_handle(handle, inode, name_index, "",
- value, size, 0);
- kfree(value);
- } else
- retval = ext4_xattr_set_handle(handle, inode, name_index, "",
- NULL, 0, 0);
- if (!retval)
- set_cached_richacl(inode, acl);
+ set_cached_richacl(inode, acl);
- return retval;
+ return 0;
}
int
@@ -109,7 +117,11 @@ retry:
if (IS_ERR(handle))
return PTR_ERR(handle);
- retval = __ext4_set_richacl(handle, inode, acl);
+ if (acl)
+ retval = __ext4_set_richacl(handle, inode, acl);
+ else
+ retval = __ext4_remove_richacl(handle, inode);
+
ext4_journal_stop(handle);
if (retval == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
goto retry;