Skip to content

Commit

Permalink
ocfs2: add ocfs2_init_acl in mknod
Browse files Browse the repository at this point in the history
We need to get the parent directories acls and let the new child inherit it.
To this, we add additional calculations for data/metadata allocation.

Signed-off-by: Tiger Yang <tiger.yang@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
  • Loading branch information
Tiger Yang authored and Mark Fasheh committed Jan 5, 2009
1 parent 060bc66 commit 89c38bd
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 8 deletions.
59 changes: 59 additions & 0 deletions fs/ocfs2/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,65 @@ int ocfs2_acl_chmod(struct inode *inode)
return ret;
}

/*
* Initialize the ACLs of a new inode. If parent directory has default ACL,
* then clone to new inode. Called from ocfs2_mknod.
*/
int ocfs2_init_acl(handle_t *handle,
struct inode *inode,
struct inode *dir,
struct buffer_head *di_bh,
struct buffer_head *dir_bh,
struct ocfs2_alloc_context *meta_ac,
struct ocfs2_alloc_context *data_ac)
{
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
struct posix_acl *acl = NULL;
int ret = 0;

if (!S_ISLNK(inode->i_mode)) {
if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) {
acl = ocfs2_get_acl_nolock(dir, ACL_TYPE_DEFAULT,
dir_bh);
if (IS_ERR(acl))
return PTR_ERR(acl);
}
if (!acl)
inode->i_mode &= ~current->fs->umask;
}
if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) {
struct posix_acl *clone;
mode_t mode;

if (S_ISDIR(inode->i_mode)) {
ret = ocfs2_set_acl(handle, inode, di_bh,
ACL_TYPE_DEFAULT, acl,
meta_ac, data_ac);
if (ret)
goto cleanup;
}
clone = posix_acl_clone(acl, GFP_NOFS);
ret = -ENOMEM;
if (!clone)
goto cleanup;

mode = inode->i_mode;
ret = posix_acl_create_masq(clone, &mode);
if (ret >= 0) {
inode->i_mode = mode;
if (ret > 0) {
ret = ocfs2_set_acl(handle, inode,
di_bh, ACL_TYPE_ACCESS,
clone, meta_ac, data_ac);
}
}
posix_acl_release(clone);
}
cleanup:
posix_acl_release(acl);
return ret;
}

