0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/sched.h>
0009 #include <linux/slab.h>
0010 #include <linux/fs.h>
0011 #include <linux/posix_acl_xattr.h>
0012 #include "jfs_incore.h"
0013 #include "jfs_txnmgr.h"
0014 #include "jfs_xattr.h"
0015 #include "jfs_acl.h"
0016
0017 struct posix_acl *jfs_get_acl(struct inode *inode, int type, bool rcu)
0018 {
0019 struct posix_acl *acl;
0020 char *ea_name;
0021 int size;
0022 char *value = NULL;
0023
0024 if (rcu)
0025 return ERR_PTR(-ECHILD);
0026
0027 switch(type) {
0028 case ACL_TYPE_ACCESS:
0029 ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
0030 break;
0031 case ACL_TYPE_DEFAULT:
0032 ea_name = XATTR_NAME_POSIX_ACL_DEFAULT;
0033 break;
0034 default:
0035 return ERR_PTR(-EINVAL);
0036 }
0037
0038 size = __jfs_getxattr(inode, ea_name, NULL, 0);
0039
0040 if (size > 0) {
0041 value = kmalloc(size, GFP_KERNEL);
0042 if (!value)
0043 return ERR_PTR(-ENOMEM);
0044 size = __jfs_getxattr(inode, ea_name, value, size);
0045 }
0046
0047 if (size < 0) {
0048 if (size == -ENODATA)
0049 acl = NULL;
0050 else
0051 acl = ERR_PTR(size);
0052 } else {
0053 acl = posix_acl_from_xattr(&init_user_ns, value, size);
0054 }
0055 kfree(value);
0056 return acl;
0057 }
0058
0059 static int __jfs_set_acl(tid_t tid, struct inode *inode, int type,
0060 struct posix_acl *acl)
0061 {
0062 char *ea_name;
0063 int rc;
0064 int size = 0;
0065 char *value = NULL;
0066
0067 switch (type) {
0068 case ACL_TYPE_ACCESS:
0069 ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
0070 break;
0071 case ACL_TYPE_DEFAULT:
0072 ea_name = XATTR_NAME_POSIX_ACL_DEFAULT;
0073 break;
0074 default:
0075 return -EINVAL;
0076 }
0077
0078 if (acl) {
0079 size = posix_acl_xattr_size(acl->a_count);
0080 value = kmalloc(size, GFP_KERNEL);
0081 if (!value)
0082 return -ENOMEM;
0083 rc = posix_acl_to_xattr(&init_user_ns, acl, value, size);
0084 if (rc < 0)
0085 goto out;
0086 }
0087 rc = __jfs_setxattr(tid, inode, ea_name, value, size, 0);
0088 out:
0089 kfree(value);
0090
0091 if (!rc)
0092 set_cached_acl(inode, type, acl);
0093
0094 return rc;
0095 }
0096
0097 int jfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
0098 struct posix_acl *acl, int type)
0099 {
0100 int rc;
0101 tid_t tid;
0102 int update_mode = 0;
0103 umode_t mode = inode->i_mode;
0104
0105 tid = txBegin(inode->i_sb, 0);
0106 mutex_lock(&JFS_IP(inode)->commit_mutex);
0107 if (type == ACL_TYPE_ACCESS && acl) {
0108 rc = posix_acl_update_mode(&init_user_ns, inode, &mode, &acl);
0109 if (rc)
0110 goto end_tx;
0111 if (mode != inode->i_mode)
0112 update_mode = 1;
0113 }
0114 rc = __jfs_set_acl(tid, inode, type, acl);
0115 if (!rc) {
0116 if (update_mode) {
0117 inode->i_mode = mode;
0118 inode->i_ctime = current_time(inode);
0119 mark_inode_dirty(inode);
0120 }
0121 rc = txCommit(tid, 1, &inode, 0);
0122 }
0123 end_tx:
0124 txEnd(tid);
0125 mutex_unlock(&JFS_IP(inode)->commit_mutex);
0126 return rc;
0127 }
0128
0129 int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
0130 {
0131 struct posix_acl *default_acl, *acl;
0132 int rc = 0;
0133
0134 rc = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
0135 if (rc)
0136 return rc;
0137
0138 if (default_acl) {
0139 rc = __jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, default_acl);
0140 posix_acl_release(default_acl);
0141 } else {
0142 inode->i_default_acl = NULL;
0143 }
0144
0145 if (acl) {
0146 if (!rc)
0147 rc = __jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
0148 posix_acl_release(acl);
0149 } else {
0150 inode->i_acl = NULL;
0151 }
0152
0153 JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) |
0154 inode->i_mode;
0155
0156 return rc;
0157 }