162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * acl.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2004, 2008 Oracle. All rights reserved. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * CREDITS: 862306a36Sopenharmony_ci * Lots of code in this file is copy from linux/fs/ext3/acl.c. 962306a36Sopenharmony_ci * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de> 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/init.h> 1362306a36Sopenharmony_ci#include <linux/module.h> 1462306a36Sopenharmony_ci#include <linux/slab.h> 1562306a36Sopenharmony_ci#include <linux/string.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <cluster/masklog.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include "ocfs2.h" 2062306a36Sopenharmony_ci#include "alloc.h" 2162306a36Sopenharmony_ci#include "dlmglue.h" 2262306a36Sopenharmony_ci#include "file.h" 2362306a36Sopenharmony_ci#include "inode.h" 2462306a36Sopenharmony_ci#include "journal.h" 2562306a36Sopenharmony_ci#include "ocfs2_fs.h" 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#include "xattr.h" 2862306a36Sopenharmony_ci#include "acl.h" 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/* 3162306a36Sopenharmony_ci * Convert from xattr value to acl struct. 3262306a36Sopenharmony_ci */ 3362306a36Sopenharmony_cistatic struct posix_acl *ocfs2_acl_from_xattr(const void *value, size_t size) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci int n, count; 3662306a36Sopenharmony_ci struct posix_acl *acl; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci if (!value) 3962306a36Sopenharmony_ci return NULL; 4062306a36Sopenharmony_ci if (size < sizeof(struct posix_acl_entry)) 4162306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci count = size / sizeof(struct posix_acl_entry); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci acl = posix_acl_alloc(count, GFP_NOFS); 4662306a36Sopenharmony_ci if (!acl) 4762306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 4862306a36Sopenharmony_ci for (n = 0; n < count; n++) { 4962306a36Sopenharmony_ci struct ocfs2_acl_entry *entry = 5062306a36Sopenharmony_ci (struct ocfs2_acl_entry *)value; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci acl->a_entries[n].e_tag = le16_to_cpu(entry->e_tag); 5362306a36Sopenharmony_ci acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm); 5462306a36Sopenharmony_ci switch(acl->a_entries[n].e_tag) { 5562306a36Sopenharmony_ci case ACL_USER: 5662306a36Sopenharmony_ci acl->a_entries[n].e_uid = 5762306a36Sopenharmony_ci make_kuid(&init_user_ns, 5862306a36Sopenharmony_ci le32_to_cpu(entry->e_id)); 5962306a36Sopenharmony_ci break; 6062306a36Sopenharmony_ci case ACL_GROUP: 6162306a36Sopenharmony_ci acl->a_entries[n].e_gid = 6262306a36Sopenharmony_ci make_kgid(&init_user_ns, 6362306a36Sopenharmony_ci le32_to_cpu(entry->e_id)); 6462306a36Sopenharmony_ci break; 6562306a36Sopenharmony_ci default: 6662306a36Sopenharmony_ci break; 6762306a36Sopenharmony_ci } 6862306a36Sopenharmony_ci value += sizeof(struct posix_acl_entry); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci } 7162306a36Sopenharmony_ci return acl; 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci/* 7562306a36Sopenharmony_ci * Convert acl struct to xattr value. 7662306a36Sopenharmony_ci */ 7762306a36Sopenharmony_cistatic void *ocfs2_acl_to_xattr(const struct posix_acl *acl, size_t *size) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci struct ocfs2_acl_entry *entry = NULL; 8062306a36Sopenharmony_ci char *ocfs2_acl; 8162306a36Sopenharmony_ci size_t n; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci *size = acl->a_count * sizeof(struct posix_acl_entry); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci ocfs2_acl = kmalloc(*size, GFP_NOFS); 8662306a36Sopenharmony_ci if (!ocfs2_acl) 8762306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci entry = (struct ocfs2_acl_entry *)ocfs2_acl; 9062306a36Sopenharmony_ci for (n = 0; n < acl->a_count; n++, entry++) { 9162306a36Sopenharmony_ci entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag); 9262306a36Sopenharmony_ci entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm); 9362306a36Sopenharmony_ci switch(acl->a_entries[n].e_tag) { 9462306a36Sopenharmony_ci case ACL_USER: 9562306a36Sopenharmony_ci entry->e_id = cpu_to_le32( 9662306a36Sopenharmony_ci from_kuid(&init_user_ns, 9762306a36Sopenharmony_ci acl->a_entries[n].e_uid)); 9862306a36Sopenharmony_ci break; 9962306a36Sopenharmony_ci case ACL_GROUP: 10062306a36Sopenharmony_ci entry->e_id = cpu_to_le32( 10162306a36Sopenharmony_ci from_kgid(&init_user_ns, 10262306a36Sopenharmony_ci acl->a_entries[n].e_gid)); 10362306a36Sopenharmony_ci break; 10462306a36Sopenharmony_ci default: 10562306a36Sopenharmony_ci entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID); 10662306a36Sopenharmony_ci break; 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci return ocfs2_acl; 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic struct posix_acl *ocfs2_get_acl_nolock(struct inode *inode, 11362306a36Sopenharmony_ci int type, 11462306a36Sopenharmony_ci struct buffer_head *di_bh) 11562306a36Sopenharmony_ci{ 11662306a36Sopenharmony_ci int name_index; 11762306a36Sopenharmony_ci char *value = NULL; 11862306a36Sopenharmony_ci struct posix_acl *acl; 11962306a36Sopenharmony_ci int retval; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci switch (type) { 12262306a36Sopenharmony_ci case ACL_TYPE_ACCESS: 12362306a36Sopenharmony_ci name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS; 12462306a36Sopenharmony_ci break; 12562306a36Sopenharmony_ci case ACL_TYPE_DEFAULT: 12662306a36Sopenharmony_ci name_index = OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT; 12762306a36Sopenharmony_ci break; 12862306a36Sopenharmony_ci default: 12962306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci retval = ocfs2_xattr_get_nolock(inode, di_bh, name_index, "", NULL, 0); 13362306a36Sopenharmony_ci if (retval > 0) { 13462306a36Sopenharmony_ci value = kmalloc(retval, GFP_NOFS); 13562306a36Sopenharmony_ci if (!value) 13662306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 13762306a36Sopenharmony_ci retval = ocfs2_xattr_get_nolock(inode, di_bh, name_index, 13862306a36Sopenharmony_ci "", value, retval); 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci if (retval > 0) 14262306a36Sopenharmony_ci acl = ocfs2_acl_from_xattr(value, retval); 14362306a36Sopenharmony_ci else if (retval == -ENODATA || retval == 0) 14462306a36Sopenharmony_ci acl = NULL; 14562306a36Sopenharmony_ci else 14662306a36Sopenharmony_ci acl = ERR_PTR(retval); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci kfree(value); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci return acl; 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/* 15462306a36Sopenharmony_ci * Helper function to set i_mode in memory and disk. Some call paths 15562306a36Sopenharmony_ci * will not have di_bh or a journal handle to pass, in which case it 15662306a36Sopenharmony_ci * will create it's own. 15762306a36Sopenharmony_ci */ 15862306a36Sopenharmony_cistatic int ocfs2_acl_set_mode(struct inode *inode, struct buffer_head *di_bh, 15962306a36Sopenharmony_ci handle_t *handle, umode_t new_mode) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci int ret, commit_handle = 0; 16262306a36Sopenharmony_ci struct ocfs2_dinode *di; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci if (di_bh == NULL) { 16562306a36Sopenharmony_ci ret = ocfs2_read_inode_block(inode, &di_bh); 16662306a36Sopenharmony_ci if (ret) { 16762306a36Sopenharmony_ci mlog_errno(ret); 16862306a36Sopenharmony_ci goto out; 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci } else 17162306a36Sopenharmony_ci get_bh(di_bh); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci if (handle == NULL) { 17462306a36Sopenharmony_ci handle = ocfs2_start_trans(OCFS2_SB(inode->i_sb), 17562306a36Sopenharmony_ci OCFS2_INODE_UPDATE_CREDITS); 17662306a36Sopenharmony_ci if (IS_ERR(handle)) { 17762306a36Sopenharmony_ci ret = PTR_ERR(handle); 17862306a36Sopenharmony_ci mlog_errno(ret); 17962306a36Sopenharmony_ci goto out_brelse; 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci commit_handle = 1; 18362306a36Sopenharmony_ci } 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci di = (struct ocfs2_dinode *)di_bh->b_data; 18662306a36Sopenharmony_ci ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh, 18762306a36Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 18862306a36Sopenharmony_ci if (ret) { 18962306a36Sopenharmony_ci mlog_errno(ret); 19062306a36Sopenharmony_ci goto out_commit; 19162306a36Sopenharmony_ci } 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci inode->i_mode = new_mode; 19462306a36Sopenharmony_ci inode_set_ctime_current(inode); 19562306a36Sopenharmony_ci di->i_mode = cpu_to_le16(inode->i_mode); 19662306a36Sopenharmony_ci di->i_ctime = cpu_to_le64(inode_get_ctime(inode).tv_sec); 19762306a36Sopenharmony_ci di->i_ctime_nsec = cpu_to_le32(inode_get_ctime(inode).tv_nsec); 19862306a36Sopenharmony_ci ocfs2_update_inode_fsync_trans(handle, inode, 0); 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci ocfs2_journal_dirty(handle, di_bh); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ciout_commit: 20362306a36Sopenharmony_ci if (commit_handle) 20462306a36Sopenharmony_ci ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); 20562306a36Sopenharmony_ciout_brelse: 20662306a36Sopenharmony_ci brelse(di_bh); 20762306a36Sopenharmony_ciout: 20862306a36Sopenharmony_ci return ret; 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci/* 21262306a36Sopenharmony_ci * Set the access or default ACL of an inode. 21362306a36Sopenharmony_ci */ 21462306a36Sopenharmony_cistatic int ocfs2_set_acl(handle_t *handle, 21562306a36Sopenharmony_ci struct inode *inode, 21662306a36Sopenharmony_ci struct buffer_head *di_bh, 21762306a36Sopenharmony_ci int type, 21862306a36Sopenharmony_ci struct posix_acl *acl, 21962306a36Sopenharmony_ci struct ocfs2_alloc_context *meta_ac, 22062306a36Sopenharmony_ci struct ocfs2_alloc_context *data_ac) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci int name_index; 22362306a36Sopenharmony_ci void *value = NULL; 22462306a36Sopenharmony_ci size_t size = 0; 22562306a36Sopenharmony_ci int ret; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci if (S_ISLNK(inode->i_mode)) 22862306a36Sopenharmony_ci return -EOPNOTSUPP; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci switch (type) { 23162306a36Sopenharmony_ci case ACL_TYPE_ACCESS: 23262306a36Sopenharmony_ci name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS; 23362306a36Sopenharmony_ci break; 23462306a36Sopenharmony_ci case ACL_TYPE_DEFAULT: 23562306a36Sopenharmony_ci name_index = OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT; 23662306a36Sopenharmony_ci if (!S_ISDIR(inode->i_mode)) 23762306a36Sopenharmony_ci return acl ? -EACCES : 0; 23862306a36Sopenharmony_ci break; 23962306a36Sopenharmony_ci default: 24062306a36Sopenharmony_ci return -EINVAL; 24162306a36Sopenharmony_ci } 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci if (acl) { 24462306a36Sopenharmony_ci value = ocfs2_acl_to_xattr(acl, &size); 24562306a36Sopenharmony_ci if (IS_ERR(value)) 24662306a36Sopenharmony_ci return (int)PTR_ERR(value); 24762306a36Sopenharmony_ci } 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci if (handle) 25062306a36Sopenharmony_ci ret = ocfs2_xattr_set_handle(handle, inode, di_bh, name_index, 25162306a36Sopenharmony_ci "", value, size, 0, 25262306a36Sopenharmony_ci meta_ac, data_ac); 25362306a36Sopenharmony_ci else 25462306a36Sopenharmony_ci ret = ocfs2_xattr_set(inode, name_index, "", value, size, 0); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci kfree(value); 25762306a36Sopenharmony_ci if (!ret) 25862306a36Sopenharmony_ci set_cached_acl(inode, type, acl); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci return ret; 26162306a36Sopenharmony_ci} 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ciint ocfs2_iop_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, 26462306a36Sopenharmony_ci struct posix_acl *acl, int type) 26562306a36Sopenharmony_ci{ 26662306a36Sopenharmony_ci struct buffer_head *bh = NULL; 26762306a36Sopenharmony_ci int status, had_lock; 26862306a36Sopenharmony_ci struct ocfs2_lock_holder oh; 26962306a36Sopenharmony_ci struct inode *inode = d_inode(dentry); 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci had_lock = ocfs2_inode_lock_tracker(inode, &bh, 1, &oh); 27262306a36Sopenharmony_ci if (had_lock < 0) 27362306a36Sopenharmony_ci return had_lock; 27462306a36Sopenharmony_ci if (type == ACL_TYPE_ACCESS && acl) { 27562306a36Sopenharmony_ci umode_t mode; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci status = posix_acl_update_mode(&nop_mnt_idmap, inode, &mode, 27862306a36Sopenharmony_ci &acl); 27962306a36Sopenharmony_ci if (status) 28062306a36Sopenharmony_ci goto unlock; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci status = ocfs2_acl_set_mode(inode, bh, NULL, mode); 28362306a36Sopenharmony_ci if (status) 28462306a36Sopenharmony_ci goto unlock; 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci status = ocfs2_set_acl(NULL, inode, bh, type, acl, NULL, NULL); 28762306a36Sopenharmony_ciunlock: 28862306a36Sopenharmony_ci ocfs2_inode_unlock_tracker(inode, 1, &oh, had_lock); 28962306a36Sopenharmony_ci brelse(bh); 29062306a36Sopenharmony_ci return status; 29162306a36Sopenharmony_ci} 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_cistruct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type, bool rcu) 29462306a36Sopenharmony_ci{ 29562306a36Sopenharmony_ci struct ocfs2_super *osb; 29662306a36Sopenharmony_ci struct buffer_head *di_bh = NULL; 29762306a36Sopenharmony_ci struct posix_acl *acl; 29862306a36Sopenharmony_ci int had_lock; 29962306a36Sopenharmony_ci struct ocfs2_lock_holder oh; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci if (rcu) 30262306a36Sopenharmony_ci return ERR_PTR(-ECHILD); 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci osb = OCFS2_SB(inode->i_sb); 30562306a36Sopenharmony_ci if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) 30662306a36Sopenharmony_ci return NULL; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci had_lock = ocfs2_inode_lock_tracker(inode, &di_bh, 0, &oh); 30962306a36Sopenharmony_ci if (had_lock < 0) 31062306a36Sopenharmony_ci return ERR_PTR(had_lock); 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci down_read(&OCFS2_I(inode)->ip_xattr_sem); 31362306a36Sopenharmony_ci acl = ocfs2_get_acl_nolock(inode, type, di_bh); 31462306a36Sopenharmony_ci up_read(&OCFS2_I(inode)->ip_xattr_sem); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci ocfs2_inode_unlock_tracker(inode, 0, &oh, had_lock); 31762306a36Sopenharmony_ci brelse(di_bh); 31862306a36Sopenharmony_ci return acl; 31962306a36Sopenharmony_ci} 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ciint ocfs2_acl_chmod(struct inode *inode, struct buffer_head *bh) 32262306a36Sopenharmony_ci{ 32362306a36Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 32462306a36Sopenharmony_ci struct posix_acl *acl; 32562306a36Sopenharmony_ci int ret; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci if (S_ISLNK(inode->i_mode)) 32862306a36Sopenharmony_ci return -EOPNOTSUPP; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) 33162306a36Sopenharmony_ci return 0; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci down_read(&OCFS2_I(inode)->ip_xattr_sem); 33462306a36Sopenharmony_ci acl = ocfs2_get_acl_nolock(inode, ACL_TYPE_ACCESS, bh); 33562306a36Sopenharmony_ci up_read(&OCFS2_I(inode)->ip_xattr_sem); 33662306a36Sopenharmony_ci if (IS_ERR_OR_NULL(acl)) 33762306a36Sopenharmony_ci return PTR_ERR_OR_ZERO(acl); 33862306a36Sopenharmony_ci ret = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode); 33962306a36Sopenharmony_ci if (ret) 34062306a36Sopenharmony_ci return ret; 34162306a36Sopenharmony_ci ret = ocfs2_set_acl(NULL, inode, NULL, ACL_TYPE_ACCESS, 34262306a36Sopenharmony_ci acl, NULL, NULL); 34362306a36Sopenharmony_ci posix_acl_release(acl); 34462306a36Sopenharmony_ci return ret; 34562306a36Sopenharmony_ci} 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci/* 34862306a36Sopenharmony_ci * Initialize the ACLs of a new inode. If parent directory has default ACL, 34962306a36Sopenharmony_ci * then clone to new inode. Called from ocfs2_mknod. 35062306a36Sopenharmony_ci */ 35162306a36Sopenharmony_ciint ocfs2_init_acl(handle_t *handle, 35262306a36Sopenharmony_ci struct inode *inode, 35362306a36Sopenharmony_ci struct inode *dir, 35462306a36Sopenharmony_ci struct buffer_head *di_bh, 35562306a36Sopenharmony_ci struct buffer_head *dir_bh, 35662306a36Sopenharmony_ci struct ocfs2_alloc_context *meta_ac, 35762306a36Sopenharmony_ci struct ocfs2_alloc_context *data_ac) 35862306a36Sopenharmony_ci{ 35962306a36Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 36062306a36Sopenharmony_ci struct posix_acl *acl = NULL; 36162306a36Sopenharmony_ci int ret = 0, ret2; 36262306a36Sopenharmony_ci umode_t mode; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci if (!S_ISLNK(inode->i_mode)) { 36562306a36Sopenharmony_ci if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) { 36662306a36Sopenharmony_ci down_read(&OCFS2_I(dir)->ip_xattr_sem); 36762306a36Sopenharmony_ci acl = ocfs2_get_acl_nolock(dir, ACL_TYPE_DEFAULT, 36862306a36Sopenharmony_ci dir_bh); 36962306a36Sopenharmony_ci up_read(&OCFS2_I(dir)->ip_xattr_sem); 37062306a36Sopenharmony_ci if (IS_ERR(acl)) 37162306a36Sopenharmony_ci return PTR_ERR(acl); 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci if (!acl) { 37462306a36Sopenharmony_ci mode = inode->i_mode & ~current_umask(); 37562306a36Sopenharmony_ci ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode); 37662306a36Sopenharmony_ci if (ret) { 37762306a36Sopenharmony_ci mlog_errno(ret); 37862306a36Sopenharmony_ci goto cleanup; 37962306a36Sopenharmony_ci } 38062306a36Sopenharmony_ci } 38162306a36Sopenharmony_ci } 38262306a36Sopenharmony_ci if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) { 38362306a36Sopenharmony_ci if (S_ISDIR(inode->i_mode)) { 38462306a36Sopenharmony_ci ret = ocfs2_set_acl(handle, inode, di_bh, 38562306a36Sopenharmony_ci ACL_TYPE_DEFAULT, acl, 38662306a36Sopenharmony_ci meta_ac, data_ac); 38762306a36Sopenharmony_ci if (ret) 38862306a36Sopenharmony_ci goto cleanup; 38962306a36Sopenharmony_ci } 39062306a36Sopenharmony_ci mode = inode->i_mode; 39162306a36Sopenharmony_ci ret = __posix_acl_create(&acl, GFP_NOFS, &mode); 39262306a36Sopenharmony_ci if (ret < 0) 39362306a36Sopenharmony_ci return ret; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci ret2 = ocfs2_acl_set_mode(inode, di_bh, handle, mode); 39662306a36Sopenharmony_ci if (ret2) { 39762306a36Sopenharmony_ci mlog_errno(ret2); 39862306a36Sopenharmony_ci ret = ret2; 39962306a36Sopenharmony_ci goto cleanup; 40062306a36Sopenharmony_ci } 40162306a36Sopenharmony_ci if (ret > 0) { 40262306a36Sopenharmony_ci ret = ocfs2_set_acl(handle, inode, 40362306a36Sopenharmony_ci di_bh, ACL_TYPE_ACCESS, 40462306a36Sopenharmony_ci acl, meta_ac, data_ac); 40562306a36Sopenharmony_ci } 40662306a36Sopenharmony_ci } 40762306a36Sopenharmony_cicleanup: 40862306a36Sopenharmony_ci posix_acl_release(acl); 40962306a36Sopenharmony_ci return ret; 41062306a36Sopenharmony_ci} 411