diff options
Diffstat (limited to 'fs/ext4/richacl.c')
| -rw-r--r-- | fs/ext4/richacl.c | 86 |
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; |
