18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* -*- mode: c; c-basic-offset: 8; -*- 38c2ecf20Sopenharmony_ci * vim: noexpandtab sw=8 ts=8 sts=0: 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * acl.c 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (C) 2004, 2008 Oracle. All rights reserved. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * CREDITS: 108c2ecf20Sopenharmony_ci * Lots of code in this file is copy from linux/fs/ext3/acl.c. 118c2ecf20Sopenharmony_ci * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de> 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/init.h> 158c2ecf20Sopenharmony_ci#include <linux/module.h> 168c2ecf20Sopenharmony_ci#include <linux/slab.h> 178c2ecf20Sopenharmony_ci#include <linux/string.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include <cluster/masklog.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include "ocfs2.h" 228c2ecf20Sopenharmony_ci#include "alloc.h" 238c2ecf20Sopenharmony_ci#include "dlmglue.h" 248c2ecf20Sopenharmony_ci#include "file.h" 258c2ecf20Sopenharmony_ci#include "inode.h" 268c2ecf20Sopenharmony_ci#include "journal.h" 278c2ecf20Sopenharmony_ci#include "ocfs2_fs.h" 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include "xattr.h" 308c2ecf20Sopenharmony_ci#include "acl.h" 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/* 338c2ecf20Sopenharmony_ci * Convert from xattr value to acl struct. 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_cistatic struct posix_acl *ocfs2_acl_from_xattr(const void *value, size_t size) 368c2ecf20Sopenharmony_ci{ 378c2ecf20Sopenharmony_ci int n, count; 388c2ecf20Sopenharmony_ci struct posix_acl *acl; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci if (!value) 418c2ecf20Sopenharmony_ci return NULL; 428c2ecf20Sopenharmony_ci if (size < sizeof(struct posix_acl_entry)) 438c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci count = size / sizeof(struct posix_acl_entry); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci acl = posix_acl_alloc(count, GFP_NOFS); 488c2ecf20Sopenharmony_ci if (!acl) 498c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 508c2ecf20Sopenharmony_ci for (n = 0; n < count; n++) { 518c2ecf20Sopenharmony_ci struct ocfs2_acl_entry *entry = 528c2ecf20Sopenharmony_ci (struct ocfs2_acl_entry *)value; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci acl->a_entries[n].e_tag = le16_to_cpu(entry->e_tag); 558c2ecf20Sopenharmony_ci acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm); 568c2ecf20Sopenharmony_ci switch(acl->a_entries[n].e_tag) { 578c2ecf20Sopenharmony_ci case ACL_USER: 588c2ecf20Sopenharmony_ci acl->a_entries[n].e_uid = 598c2ecf20Sopenharmony_ci make_kuid(&init_user_ns, 608c2ecf20Sopenharmony_ci le32_to_cpu(entry->e_id)); 618c2ecf20Sopenharmony_ci break; 628c2ecf20Sopenharmony_ci case ACL_GROUP: 638c2ecf20Sopenharmony_ci acl->a_entries[n].e_gid = 648c2ecf20Sopenharmony_ci make_kgid(&init_user_ns, 658c2ecf20Sopenharmony_ci le32_to_cpu(entry->e_id)); 668c2ecf20Sopenharmony_ci break; 678c2ecf20Sopenharmony_ci default: 688c2ecf20Sopenharmony_ci break; 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci value += sizeof(struct posix_acl_entry); 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci } 738c2ecf20Sopenharmony_ci return acl; 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci/* 778c2ecf20Sopenharmony_ci * Convert acl struct to xattr value. 788c2ecf20Sopenharmony_ci */ 798c2ecf20Sopenharmony_cistatic void *ocfs2_acl_to_xattr(const struct posix_acl *acl, size_t *size) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci struct ocfs2_acl_entry *entry = NULL; 828c2ecf20Sopenharmony_ci char *ocfs2_acl; 838c2ecf20Sopenharmony_ci size_t n; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci *size = acl->a_count * sizeof(struct posix_acl_entry); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci ocfs2_acl = kmalloc(*size, GFP_NOFS); 888c2ecf20Sopenharmony_ci if (!ocfs2_acl) 898c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci entry = (struct ocfs2_acl_entry *)ocfs2_acl; 928c2ecf20Sopenharmony_ci for (n = 0; n < acl->a_count; n++, entry++) { 938c2ecf20Sopenharmony_ci entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag); 948c2ecf20Sopenharmony_ci entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm); 958c2ecf20Sopenharmony_ci switch(acl->a_entries[n].e_tag) { 968c2ecf20Sopenharmony_ci case ACL_USER: 978c2ecf20Sopenharmony_ci entry->e_id = cpu_to_le32( 988c2ecf20Sopenharmony_ci from_kuid(&init_user_ns, 998c2ecf20Sopenharmony_ci acl->a_entries[n].e_uid)); 1008c2ecf20Sopenharmony_ci break; 1018c2ecf20Sopenharmony_ci case ACL_GROUP: 1028c2ecf20Sopenharmony_ci entry->e_id = cpu_to_le32( 1038c2ecf20Sopenharmony_ci from_kgid(&init_user_ns, 1048c2ecf20Sopenharmony_ci acl->a_entries[n].e_gid)); 1058c2ecf20Sopenharmony_ci break; 1068c2ecf20Sopenharmony_ci default: 1078c2ecf20Sopenharmony_ci entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID); 1088c2ecf20Sopenharmony_ci break; 1098c2ecf20Sopenharmony_ci } 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci return ocfs2_acl; 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cistatic struct posix_acl *ocfs2_get_acl_nolock(struct inode *inode, 1158c2ecf20Sopenharmony_ci int type, 1168c2ecf20Sopenharmony_ci struct buffer_head *di_bh) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci int name_index; 1198c2ecf20Sopenharmony_ci char *value = NULL; 1208c2ecf20Sopenharmony_ci struct posix_acl *acl; 1218c2ecf20Sopenharmony_ci int retval; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci switch (type) { 1248c2ecf20Sopenharmony_ci case ACL_TYPE_ACCESS: 1258c2ecf20Sopenharmony_ci name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS; 1268c2ecf20Sopenharmony_ci break; 1278c2ecf20Sopenharmony_ci case ACL_TYPE_DEFAULT: 1288c2ecf20Sopenharmony_ci name_index = OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT; 1298c2ecf20Sopenharmony_ci break; 1308c2ecf20Sopenharmony_ci default: 1318c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 1328c2ecf20Sopenharmony_ci } 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci retval = ocfs2_xattr_get_nolock(inode, di_bh, name_index, "", NULL, 0); 1358c2ecf20Sopenharmony_ci if (retval > 0) { 1368c2ecf20Sopenharmony_ci value = kmalloc(retval, GFP_NOFS); 1378c2ecf20Sopenharmony_ci if (!value) 1388c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 1398c2ecf20Sopenharmony_ci retval = ocfs2_xattr_get_nolock(inode, di_bh, name_index, 1408c2ecf20Sopenharmony_ci "", value, retval); 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci if (retval > 0) 1448c2ecf20Sopenharmony_ci acl = ocfs2_acl_from_xattr(value, retval); 1458c2ecf20Sopenharmony_ci else if (retval == -ENODATA || retval == 0) 1468c2ecf20Sopenharmony_ci acl = NULL; 1478c2ecf20Sopenharmony_ci else 1488c2ecf20Sopenharmony_ci acl = ERR_PTR(retval); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci kfree(value); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci return acl; 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci/* 1568c2ecf20Sopenharmony_ci * Helper function to set i_mode in memory and disk. Some call paths 1578c2ecf20Sopenharmony_ci * will not have di_bh or a journal handle to pass, in which case it 1588c2ecf20Sopenharmony_ci * will create it's own. 1598c2ecf20Sopenharmony_ci */ 1608c2ecf20Sopenharmony_cistatic int ocfs2_acl_set_mode(struct inode *inode, struct buffer_head *di_bh, 1618c2ecf20Sopenharmony_ci handle_t *handle, umode_t new_mode) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci int ret, commit_handle = 0; 1648c2ecf20Sopenharmony_ci struct ocfs2_dinode *di; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci if (di_bh == NULL) { 1678c2ecf20Sopenharmony_ci ret = ocfs2_read_inode_block(inode, &di_bh); 1688c2ecf20Sopenharmony_ci if (ret) { 1698c2ecf20Sopenharmony_ci mlog_errno(ret); 1708c2ecf20Sopenharmony_ci goto out; 1718c2ecf20Sopenharmony_ci } 1728c2ecf20Sopenharmony_ci } else 1738c2ecf20Sopenharmony_ci get_bh(di_bh); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci if (handle == NULL) { 1768c2ecf20Sopenharmony_ci handle = ocfs2_start_trans(OCFS2_SB(inode->i_sb), 1778c2ecf20Sopenharmony_ci OCFS2_INODE_UPDATE_CREDITS); 1788c2ecf20Sopenharmony_ci if (IS_ERR(handle)) { 1798c2ecf20Sopenharmony_ci ret = PTR_ERR(handle); 1808c2ecf20Sopenharmony_ci mlog_errno(ret); 1818c2ecf20Sopenharmony_ci goto out_brelse; 1828c2ecf20Sopenharmony_ci } 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci commit_handle = 1; 1858c2ecf20Sopenharmony_ci } 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci di = (struct ocfs2_dinode *)di_bh->b_data; 1888c2ecf20Sopenharmony_ci ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh, 1898c2ecf20Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 1908c2ecf20Sopenharmony_ci if (ret) { 1918c2ecf20Sopenharmony_ci mlog_errno(ret); 1928c2ecf20Sopenharmony_ci goto out_commit; 1938c2ecf20Sopenharmony_ci } 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci inode->i_mode = new_mode; 1968c2ecf20Sopenharmony_ci inode->i_ctime = current_time(inode); 1978c2ecf20Sopenharmony_ci di->i_mode = cpu_to_le16(inode->i_mode); 1988c2ecf20Sopenharmony_ci di->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec); 1998c2ecf20Sopenharmony_ci di->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec); 2008c2ecf20Sopenharmony_ci ocfs2_update_inode_fsync_trans(handle, inode, 0); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci ocfs2_journal_dirty(handle, di_bh); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ciout_commit: 2058c2ecf20Sopenharmony_ci if (commit_handle) 2068c2ecf20Sopenharmony_ci ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); 2078c2ecf20Sopenharmony_ciout_brelse: 2088c2ecf20Sopenharmony_ci brelse(di_bh); 2098c2ecf20Sopenharmony_ciout: 2108c2ecf20Sopenharmony_ci return ret; 2118c2ecf20Sopenharmony_ci} 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci/* 2148c2ecf20Sopenharmony_ci * Set the access or default ACL of an inode. 2158c2ecf20Sopenharmony_ci */ 2168c2ecf20Sopenharmony_cistatic int ocfs2_set_acl(handle_t *handle, 2178c2ecf20Sopenharmony_ci struct inode *inode, 2188c2ecf20Sopenharmony_ci struct buffer_head *di_bh, 2198c2ecf20Sopenharmony_ci int type, 2208c2ecf20Sopenharmony_ci struct posix_acl *acl, 2218c2ecf20Sopenharmony_ci struct ocfs2_alloc_context *meta_ac, 2228c2ecf20Sopenharmony_ci struct ocfs2_alloc_context *data_ac) 2238c2ecf20Sopenharmony_ci{ 2248c2ecf20Sopenharmony_ci int name_index; 2258c2ecf20Sopenharmony_ci void *value = NULL; 2268c2ecf20Sopenharmony_ci size_t size = 0; 2278c2ecf20Sopenharmony_ci int ret; 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci if (S_ISLNK(inode->i_mode)) 2308c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci switch (type) { 2338c2ecf20Sopenharmony_ci case ACL_TYPE_ACCESS: 2348c2ecf20Sopenharmony_ci name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS; 2358c2ecf20Sopenharmony_ci break; 2368c2ecf20Sopenharmony_ci case ACL_TYPE_DEFAULT: 2378c2ecf20Sopenharmony_ci name_index = OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT; 2388c2ecf20Sopenharmony_ci if (!S_ISDIR(inode->i_mode)) 2398c2ecf20Sopenharmony_ci return acl ? -EACCES : 0; 2408c2ecf20Sopenharmony_ci break; 2418c2ecf20Sopenharmony_ci default: 2428c2ecf20Sopenharmony_ci return -EINVAL; 2438c2ecf20Sopenharmony_ci } 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci if (acl) { 2468c2ecf20Sopenharmony_ci value = ocfs2_acl_to_xattr(acl, &size); 2478c2ecf20Sopenharmony_ci if (IS_ERR(value)) 2488c2ecf20Sopenharmony_ci return (int)PTR_ERR(value); 2498c2ecf20Sopenharmony_ci } 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci if (handle) 2528c2ecf20Sopenharmony_ci ret = ocfs2_xattr_set_handle(handle, inode, di_bh, name_index, 2538c2ecf20Sopenharmony_ci "", value, size, 0, 2548c2ecf20Sopenharmony_ci meta_ac, data_ac); 2558c2ecf20Sopenharmony_ci else 2568c2ecf20Sopenharmony_ci ret = ocfs2_xattr_set(inode, name_index, "", value, size, 0); 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci kfree(value); 2598c2ecf20Sopenharmony_ci if (!ret) 2608c2ecf20Sopenharmony_ci set_cached_acl(inode, type, acl); 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci return ret; 2638c2ecf20Sopenharmony_ci} 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ciint ocfs2_iop_set_acl(struct inode *inode, struct posix_acl *acl, int type) 2668c2ecf20Sopenharmony_ci{ 2678c2ecf20Sopenharmony_ci struct buffer_head *bh = NULL; 2688c2ecf20Sopenharmony_ci int status, had_lock; 2698c2ecf20Sopenharmony_ci struct ocfs2_lock_holder oh; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci had_lock = ocfs2_inode_lock_tracker(inode, &bh, 1, &oh); 2728c2ecf20Sopenharmony_ci if (had_lock < 0) 2738c2ecf20Sopenharmony_ci return had_lock; 2748c2ecf20Sopenharmony_ci if (type == ACL_TYPE_ACCESS && acl) { 2758c2ecf20Sopenharmony_ci umode_t mode; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci status = posix_acl_update_mode(inode, &mode, &acl); 2788c2ecf20Sopenharmony_ci if (status) 2798c2ecf20Sopenharmony_ci goto unlock; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci status = ocfs2_acl_set_mode(inode, bh, NULL, mode); 2828c2ecf20Sopenharmony_ci if (status) 2838c2ecf20Sopenharmony_ci goto unlock; 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci status = ocfs2_set_acl(NULL, inode, bh, type, acl, NULL, NULL); 2868c2ecf20Sopenharmony_ciunlock: 2878c2ecf20Sopenharmony_ci ocfs2_inode_unlock_tracker(inode, 1, &oh, had_lock); 2888c2ecf20Sopenharmony_ci brelse(bh); 2898c2ecf20Sopenharmony_ci return status; 2908c2ecf20Sopenharmony_ci} 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_cistruct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type) 2938c2ecf20Sopenharmony_ci{ 2948c2ecf20Sopenharmony_ci struct ocfs2_super *osb; 2958c2ecf20Sopenharmony_ci struct buffer_head *di_bh = NULL; 2968c2ecf20Sopenharmony_ci struct posix_acl *acl; 2978c2ecf20Sopenharmony_ci int had_lock; 2988c2ecf20Sopenharmony_ci struct ocfs2_lock_holder oh; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci osb = OCFS2_SB(inode->i_sb); 3018c2ecf20Sopenharmony_ci if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) 3028c2ecf20Sopenharmony_ci return NULL; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci had_lock = ocfs2_inode_lock_tracker(inode, &di_bh, 0, &oh); 3058c2ecf20Sopenharmony_ci if (had_lock < 0) 3068c2ecf20Sopenharmony_ci return ERR_PTR(had_lock); 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci down_read(&OCFS2_I(inode)->ip_xattr_sem); 3098c2ecf20Sopenharmony_ci acl = ocfs2_get_acl_nolock(inode, type, di_bh); 3108c2ecf20Sopenharmony_ci up_read(&OCFS2_I(inode)->ip_xattr_sem); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci ocfs2_inode_unlock_tracker(inode, 0, &oh, had_lock); 3138c2ecf20Sopenharmony_ci brelse(di_bh); 3148c2ecf20Sopenharmony_ci return acl; 3158c2ecf20Sopenharmony_ci} 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ciint ocfs2_acl_chmod(struct inode *inode, struct buffer_head *bh) 3188c2ecf20Sopenharmony_ci{ 3198c2ecf20Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 3208c2ecf20Sopenharmony_ci struct posix_acl *acl; 3218c2ecf20Sopenharmony_ci int ret; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci if (S_ISLNK(inode->i_mode)) 3248c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) 3278c2ecf20Sopenharmony_ci return 0; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci down_read(&OCFS2_I(inode)->ip_xattr_sem); 3308c2ecf20Sopenharmony_ci acl = ocfs2_get_acl_nolock(inode, ACL_TYPE_ACCESS, bh); 3318c2ecf20Sopenharmony_ci up_read(&OCFS2_I(inode)->ip_xattr_sem); 3328c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(acl)) 3338c2ecf20Sopenharmony_ci return PTR_ERR_OR_ZERO(acl); 3348c2ecf20Sopenharmony_ci ret = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode); 3358c2ecf20Sopenharmony_ci if (ret) 3368c2ecf20Sopenharmony_ci return ret; 3378c2ecf20Sopenharmony_ci ret = ocfs2_set_acl(NULL, inode, NULL, ACL_TYPE_ACCESS, 3388c2ecf20Sopenharmony_ci acl, NULL, NULL); 3398c2ecf20Sopenharmony_ci posix_acl_release(acl); 3408c2ecf20Sopenharmony_ci return ret; 3418c2ecf20Sopenharmony_ci} 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci/* 3448c2ecf20Sopenharmony_ci * Initialize the ACLs of a new inode. If parent directory has default ACL, 3458c2ecf20Sopenharmony_ci * then clone to new inode. Called from ocfs2_mknod. 3468c2ecf20Sopenharmony_ci */ 3478c2ecf20Sopenharmony_ciint ocfs2_init_acl(handle_t *handle, 3488c2ecf20Sopenharmony_ci struct inode *inode, 3498c2ecf20Sopenharmony_ci struct inode *dir, 3508c2ecf20Sopenharmony_ci struct buffer_head *di_bh, 3518c2ecf20Sopenharmony_ci struct buffer_head *dir_bh, 3528c2ecf20Sopenharmony_ci struct ocfs2_alloc_context *meta_ac, 3538c2ecf20Sopenharmony_ci struct ocfs2_alloc_context *data_ac) 3548c2ecf20Sopenharmony_ci{ 3558c2ecf20Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 3568c2ecf20Sopenharmony_ci struct posix_acl *acl = NULL; 3578c2ecf20Sopenharmony_ci int ret = 0, ret2; 3588c2ecf20Sopenharmony_ci umode_t mode; 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci if (!S_ISLNK(inode->i_mode)) { 3618c2ecf20Sopenharmony_ci if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) { 3628c2ecf20Sopenharmony_ci down_read(&OCFS2_I(dir)->ip_xattr_sem); 3638c2ecf20Sopenharmony_ci acl = ocfs2_get_acl_nolock(dir, ACL_TYPE_DEFAULT, 3648c2ecf20Sopenharmony_ci dir_bh); 3658c2ecf20Sopenharmony_ci up_read(&OCFS2_I(dir)->ip_xattr_sem); 3668c2ecf20Sopenharmony_ci if (IS_ERR(acl)) 3678c2ecf20Sopenharmony_ci return PTR_ERR(acl); 3688c2ecf20Sopenharmony_ci } 3698c2ecf20Sopenharmony_ci if (!acl) { 3708c2ecf20Sopenharmony_ci mode = inode->i_mode & ~current_umask(); 3718c2ecf20Sopenharmony_ci ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode); 3728c2ecf20Sopenharmony_ci if (ret) { 3738c2ecf20Sopenharmony_ci mlog_errno(ret); 3748c2ecf20Sopenharmony_ci goto cleanup; 3758c2ecf20Sopenharmony_ci } 3768c2ecf20Sopenharmony_ci } 3778c2ecf20Sopenharmony_ci } 3788c2ecf20Sopenharmony_ci if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) { 3798c2ecf20Sopenharmony_ci if (S_ISDIR(inode->i_mode)) { 3808c2ecf20Sopenharmony_ci ret = ocfs2_set_acl(handle, inode, di_bh, 3818c2ecf20Sopenharmony_ci ACL_TYPE_DEFAULT, acl, 3828c2ecf20Sopenharmony_ci meta_ac, data_ac); 3838c2ecf20Sopenharmony_ci if (ret) 3848c2ecf20Sopenharmony_ci goto cleanup; 3858c2ecf20Sopenharmony_ci } 3868c2ecf20Sopenharmony_ci mode = inode->i_mode; 3878c2ecf20Sopenharmony_ci ret = __posix_acl_create(&acl, GFP_NOFS, &mode); 3888c2ecf20Sopenharmony_ci if (ret < 0) 3898c2ecf20Sopenharmony_ci return ret; 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci ret2 = ocfs2_acl_set_mode(inode, di_bh, handle, mode); 3928c2ecf20Sopenharmony_ci if (ret2) { 3938c2ecf20Sopenharmony_ci mlog_errno(ret2); 3948c2ecf20Sopenharmony_ci ret = ret2; 3958c2ecf20Sopenharmony_ci goto cleanup; 3968c2ecf20Sopenharmony_ci } 3978c2ecf20Sopenharmony_ci if (ret > 0) { 3988c2ecf20Sopenharmony_ci ret = ocfs2_set_acl(handle, inode, 3998c2ecf20Sopenharmony_ci di_bh, ACL_TYPE_ACCESS, 4008c2ecf20Sopenharmony_ci acl, meta_ac, data_ac); 4018c2ecf20Sopenharmony_ci } 4028c2ecf20Sopenharmony_ci } 4038c2ecf20Sopenharmony_cicleanup: 4048c2ecf20Sopenharmony_ci posix_acl_release(acl); 4058c2ecf20Sopenharmony_ci return ret; 4068c2ecf20Sopenharmony_ci} 407