static size_t ocfs2_xattr_list_acl_access(struct inode *inode,
char *list,
size_t list_len,
Expand Down
14 changes: 14 additions & 0 deletions fs/ocfs2/acl.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ struct ocfs2_acl_entry {

extern int ocfs2_check_acl(struct inode *, int);
extern int ocfs2_acl_chmod(struct inode *);
extern int ocfs2_init_acl(handle_t *, struct inode *, struct inode *,
struct buffer_head *, struct buffer_head *,
struct ocfs2_alloc_context *,
struct ocfs2_alloc_context *);

#else /* CONFIG_OCFS2_FS_POSIX_ACL*/

Expand All @@ -38,6 +42,16 @@ static inline int ocfs2_acl_chmod(struct inode *inode)
{
return 0;
}
static inline int ocfs2_init_acl(handle_t *handle,
struct inode *inode,
struct inode *dir,
struct buffer_head *di_bh,
struct buffer_head *dir_bh,
struct ocfs2_alloc_context *meta_ac,
struct ocfs2_alloc_context *data_ac)
{
return 0;
}

#endif /* CONFIG_OCFS2_FS_POSIX_ACL*/

Expand Down
23 changes: 15 additions & 8 deletions fs/ocfs2/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
#include "sysfile.h"
#include "uptodate.h"
#include "xattr.h"
#include "acl.h"

#include "buffer_head_io.h"

Expand Down Expand Up @@ -302,14 +303,13 @@ static int ocfs2_mknod(struct inode *dir,
}
}

/* calculate meta data/clusters for setting security xattr */
if (si.enable) {
status = ocfs2_calc_security_init(dir, &si, &want_clusters,
&xattr_credits, &xattr_ac);
if (status < 0) {
mlog_errno(status);
goto leave;
}
/* calculate meta data/clusters for setting security and acl xattr */
status = ocfs2_calc_xattr_init(dir, parent_fe_bh, mode,
&si, &want_clusters,
&xattr_credits, &xattr_ac);
if (status < 0) {
mlog_errno(status);
goto leave;
}

/* Reserve a cluster if creating an extent based directory. */
Expand Down Expand Up @@ -363,6 +363,13 @@ static int ocfs2_mknod(struct inode *dir,
inc_nlink(dir);
}

status = ocfs2_init_acl(handle, inode, dir, new_fe_bh, parent_fe_bh,
xattr_ac, data_ac);
if (status < 0) {
mlog_errno(status);
goto leave;
}

if (si.enable) {
status = ocfs2_init_security_set(handle, inode, new_fe_bh, &si,
xattr_ac, data_ac);
Expand Down
79 changes: 79 additions & 0 deletions fs/ocfs2/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ struct ocfs2_xattr_set_ctxt {
#define OCFS2_XATTR_FREE_IN_IBODY (OCFS2_MIN_XATTR_INLINE_SIZE \
- sizeof(struct ocfs2_xattr_header) \
- sizeof(__u32))
#define OCFS2_XATTR_FREE_IN_BLOCK(ptr) ((ptr)->i_sb->s_blocksize \
- sizeof(struct ocfs2_xattr_block) \
- sizeof(struct ocfs2_xattr_header) \
- sizeof(__u32))

static struct ocfs2_xattr_def_value_root def_xv = {
.xv.xr_list.l_count = cpu_to_le16(1),
Expand Down Expand Up @@ -402,6 +406,81 @@ int ocfs2_calc_security_init(struct inode *dir,
return ret;
}

int ocfs2_calc_xattr_init(struct inode *dir,
struct buffer_head *dir_bh,
int mode,
struct ocfs2_security_xattr_info *si,
int *want_clusters,
int *xattr_credits,
struct ocfs2_alloc_context **xattr_ac)
{
int ret = 0;
struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
int s_size = 0;
int a_size = 0;
int acl_len = 0;

if (si->enable)
s_size = ocfs2_xattr_entry_real_size(strlen(si->name),
si->value_len);

if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) {
acl_len = ocfs2_xattr_get_nolock(dir, dir_bh,
OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT,
"", NULL, 0);
if (acl_len > 0) {
a_size = ocfs2_xattr_entry_real_size(0, acl_len);
if (S_ISDIR(mode))
a_size <<= 1;
} else if (acl_len != 0 && acl_len != -ENODATA) {
mlog_errno(ret);
return ret;
}
}

if (!(s_size + a_size))
return ret;

/*
* The max space of security xattr taken inline is
* 256(name) + 80(value) + 16(entry) = 352 bytes,
* The max space of acl xattr taken inline is
* 80(value) + 16(entry) * 2(if directory) = 192 bytes,
* when blocksize = 512, may reserve one more cluser for
* xattr bucket, otherwise reserve one metadata block
* for them is ok.
*/
if (dir->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE ||
(s_size + a_size) > OCFS2_XATTR_FREE_IN_IBODY) {
ret = ocfs2_reserve_new_metadata_blocks(osb, 1, xattr_ac);
if (ret) {
mlog_errno(ret);
return ret;
}
*xattr_credits += OCFS2_XATTR_BLOCK_CREATE_CREDITS;
}

if (dir->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE &&
(s_size + a_size) > OCFS2_XATTR_FREE_IN_BLOCK(dir)) {
*want_clusters += 1;
*xattr_credits += ocfs2_blocks_per_xattr_bucket(dir->i_sb);
}

/* reserve clusters for xattr value which will be set in B tree*/
if (si->enable && si->value_len > OCFS2_XATTR_INLINE_SIZE)
*want_clusters += ocfs2_clusters_for_bytes(dir->i_sb,
si->value_len);
if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL &&
acl_len > OCFS2_XATTR_INLINE_SIZE) {
*want_clusters += ocfs2_clusters_for_bytes(dir->i_sb, acl_len);
if (S_ISDIR(mode))
*want_clusters += ocfs2_clusters_for_bytes(dir->i_sb,
acl_len);
}

return ret;
}

static int ocfs2_xattr_extend_allocation(struct inode *inode,
u32 clusters_to_add,
struct buffer_head *xattr_bh,
Expand Down
3 changes: 3 additions & 0 deletions fs/ocfs2/xattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,8 @@ int ocfs2_init_security_set(handle_t *, struct inode *,
int ocfs2_calc_security_init(struct inode *,
struct ocfs2_security_xattr_info *,
int *, int *, struct ocfs2_alloc_context **);
int ocfs2_calc_xattr_init(struct inode *, struct buffer_head *,
int, struct ocfs2_security_xattr_info *,
int *, int *, struct ocfs2_alloc_context **);

#endif /* OCFS2_XATTR_H */

0 comments on commit 89c38bd

Please sign in to comment.