1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
216f7e0feSRandy Dunlap #include <linux/capability.h>
31da177e4SLinus Torvalds #include <linux/fs.h>
41da177e4SLinus Torvalds #include <linux/posix_acl.h>
5f466c6fdSAl Viro #include "reiserfs.h"
61da177e4SLinus Torvalds #include <linux/errno.h>
71da177e4SLinus Torvalds #include <linux/pagemap.h>
81da177e4SLinus Torvalds #include <linux/xattr.h>
95a0e3ad6STejun Heo #include <linux/slab.h>
109a59f452SChristoph Hellwig #include <linux/posix_acl_xattr.h>
11c45ac888SAl Viro #include "xattr.h"
12a3063ab8SAl Viro #include "acl.h"
1317093991SFabian Frederick #include <linux/uaccess.h>
141da177e4SLinus Torvalds
1547f70d08SChristoph Hellwig static int __reiserfs_set_acl(struct reiserfs_transaction_handle *th,
160ab2621eSJeff Mahoney struct inode *inode, int type,
17bd4c625cSLinus Torvalds struct posix_acl *acl);
181da177e4SLinus Torvalds
1947f70d08SChristoph Hellwig
2047f70d08SChristoph Hellwig int
reiserfs_set_acl(struct mnt_idmap * idmap,struct dentry * dentry,struct posix_acl * acl,int type)2113e83a49SChristian Brauner reiserfs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
22549c7297SChristian Brauner struct posix_acl *acl, int type)
231da177e4SLinus Torvalds {
240ab2621eSJeff Mahoney int error, error2;
250ab2621eSJeff Mahoney struct reiserfs_transaction_handle th;
260ab2621eSJeff Mahoney size_t jcreate_blocks;
2747f70d08SChristoph Hellwig int size = acl ? posix_acl_xattr_size(acl->a_count) : 0;
28fcea8aedSErnesto A. Fernández int update_mode = 0;
29138060baSChristian Brauner struct inode *inode = d_inode(dentry);
30fcea8aedSErnesto A. Fernández umode_t mode = inode->i_mode;
311da177e4SLinus Torvalds
32098297b2SJeff Mahoney /*
33098297b2SJeff Mahoney * Pessimism: We can't assume that anything from the xattr root up
34098297b2SJeff Mahoney * has been created.
35098297b2SJeff Mahoney */
360ab2621eSJeff Mahoney
370ab2621eSJeff Mahoney jcreate_blocks = reiserfs_xattr_jcreate_nblocks(inode) +
380ab2621eSJeff Mahoney reiserfs_xattr_nblocks(inode, size) * 2;
390ab2621eSJeff Mahoney
400ab2621eSJeff Mahoney reiserfs_write_lock(inode->i_sb);
410ab2621eSJeff Mahoney error = journal_begin(&th, inode->i_sb, jcreate_blocks);
424c05141dSJeff Mahoney reiserfs_write_unlock(inode->i_sb);
430ab2621eSJeff Mahoney if (error == 0) {
446883cd7fSJan Kara if (type == ACL_TYPE_ACCESS && acl) {
45700b7940SChristian Brauner error = posix_acl_update_mode(&nop_mnt_idmap, inode,
46e65ce2a5SChristian Brauner &mode, &acl);
476883cd7fSJan Kara if (error)
486883cd7fSJan Kara goto unlock;
49fcea8aedSErnesto A. Fernández update_mode = 1;
506883cd7fSJan Kara }
5147f70d08SChristoph Hellwig error = __reiserfs_set_acl(&th, inode, type, acl);
52fcea8aedSErnesto A. Fernández if (!error && update_mode)
53fcea8aedSErnesto A. Fernández inode->i_mode = mode;
546883cd7fSJan Kara unlock:
554c05141dSJeff Mahoney reiserfs_write_lock(inode->i_sb);
5658d85426SJeff Mahoney error2 = journal_end(&th);
574c05141dSJeff Mahoney reiserfs_write_unlock(inode->i_sb);
580ab2621eSJeff Mahoney if (error2)
590ab2621eSJeff Mahoney error = error2;
600ab2621eSJeff Mahoney }
611da177e4SLinus Torvalds
621da177e4SLinus Torvalds return error;
631da177e4SLinus Torvalds }
641da177e4SLinus Torvalds
651da177e4SLinus Torvalds /*
661da177e4SLinus Torvalds * Convert from filesystem to in-memory representation.
671da177e4SLinus Torvalds */
reiserfs_posix_acl_from_disk(const void * value,size_t size)689dad943aSChristoph Hellwig static struct posix_acl *reiserfs_posix_acl_from_disk(const void *value, size_t size)
691da177e4SLinus Torvalds {
701da177e4SLinus Torvalds const char *end = (char *)value + size;
711da177e4SLinus Torvalds int n, count;
721da177e4SLinus Torvalds struct posix_acl *acl;
731da177e4SLinus Torvalds
741da177e4SLinus Torvalds if (!value)
751da177e4SLinus Torvalds return NULL;
761da177e4SLinus Torvalds if (size < sizeof(reiserfs_acl_header))
771da177e4SLinus Torvalds return ERR_PTR(-EINVAL);
781da177e4SLinus Torvalds if (((reiserfs_acl_header *) value)->a_version !=
791da177e4SLinus Torvalds cpu_to_le32(REISERFS_ACL_VERSION))
801da177e4SLinus Torvalds return ERR_PTR(-EINVAL);
811da177e4SLinus Torvalds value = (char *)value + sizeof(reiserfs_acl_header);
821da177e4SLinus Torvalds count = reiserfs_acl_count(size);
831da177e4SLinus Torvalds if (count < 0)
841da177e4SLinus Torvalds return ERR_PTR(-EINVAL);
851da177e4SLinus Torvalds if (count == 0)
861da177e4SLinus Torvalds return NULL;
871da177e4SLinus Torvalds acl = posix_acl_alloc(count, GFP_NOFS);
881da177e4SLinus Torvalds if (!acl)
891da177e4SLinus Torvalds return ERR_PTR(-ENOMEM);
901da177e4SLinus Torvalds for (n = 0; n < count; n++) {
91bd4c625cSLinus Torvalds reiserfs_acl_entry *entry = (reiserfs_acl_entry *) value;
921da177e4SLinus Torvalds if ((char *)value + sizeof(reiserfs_acl_entry_short) > end)
931da177e4SLinus Torvalds goto fail;
941da177e4SLinus Torvalds acl->a_entries[n].e_tag = le16_to_cpu(entry->e_tag);
951da177e4SLinus Torvalds acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm);
961da177e4SLinus Torvalds switch (acl->a_entries[n].e_tag) {
971da177e4SLinus Torvalds case ACL_USER_OBJ:
981da177e4SLinus Torvalds case ACL_GROUP_OBJ:
991da177e4SLinus Torvalds case ACL_MASK:
1001da177e4SLinus Torvalds case ACL_OTHER:
1011da177e4SLinus Torvalds value = (char *)value +
1021da177e4SLinus Torvalds sizeof(reiserfs_acl_entry_short);
1031da177e4SLinus Torvalds break;
1041da177e4SLinus Torvalds
1051da177e4SLinus Torvalds case ACL_USER:
106df814654SEric W. Biederman value = (char *)value + sizeof(reiserfs_acl_entry);
107df814654SEric W. Biederman if ((char *)value > end)
108df814654SEric W. Biederman goto fail;
109df814654SEric W. Biederman acl->a_entries[n].e_uid =
110df814654SEric W. Biederman make_kuid(&init_user_ns,
111df814654SEric W. Biederman le32_to_cpu(entry->e_id));
112df814654SEric W. Biederman break;
1131da177e4SLinus Torvalds case ACL_GROUP:
1141da177e4SLinus Torvalds value = (char *)value + sizeof(reiserfs_acl_entry);
1151da177e4SLinus Torvalds if ((char *)value > end)
1161da177e4SLinus Torvalds goto fail;
117df814654SEric W. Biederman acl->a_entries[n].e_gid =
118df814654SEric W. Biederman make_kgid(&init_user_ns,
119df814654SEric W. Biederman le32_to_cpu(entry->e_id));
1201da177e4SLinus Torvalds break;
1211da177e4SLinus Torvalds
1221da177e4SLinus Torvalds default:
1231da177e4SLinus Torvalds goto fail;
1241da177e4SLinus Torvalds }
1251da177e4SLinus Torvalds }
1261da177e4SLinus Torvalds if (value != end)
1271da177e4SLinus Torvalds goto fail;
1281da177e4SLinus Torvalds return acl;
1291da177e4SLinus Torvalds
1301da177e4SLinus Torvalds fail:
1311da177e4SLinus Torvalds posix_acl_release(acl);
1321da177e4SLinus Torvalds return ERR_PTR(-EINVAL);
1331da177e4SLinus Torvalds }
1341da177e4SLinus Torvalds
1351da177e4SLinus Torvalds /*
1361da177e4SLinus Torvalds * Convert from in-memory to filesystem representation.
1371da177e4SLinus Torvalds */
reiserfs_posix_acl_to_disk(const struct posix_acl * acl,size_t * size)1389dad943aSChristoph Hellwig static void *reiserfs_posix_acl_to_disk(const struct posix_acl *acl, size_t * size)
1391da177e4SLinus Torvalds {
1401da177e4SLinus Torvalds reiserfs_acl_header *ext_acl;
1411da177e4SLinus Torvalds char *e;
1421da177e4SLinus Torvalds int n;
1431da177e4SLinus Torvalds
1441da177e4SLinus Torvalds *size = reiserfs_acl_size(acl->a_count);
1455cbded58SRobert P. J. Day ext_acl = kmalloc(sizeof(reiserfs_acl_header) +
146bd4c625cSLinus Torvalds acl->a_count *
147bd4c625cSLinus Torvalds sizeof(reiserfs_acl_entry),
148bd4c625cSLinus Torvalds GFP_NOFS);
1491da177e4SLinus Torvalds if (!ext_acl)
1501da177e4SLinus Torvalds return ERR_PTR(-ENOMEM);
1511da177e4SLinus Torvalds ext_acl->a_version = cpu_to_le32(REISERFS_ACL_VERSION);
1521da177e4SLinus Torvalds e = (char *)ext_acl + sizeof(reiserfs_acl_header);
1531da177e4SLinus Torvalds for (n = 0; n < acl->a_count; n++) {
154df814654SEric W. Biederman const struct posix_acl_entry *acl_e = &acl->a_entries[n];
1551da177e4SLinus Torvalds reiserfs_acl_entry *entry = (reiserfs_acl_entry *) e;
1561da177e4SLinus Torvalds entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag);
1571da177e4SLinus Torvalds entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm);
1581da177e4SLinus Torvalds switch (acl->a_entries[n].e_tag) {
1591da177e4SLinus Torvalds case ACL_USER:
160df814654SEric W. Biederman entry->e_id = cpu_to_le32(
161df814654SEric W. Biederman from_kuid(&init_user_ns, acl_e->e_uid));
162df814654SEric W. Biederman e += sizeof(reiserfs_acl_entry);
163df814654SEric W. Biederman break;
1641da177e4SLinus Torvalds case ACL_GROUP:
165df814654SEric W. Biederman entry->e_id = cpu_to_le32(
166df814654SEric W. Biederman from_kgid(&init_user_ns, acl_e->e_gid));
1671da177e4SLinus Torvalds e += sizeof(reiserfs_acl_entry);
1681da177e4SLinus Torvalds break;
1691da177e4SLinus Torvalds
1701da177e4SLinus Torvalds case ACL_USER_OBJ:
1711da177e4SLinus Torvalds case ACL_GROUP_OBJ:
1721da177e4SLinus Torvalds case ACL_MASK:
1731da177e4SLinus Torvalds case ACL_OTHER:
1741da177e4SLinus Torvalds e += sizeof(reiserfs_acl_entry_short);
1751da177e4SLinus Torvalds break;
1761da177e4SLinus Torvalds
1771da177e4SLinus Torvalds default:
1781da177e4SLinus Torvalds goto fail;
1791da177e4SLinus Torvalds }
1801da177e4SLinus Torvalds }
1811da177e4SLinus Torvalds return (char *)ext_acl;
1821da177e4SLinus Torvalds
1831da177e4SLinus Torvalds fail:
1841da177e4SLinus Torvalds kfree(ext_acl);
1851da177e4SLinus Torvalds return ERR_PTR(-EINVAL);
1861da177e4SLinus Torvalds }
1871da177e4SLinus Torvalds
1881da177e4SLinus Torvalds /*
1891da177e4SLinus Torvalds * Inode operation get_posix_acl().
1901da177e4SLinus Torvalds *
1911b1dcc1bSJes Sorensen * inode->i_mutex: down
1921da177e4SLinus Torvalds * BKL held [before 2.5.x]
1931da177e4SLinus Torvalds */
reiserfs_get_acl(struct inode * inode,int type,bool rcu)1940cad6246SMiklos Szeredi struct posix_acl *reiserfs_get_acl(struct inode *inode, int type, bool rcu)
1951da177e4SLinus Torvalds {
1961da177e4SLinus Torvalds char *name, *value;
197073aaa1bSAl Viro struct posix_acl *acl;
1983cdc409cSAdrian Bunk int size;
1991da177e4SLinus Torvalds int retval;
2001da177e4SLinus Torvalds
2010cad6246SMiklos Szeredi if (rcu)
2020cad6246SMiklos Szeredi return ERR_PTR(-ECHILD);
2030cad6246SMiklos Szeredi
2041da177e4SLinus Torvalds switch (type) {
2051da177e4SLinus Torvalds case ACL_TYPE_ACCESS:
20697d79299SAndreas Gruenbacher name = XATTR_NAME_POSIX_ACL_ACCESS;
2071da177e4SLinus Torvalds break;
2081da177e4SLinus Torvalds case ACL_TYPE_DEFAULT:
20997d79299SAndreas Gruenbacher name = XATTR_NAME_POSIX_ACL_DEFAULT;
2101da177e4SLinus Torvalds break;
2111da177e4SLinus Torvalds default:
212073aaa1bSAl Viro BUG();
2131da177e4SLinus Torvalds }
2141da177e4SLinus Torvalds
2151da177e4SLinus Torvalds size = reiserfs_xattr_get(inode, name, NULL, 0);
2163cdc409cSAdrian Bunk if (size < 0) {
217b8a7a3a6SAndreas Gruenbacher if (size == -ENODATA || size == -ENOSYS)
2181da177e4SLinus Torvalds return NULL;
2191da177e4SLinus Torvalds return ERR_PTR(size);
2201da177e4SLinus Torvalds }
2211da177e4SLinus Torvalds
2221da177e4SLinus Torvalds value = kmalloc(size, GFP_NOFS);
2231da177e4SLinus Torvalds if (!value)
2241da177e4SLinus Torvalds return ERR_PTR(-ENOMEM);
2251da177e4SLinus Torvalds
2261da177e4SLinus Torvalds retval = reiserfs_xattr_get(inode, name, value, size);
2271da177e4SLinus Torvalds if (retval == -ENODATA || retval == -ENOSYS) {
228098297b2SJeff Mahoney /*
229098297b2SJeff Mahoney * This shouldn't actually happen as it should have
230098297b2SJeff Mahoney * been caught above.. but just in case
231098297b2SJeff Mahoney */
2321da177e4SLinus Torvalds acl = NULL;
2331da177e4SLinus Torvalds } else if (retval < 0) {
2341da177e4SLinus Torvalds acl = ERR_PTR(retval);
2351da177e4SLinus Torvalds } else {
2369dad943aSChristoph Hellwig acl = reiserfs_posix_acl_from_disk(value, retval);
2371da177e4SLinus Torvalds }
2381da177e4SLinus Torvalds
2391da177e4SLinus Torvalds kfree(value);
2401da177e4SLinus Torvalds return acl;
2411da177e4SLinus Torvalds }
2421da177e4SLinus Torvalds
2431da177e4SLinus Torvalds /*
2441da177e4SLinus Torvalds * Inode operation set_posix_acl().
2451da177e4SLinus Torvalds *
2461b1dcc1bSJes Sorensen * inode->i_mutex: down
2471da177e4SLinus Torvalds * BKL held [before 2.5.x]
2481da177e4SLinus Torvalds */
2491da177e4SLinus Torvalds static int
__reiserfs_set_acl(struct reiserfs_transaction_handle * th,struct inode * inode,int type,struct posix_acl * acl)25047f70d08SChristoph Hellwig __reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
2510ab2621eSJeff Mahoney int type, struct posix_acl *acl)
2521da177e4SLinus Torvalds {
2531da177e4SLinus Torvalds char *name;
2541da177e4SLinus Torvalds void *value = NULL;
25548b32a35SJeff Mahoney size_t size = 0;
2561da177e4SLinus Torvalds int error;
2571da177e4SLinus Torvalds
2581da177e4SLinus Torvalds switch (type) {
2591da177e4SLinus Torvalds case ACL_TYPE_ACCESS:
26097d79299SAndreas Gruenbacher name = XATTR_NAME_POSIX_ACL_ACCESS;
2611da177e4SLinus Torvalds break;
2621da177e4SLinus Torvalds case ACL_TYPE_DEFAULT:
26397d79299SAndreas Gruenbacher name = XATTR_NAME_POSIX_ACL_DEFAULT;
2641da177e4SLinus Torvalds if (!S_ISDIR(inode->i_mode))
2651da177e4SLinus Torvalds return acl ? -EACCES : 0;
2661da177e4SLinus Torvalds break;
2671da177e4SLinus Torvalds default:
2681da177e4SLinus Torvalds return -EINVAL;
2691da177e4SLinus Torvalds }
2701da177e4SLinus Torvalds
2711da177e4SLinus Torvalds if (acl) {
2729dad943aSChristoph Hellwig value = reiserfs_posix_acl_to_disk(acl, &size);
2731da177e4SLinus Torvalds if (IS_ERR(value))
2741da177e4SLinus Torvalds return (int)PTR_ERR(value);
27548b32a35SJeff Mahoney }
27648b32a35SJeff Mahoney
2770ab2621eSJeff Mahoney error = reiserfs_xattr_set_handle(th, inode, name, value, size, 0);
27848b32a35SJeff Mahoney
27948b32a35SJeff Mahoney /*
28048b32a35SJeff Mahoney * Ensure that the inode gets dirtied if we're only using
28148b32a35SJeff Mahoney * the mode bits and an old ACL didn't exist. We don't need
28248b32a35SJeff Mahoney * to check if the inode is hashed here since we won't get
28348b32a35SJeff Mahoney * called by reiserfs_inherit_default_acl().
2841da177e4SLinus Torvalds */
28548b32a35SJeff Mahoney if (error == -ENODATA) {
2861da177e4SLinus Torvalds error = 0;
28748b32a35SJeff Mahoney if (type == ACL_TYPE_ACCESS) {
288*ae834901SJeff Layton inode_set_ctime_current(inode);
28948b32a35SJeff Mahoney mark_inode_dirty(inode);
2901da177e4SLinus Torvalds }
2911da177e4SLinus Torvalds }
2921da177e4SLinus Torvalds
2931da177e4SLinus Torvalds kfree(value);
2941da177e4SLinus Torvalds
295d984561bSJeff Mahoney if (!error)
296073aaa1bSAl Viro set_cached_acl(inode, type, acl);
2971da177e4SLinus Torvalds
2981da177e4SLinus Torvalds return error;
2991da177e4SLinus Torvalds }
3001da177e4SLinus Torvalds
301098297b2SJeff Mahoney /*
302098297b2SJeff Mahoney * dir->i_mutex: locked,
303098297b2SJeff Mahoney * inode is new and not released into the wild yet
304098297b2SJeff Mahoney */
3051da177e4SLinus Torvalds int
reiserfs_inherit_default_acl(struct reiserfs_transaction_handle * th,struct inode * dir,struct dentry * dentry,struct inode * inode)3060ab2621eSJeff Mahoney reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
3070ab2621eSJeff Mahoney struct inode *dir, struct dentry *dentry,
308bd4c625cSLinus Torvalds struct inode *inode)
3091da177e4SLinus Torvalds {
31047f70d08SChristoph Hellwig struct posix_acl *default_acl, *acl;
3111da177e4SLinus Torvalds int err = 0;
3121da177e4SLinus Torvalds
3131da177e4SLinus Torvalds /* ACLs only get applied to files and directories */
3141da177e4SLinus Torvalds if (S_ISLNK(inode->i_mode))
3151da177e4SLinus Torvalds return 0;
3161da177e4SLinus Torvalds
317098297b2SJeff Mahoney /*
318098297b2SJeff Mahoney * ACLs can only be used on "new" objects, so if it's an old object
319098297b2SJeff Mahoney * there is nothing to inherit from
320098297b2SJeff Mahoney */
3211da177e4SLinus Torvalds if (get_inode_sd_version(dir) == STAT_DATA_V1)
3221da177e4SLinus Torvalds goto apply_umask;
3231da177e4SLinus Torvalds
324098297b2SJeff Mahoney /*
325098297b2SJeff Mahoney * Don't apply ACLs to objects in the .reiserfs_priv tree.. This
3261da177e4SLinus Torvalds * would be useless since permissions are ignored, and a pain because
327098297b2SJeff Mahoney * it introduces locking cycles
328098297b2SJeff Mahoney */
32960e4cf67SJeff Mahoney if (IS_PRIVATE(inode))
3301da177e4SLinus Torvalds goto apply_umask;
3311da177e4SLinus Torvalds
33247f70d08SChristoph Hellwig err = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
3331da177e4SLinus Torvalds if (err)
334826cae2fSAl Viro return err;
3351da177e4SLinus Torvalds
33647f70d08SChristoph Hellwig if (default_acl) {
33747f70d08SChristoph Hellwig err = __reiserfs_set_acl(th, inode, ACL_TYPE_DEFAULT,
33847f70d08SChristoph Hellwig default_acl);
33947f70d08SChristoph Hellwig posix_acl_release(default_acl);
34047f70d08SChristoph Hellwig }
34147f70d08SChristoph Hellwig if (acl) {
34247f70d08SChristoph Hellwig if (!err)
34347f70d08SChristoph Hellwig err = __reiserfs_set_acl(th, inode, ACL_TYPE_ACCESS,
34447f70d08SChristoph Hellwig acl);
3451da177e4SLinus Torvalds posix_acl_release(acl);
34647f70d08SChristoph Hellwig }
34747f70d08SChristoph Hellwig
34847f70d08SChristoph Hellwig return err;
34947f70d08SChristoph Hellwig
3501da177e4SLinus Torvalds apply_umask:
3511da177e4SLinus Torvalds /* no ACL, apply umask */
352ce3b0f8dSAl Viro inode->i_mode &= ~current_umask();
3531da177e4SLinus Torvalds return err;
3541da177e4SLinus Torvalds }
3551da177e4SLinus Torvalds
3560ab2621eSJeff Mahoney /* This is used to cache the default acl before a new object is created.
3570ab2621eSJeff Mahoney * The biggest reason for this is to get an idea of how many blocks will
3580ab2621eSJeff Mahoney * actually be required for the create operation if we must inherit an ACL.
3590ab2621eSJeff Mahoney * An ACL write can add up to 3 object creations and an additional file write
3600ab2621eSJeff Mahoney * so we'd prefer not to reserve that many blocks in the journal if we can.
3610ab2621eSJeff Mahoney * It also has the advantage of not loading the ACL with a transaction open,
3620ab2621eSJeff Mahoney * this may seem silly, but if the owner of the directory is doing the
3630ab2621eSJeff Mahoney * creation, the ACL may not be loaded since the permissions wouldn't require
3640ab2621eSJeff Mahoney * it.
3650ab2621eSJeff Mahoney * We return the number of blocks required for the transaction.
3660ab2621eSJeff Mahoney */
reiserfs_cache_default_acl(struct inode * inode)367bd4c625cSLinus Torvalds int reiserfs_cache_default_acl(struct inode *inode)
3681da177e4SLinus Torvalds {
3691da177e4SLinus Torvalds struct posix_acl *acl;
3700ab2621eSJeff Mahoney int nblocks = 0;
3710ab2621eSJeff Mahoney
3720ab2621eSJeff Mahoney if (IS_PRIVATE(inode))
3730ab2621eSJeff Mahoney return 0;
3740ab2621eSJeff Mahoney
375cac2f8b8SChristian Brauner acl = get_inode_acl(inode, ACL_TYPE_DEFAULT);
3760ab2621eSJeff Mahoney
3770ab2621eSJeff Mahoney if (acl && !IS_ERR(acl)) {
3780ab2621eSJeff Mahoney int size = reiserfs_acl_size(acl->a_count);
3790ab2621eSJeff Mahoney
3800ab2621eSJeff Mahoney /* Other xattrs can be created during inode creation. We don't
3810ab2621eSJeff Mahoney * want to claim too many blocks, so we check to see if we
3829436fb4dSRandy Dunlap * need to create the tree to the xattrs, and then we
3830ab2621eSJeff Mahoney * just want two files. */
3840ab2621eSJeff Mahoney nblocks = reiserfs_xattr_jcreate_nblocks(inode);
3850ab2621eSJeff Mahoney nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
3860ab2621eSJeff Mahoney
3870ab2621eSJeff Mahoney REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
3880ab2621eSJeff Mahoney
3890ab2621eSJeff Mahoney /* We need to account for writes + bitmaps for two files */
3900ab2621eSJeff Mahoney nblocks += reiserfs_xattr_nblocks(inode, size) * 4;
3911da177e4SLinus Torvalds posix_acl_release(acl);
3921da177e4SLinus Torvalds }
3931da177e4SLinus Torvalds
3940ab2621eSJeff Mahoney return nblocks;
3951da177e4SLinus Torvalds }
3961da177e4SLinus Torvalds
3974c05141dSJeff Mahoney /*
3984c05141dSJeff Mahoney * Called under i_mutex
3994c05141dSJeff Mahoney */
reiserfs_acl_chmod(struct dentry * dentry)400138060baSChristian Brauner int reiserfs_acl_chmod(struct dentry *dentry)
4011da177e4SLinus Torvalds {
402138060baSChristian Brauner struct inode *inode = d_inode(dentry);
403138060baSChristian Brauner
4044a857011SJeff Mahoney if (IS_PRIVATE(inode))
4054a857011SJeff Mahoney return 0;
4061da177e4SLinus Torvalds if (get_inode_sd_version(inode) == STAT_DATA_V1 ||
40747f70d08SChristoph Hellwig !reiserfs_posixacl(inode->i_sb))
4081da177e4SLinus Torvalds return 0;
40947f70d08SChristoph Hellwig
41013e83a49SChristian Brauner return posix_acl_chmod(&nop_mnt_idmap, dentry, inode->i_mode);
4111da177e4SLinus Torvalds }
412