Commit fcefd25a authored by Mark Fasheh's avatar Mark Fasheh Committed by Joel Becker

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: default avatarMark Fasheh <mfasheh@suse.com>
Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
parent 6527f8f8
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include "alloc.h" #include "alloc.h"
#include "dlmglue.h" #include "dlmglue.h"
#include "file.h" #include "file.h"
#include "inode.h"
#include "journal.h"
#include "ocfs2_fs.h" #include "ocfs2_fs.h"
#include "xattr.h" #include "xattr.h"
...@@ -165,6 +167,60 @@ static struct posix_acl *ocfs2_get_acl(struct inode *inode, int type) ...@@ -165,6 +167,60 @@ static struct posix_acl *ocfs2_get_acl(struct inode *inode, int type)
return acl; return acl;
} }
/*
* Helper function to set i_mode in memory and disk. Some call paths
* will not have di_bh or a journal handle to pass, in which case it
* will create it's own.
*/
static int ocfs2_acl_set_mode(struct inode *inode, struct buffer_head *di_bh,
handle_t *handle, umode_t new_mode)
{
int ret, commit_handle = 0;
struct ocfs2_dinode *di;
if (di_bh == NULL) {
ret = ocfs2_read_inode_block(inode, &di_bh);
if (ret) {
mlog_errno(ret);
goto out;
}
} else
get_bh(di_bh);
if (handle == NULL) {
handle = ocfs2_start_trans(OCFS2_SB(inode->i_sb),
OCFS2_INODE_UPDATE_CREDITS);
if (IS_ERR(handle)) {
ret = PTR_ERR(handle);
mlog_errno(ret);
goto out_brelse;
}
commit_handle = 1;
}
di = (struct ocfs2_dinode *)di_bh->b_data;
ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh,
OCFS2_JOURNAL_ACCESS_WRITE);
if (ret) {
mlog_errno(ret);
goto out_commit;
}
inode->i_mode = new_mode;
di->i_mode = cpu_to_le16(inode->i_mode);
ocfs2_journal_dirty(handle, di_bh);
out_commit:
if (commit_handle)
ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
out_brelse:
brelse(di_bh);
out:
return ret;
}
/* /*
* Set the access or default ACL of an inode. * Set the access or default ACL of an inode.
*/ */
...@@ -193,9 +249,14 @@ static int ocfs2_set_acl(handle_t *handle, ...@@ -193,9 +249,14 @@ static int ocfs2_set_acl(handle_t *handle,
if (ret < 0) if (ret < 0)
return ret; return ret;
else { else {
inode->i_mode = mode;
if (ret == 0) if (ret == 0)
acl = NULL; acl = NULL;
ret = ocfs2_acl_set_mode(inode, di_bh,
handle, mode);
if (ret)
return ret;
} }
} }
break; break;
...@@ -283,6 +344,7 @@ int ocfs2_init_acl(handle_t *handle, ...@@ -283,6 +344,7 @@ int ocfs2_init_acl(handle_t *handle,
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
struct posix_acl *acl = NULL; struct posix_acl *acl = NULL;
int ret = 0; int ret = 0;
mode_t mode;
if (!S_ISLNK(inode->i_mode)) { if (!S_ISLNK(inode->i_mode)) {
if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) { if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) {
...@@ -291,12 +353,17 @@ int ocfs2_init_acl(handle_t *handle, ...@@ -291,12 +353,17 @@ int ocfs2_init_acl(handle_t *handle,
if (IS_ERR(acl)) if (IS_ERR(acl))
return PTR_ERR(acl); return PTR_ERR(acl);
} }
if (!acl) if (!acl) {
inode->i_mode &= ~current_umask(); mode = inode->i_mode & ~current_umask();
ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
if (ret) {
mlog_errno(ret);
goto cleanup;
}
}
} }
if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) { if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) {
struct posix_acl *clone; struct posix_acl *clone;
mode_t mode;
if (S_ISDIR(inode->i_mode)) { if (S_ISDIR(inode->i_mode)) {
ret = ocfs2_set_acl(handle, inode, di_bh, ret = ocfs2_set_acl(handle, inode, di_bh,
...@@ -313,7 +380,7 @@ int ocfs2_init_acl(handle_t *handle, ...@@ -313,7 +380,7 @@ int ocfs2_init_acl(handle_t *handle,
mode = inode->i_mode; mode = inode->i_mode;
ret = posix_acl_create_masq(clone, &mode); ret = posix_acl_create_masq(clone, &mode);
if (ret >= 0) { if (ret >= 0) {
inode->i_mode = mode; ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
if (ret > 0) { if (ret > 0) {
ret = ocfs2_set_acl(handle, inode, ret = ocfs2_set_acl(handle, inode,
di_bh, ACL_TYPE_ACCESS, di_bh, ACL_TYPE_ACCESS,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment