aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/gfs2/acl.c164
-rw-r--r--fs/gfs2/acl.h2
-rw-r--r--fs/gfs2/inode.c2
-rw-r--r--fs/gfs2/xattr.c56
-rw-r--r--fs/gfs2/xattr.h8
5 files changed, 132 insertions, 100 deletions
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index 1be314837d31..bd0fce964c41 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -27,53 +27,40 @@
27#include "trans.h" 27#include "trans.h"
28#include "util.h" 28#include "util.h"
29 29
30static int acl_get(struct gfs2_inode *ip, const char *name, 30static const char *gfs2_acl_name(int type)
31 struct posix_acl **acl, struct gfs2_ea_location *el,
32 char **datap, unsigned int *lenp)
33{ 31{
34 char *data; 32 switch (type) {
35 unsigned int len; 33 case ACL_TYPE_ACCESS:
36 int error; 34 return GFS2_POSIX_ACL_ACCESS;
35 case ACL_TYPE_DEFAULT:
36 return GFS2_POSIX_ACL_DEFAULT;
37 }
38 return NULL;
39}
37 40
38 el->el_bh = NULL; 41static struct posix_acl *gfs2_acl_get(struct gfs2_inode *ip, int type)
42{
43 struct posix_acl *acl;
44 const char *name;
45 char *data;
46 int len;
39 47
40 if (!ip->i_eattr) 48 if (!ip->i_eattr)
41 return 0; 49 return NULL;
42
43 error = gfs2_ea_find(ip, GFS2_EATYPE_SYS, name, el);
44 if (error)
45 return error;
46 if (!el->el_ea)
47 return 0;
48 if (!GFS2_EA_DATA_LEN(el->el_ea))
49 goto out;
50
51 len = GFS2_EA_DATA_LEN(el->el_ea);
52 data = kmalloc(len, GFP_NOFS);
53 error = -ENOMEM;
54 if (!data)
55 goto out;
56 50
57 error = gfs2_ea_get_copy(ip, el, data, len); 51 name = gfs2_acl_name(type);
58 if (error < 0) 52 if (name == NULL)
59 goto out_kfree; 53 return ERR_PTR(-EINVAL);
60 error = 0;
61 54
62 if (acl) { 55 len = gfs2_xattr_acl_get(ip, name, &data);
63 *acl = posix_acl_from_xattr(data, len); 56 if (len < 0)
64 if (IS_ERR(*acl)) 57 return ERR_PTR(len);
65 error = PTR_ERR(*acl); 58 if (len == 0)
66 } 59 return NULL;
67 60
68out_kfree: 61 acl = posix_acl_from_xattr(data, len);
69 if (error || !datap) { 62 kfree(data);
70 kfree(data); 63 return acl;
71 } else {
72 *datap = data;
73 *lenp = len;
74 }
75out:
76 return error;
77} 64}
78 65
79/** 66/**
@@ -86,14 +73,12 @@ out:
86 73
87int gfs2_check_acl(struct inode *inode, int mask) 74int gfs2_check_acl(struct inode *inode, int mask)
88{ 75{
89 struct gfs2_ea_location el; 76 struct posix_acl *acl;
90 struct posix_acl *acl = NULL;
91 int error; 77 int error;
92 78
93 error = acl_get(GFS2_I(inode), GFS2_POSIX_ACL_ACCESS, &acl, &el, NULL, NULL); 79 acl = gfs2_acl_get(GFS2_I(inode), ACL_TYPE_ACCESS);
94 brelse(el.el_bh); 80 if (IS_ERR(acl))
95 if (error) 81 return PTR_ERR(acl);
96 return error;
97 82
98 if (acl) { 83 if (acl) {
99 error = posix_acl_permission(inode, acl, mask); 84 error = posix_acl_permission(inode, acl, mask);
@@ -120,32 +105,57 @@ static int gfs2_set_mode(struct inode *inode, mode_t mode)
120 return error; 105 return error;
121} 106}
122 107
123int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip) 108static int gfs2_acl_set(struct inode *inode, int type, struct posix_acl *acl)
124{ 109{
125 struct gfs2_ea_location el;
126 struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
127 struct posix_acl *acl = NULL, *clone;
128 mode_t mode = ip->i_inode.i_mode;
129 char *data = NULL;
130 unsigned int len;
131 int error; 110 int error;
111 int len;
112 char *data;
113 const char *name = gfs2_acl_name(type);
114
115 BUG_ON(name == NULL);
116 len = posix_acl_to_xattr(acl, NULL, 0);
117 if (len == 0)
118 return 0;
119 data = kmalloc(len, GFP_NOFS);
120 if (data == NULL)
121 return -ENOMEM;
122 error = posix_acl_to_xattr(acl, data, len);
123 if (error < 0)
124 goto out;
125 error = gfs2_xattr_set(inode, GFS2_EATYPE_SYS, name, data, len, 0);
126out:
127 kfree(data);
128 return error;
129}
130
131int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode)
132{
133 struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
134 struct posix_acl *acl, *clone;
135 mode_t mode = inode->i_mode;
136 int error = 0;
132 137
133 if (!sdp->sd_args.ar_posix_acl) 138 if (!sdp->sd_args.ar_posix_acl)
134 return 0; 139 return 0;
135 if (S_ISLNK(ip->i_inode.i_mode)) 140 if (S_ISLNK(inode->i_mode))
136 return 0; 141 return 0;
137 142
138 error = acl_get(dip, GFS2_POSIX_ACL_DEFAULT, &acl, &el, &data, &len); 143 acl = gfs2_acl_get(dip, ACL_TYPE_DEFAULT);
139 brelse(el.el_bh); 144 if (IS_ERR(acl))
140 if (error) 145 return PTR_ERR(acl);
141 return error;
142 if (!acl) { 146 if (!acl) {
143 mode &= ~current_umask(); 147 mode &= ~current_umask();
144 if (mode != ip->i_inode.i_mode) 148 if (mode != inode->i_mode)
145 error = gfs2_set_mode(&ip->i_inode, mode); 149 error = gfs2_set_mode(inode, mode);
146 return error; 150 return error;
147 } 151 }
148 152
153 if (S_ISDIR(inode->i_mode)) {
154 error = gfs2_acl_set(inode, ACL_TYPE_DEFAULT, acl);
155 if (error)
156 goto out;
157 }
158
149 clone = posix_acl_clone(acl, GFP_NOFS); 159 clone = posix_acl_clone(acl, GFP_NOFS);
150 error = -ENOMEM; 160 error = -ENOMEM;
151 if (!clone) 161 if (!clone)
@@ -153,43 +163,32 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip)
153 posix_acl_release(acl); 163 posix_acl_release(acl);
154 acl = clone; 164 acl = clone;
155 165
156 if (S_ISDIR(ip->i_inode.i_mode)) {
157 error = gfs2_xattr_set(&ip->i_inode, GFS2_EATYPE_SYS,
158 GFS2_POSIX_ACL_DEFAULT, data, len, 0);
159 if (error)
160 goto out;
161 }
162
163 error = posix_acl_create_masq(acl, &mode); 166 error = posix_acl_create_masq(acl, &mode);
164 if (error < 0) 167 if (error < 0)
165 goto out; 168 goto out;
166 if (error == 0) 169 if (error == 0)
167 goto munge; 170 goto munge;
168 171
169 posix_acl_to_xattr(acl, data, len); 172 error = gfs2_acl_set(inode, ACL_TYPE_ACCESS, acl);
170 error = gfs2_xattr_set(&ip->i_inode, GFS2_EATYPE_SYS,
171 GFS2_POSIX_ACL_ACCESS, data, len, 0);
172 if (error) 173 if (error)
173 goto out; 174 goto out;
174munge: 175munge:
175 error = gfs2_set_mode(&ip->i_inode, mode); 176 error = gfs2_set_mode(inode, mode);
176out: 177out:
177 posix_acl_release(acl); 178 posix_acl_release(acl);
178 kfree(data);
179 return error; 179 return error;
180} 180}
181 181
182int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr) 182int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)
183{ 183{
184 struct posix_acl *acl = NULL, *clone; 184 struct posix_acl *acl, *clone;
185 struct gfs2_ea_location el;
186 char *data; 185 char *data;
187 unsigned int len; 186 unsigned int len;
188 int error; 187 int error;
189 188
190 error = acl_get(ip, GFS2_POSIX_ACL_ACCESS, &acl, &el, &data, &len); 189 acl = gfs2_acl_get(ip, ACL_TYPE_ACCESS);
191 if (error) 190 if (IS_ERR(acl))
192 goto out_brelse; 191 return PTR_ERR(acl);
193 if (!acl) 192 if (!acl)
194 return gfs2_setattr_simple(ip, attr); 193 return gfs2_setattr_simple(ip, attr);
195 194
@@ -202,15 +201,18 @@ int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)
202 201
203 error = posix_acl_chmod_masq(acl, attr->ia_mode); 202 error = posix_acl_chmod_masq(acl, attr->ia_mode);
204 if (!error) { 203 if (!error) {
204 len = posix_acl_to_xattr(acl, NULL, 0);
205 data = kmalloc(len, GFP_NOFS);
206 error = -ENOMEM;
207 if (data == NULL)
208 goto out;
205 posix_acl_to_xattr(acl, data, len); 209 posix_acl_to_xattr(acl, data, len);
206 error = gfs2_ea_acl_chmod(ip, &el, attr, data); 210 error = gfs2_xattr_acl_chmod(ip, attr, data);
211 kfree(data);
207 } 212 }
208 213
209out: 214out:
210 posix_acl_release(acl); 215 posix_acl_release(acl);
211 kfree(data);
212out_brelse:
213 brelse(el.el_bh);
214 return error; 216 return error;
215} 217}
216 218
diff --git a/fs/gfs2/acl.h b/fs/gfs2/acl.h
index cc954390b6da..9306a2e6620c 100644
--- a/fs/gfs2/acl.h
+++ b/fs/gfs2/acl.h
@@ -17,7 +17,7 @@
17#define GFS2_ACL_MAX_ENTRIES 25 17#define GFS2_ACL_MAX_ENTRIES 25
18 18
19extern int gfs2_check_acl(struct inode *inode, int mask); 19extern int gfs2_check_acl(struct inode *inode, int mask);
20extern int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip); 20extern int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode);
21extern int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr); 21extern int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr);
22extern struct xattr_handler gfs2_xattr_system_handler; 22extern struct xattr_handler gfs2_xattr_system_handler;
23 23
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index fb15d3b1f409..6380cd9314b0 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -871,7 +871,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
871 if (error) 871 if (error)
872 goto fail_gunlock2; 872 goto fail_gunlock2;
873 873
874 error = gfs2_acl_create(dip, GFS2_I(inode)); 874 error = gfs2_acl_create(dip, inode);
875 if (error) 875 if (error)
876 goto fail_gunlock2; 876 goto fail_gunlock2;
877 877
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
index 6b803540951e..912f5cbc4740 100644
--- a/fs/gfs2/xattr.c
+++ b/fs/gfs2/xattr.c
@@ -186,8 +186,8 @@ static int ea_find_i(struct gfs2_inode *ip, struct buffer_head *bh,
186 return 0; 186 return 0;
187} 187}
188 188
189int gfs2_ea_find(struct gfs2_inode *ip, int type, const char *name, 189static int gfs2_ea_find(struct gfs2_inode *ip, int type, const char *name,
190 struct gfs2_ea_location *el) 190 struct gfs2_ea_location *el)
191{ 191{
192 struct ea_find ef; 192 struct ea_find ef;
193 int error; 193 int error;
@@ -516,8 +516,8 @@ out:
516 return error; 516 return error;
517} 517}
518 518
519int gfs2_ea_get_copy(struct gfs2_inode *ip, struct gfs2_ea_location *el, 519static int gfs2_ea_get_copy(struct gfs2_inode *ip, struct gfs2_ea_location *el,
520 char *data, size_t size) 520 char *data, size_t size)
521{ 521{
522 int ret; 522 int ret;
523 size_t len = GFS2_EA_DATA_LEN(el->el_ea); 523 size_t len = GFS2_EA_DATA_LEN(el->el_ea);
@@ -534,6 +534,36 @@ int gfs2_ea_get_copy(struct gfs2_inode *ip, struct gfs2_ea_location *el,
534 return len; 534 return len;
535} 535}
536 536
537int gfs2_xattr_acl_get(struct gfs2_inode *ip, const char *name, char **ppdata)
538{
539 struct gfs2_ea_location el;
540 int error;
541 int len;
542 char *data;
543
544 error = gfs2_ea_find(ip, GFS2_EATYPE_SYS, name, &el);
545 if (error)
546 return error;
547 if (!el.el_ea)
548 goto out;
549 if (!GFS2_EA_DATA_LEN(el.el_ea))
550 goto out;
551
552 len = GFS2_EA_DATA_LEN(el.el_ea);
553 data = kmalloc(len, GFP_NOFS);
554 error = -ENOMEM;
555 if (data == NULL)
556 goto out;
557
558 error = gfs2_ea_get_copy(ip, &el, data, len);
559 if (error == 0)
560 error = len;
561 *ppdata = data;
562out:
563 brelse(el.el_bh);
564 return error;
565}
566
537/** 567/**
538 * gfs2_xattr_get - Get a GFS2 extended attribute 568 * gfs2_xattr_get - Get a GFS2 extended attribute
539 * @inode: The inode 569 * @inode: The inode
@@ -1259,22 +1289,26 @@ fail:
1259 return error; 1289 return error;
1260} 1290}
1261 1291
1262int gfs2_ea_acl_chmod(struct gfs2_inode *ip, struct gfs2_ea_location *el, 1292int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data)
1263 struct iattr *attr, char *data)
1264{ 1293{
1294 struct gfs2_ea_location el;
1265 struct buffer_head *dibh; 1295 struct buffer_head *dibh;
1266 int error; 1296 int error;
1267 1297
1268 if (GFS2_EA_IS_STUFFED(el->el_ea)) { 1298 error = gfs2_ea_find(ip, GFS2_EATYPE_SYS, GFS2_POSIX_ACL_ACCESS, &el);
1299 if (error)
1300 return error;
1301
1302 if (GFS2_EA_IS_STUFFED(el.el_ea)) {
1269 error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), RES_DINODE + RES_EATTR, 0); 1303 error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), RES_DINODE + RES_EATTR, 0);
1270 if (error) 1304 if (error)
1271 return error; 1305 return error;
1272 1306
1273 gfs2_trans_add_bh(ip->i_gl, el->el_bh, 1); 1307 gfs2_trans_add_bh(ip->i_gl, el.el_bh, 1);
1274 memcpy(GFS2_EA2DATA(el->el_ea), data, 1308 memcpy(GFS2_EA2DATA(el.el_ea), data,
1275 GFS2_EA_DATA_LEN(el->el_ea)); 1309 GFS2_EA_DATA_LEN(el.el_ea));
1276 } else 1310 } else
1277 error = ea_acl_chmod_unstuffed(ip, el->el_ea, data); 1311 error = ea_acl_chmod_unstuffed(ip, el.el_ea, data);
1278 1312
1279 if (error) 1313 if (error)
1280 return error; 1314 return error;
diff --git a/fs/gfs2/xattr.h b/fs/gfs2/xattr.h
index cbdfd7743733..8d6ae5813c4d 100644
--- a/fs/gfs2/xattr.h
+++ b/fs/gfs2/xattr.h
@@ -62,11 +62,7 @@ extern int gfs2_ea_dealloc(struct gfs2_inode *ip);
62 62
63/* Exported to acl.c */ 63/* Exported to acl.c */
64 64
65extern int gfs2_ea_find(struct gfs2_inode *ip, int type, const char *name, 65extern int gfs2_xattr_acl_get(struct gfs2_inode *ip, const char *name, char **data);
66 struct gfs2_ea_location *el); 66extern int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data);
67extern int gfs2_ea_get_copy(struct gfs2_inode *ip, struct gfs2_ea_location *el,
68 char *data, size_t size);
69extern int gfs2_ea_acl_chmod(struct gfs2_inode *ip, struct gfs2_ea_location *el,
70 struct iattr *attr, char *data);
71 67
72#endif /* __EATTR_DOT_H__ */ 68#endif /* __EATTR_DOT_H__ */