aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jfs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2013-12-20 08:16:51 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2014-01-25 23:58:22 -0500
commit2cc6a5a01cdbeb0e46f3aa144819d5d7cee458a1 (patch)
treed97137eadb3a11dfd12c7bc7bb552ce21e8e4688 /fs/jfs
parent2401dc2975fc5a33021dc8347ea82984c4707a08 (diff)
jfs: use generic posix ACL infrastructure
Copy the scheme I introduced to btrfs many years ago to only use the xattr handler for ACLs, but pass plain attrs straight through. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Kleikamp <dave.kleikamp@oracle.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/jfs')
-rw-r--r--fs/jfs/acl.c105
-rw-r--r--fs/jfs/file.c4
-rw-r--r--fs/jfs/jfs_acl.h7
-rw-r--r--fs/jfs/jfs_xattr.h2
-rw-r--r--fs/jfs/namei.c1
-rw-r--r--fs/jfs/super.c2
-rw-r--r--fs/jfs/xattr.c108
7 files changed, 89 insertions, 140 deletions
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index 28d529ae9a4a..e973b85d6afd 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -72,7 +72,7 @@ struct posix_acl *jfs_get_acl(struct inode *inode, int type)
72 return acl; 72 return acl;
73} 73}
74 74
75static int jfs_set_acl(tid_t tid, struct inode *inode, int type, 75static int __jfs_set_acl(tid_t tid, struct inode *inode, int type,
76 struct posix_acl *acl) 76 struct posix_acl *acl)
77{ 77{
78 char *ea_name; 78 char *ea_name;
@@ -80,21 +80,22 @@ static int jfs_set_acl(tid_t tid, struct inode *inode, int type,
80 int size = 0; 80 int size = 0;
81 char *value = NULL; 81 char *value = NULL;
82 82
83 if (S_ISLNK(inode->i_mode)) 83 switch (type) {
84 return -EOPNOTSUPP; 84 case ACL_TYPE_ACCESS:
85 85 ea_name = POSIX_ACL_XATTR_ACCESS;
86 switch(type) { 86 rc = posix_acl_equiv_mode(acl, &inode->i_mode);
87 case ACL_TYPE_ACCESS: 87 if (rc < 0)
88 ea_name = POSIX_ACL_XATTR_ACCESS; 88 return rc;
89 break; 89 if (rc == 0)
90 case ACL_TYPE_DEFAULT: 90 acl = NULL;
91 ea_name = POSIX_ACL_XATTR_DEFAULT; 91 break;
92 if (!S_ISDIR(inode->i_mode)) 92 case ACL_TYPE_DEFAULT:
93 return acl ? -EACCES : 0; 93 ea_name = POSIX_ACL_XATTR_DEFAULT;
94 break; 94 break;
95 default: 95 default:
96 return -EINVAL; 96 return -EINVAL;
97 } 97 }
98
98 if (acl) { 99 if (acl) {
99 size = posix_acl_xattr_size(acl->a_count); 100 size = posix_acl_xattr_size(acl->a_count);
100 value = kmalloc(size, GFP_KERNEL); 101 value = kmalloc(size, GFP_KERNEL);
@@ -114,65 +115,43 @@ out:
114 return rc; 115 return rc;
115} 116}
116 117
118int jfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
119{
120 int rc;
121 tid_t tid;
122
123 tid = txBegin(inode->i_sb, 0);
124 mutex_lock(&JFS_IP(inode)->commit_mutex);
125 rc = __jfs_set_acl(tid, inode, type, acl);
126 if (!rc)
127 rc = txCommit(tid, 1, &inode, 0);
128 txEnd(tid);
129 mutex_unlock(&JFS_IP(inode)->commit_mutex);
130 return rc;
131}
132
117int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir) 133int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
118{ 134{
119 struct posix_acl *acl = NULL; 135 struct posix_acl *default_acl, *acl;
120 int rc = 0; 136 int rc = 0;
121 137
122 if (S_ISLNK(inode->i_mode)) 138 rc = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
123 return 0; 139 if (rc)
140 return rc;
124 141
125 acl = jfs_get_acl(dir, ACL_TYPE_DEFAULT); 142 if (default_acl) {
126 if (IS_ERR(acl)) 143 rc = __jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, default_acl);
127 return PTR_ERR(acl); 144 posix_acl_release(default_acl);
145 }
128 146
129 if (acl) { 147 if (acl) {
130 if (S_ISDIR(inode->i_mode)) { 148 if (!rc)
131 rc = jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, acl); 149 rc = __jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
132 if (rc)
133 goto cleanup;
134 }
135 rc = __posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
136 if (rc < 0)
137 goto cleanup; /* posix_acl_release(NULL) is no-op */
138 if (rc > 0)
139 rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
140cleanup:
141 posix_acl_release(acl); 150 posix_acl_release(acl);
142 } else 151 }
143 inode->i_mode &= ~current_umask();
144 152
145 JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) | 153 JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) |
146 inode->i_mode; 154 inode->i_mode;
147 155
148 return rc; 156 return rc;
149} 157}
150
151int jfs_acl_chmod(struct inode *inode)
152{
153 struct posix_acl *acl;
154 int rc;
155 tid_t tid;
156
157 if (S_ISLNK(inode->i_mode))
158 return -EOPNOTSUPP;
159
160 acl = jfs_get_acl(inode, ACL_TYPE_ACCESS);
161 if (IS_ERR(acl) || !acl)
162 return PTR_ERR(acl);
163
164 rc = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
165 if (rc)
166 return rc;
167
168 tid = txBegin(inode->i_sb, 0);
169 mutex_lock(&JFS_IP(inode)->commit_mutex);
170 rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
171 if (!rc)
172 rc = txCommit(tid, 1, &inode, 0);
173 txEnd(tid);
174 mutex_unlock(&JFS_IP(inode)->commit_mutex);
175
176 posix_acl_release(acl);
177 return rc;
178}
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index dd7442c58358..794da944d5cd 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -19,6 +19,7 @@
19 19
20#include <linux/mm.h> 20#include <linux/mm.h>
21#include <linux/fs.h> 21#include <linux/fs.h>
22#include <linux/posix_acl.h>
22#include <linux/quotaops.h> 23#include <linux/quotaops.h>
23#include "jfs_incore.h" 24#include "jfs_incore.h"
24#include "jfs_inode.h" 25#include "jfs_inode.h"
@@ -131,7 +132,7 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
131 mark_inode_dirty(inode); 132 mark_inode_dirty(inode);
132 133
133 if (iattr->ia_valid & ATTR_MODE) 134 if (iattr->ia_valid & ATTR_MODE)
134 rc = jfs_acl_chmod(inode); 135 rc = posix_acl_chmod(inode, inode->i_mode);
135 return rc; 136 return rc;
136} 137}
137 138
@@ -143,6 +144,7 @@ const struct inode_operations jfs_file_inode_operations = {
143 .setattr = jfs_setattr, 144 .setattr = jfs_setattr,
144#ifdef CONFIG_JFS_POSIX_ACL 145#ifdef CONFIG_JFS_POSIX_ACL
145 .get_acl = jfs_get_acl, 146 .get_acl = jfs_get_acl,
147 .set_acl = jfs_set_acl,
146#endif 148#endif
147}; 149};
148 150
diff --git a/fs/jfs/jfs_acl.h b/fs/jfs/jfs_acl.h
index ad84fe50ca9e..489f993b7b13 100644
--- a/fs/jfs/jfs_acl.h
+++ b/fs/jfs/jfs_acl.h
@@ -21,8 +21,8 @@
21#ifdef CONFIG_JFS_POSIX_ACL 21#ifdef CONFIG_JFS_POSIX_ACL
22 22
23struct posix_acl *jfs_get_acl(struct inode *inode, int type); 23struct posix_acl *jfs_get_acl(struct inode *inode, int type);
24int jfs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
24int jfs_init_acl(tid_t, struct inode *, struct inode *); 25int jfs_init_acl(tid_t, struct inode *, struct inode *);
25int jfs_acl_chmod(struct inode *inode);
26 26
27#else 27#else
28 28
@@ -32,10 +32,5 @@ static inline int jfs_init_acl(tid_t tid, struct inode *inode,
32 return 0; 32 return 0;
33} 33}
34 34
35static inline int jfs_acl_chmod(struct inode *inode)
36{
37 return 0;
38}
39
40#endif 35#endif
41#endif /* _H_JFS_ACL */ 36#endif /* _H_JFS_ACL */
diff --git a/fs/jfs/jfs_xattr.h b/fs/jfs/jfs_xattr.h
index e9e100fd7c09..e8d717dabca3 100644
--- a/fs/jfs/jfs_xattr.h
+++ b/fs/jfs/jfs_xattr.h
@@ -61,6 +61,8 @@ extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t);
61extern ssize_t jfs_listxattr(struct dentry *, char *, size_t); 61extern ssize_t jfs_listxattr(struct dentry *, char *, size_t);
62extern int jfs_removexattr(struct dentry *, const char *); 62extern int jfs_removexattr(struct dentry *, const char *);
63 63
64extern const struct xattr_handler *jfs_xattr_handlers[];
65
64#ifdef CONFIG_JFS_SECURITY 66#ifdef CONFIG_JFS_SECURITY
65extern int jfs_init_security(tid_t, struct inode *, struct inode *, 67extern int jfs_init_security(tid_t, struct inode *, struct inode *,
66 const struct qstr *); 68 const struct qstr *);
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index aa8a3370631b..d59c7defb1ef 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -1524,6 +1524,7 @@ const struct inode_operations jfs_dir_inode_operations = {
1524 .setattr = jfs_setattr, 1524 .setattr = jfs_setattr,
1525#ifdef CONFIG_JFS_POSIX_ACL 1525#ifdef CONFIG_JFS_POSIX_ACL
1526 .get_acl = jfs_get_acl, 1526 .get_acl = jfs_get_acl,
1527 .set_acl = jfs_set_acl,
1527#endif 1528#endif
1528}; 1529};
1529 1530
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 6669aa2042c3..e2b7483444fd 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -44,6 +44,7 @@
44#include "jfs_imap.h" 44#include "jfs_imap.h"
45#include "jfs_acl.h" 45#include "jfs_acl.h"
46#include "jfs_debug.h" 46#include "jfs_debug.h"
47#include "jfs_xattr.h"
47 48
48MODULE_DESCRIPTION("The Journaled Filesystem (JFS)"); 49MODULE_DESCRIPTION("The Journaled Filesystem (JFS)");
49MODULE_AUTHOR("Steve Best/Dave Kleikamp/Barry Arndt, IBM"); 50MODULE_AUTHOR("Steve Best/Dave Kleikamp/Barry Arndt, IBM");
@@ -522,6 +523,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
522 */ 523 */
523 sb->s_op = &jfs_super_operations; 524 sb->s_op = &jfs_super_operations;
524 sb->s_export_op = &jfs_export_operations; 525 sb->s_export_op = &jfs_export_operations;
526 sb->s_xattr = jfs_xattr_handlers;
525#ifdef CONFIG_QUOTA 527#ifdef CONFIG_QUOTA
526 sb->dq_op = &dquot_operations; 528 sb->dq_op = &dquot_operations;
527 sb->s_qcop = &dquot_quotactl_ops; 529 sb->s_qcop = &dquot_quotactl_ops;
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index d3472f4cd530..5324e4e2b992 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -666,81 +666,12 @@ static int ea_put(tid_t tid, struct inode *inode, struct ea_buffer *ea_buf,
666} 666}
667 667
668/* 668/*
669 * can_set_system_xattr
670 *
671 * This code is specific to the system.* namespace. It contains policy
672 * which doesn't belong in the main xattr codepath.
673 */
674static int can_set_system_xattr(struct inode *inode, const char *name,
675 const void *value, size_t value_len)
676{
677#ifdef CONFIG_JFS_POSIX_ACL
678 struct posix_acl *acl;
679 int rc;
680
681 if (!inode_owner_or_capable(inode))
682 return -EPERM;
683
684 /*
685 * POSIX_ACL_XATTR_ACCESS is tied to i_mode
686 */
687 if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0) {
688 acl = posix_acl_from_xattr(&init_user_ns, value, value_len);
689 if (IS_ERR(acl)) {
690 rc = PTR_ERR(acl);
691 printk(KERN_ERR "posix_acl_from_xattr returned %d\n",
692 rc);
693 return rc;
694 }
695 if (acl) {
696 rc = posix_acl_equiv_mode(acl, &inode->i_mode);
697 posix_acl_release(acl);
698 if (rc < 0) {
699 printk(KERN_ERR
700 "posix_acl_equiv_mode returned %d\n",
701 rc);
702 return rc;
703 }
704 mark_inode_dirty(inode);
705 }
706 /*
707 * We're changing the ACL. Get rid of the cached one
708 */
709 forget_cached_acl(inode, ACL_TYPE_ACCESS);
710
711 return 0;
712 } else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0) {
713 acl = posix_acl_from_xattr(&init_user_ns, value, value_len);
714 if (IS_ERR(acl)) {
715 rc = PTR_ERR(acl);
716 printk(KERN_ERR "posix_acl_from_xattr returned %d\n",
717 rc);
718 return rc;
719 }
720 posix_acl_release(acl);
721
722 /*
723 * We're changing the default ACL. Get rid of the cached one
724 */
725 forget_cached_acl(inode, ACL_TYPE_DEFAULT);
726
727 return 0;
728 }
729#endif /* CONFIG_JFS_POSIX_ACL */
730 return -EOPNOTSUPP;
731}
732
733/*
734 * Most of the permission checking is done by xattr_permission in the vfs. 669 * Most of the permission checking is done by xattr_permission in the vfs.
735 * The local file system is responsible for handling the system.* namespace.
736 * We also need to verify that this is a namespace that we recognize. 670 * We also need to verify that this is a namespace that we recognize.
737 */ 671 */
738static int can_set_xattr(struct inode *inode, const char *name, 672static int can_set_xattr(struct inode *inode, const char *name,
739 const void *value, size_t value_len) 673 const void *value, size_t value_len)
740{ 674{
741 if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
742 return can_set_system_xattr(inode, name, value, value_len);
743
744 if (!strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)) { 675 if (!strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)) {
745 /* 676 /*
746 * This makes sure that we aren't trying to set an 677 * This makes sure that we aren't trying to set an
@@ -748,7 +679,7 @@ static int can_set_xattr(struct inode *inode, const char *name,
748 * with "os2." 679 * with "os2."
749 */ 680 */
750 if (is_known_namespace(name + XATTR_OS2_PREFIX_LEN)) 681 if (is_known_namespace(name + XATTR_OS2_PREFIX_LEN))
751 return -EOPNOTSUPP; 682 return -EOPNOTSUPP;
752 return 0; 683 return 0;
753 } 684 }
754 685
@@ -913,6 +844,14 @@ int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
913 if ((rc = can_set_xattr(inode, name, value, value_len))) 844 if ((rc = can_set_xattr(inode, name, value, value_len)))
914 return rc; 845 return rc;
915 846
847 /*
848 * If this is a request for a synthetic attribute in the system.*
849 * namespace use the generic infrastructure to resolve a handler
850 * for it via sb->s_xattr.
851 */
852 if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
853 return generic_setxattr(dentry, name, value, value_len, flags);
854
916 if (value == NULL) { /* empty EA, do not remove */ 855 if (value == NULL) { /* empty EA, do not remove */
917 value = ""; 856 value = "";
918 value_len = 0; 857 value_len = 0;
@@ -986,6 +925,14 @@ ssize_t jfs_getxattr(struct dentry *dentry, const char *name, void *data,
986{ 925{
987 int err; 926 int err;
988 927
928 /*
929 * If this is a request for a synthetic attribute in the system.*
930 * namespace use the generic infrastructure to resolve a handler
931 * for it via sb->s_xattr.
932 */
933 if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
934 return generic_getxattr(dentry, name, data, buf_size);
935
989 if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { 936 if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
990 /* 937 /*
991 * skip past "os2." prefix 938 * skip past "os2." prefix
@@ -1077,6 +1024,14 @@ int jfs_removexattr(struct dentry *dentry, const char *name)
1077 if ((rc = can_set_xattr(inode, name, NULL, 0))) 1024 if ((rc = can_set_xattr(inode, name, NULL, 0)))
1078 return rc; 1025 return rc;
1079 1026
1027 /*
1028 * If this is a request for a synthetic attribute in the system.*
1029 * namespace use the generic infrastructure to resolve a handler
1030 * for it via sb->s_xattr.
1031 */
1032 if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
1033 return generic_removexattr(dentry, name);
1034
1080 tid = txBegin(inode->i_sb, 0); 1035 tid = txBegin(inode->i_sb, 0);
1081 mutex_lock(&ji->commit_mutex); 1036 mutex_lock(&ji->commit_mutex);
1082 rc = __jfs_setxattr(tid, dentry->d_inode, name, NULL, 0, XATTR_REPLACE); 1037 rc = __jfs_setxattr(tid, dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
@@ -1088,6 +1043,19 @@ int jfs_removexattr(struct dentry *dentry, const char *name)
1088 return rc; 1043 return rc;
1089} 1044}
1090 1045
1046/*
1047 * List of handlers for synthetic system.* attributes. All real ondisk
1048 * attributes are handled directly.
1049 */
1050const struct xattr_handler *jfs_xattr_handlers[] = {
1051#ifdef JFS_POSIX_ACL
1052 &posix_acl_access_xattr_handler,
1053 &posix_acl_default_xattr_handler,
1054#endif
1055 NULL,
1056};
1057
1058
1091#ifdef CONFIG_JFS_SECURITY 1059#ifdef CONFIG_JFS_SECURITY
1092static int jfs_initxattrs(struct inode *inode, const struct xattr *xattr_array, 1060static int jfs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
1093 void *fs_info) 1061 void *fs_info)