diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/gfs2/acl.c | 164 | ||||
-rw-r--r-- | fs/gfs2/acl.h | 2 | ||||
-rw-r--r-- | fs/gfs2/inode.c | 2 | ||||
-rw-r--r-- | fs/gfs2/xattr.c | 56 | ||||
-rw-r--r-- | fs/gfs2/xattr.h | 8 |
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 | ||
30 | static int acl_get(struct gfs2_inode *ip, const char *name, | 30 | static 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; | 41 | static 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 | ||
68 | out_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 | } | ||
75 | out: | ||
76 | return error; | ||
77 | } | 64 | } |
78 | 65 | ||
79 | /** | 66 | /** |
@@ -86,14 +73,12 @@ out: | |||
86 | 73 | ||
87 | int gfs2_check_acl(struct inode *inode, int mask) | 74 | int 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 | ||
123 | int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip) | 108 | static 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); | ||
126 | out: | ||
127 | kfree(data); | ||
128 | return error; | ||
129 | } | ||
130 | |||
131 | int 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; |
174 | munge: | 175 | munge: |
175 | error = gfs2_set_mode(&ip->i_inode, mode); | 176 | error = gfs2_set_mode(inode, mode); |
176 | out: | 177 | out: |
177 | posix_acl_release(acl); | 178 | posix_acl_release(acl); |
178 | kfree(data); | ||
179 | return error; | 179 | return error; |
180 | } | 180 | } |
181 | 181 | ||
182 | int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr) | 182 | int 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 | ||
209 | out: | 214 | out: |
210 | posix_acl_release(acl); | 215 | posix_acl_release(acl); |
211 | kfree(data); | ||
212 | out_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 | ||
19 | extern int gfs2_check_acl(struct inode *inode, int mask); | 19 | extern int gfs2_check_acl(struct inode *inode, int mask); |
20 | extern int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip); | 20 | extern int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode); |
21 | extern int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr); | 21 | extern int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr); |
22 | extern struct xattr_handler gfs2_xattr_system_handler; | 22 | extern 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 | ||
189 | int gfs2_ea_find(struct gfs2_inode *ip, int type, const char *name, | 189 | static 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 | ||
519 | int gfs2_ea_get_copy(struct gfs2_inode *ip, struct gfs2_ea_location *el, | 519 | static 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 | ||
537 | int 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; | ||
562 | out: | ||
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 | ||
1262 | int gfs2_ea_acl_chmod(struct gfs2_inode *ip, struct gfs2_ea_location *el, | 1292 | int 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 | ||
65 | extern int gfs2_ea_find(struct gfs2_inode *ip, int type, const char *name, | 65 | extern int gfs2_xattr_acl_get(struct gfs2_inode *ip, const char *name, char **data); |
66 | struct gfs2_ea_location *el); | 66 | extern int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data); |
67 | extern int gfs2_ea_get_copy(struct gfs2_inode *ip, struct gfs2_ea_location *el, | ||
68 | char *data, size_t size); | ||
69 | extern 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__ */ |