aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMark Fasheh <mfasheh@suse.com>2010-03-15 18:39:00 -0400
committerJoel Becker <joel.becker@oracle.com>2010-03-17 15:28:22 -0400
commitfcefd25ac89239cb57fa198f125a79ff85468c75 (patch)
treebe758d25079055bebe26dd9ad9a7db6121158a75 /fs
parent6527f8f848ec84b9daf1cb07601266126b8507ab (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')
-rw-r--r--fs/ocfs2/acl.c77
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 */
175static 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
215out_commit:
216 if (commit_handle)
217 ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
218out_brelse:
219 brelse(di_bh);
220out:
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 */
171static int ocfs2_set_acl(handle_t *handle, 227static 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,