diff options
author | Mark Fasheh <mfasheh@suse.com> | 2010-03-15 18:39:00 -0400 |
---|---|---|
committer | Joel Becker <joel.becker@oracle.com> | 2010-03-17 15:28:22 -0400 |
commit | fcefd25ac89239cb57fa198f125a79ff85468c75 (patch) | |
tree | be758d25079055bebe26dd9ad9a7db6121158a75 /fs/ocfs2 | |
parent | 6527f8f848ec84b9daf1cb07601266126b8507ab (diff) |
ocfs2: set i_mode on disk during acl operations
ocfs2_set_acl() and ocfs2_init_acl() were setting i_mode on the in-memory
inode, but never setting it on the disk copy. Thus, acls were some times not
getting propagated between nodes. This patch fixes the issue by adding a
helper function ocfs2_acl_set_mode() which does this the right way.
ocfs2_set_acl() and ocfs2_init_acl() are then updated to call
ocfs2_acl_set_mode().
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r-- | fs/ocfs2/acl.c | 77 |
1 files changed, 72 insertions, 5 deletions
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c index 0501974bedd0..8ccf0f8c9cc8 100644 --- a/fs/ocfs2/acl.c +++ b/fs/ocfs2/acl.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include "alloc.h" | 30 | #include "alloc.h" |
31 | #include "dlmglue.h" | 31 | #include "dlmglue.h" |
32 | #include "file.h" | 32 | #include "file.h" |
33 | #include "inode.h" | ||
34 | #include "journal.h" | ||
33 | #include "ocfs2_fs.h" | 35 | #include "ocfs2_fs.h" |
34 | 36 | ||
35 | #include "xattr.h" | 37 | #include "xattr.h" |
@@ -166,6 +168,60 @@ static struct posix_acl *ocfs2_get_acl(struct inode *inode, int type) | |||
166 | } | 168 | } |
167 | 169 | ||
168 | /* | 170 | /* |
171 | * Helper function to set i_mode in memory and disk. Some call paths | ||
172 | * will not have di_bh or a journal handle to pass, in which case it | ||
173 | * will create it's own. | ||
174 | */ | ||
175 | static int ocfs2_acl_set_mode(struct inode *inode, struct buffer_head *di_bh, | ||
176 | handle_t *handle, umode_t new_mode) | ||
177 | { | ||
178 | int ret, commit_handle = 0; | ||
179 | struct ocfs2_dinode *di; | ||
180 | |||
181 | if (di_bh == NULL) { | ||
182 | ret = ocfs2_read_inode_block(inode, &di_bh); | ||
183 | if (ret) { | ||
184 | mlog_errno(ret); | ||
185 | goto out; | ||
186 | } | ||
187 | } else | ||
188 | get_bh(di_bh); | ||
189 | |||
190 | if (handle == NULL) { | ||
191 | handle = ocfs2_start_trans(OCFS2_SB(inode->i_sb), | ||
192 | OCFS2_INODE_UPDATE_CREDITS); | ||
193 | if (IS_ERR(handle)) { | ||
194 | ret = PTR_ERR(handle); | ||
195 | mlog_errno(ret); | ||
196 | goto out_brelse; | ||
197 | } | ||
198 | |||
199 | commit_handle = 1; | ||
200 | } | ||
201 | |||
202 | di = (struct ocfs2_dinode *)di_bh->b_data; | ||
203 | ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh, | ||
204 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
205 | if (ret) { | ||
206 | mlog_errno(ret); | ||
207 | goto out_commit; | ||
208 | } | ||
209 | |||
210 | inode->i_mode = new_mode; | ||
211 | di->i_mode = cpu_to_le16(inode->i_mode); | ||
212 | |||
213 | ocfs2_journal_dirty(handle, di_bh); | ||
214 | |||
215 | out_commit: | ||
216 | if (commit_handle) | ||
217 | ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); | ||
218 | out_brelse: | ||
219 | brelse(di_bh); | ||
220 | out: | ||
221 | return ret; | ||
222 | } | ||
223 | |||
224 | /* | ||
169 | * Set the access or default ACL of an inode. | 225 | * Set the access or default ACL of an inode. |
170 | */ | 226 | */ |
171 | static int ocfs2_set_acl(handle_t *handle, | 227 | static int ocfs2_set_acl(handle_t *handle, |
@@ -193,9 +249,14 @@ static int ocfs2_set_acl(handle_t *handle, | |||
193 | if (ret < 0) | 249 | if (ret < 0) |
194 | return ret; | 250 | return ret; |
195 | else { | 251 | else { |
196 | inode->i_mode = mode; | ||
197 | if (ret == 0) | 252 | if (ret == 0) |
198 | acl = NULL; | 253 | acl = NULL; |
254 | |||
255 | ret = ocfs2_acl_set_mode(inode, di_bh, | ||
256 | handle, mode); | ||
257 | if (ret) | ||
258 | return ret; | ||
259 | |||
199 | } | 260 | } |
200 | } | 261 | } |
201 | break; | 262 | break; |
@@ -283,6 +344,7 @@ int ocfs2_init_acl(handle_t *handle, | |||
283 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 344 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
284 | struct posix_acl *acl = NULL; | 345 | struct posix_acl *acl = NULL; |
285 | int ret = 0; | 346 | int ret = 0; |
347 | mode_t mode; | ||
286 | 348 | ||
287 | if (!S_ISLNK(inode->i_mode)) { | 349 | if (!S_ISLNK(inode->i_mode)) { |
288 | if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) { | 350 | if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) { |
@@ -291,12 +353,17 @@ int ocfs2_init_acl(handle_t *handle, | |||
291 | if (IS_ERR(acl)) | 353 | if (IS_ERR(acl)) |
292 | return PTR_ERR(acl); | 354 | return PTR_ERR(acl); |
293 | } | 355 | } |
294 | if (!acl) | 356 | if (!acl) { |
295 | inode->i_mode &= ~current_umask(); | 357 | mode = inode->i_mode & ~current_umask(); |
358 | ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode); | ||
359 | if (ret) { | ||
360 | mlog_errno(ret); | ||
361 | goto cleanup; | ||
362 | } | ||
363 | } | ||
296 | } | 364 | } |
297 | if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) { | 365 | if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) { |
298 | struct posix_acl *clone; | 366 | struct posix_acl *clone; |
299 | mode_t mode; | ||
300 | 367 | ||
301 | if (S_ISDIR(inode->i_mode)) { | 368 | if (S_ISDIR(inode->i_mode)) { |
302 | ret = ocfs2_set_acl(handle, inode, di_bh, | 369 | ret = ocfs2_set_acl(handle, inode, di_bh, |
@@ -313,7 +380,7 @@ int ocfs2_init_acl(handle_t *handle, | |||
313 | mode = inode->i_mode; | 380 | mode = inode->i_mode; |
314 | ret = posix_acl_create_masq(clone, &mode); | 381 | ret = posix_acl_create_masq(clone, &mode); |
315 | if (ret >= 0) { | 382 | if (ret >= 0) { |
316 | inode->i_mode = mode; | 383 | ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode); |
317 | if (ret > 0) { | 384 | if (ret > 0) { |
318 | ret = ocfs2_set_acl(handle, inode, | 385 | ret = ocfs2_set_acl(handle, inode, |
319 | di_bh, ACL_TYPE_ACCESS, | 386 | di_bh, ACL_TYPE_ACCESS, |