162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include <linux/capability.h> 362306a36Sopenharmony_ci#include <linux/fs.h> 462306a36Sopenharmony_ci#include <linux/posix_acl.h> 562306a36Sopenharmony_ci#include "reiserfs.h" 662306a36Sopenharmony_ci#include <linux/errno.h> 762306a36Sopenharmony_ci#include <linux/pagemap.h> 862306a36Sopenharmony_ci#include <linux/xattr.h> 962306a36Sopenharmony_ci#include <linux/slab.h> 1062306a36Sopenharmony_ci#include <linux/posix_acl_xattr.h> 1162306a36Sopenharmony_ci#include "xattr.h" 1262306a36Sopenharmony_ci#include "acl.h" 1362306a36Sopenharmony_ci#include <linux/uaccess.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_cistatic int __reiserfs_set_acl(struct reiserfs_transaction_handle *th, 1662306a36Sopenharmony_ci struct inode *inode, int type, 1762306a36Sopenharmony_ci struct posix_acl *acl); 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ciint 2162306a36Sopenharmony_cireiserfs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, 2262306a36Sopenharmony_ci struct posix_acl *acl, int type) 2362306a36Sopenharmony_ci{ 2462306a36Sopenharmony_ci int error, error2; 2562306a36Sopenharmony_ci struct reiserfs_transaction_handle th; 2662306a36Sopenharmony_ci size_t jcreate_blocks; 2762306a36Sopenharmony_ci int size = acl ? posix_acl_xattr_size(acl->a_count) : 0; 2862306a36Sopenharmony_ci int update_mode = 0; 2962306a36Sopenharmony_ci struct inode *inode = d_inode(dentry); 3062306a36Sopenharmony_ci umode_t mode = inode->i_mode; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci /* 3362306a36Sopenharmony_ci * Pessimism: We can't assume that anything from the xattr root up 3462306a36Sopenharmony_ci * has been created. 3562306a36Sopenharmony_ci */ 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci jcreate_blocks = reiserfs_xattr_jcreate_nblocks(inode) + 3862306a36Sopenharmony_ci reiserfs_xattr_nblocks(inode, size) * 2; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci reiserfs_write_lock(inode->i_sb); 4162306a36Sopenharmony_ci error = journal_begin(&th, inode->i_sb, jcreate_blocks); 4262306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 4362306a36Sopenharmony_ci if (error == 0) { 4462306a36Sopenharmony_ci if (type == ACL_TYPE_ACCESS && acl) { 4562306a36Sopenharmony_ci error = posix_acl_update_mode(&nop_mnt_idmap, inode, 4662306a36Sopenharmony_ci &mode, &acl); 4762306a36Sopenharmony_ci if (error) 4862306a36Sopenharmony_ci goto unlock; 4962306a36Sopenharmony_ci update_mode = 1; 5062306a36Sopenharmony_ci } 5162306a36Sopenharmony_ci error = __reiserfs_set_acl(&th, inode, type, acl); 5262306a36Sopenharmony_ci if (!error && update_mode) 5362306a36Sopenharmony_ci inode->i_mode = mode; 5462306a36Sopenharmony_ciunlock: 5562306a36Sopenharmony_ci reiserfs_write_lock(inode->i_sb); 5662306a36Sopenharmony_ci error2 = journal_end(&th); 5762306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 5862306a36Sopenharmony_ci if (error2) 5962306a36Sopenharmony_ci error = error2; 6062306a36Sopenharmony_ci } 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci return error; 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci/* 6662306a36Sopenharmony_ci * Convert from filesystem to in-memory representation. 6762306a36Sopenharmony_ci */ 6862306a36Sopenharmony_cistatic struct posix_acl *reiserfs_posix_acl_from_disk(const void *value, size_t size) 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci const char *end = (char *)value + size; 7162306a36Sopenharmony_ci int n, count; 7262306a36Sopenharmony_ci struct posix_acl *acl; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci if (!value) 7562306a36Sopenharmony_ci return NULL; 7662306a36Sopenharmony_ci if (size < sizeof(reiserfs_acl_header)) 7762306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 7862306a36Sopenharmony_ci if (((reiserfs_acl_header *) value)->a_version != 7962306a36Sopenharmony_ci cpu_to_le32(REISERFS_ACL_VERSION)) 8062306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 8162306a36Sopenharmony_ci value = (char *)value + sizeof(reiserfs_acl_header); 8262306a36Sopenharmony_ci count = reiserfs_acl_count(size); 8362306a36Sopenharmony_ci if (count < 0) 8462306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 8562306a36Sopenharmony_ci if (count == 0) 8662306a36Sopenharmony_ci return NULL; 8762306a36Sopenharmony_ci acl = posix_acl_alloc(count, GFP_NOFS); 8862306a36Sopenharmony_ci if (!acl) 8962306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 9062306a36Sopenharmony_ci for (n = 0; n < count; n++) { 9162306a36Sopenharmony_ci reiserfs_acl_entry *entry = (reiserfs_acl_entry *) value; 9262306a36Sopenharmony_ci if ((char *)value + sizeof(reiserfs_acl_entry_short) > end) 9362306a36Sopenharmony_ci goto fail; 9462306a36Sopenharmony_ci acl->a_entries[n].e_tag = le16_to_cpu(entry->e_tag); 9562306a36Sopenharmony_ci acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm); 9662306a36Sopenharmony_ci switch (acl->a_entries[n].e_tag) { 9762306a36Sopenharmony_ci case ACL_USER_OBJ: 9862306a36Sopenharmony_ci case ACL_GROUP_OBJ: 9962306a36Sopenharmony_ci case ACL_MASK: 10062306a36Sopenharmony_ci case ACL_OTHER: 10162306a36Sopenharmony_ci value = (char *)value + 10262306a36Sopenharmony_ci sizeof(reiserfs_acl_entry_short); 10362306a36Sopenharmony_ci break; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci case ACL_USER: 10662306a36Sopenharmony_ci value = (char *)value + sizeof(reiserfs_acl_entry); 10762306a36Sopenharmony_ci if ((char *)value > end) 10862306a36Sopenharmony_ci goto fail; 10962306a36Sopenharmony_ci acl->a_entries[n].e_uid = 11062306a36Sopenharmony_ci make_kuid(&init_user_ns, 11162306a36Sopenharmony_ci le32_to_cpu(entry->e_id)); 11262306a36Sopenharmony_ci break; 11362306a36Sopenharmony_ci case ACL_GROUP: 11462306a36Sopenharmony_ci value = (char *)value + sizeof(reiserfs_acl_entry); 11562306a36Sopenharmony_ci if ((char *)value > end) 11662306a36Sopenharmony_ci goto fail; 11762306a36Sopenharmony_ci acl->a_entries[n].e_gid = 11862306a36Sopenharmony_ci make_kgid(&init_user_ns, 11962306a36Sopenharmony_ci le32_to_cpu(entry->e_id)); 12062306a36Sopenharmony_ci break; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci default: 12362306a36Sopenharmony_ci goto fail; 12462306a36Sopenharmony_ci } 12562306a36Sopenharmony_ci } 12662306a36Sopenharmony_ci if (value != end) 12762306a36Sopenharmony_ci goto fail; 12862306a36Sopenharmony_ci return acl; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cifail: 13162306a36Sopenharmony_ci posix_acl_release(acl); 13262306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 13362306a36Sopenharmony_ci} 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci/* 13662306a36Sopenharmony_ci * Convert from in-memory to filesystem representation. 13762306a36Sopenharmony_ci */ 13862306a36Sopenharmony_cistatic void *reiserfs_posix_acl_to_disk(const struct posix_acl *acl, size_t * size) 13962306a36Sopenharmony_ci{ 14062306a36Sopenharmony_ci reiserfs_acl_header *ext_acl; 14162306a36Sopenharmony_ci char *e; 14262306a36Sopenharmony_ci int n; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci *size = reiserfs_acl_size(acl->a_count); 14562306a36Sopenharmony_ci ext_acl = kmalloc(sizeof(reiserfs_acl_header) + 14662306a36Sopenharmony_ci acl->a_count * 14762306a36Sopenharmony_ci sizeof(reiserfs_acl_entry), 14862306a36Sopenharmony_ci GFP_NOFS); 14962306a36Sopenharmony_ci if (!ext_acl) 15062306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 15162306a36Sopenharmony_ci ext_acl->a_version = cpu_to_le32(REISERFS_ACL_VERSION); 15262306a36Sopenharmony_ci e = (char *)ext_acl + sizeof(reiserfs_acl_header); 15362306a36Sopenharmony_ci for (n = 0; n < acl->a_count; n++) { 15462306a36Sopenharmony_ci const struct posix_acl_entry *acl_e = &acl->a_entries[n]; 15562306a36Sopenharmony_ci reiserfs_acl_entry *entry = (reiserfs_acl_entry *) e; 15662306a36Sopenharmony_ci entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag); 15762306a36Sopenharmony_ci entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm); 15862306a36Sopenharmony_ci switch (acl->a_entries[n].e_tag) { 15962306a36Sopenharmony_ci case ACL_USER: 16062306a36Sopenharmony_ci entry->e_id = cpu_to_le32( 16162306a36Sopenharmony_ci from_kuid(&init_user_ns, acl_e->e_uid)); 16262306a36Sopenharmony_ci e += sizeof(reiserfs_acl_entry); 16362306a36Sopenharmony_ci break; 16462306a36Sopenharmony_ci case ACL_GROUP: 16562306a36Sopenharmony_ci entry->e_id = cpu_to_le32( 16662306a36Sopenharmony_ci from_kgid(&init_user_ns, acl_e->e_gid)); 16762306a36Sopenharmony_ci e += sizeof(reiserfs_acl_entry); 16862306a36Sopenharmony_ci break; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci case ACL_USER_OBJ: 17162306a36Sopenharmony_ci case ACL_GROUP_OBJ: 17262306a36Sopenharmony_ci case ACL_MASK: 17362306a36Sopenharmony_ci case ACL_OTHER: 17462306a36Sopenharmony_ci e += sizeof(reiserfs_acl_entry_short); 17562306a36Sopenharmony_ci break; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci default: 17862306a36Sopenharmony_ci goto fail; 17962306a36Sopenharmony_ci } 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci return (char *)ext_acl; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cifail: 18462306a36Sopenharmony_ci kfree(ext_acl); 18562306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 18662306a36Sopenharmony_ci} 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci/* 18962306a36Sopenharmony_ci * Inode operation get_posix_acl(). 19062306a36Sopenharmony_ci * 19162306a36Sopenharmony_ci * inode->i_mutex: down 19262306a36Sopenharmony_ci * BKL held [before 2.5.x] 19362306a36Sopenharmony_ci */ 19462306a36Sopenharmony_cistruct posix_acl *reiserfs_get_acl(struct inode *inode, int type, bool rcu) 19562306a36Sopenharmony_ci{ 19662306a36Sopenharmony_ci char *name, *value; 19762306a36Sopenharmony_ci struct posix_acl *acl; 19862306a36Sopenharmony_ci int size; 19962306a36Sopenharmony_ci int retval; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci if (rcu) 20262306a36Sopenharmony_ci return ERR_PTR(-ECHILD); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci switch (type) { 20562306a36Sopenharmony_ci case ACL_TYPE_ACCESS: 20662306a36Sopenharmony_ci name = XATTR_NAME_POSIX_ACL_ACCESS; 20762306a36Sopenharmony_ci break; 20862306a36Sopenharmony_ci case ACL_TYPE_DEFAULT: 20962306a36Sopenharmony_ci name = XATTR_NAME_POSIX_ACL_DEFAULT; 21062306a36Sopenharmony_ci break; 21162306a36Sopenharmony_ci default: 21262306a36Sopenharmony_ci BUG(); 21362306a36Sopenharmony_ci } 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci size = reiserfs_xattr_get(inode, name, NULL, 0); 21662306a36Sopenharmony_ci if (size < 0) { 21762306a36Sopenharmony_ci if (size == -ENODATA || size == -ENOSYS) 21862306a36Sopenharmony_ci return NULL; 21962306a36Sopenharmony_ci return ERR_PTR(size); 22062306a36Sopenharmony_ci } 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci value = kmalloc(size, GFP_NOFS); 22362306a36Sopenharmony_ci if (!value) 22462306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci retval = reiserfs_xattr_get(inode, name, value, size); 22762306a36Sopenharmony_ci if (retval == -ENODATA || retval == -ENOSYS) { 22862306a36Sopenharmony_ci /* 22962306a36Sopenharmony_ci * This shouldn't actually happen as it should have 23062306a36Sopenharmony_ci * been caught above.. but just in case 23162306a36Sopenharmony_ci */ 23262306a36Sopenharmony_ci acl = NULL; 23362306a36Sopenharmony_ci } else if (retval < 0) { 23462306a36Sopenharmony_ci acl = ERR_PTR(retval); 23562306a36Sopenharmony_ci } else { 23662306a36Sopenharmony_ci acl = reiserfs_posix_acl_from_disk(value, retval); 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci kfree(value); 24062306a36Sopenharmony_ci return acl; 24162306a36Sopenharmony_ci} 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci/* 24462306a36Sopenharmony_ci * Inode operation set_posix_acl(). 24562306a36Sopenharmony_ci * 24662306a36Sopenharmony_ci * inode->i_mutex: down 24762306a36Sopenharmony_ci * BKL held [before 2.5.x] 24862306a36Sopenharmony_ci */ 24962306a36Sopenharmony_cistatic int 25062306a36Sopenharmony_ci__reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, 25162306a36Sopenharmony_ci int type, struct posix_acl *acl) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci char *name; 25462306a36Sopenharmony_ci void *value = NULL; 25562306a36Sopenharmony_ci size_t size = 0; 25662306a36Sopenharmony_ci int error; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci switch (type) { 25962306a36Sopenharmony_ci case ACL_TYPE_ACCESS: 26062306a36Sopenharmony_ci name = XATTR_NAME_POSIX_ACL_ACCESS; 26162306a36Sopenharmony_ci break; 26262306a36Sopenharmony_ci case ACL_TYPE_DEFAULT: 26362306a36Sopenharmony_ci name = XATTR_NAME_POSIX_ACL_DEFAULT; 26462306a36Sopenharmony_ci if (!S_ISDIR(inode->i_mode)) 26562306a36Sopenharmony_ci return acl ? -EACCES : 0; 26662306a36Sopenharmony_ci break; 26762306a36Sopenharmony_ci default: 26862306a36Sopenharmony_ci return -EINVAL; 26962306a36Sopenharmony_ci } 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci if (acl) { 27262306a36Sopenharmony_ci value = reiserfs_posix_acl_to_disk(acl, &size); 27362306a36Sopenharmony_ci if (IS_ERR(value)) 27462306a36Sopenharmony_ci return (int)PTR_ERR(value); 27562306a36Sopenharmony_ci } 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci error = reiserfs_xattr_set_handle(th, inode, name, value, size, 0); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci /* 28062306a36Sopenharmony_ci * Ensure that the inode gets dirtied if we're only using 28162306a36Sopenharmony_ci * the mode bits and an old ACL didn't exist. We don't need 28262306a36Sopenharmony_ci * to check if the inode is hashed here since we won't get 28362306a36Sopenharmony_ci * called by reiserfs_inherit_default_acl(). 28462306a36Sopenharmony_ci */ 28562306a36Sopenharmony_ci if (error == -ENODATA) { 28662306a36Sopenharmony_ci error = 0; 28762306a36Sopenharmony_ci if (type == ACL_TYPE_ACCESS) { 28862306a36Sopenharmony_ci inode_set_ctime_current(inode); 28962306a36Sopenharmony_ci mark_inode_dirty(inode); 29062306a36Sopenharmony_ci } 29162306a36Sopenharmony_ci } 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci kfree(value); 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci if (!error) 29662306a36Sopenharmony_ci set_cached_acl(inode, type, acl); 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci return error; 29962306a36Sopenharmony_ci} 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci/* 30262306a36Sopenharmony_ci * dir->i_mutex: locked, 30362306a36Sopenharmony_ci * inode is new and not released into the wild yet 30462306a36Sopenharmony_ci */ 30562306a36Sopenharmony_ciint 30662306a36Sopenharmony_cireiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th, 30762306a36Sopenharmony_ci struct inode *dir, struct dentry *dentry, 30862306a36Sopenharmony_ci struct inode *inode) 30962306a36Sopenharmony_ci{ 31062306a36Sopenharmony_ci struct posix_acl *default_acl, *acl; 31162306a36Sopenharmony_ci int err = 0; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci /* ACLs only get applied to files and directories */ 31462306a36Sopenharmony_ci if (S_ISLNK(inode->i_mode)) 31562306a36Sopenharmony_ci return 0; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci /* 31862306a36Sopenharmony_ci * ACLs can only be used on "new" objects, so if it's an old object 31962306a36Sopenharmony_ci * there is nothing to inherit from 32062306a36Sopenharmony_ci */ 32162306a36Sopenharmony_ci if (get_inode_sd_version(dir) == STAT_DATA_V1) 32262306a36Sopenharmony_ci goto apply_umask; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci /* 32562306a36Sopenharmony_ci * Don't apply ACLs to objects in the .reiserfs_priv tree.. This 32662306a36Sopenharmony_ci * would be useless since permissions are ignored, and a pain because 32762306a36Sopenharmony_ci * it introduces locking cycles 32862306a36Sopenharmony_ci */ 32962306a36Sopenharmony_ci if (IS_PRIVATE(inode)) 33062306a36Sopenharmony_ci goto apply_umask; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci err = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl); 33362306a36Sopenharmony_ci if (err) 33462306a36Sopenharmony_ci return err; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci if (default_acl) { 33762306a36Sopenharmony_ci err = __reiserfs_set_acl(th, inode, ACL_TYPE_DEFAULT, 33862306a36Sopenharmony_ci default_acl); 33962306a36Sopenharmony_ci posix_acl_release(default_acl); 34062306a36Sopenharmony_ci } 34162306a36Sopenharmony_ci if (acl) { 34262306a36Sopenharmony_ci if (!err) 34362306a36Sopenharmony_ci err = __reiserfs_set_acl(th, inode, ACL_TYPE_ACCESS, 34462306a36Sopenharmony_ci acl); 34562306a36Sopenharmony_ci posix_acl_release(acl); 34662306a36Sopenharmony_ci } 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci return err; 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ciapply_umask: 35162306a36Sopenharmony_ci /* no ACL, apply umask */ 35262306a36Sopenharmony_ci inode->i_mode &= ~current_umask(); 35362306a36Sopenharmony_ci return err; 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci/* This is used to cache the default acl before a new object is created. 35762306a36Sopenharmony_ci * The biggest reason for this is to get an idea of how many blocks will 35862306a36Sopenharmony_ci * actually be required for the create operation if we must inherit an ACL. 35962306a36Sopenharmony_ci * An ACL write can add up to 3 object creations and an additional file write 36062306a36Sopenharmony_ci * so we'd prefer not to reserve that many blocks in the journal if we can. 36162306a36Sopenharmony_ci * It also has the advantage of not loading the ACL with a transaction open, 36262306a36Sopenharmony_ci * this may seem silly, but if the owner of the directory is doing the 36362306a36Sopenharmony_ci * creation, the ACL may not be loaded since the permissions wouldn't require 36462306a36Sopenharmony_ci * it. 36562306a36Sopenharmony_ci * We return the number of blocks required for the transaction. 36662306a36Sopenharmony_ci */ 36762306a36Sopenharmony_ciint reiserfs_cache_default_acl(struct inode *inode) 36862306a36Sopenharmony_ci{ 36962306a36Sopenharmony_ci struct posix_acl *acl; 37062306a36Sopenharmony_ci int nblocks = 0; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci if (IS_PRIVATE(inode)) 37362306a36Sopenharmony_ci return 0; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci acl = get_inode_acl(inode, ACL_TYPE_DEFAULT); 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci if (acl && !IS_ERR(acl)) { 37862306a36Sopenharmony_ci int size = reiserfs_acl_size(acl->a_count); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci /* Other xattrs can be created during inode creation. We don't 38162306a36Sopenharmony_ci * want to claim too many blocks, so we check to see if we 38262306a36Sopenharmony_ci * need to create the tree to the xattrs, and then we 38362306a36Sopenharmony_ci * just want two files. */ 38462306a36Sopenharmony_ci nblocks = reiserfs_xattr_jcreate_nblocks(inode); 38562306a36Sopenharmony_ci nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci REISERFS_I(inode)->i_flags |= i_has_xattr_dir; 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci /* We need to account for writes + bitmaps for two files */ 39062306a36Sopenharmony_ci nblocks += reiserfs_xattr_nblocks(inode, size) * 4; 39162306a36Sopenharmony_ci posix_acl_release(acl); 39262306a36Sopenharmony_ci } 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci return nblocks; 39562306a36Sopenharmony_ci} 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci/* 39862306a36Sopenharmony_ci * Called under i_mutex 39962306a36Sopenharmony_ci */ 40062306a36Sopenharmony_ciint reiserfs_acl_chmod(struct dentry *dentry) 40162306a36Sopenharmony_ci{ 40262306a36Sopenharmony_ci struct inode *inode = d_inode(dentry); 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci if (IS_PRIVATE(inode)) 40562306a36Sopenharmony_ci return 0; 40662306a36Sopenharmony_ci if (get_inode_sd_version(inode) == STAT_DATA_V1 || 40762306a36Sopenharmony_ci !reiserfs_posixacl(inode->i_sb)) 40862306a36Sopenharmony_ci return 0; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci return posix_acl_chmod(&nop_mnt_idmap, dentry, inode->i_mode); 41162306a36Sopenharmony_ci} 412