18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <linux/capability.h>
38c2ecf20Sopenharmony_ci#include <linux/fs.h>
48c2ecf20Sopenharmony_ci#include <linux/posix_acl.h>
58c2ecf20Sopenharmony_ci#include "reiserfs.h"
68c2ecf20Sopenharmony_ci#include <linux/errno.h>
78c2ecf20Sopenharmony_ci#include <linux/pagemap.h>
88c2ecf20Sopenharmony_ci#include <linux/xattr.h>
98c2ecf20Sopenharmony_ci#include <linux/slab.h>
108c2ecf20Sopenharmony_ci#include <linux/posix_acl_xattr.h>
118c2ecf20Sopenharmony_ci#include "xattr.h"
128c2ecf20Sopenharmony_ci#include "acl.h"
138c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_cistatic int __reiserfs_set_acl(struct reiserfs_transaction_handle *th,
168c2ecf20Sopenharmony_ci			    struct inode *inode, int type,
178c2ecf20Sopenharmony_ci			    struct posix_acl *acl);
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ciint
218c2ecf20Sopenharmony_cireiserfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
228c2ecf20Sopenharmony_ci{
238c2ecf20Sopenharmony_ci	int error, error2;
248c2ecf20Sopenharmony_ci	struct reiserfs_transaction_handle th;
258c2ecf20Sopenharmony_ci	size_t jcreate_blocks;
268c2ecf20Sopenharmony_ci	int size = acl ? posix_acl_xattr_size(acl->a_count) : 0;
278c2ecf20Sopenharmony_ci	int update_mode = 0;
288c2ecf20Sopenharmony_ci	umode_t mode = inode->i_mode;
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	/*
318c2ecf20Sopenharmony_ci	 * Pessimism: We can't assume that anything from the xattr root up
328c2ecf20Sopenharmony_ci	 * has been created.
338c2ecf20Sopenharmony_ci	 */
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	jcreate_blocks = reiserfs_xattr_jcreate_nblocks(inode) +
368c2ecf20Sopenharmony_ci			 reiserfs_xattr_nblocks(inode, size) * 2;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	reiserfs_write_lock(inode->i_sb);
398c2ecf20Sopenharmony_ci	error = journal_begin(&th, inode->i_sb, jcreate_blocks);
408c2ecf20Sopenharmony_ci	reiserfs_write_unlock(inode->i_sb);
418c2ecf20Sopenharmony_ci	if (error == 0) {
428c2ecf20Sopenharmony_ci		if (type == ACL_TYPE_ACCESS && acl) {
438c2ecf20Sopenharmony_ci			error = posix_acl_update_mode(inode, &mode, &acl);
448c2ecf20Sopenharmony_ci			if (error)
458c2ecf20Sopenharmony_ci				goto unlock;
468c2ecf20Sopenharmony_ci			update_mode = 1;
478c2ecf20Sopenharmony_ci		}
488c2ecf20Sopenharmony_ci		error = __reiserfs_set_acl(&th, inode, type, acl);
498c2ecf20Sopenharmony_ci		if (!error && update_mode)
508c2ecf20Sopenharmony_ci			inode->i_mode = mode;
518c2ecf20Sopenharmony_ciunlock:
528c2ecf20Sopenharmony_ci		reiserfs_write_lock(inode->i_sb);
538c2ecf20Sopenharmony_ci		error2 = journal_end(&th);
548c2ecf20Sopenharmony_ci		reiserfs_write_unlock(inode->i_sb);
558c2ecf20Sopenharmony_ci		if (error2)
568c2ecf20Sopenharmony_ci			error = error2;
578c2ecf20Sopenharmony_ci	}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	return error;
608c2ecf20Sopenharmony_ci}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci/*
638c2ecf20Sopenharmony_ci * Convert from filesystem to in-memory representation.
648c2ecf20Sopenharmony_ci */
658c2ecf20Sopenharmony_cistatic struct posix_acl *reiserfs_posix_acl_from_disk(const void *value, size_t size)
668c2ecf20Sopenharmony_ci{
678c2ecf20Sopenharmony_ci	const char *end = (char *)value + size;
688c2ecf20Sopenharmony_ci	int n, count;
698c2ecf20Sopenharmony_ci	struct posix_acl *acl;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	if (!value)
728c2ecf20Sopenharmony_ci		return NULL;
738c2ecf20Sopenharmony_ci	if (size < sizeof(reiserfs_acl_header))
748c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
758c2ecf20Sopenharmony_ci	if (((reiserfs_acl_header *) value)->a_version !=
768c2ecf20Sopenharmony_ci	    cpu_to_le32(REISERFS_ACL_VERSION))
778c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
788c2ecf20Sopenharmony_ci	value = (char *)value + sizeof(reiserfs_acl_header);
798c2ecf20Sopenharmony_ci	count = reiserfs_acl_count(size);
808c2ecf20Sopenharmony_ci	if (count < 0)
818c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
828c2ecf20Sopenharmony_ci	if (count == 0)
838c2ecf20Sopenharmony_ci		return NULL;
848c2ecf20Sopenharmony_ci	acl = posix_acl_alloc(count, GFP_NOFS);
858c2ecf20Sopenharmony_ci	if (!acl)
868c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
878c2ecf20Sopenharmony_ci	for (n = 0; n < count; n++) {
888c2ecf20Sopenharmony_ci		reiserfs_acl_entry *entry = (reiserfs_acl_entry *) value;
898c2ecf20Sopenharmony_ci		if ((char *)value + sizeof(reiserfs_acl_entry_short) > end)
908c2ecf20Sopenharmony_ci			goto fail;
918c2ecf20Sopenharmony_ci		acl->a_entries[n].e_tag = le16_to_cpu(entry->e_tag);
928c2ecf20Sopenharmony_ci		acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm);
938c2ecf20Sopenharmony_ci		switch (acl->a_entries[n].e_tag) {
948c2ecf20Sopenharmony_ci		case ACL_USER_OBJ:
958c2ecf20Sopenharmony_ci		case ACL_GROUP_OBJ:
968c2ecf20Sopenharmony_ci		case ACL_MASK:
978c2ecf20Sopenharmony_ci		case ACL_OTHER:
988c2ecf20Sopenharmony_ci			value = (char *)value +
998c2ecf20Sopenharmony_ci			    sizeof(reiserfs_acl_entry_short);
1008c2ecf20Sopenharmony_ci			break;
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci		case ACL_USER:
1038c2ecf20Sopenharmony_ci			value = (char *)value + sizeof(reiserfs_acl_entry);
1048c2ecf20Sopenharmony_ci			if ((char *)value > end)
1058c2ecf20Sopenharmony_ci				goto fail;
1068c2ecf20Sopenharmony_ci			acl->a_entries[n].e_uid =
1078c2ecf20Sopenharmony_ci				make_kuid(&init_user_ns,
1088c2ecf20Sopenharmony_ci					  le32_to_cpu(entry->e_id));
1098c2ecf20Sopenharmony_ci			break;
1108c2ecf20Sopenharmony_ci		case ACL_GROUP:
1118c2ecf20Sopenharmony_ci			value = (char *)value + sizeof(reiserfs_acl_entry);
1128c2ecf20Sopenharmony_ci			if ((char *)value > end)
1138c2ecf20Sopenharmony_ci				goto fail;
1148c2ecf20Sopenharmony_ci			acl->a_entries[n].e_gid =
1158c2ecf20Sopenharmony_ci				make_kgid(&init_user_ns,
1168c2ecf20Sopenharmony_ci					  le32_to_cpu(entry->e_id));
1178c2ecf20Sopenharmony_ci			break;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci		default:
1208c2ecf20Sopenharmony_ci			goto fail;
1218c2ecf20Sopenharmony_ci		}
1228c2ecf20Sopenharmony_ci	}
1238c2ecf20Sopenharmony_ci	if (value != end)
1248c2ecf20Sopenharmony_ci		goto fail;
1258c2ecf20Sopenharmony_ci	return acl;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cifail:
1288c2ecf20Sopenharmony_ci	posix_acl_release(acl);
1298c2ecf20Sopenharmony_ci	return ERR_PTR(-EINVAL);
1308c2ecf20Sopenharmony_ci}
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci/*
1338c2ecf20Sopenharmony_ci * Convert from in-memory to filesystem representation.
1348c2ecf20Sopenharmony_ci */
1358c2ecf20Sopenharmony_cistatic void *reiserfs_posix_acl_to_disk(const struct posix_acl *acl, size_t * size)
1368c2ecf20Sopenharmony_ci{
1378c2ecf20Sopenharmony_ci	reiserfs_acl_header *ext_acl;
1388c2ecf20Sopenharmony_ci	char *e;
1398c2ecf20Sopenharmony_ci	int n;
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	*size = reiserfs_acl_size(acl->a_count);
1428c2ecf20Sopenharmony_ci	ext_acl = kmalloc(sizeof(reiserfs_acl_header) +
1438c2ecf20Sopenharmony_ci						  acl->a_count *
1448c2ecf20Sopenharmony_ci						  sizeof(reiserfs_acl_entry),
1458c2ecf20Sopenharmony_ci						  GFP_NOFS);
1468c2ecf20Sopenharmony_ci	if (!ext_acl)
1478c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
1488c2ecf20Sopenharmony_ci	ext_acl->a_version = cpu_to_le32(REISERFS_ACL_VERSION);
1498c2ecf20Sopenharmony_ci	e = (char *)ext_acl + sizeof(reiserfs_acl_header);
1508c2ecf20Sopenharmony_ci	for (n = 0; n < acl->a_count; n++) {
1518c2ecf20Sopenharmony_ci		const struct posix_acl_entry *acl_e = &acl->a_entries[n];
1528c2ecf20Sopenharmony_ci		reiserfs_acl_entry *entry = (reiserfs_acl_entry *) e;
1538c2ecf20Sopenharmony_ci		entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag);
1548c2ecf20Sopenharmony_ci		entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm);
1558c2ecf20Sopenharmony_ci		switch (acl->a_entries[n].e_tag) {
1568c2ecf20Sopenharmony_ci		case ACL_USER:
1578c2ecf20Sopenharmony_ci			entry->e_id = cpu_to_le32(
1588c2ecf20Sopenharmony_ci				from_kuid(&init_user_ns, acl_e->e_uid));
1598c2ecf20Sopenharmony_ci			e += sizeof(reiserfs_acl_entry);
1608c2ecf20Sopenharmony_ci			break;
1618c2ecf20Sopenharmony_ci		case ACL_GROUP:
1628c2ecf20Sopenharmony_ci			entry->e_id = cpu_to_le32(
1638c2ecf20Sopenharmony_ci				from_kgid(&init_user_ns, acl_e->e_gid));
1648c2ecf20Sopenharmony_ci			e += sizeof(reiserfs_acl_entry);
1658c2ecf20Sopenharmony_ci			break;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci		case ACL_USER_OBJ:
1688c2ecf20Sopenharmony_ci		case ACL_GROUP_OBJ:
1698c2ecf20Sopenharmony_ci		case ACL_MASK:
1708c2ecf20Sopenharmony_ci		case ACL_OTHER:
1718c2ecf20Sopenharmony_ci			e += sizeof(reiserfs_acl_entry_short);
1728c2ecf20Sopenharmony_ci			break;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci		default:
1758c2ecf20Sopenharmony_ci			goto fail;
1768c2ecf20Sopenharmony_ci		}
1778c2ecf20Sopenharmony_ci	}
1788c2ecf20Sopenharmony_ci	return (char *)ext_acl;
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_cifail:
1818c2ecf20Sopenharmony_ci	kfree(ext_acl);
1828c2ecf20Sopenharmony_ci	return ERR_PTR(-EINVAL);
1838c2ecf20Sopenharmony_ci}
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci/*
1868c2ecf20Sopenharmony_ci * Inode operation get_posix_acl().
1878c2ecf20Sopenharmony_ci *
1888c2ecf20Sopenharmony_ci * inode->i_mutex: down
1898c2ecf20Sopenharmony_ci * BKL held [before 2.5.x]
1908c2ecf20Sopenharmony_ci */
1918c2ecf20Sopenharmony_cistruct posix_acl *reiserfs_get_acl(struct inode *inode, int type)
1928c2ecf20Sopenharmony_ci{
1938c2ecf20Sopenharmony_ci	char *name, *value;
1948c2ecf20Sopenharmony_ci	struct posix_acl *acl;
1958c2ecf20Sopenharmony_ci	int size;
1968c2ecf20Sopenharmony_ci	int retval;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	switch (type) {
1998c2ecf20Sopenharmony_ci	case ACL_TYPE_ACCESS:
2008c2ecf20Sopenharmony_ci		name = XATTR_NAME_POSIX_ACL_ACCESS;
2018c2ecf20Sopenharmony_ci		break;
2028c2ecf20Sopenharmony_ci	case ACL_TYPE_DEFAULT:
2038c2ecf20Sopenharmony_ci		name = XATTR_NAME_POSIX_ACL_DEFAULT;
2048c2ecf20Sopenharmony_ci		break;
2058c2ecf20Sopenharmony_ci	default:
2068c2ecf20Sopenharmony_ci		BUG();
2078c2ecf20Sopenharmony_ci	}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	size = reiserfs_xattr_get(inode, name, NULL, 0);
2108c2ecf20Sopenharmony_ci	if (size < 0) {
2118c2ecf20Sopenharmony_ci		if (size == -ENODATA || size == -ENOSYS)
2128c2ecf20Sopenharmony_ci			return NULL;
2138c2ecf20Sopenharmony_ci		return ERR_PTR(size);
2148c2ecf20Sopenharmony_ci	}
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	value = kmalloc(size, GFP_NOFS);
2178c2ecf20Sopenharmony_ci	if (!value)
2188c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	retval = reiserfs_xattr_get(inode, name, value, size);
2218c2ecf20Sopenharmony_ci	if (retval == -ENODATA || retval == -ENOSYS) {
2228c2ecf20Sopenharmony_ci		/*
2238c2ecf20Sopenharmony_ci		 * This shouldn't actually happen as it should have
2248c2ecf20Sopenharmony_ci		 * been caught above.. but just in case
2258c2ecf20Sopenharmony_ci		 */
2268c2ecf20Sopenharmony_ci		acl = NULL;
2278c2ecf20Sopenharmony_ci	} else if (retval < 0) {
2288c2ecf20Sopenharmony_ci		acl = ERR_PTR(retval);
2298c2ecf20Sopenharmony_ci	} else {
2308c2ecf20Sopenharmony_ci		acl = reiserfs_posix_acl_from_disk(value, retval);
2318c2ecf20Sopenharmony_ci	}
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	kfree(value);
2348c2ecf20Sopenharmony_ci	return acl;
2358c2ecf20Sopenharmony_ci}
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci/*
2388c2ecf20Sopenharmony_ci * Inode operation set_posix_acl().
2398c2ecf20Sopenharmony_ci *
2408c2ecf20Sopenharmony_ci * inode->i_mutex: down
2418c2ecf20Sopenharmony_ci * BKL held [before 2.5.x]
2428c2ecf20Sopenharmony_ci */
2438c2ecf20Sopenharmony_cistatic int
2448c2ecf20Sopenharmony_ci__reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
2458c2ecf20Sopenharmony_ci		 int type, struct posix_acl *acl)
2468c2ecf20Sopenharmony_ci{
2478c2ecf20Sopenharmony_ci	char *name;
2488c2ecf20Sopenharmony_ci	void *value = NULL;
2498c2ecf20Sopenharmony_ci	size_t size = 0;
2508c2ecf20Sopenharmony_ci	int error;
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	switch (type) {
2538c2ecf20Sopenharmony_ci	case ACL_TYPE_ACCESS:
2548c2ecf20Sopenharmony_ci		name = XATTR_NAME_POSIX_ACL_ACCESS;
2558c2ecf20Sopenharmony_ci		break;
2568c2ecf20Sopenharmony_ci	case ACL_TYPE_DEFAULT:
2578c2ecf20Sopenharmony_ci		name = XATTR_NAME_POSIX_ACL_DEFAULT;
2588c2ecf20Sopenharmony_ci		if (!S_ISDIR(inode->i_mode))
2598c2ecf20Sopenharmony_ci			return acl ? -EACCES : 0;
2608c2ecf20Sopenharmony_ci		break;
2618c2ecf20Sopenharmony_ci	default:
2628c2ecf20Sopenharmony_ci		return -EINVAL;
2638c2ecf20Sopenharmony_ci	}
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	if (acl) {
2668c2ecf20Sopenharmony_ci		value = reiserfs_posix_acl_to_disk(acl, &size);
2678c2ecf20Sopenharmony_ci		if (IS_ERR(value))
2688c2ecf20Sopenharmony_ci			return (int)PTR_ERR(value);
2698c2ecf20Sopenharmony_ci	}
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	error = reiserfs_xattr_set_handle(th, inode, name, value, size, 0);
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	/*
2748c2ecf20Sopenharmony_ci	 * Ensure that the inode gets dirtied if we're only using
2758c2ecf20Sopenharmony_ci	 * the mode bits and an old ACL didn't exist. We don't need
2768c2ecf20Sopenharmony_ci	 * to check if the inode is hashed here since we won't get
2778c2ecf20Sopenharmony_ci	 * called by reiserfs_inherit_default_acl().
2788c2ecf20Sopenharmony_ci	 */
2798c2ecf20Sopenharmony_ci	if (error == -ENODATA) {
2808c2ecf20Sopenharmony_ci		error = 0;
2818c2ecf20Sopenharmony_ci		if (type == ACL_TYPE_ACCESS) {
2828c2ecf20Sopenharmony_ci			inode->i_ctime = current_time(inode);
2838c2ecf20Sopenharmony_ci			mark_inode_dirty(inode);
2848c2ecf20Sopenharmony_ci		}
2858c2ecf20Sopenharmony_ci	}
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	kfree(value);
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	if (!error)
2908c2ecf20Sopenharmony_ci		set_cached_acl(inode, type, acl);
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	return error;
2938c2ecf20Sopenharmony_ci}
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci/*
2968c2ecf20Sopenharmony_ci * dir->i_mutex: locked,
2978c2ecf20Sopenharmony_ci * inode is new and not released into the wild yet
2988c2ecf20Sopenharmony_ci */
2998c2ecf20Sopenharmony_ciint
3008c2ecf20Sopenharmony_cireiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
3018c2ecf20Sopenharmony_ci			     struct inode *dir, struct dentry *dentry,
3028c2ecf20Sopenharmony_ci			     struct inode *inode)
3038c2ecf20Sopenharmony_ci{
3048c2ecf20Sopenharmony_ci	struct posix_acl *default_acl, *acl;
3058c2ecf20Sopenharmony_ci	int err = 0;
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	/* ACLs only get applied to files and directories */
3088c2ecf20Sopenharmony_ci	if (S_ISLNK(inode->i_mode))
3098c2ecf20Sopenharmony_ci		return 0;
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	/*
3128c2ecf20Sopenharmony_ci	 * ACLs can only be used on "new" objects, so if it's an old object
3138c2ecf20Sopenharmony_ci	 * there is nothing to inherit from
3148c2ecf20Sopenharmony_ci	 */
3158c2ecf20Sopenharmony_ci	if (get_inode_sd_version(dir) == STAT_DATA_V1)
3168c2ecf20Sopenharmony_ci		goto apply_umask;
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	/*
3198c2ecf20Sopenharmony_ci	 * Don't apply ACLs to objects in the .reiserfs_priv tree.. This
3208c2ecf20Sopenharmony_ci	 * would be useless since permissions are ignored, and a pain because
3218c2ecf20Sopenharmony_ci	 * it introduces locking cycles
3228c2ecf20Sopenharmony_ci	 */
3238c2ecf20Sopenharmony_ci	if (IS_PRIVATE(inode))
3248c2ecf20Sopenharmony_ci		goto apply_umask;
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	err = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
3278c2ecf20Sopenharmony_ci	if (err)
3288c2ecf20Sopenharmony_ci		return err;
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	if (default_acl) {
3318c2ecf20Sopenharmony_ci		err = __reiserfs_set_acl(th, inode, ACL_TYPE_DEFAULT,
3328c2ecf20Sopenharmony_ci					 default_acl);
3338c2ecf20Sopenharmony_ci		posix_acl_release(default_acl);
3348c2ecf20Sopenharmony_ci	}
3358c2ecf20Sopenharmony_ci	if (acl) {
3368c2ecf20Sopenharmony_ci		if (!err)
3378c2ecf20Sopenharmony_ci			err = __reiserfs_set_acl(th, inode, ACL_TYPE_ACCESS,
3388c2ecf20Sopenharmony_ci						 acl);
3398c2ecf20Sopenharmony_ci		posix_acl_release(acl);
3408c2ecf20Sopenharmony_ci	}
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	return err;
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ciapply_umask:
3458c2ecf20Sopenharmony_ci	/* no ACL, apply umask */
3468c2ecf20Sopenharmony_ci	inode->i_mode &= ~current_umask();
3478c2ecf20Sopenharmony_ci	return err;
3488c2ecf20Sopenharmony_ci}
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci/* This is used to cache the default acl before a new object is created.
3518c2ecf20Sopenharmony_ci * The biggest reason for this is to get an idea of how many blocks will
3528c2ecf20Sopenharmony_ci * actually be required for the create operation if we must inherit an ACL.
3538c2ecf20Sopenharmony_ci * An ACL write can add up to 3 object creations and an additional file write
3548c2ecf20Sopenharmony_ci * so we'd prefer not to reserve that many blocks in the journal if we can.
3558c2ecf20Sopenharmony_ci * It also has the advantage of not loading the ACL with a transaction open,
3568c2ecf20Sopenharmony_ci * this may seem silly, but if the owner of the directory is doing the
3578c2ecf20Sopenharmony_ci * creation, the ACL may not be loaded since the permissions wouldn't require
3588c2ecf20Sopenharmony_ci * it.
3598c2ecf20Sopenharmony_ci * We return the number of blocks required for the transaction.
3608c2ecf20Sopenharmony_ci */
3618c2ecf20Sopenharmony_ciint reiserfs_cache_default_acl(struct inode *inode)
3628c2ecf20Sopenharmony_ci{
3638c2ecf20Sopenharmony_ci	struct posix_acl *acl;
3648c2ecf20Sopenharmony_ci	int nblocks = 0;
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	if (IS_PRIVATE(inode))
3678c2ecf20Sopenharmony_ci		return 0;
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	acl = get_acl(inode, ACL_TYPE_DEFAULT);
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci	if (acl && !IS_ERR(acl)) {
3728c2ecf20Sopenharmony_ci		int size = reiserfs_acl_size(acl->a_count);
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci		/* Other xattrs can be created during inode creation. We don't
3758c2ecf20Sopenharmony_ci		 * want to claim too many blocks, so we check to see if we
3768c2ecf20Sopenharmony_ci		 * need to create the tree to the xattrs, and then we
3778c2ecf20Sopenharmony_ci		 * just want two files. */
3788c2ecf20Sopenharmony_ci		nblocks = reiserfs_xattr_jcreate_nblocks(inode);
3798c2ecf20Sopenharmony_ci		nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci		REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci		/* We need to account for writes + bitmaps for two files */
3848c2ecf20Sopenharmony_ci		nblocks += reiserfs_xattr_nblocks(inode, size) * 4;
3858c2ecf20Sopenharmony_ci		posix_acl_release(acl);
3868c2ecf20Sopenharmony_ci	}
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	return nblocks;
3898c2ecf20Sopenharmony_ci}
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci/*
3928c2ecf20Sopenharmony_ci * Called under i_mutex
3938c2ecf20Sopenharmony_ci */
3948c2ecf20Sopenharmony_ciint reiserfs_acl_chmod(struct inode *inode)
3958c2ecf20Sopenharmony_ci{
3968c2ecf20Sopenharmony_ci	if (IS_PRIVATE(inode))
3978c2ecf20Sopenharmony_ci		return 0;
3988c2ecf20Sopenharmony_ci	if (get_inode_sd_version(inode) == STAT_DATA_V1 ||
3998c2ecf20Sopenharmony_ci	    !reiserfs_posixacl(inode->i_sb))
4008c2ecf20Sopenharmony_ci		return 0;
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	return posix_acl_chmod(inode, inode->i_mode);
4038c2ecf20Sopenharmony_ci}
404