Commit af60eee1 authored by Nathan Scott's avatar Nathan Scott Committed by Stephen Lord

[XFS] Fix up the default ACL inherit case, in the presence of failure during...

[XFS] Fix up the default ACL inherit case, in the presence of failure during applying the default ACL (eg. from ENOSPC).

SGI Modid: 2.5.x-xfs:slinx:155553a
parent 3284f263
......@@ -109,14 +109,20 @@ linvfs_mknod(
struct inode *ip;
vattr_t va;
vnode_t *vp = NULL, *dvp = LINVFS_GET_VP(dir);
xfs_acl_t *default_acl = NULL;
xattr_exists_t test_default_acl = _ACL_DEFAULT_EXISTS;
int have_default_acl = 0;
int error = EINVAL;
int error;
if (test_default_acl)
have_default_acl = test_default_acl(dvp);
if (test_default_acl && test_default_acl(dvp)) {
if (!_ACL_ALLOC(default_acl))
return -ENOMEM;
if (!_ACL_GET_DEFAULT(dvp, default_acl)) {
_ACL_FREE(default_acl);
default_acl = NULL;
}
}
if (IS_POSIXACL(dir) && !have_default_acl && has_fs_struct(current))
if (IS_POSIXACL(dir) && !default_acl && has_fs_struct(current))
mode &= ~current->fs->umask;
memset(&va, 0, sizeof(va));
......@@ -140,13 +146,36 @@ linvfs_mknod(
break;
}
if (default_acl) {
if (!error) {
error = _ACL_INHERIT(vp, &va, default_acl);
if (!error) {
VMODIFY(vp);
} else {
struct dentry teardown = {};
int err2;
/* Oh, the horror.
* If we can't add the ACL we must back out.
* ENOSPC can hit here, among other things.
*/
teardown.d_inode = ip = LINVFS_GET_IP(vp);
teardown.d_name = dentry->d_name;
remove_inode_hash(ip);
make_bad_inode(ip);
if (S_ISDIR(mode))
VOP_RMDIR(dvp, &teardown, NULL, err2);
else
VOP_REMOVE(dvp, &teardown, NULL, err2);
VN_RELE(vp);
}
}
_ACL_FREE(default_acl);
}
if (!error) {
ASSERT(vp);
ip = LINVFS_GET_IP(vp);
if (!ip) {
VN_RELE(vp);
return -ENOMEM;
}
if (S_ISCHR(mode) || S_ISBLK(mode))
ip->i_rdev = to_kdev_t(rdev);
......@@ -155,19 +184,6 @@ linvfs_mknod(
d_instantiate(dentry, ip);
validate_fields(dir);
}
if (!error && have_default_acl) {
_ACL_DECL (pdacl);
if (!_ACL_ALLOC(pdacl)) {
error = -ENOMEM;
} else {
if (_ACL_GET_DEFAULT(dvp, pdacl))
error = _ACL_INHERIT(vp, &va, pdacl);
VMODIFY(vp);
_ACL_FREE(pdacl);
}
}
return -error;
}
......
......@@ -1718,6 +1718,7 @@ xfs_attr_node_get(xfs_da_args_t *args)
int i;
state = xfs_da_state_alloc();
state->holeok = 1;
state->args = args;
state->mp = args->dp->i_mount;
state->blocksize = state->mp->m_sb.sb_blocksize;
......
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
......@@ -1141,10 +1141,13 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
xfs_da_node_entry_t *btree;
xfs_dablk_t blkno;
int probe, span, max, error, retval;
xfs_daddr_t mappedbno;
xfs_dahash_t hashval;
xfs_da_args_t *args;
args = state->args;
mappedbno = state->holeok ? -2 : -1;
/*
* Descend thru the B-tree searching each level for the right
* node to use, until the right hashval is found.
......@@ -1160,15 +1163,15 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
* Read the next node down in the tree.
*/
blk->blkno = blkno;
error = xfs_da_read_buf(state->args->trans, state->args->dp,
blkno, -1, &blk->bp,
state->args->whichfork);
error = xfs_da_read_buf(args->trans, args->dp, blkno,
mappedbno, &blk->bp, args->whichfork);
if (!error && unlikely(state->holeok && !blk->bp))
error = XFS_ERROR(ENOATTR); /* always attr here */
if (error) {
blk->blkno = 0;
state->path.active--;
return(error);
}
ASSERT(blk->bp != NULL);
curr = blk->bp->data;
ASSERT(INT_GET(curr->magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC ||
INT_GET(curr->magic, ARCH_CONVERT) == XFS_DIRX_LEAF_MAGIC(state->mp) ||
......@@ -1187,7 +1190,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
*/
max = INT_GET(node->hdr.count, ARCH_CONVERT);
probe = span = max / 2;
hashval = state->args->hashval;
hashval = args->hashval;
for (btree = &node->btree[probe]; span > 4;
btree = &node->btree[probe]) {
span /= 2;
......@@ -1250,22 +1253,22 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
for (;;) {
if (blk->magic == XFS_DIR_LEAF_MAGIC) {
ASSERT(XFS_DIR_IS_V1(state->mp));
retval = xfs_dir_leaf_lookup_int(blk->bp, state->args,
retval = xfs_dir_leaf_lookup_int(blk->bp, args,
&blk->index);
} else if (blk->magic == XFS_DIR2_LEAFN_MAGIC) {
ASSERT(XFS_DIR_IS_V2(state->mp));
retval = xfs_dir2_leafn_lookup_int(blk->bp, state->args,
retval = xfs_dir2_leafn_lookup_int(blk->bp, args,
&blk->index, state);
}
#ifdef __KERNEL__
else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
retval = xfs_attr_leaf_lookup_int(blk->bp, state->args);
blk->index = state->args->index;
state->args->blkno = blk->blkno;
retval = xfs_attr_leaf_lookup_int(blk->bp, args);
blk->index = args->index;
args->blkno = blk->blkno;
}
#endif
if (((retval == ENOENT) || (retval == ENOATTR)) &&
(blk->hashval == state->args->hashval)) {
(blk->hashval == args->hashval)) {
error = xfs_da_path_shift(state, &state->path, 1, 1,
&retval);
if (error)
......
......@@ -185,14 +185,14 @@ typedef struct xfs_da_args {
int index; /* index of attr of interest in blk */
xfs_dablk_t rmtblkno; /* remote attr value starting blkno */
int rmtblkcnt; /* remote attr value block count */
int rename; /* T/F: this is an atomic rename op */
xfs_dablk_t blkno2; /* blkno of 2nd attr leaf of interest */
int index2; /* index of 2nd attr in blk */
xfs_dablk_t rmtblkno2; /* remote attr value starting blkno */
int rmtblkcnt2; /* remote attr value block count */
int justcheck; /* check for ok with no space */
int addname; /* T/F: this is an add operation */
int oknoent; /* T/F: ok to return ENOENT, else die */
int justcheck : 1; /* T/F: check for ok with no space */
int rename : 1; /* T/F: this is an atomic rename op */
int addname : 1; /* T/F: this is an add operation */
int oknoent : 1; /* T/F: ok to return ENOENT, else die */
} xfs_da_args_t;
/*
......@@ -253,6 +253,7 @@ typedef struct xfs_da_state {
xfs_da_state_path_t path; /* search/split paths */
xfs_da_state_path_t altpath; /* alternate path for join */
unsigned int inleaf : 1; /* insert into 1->lf, 0->splf */
unsigned int holeok : 1; /* T/F: can deal with a hole */
unsigned int extravalid : 1; /* T/F: extrablk is in use */
unsigned int extraafter : 1; /* T/F: extrablk is after new */
xfs_da_state_blk_t extrablk; /* for double-splits on leafs */
......
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