]> git.hungrycats.org Git - linux/commitdiff
[XFS] Fix up the default ACL inherit case, in the presence of failure during applying...
authorNathan Scott <nathans@sgi.com>
Tue, 12 Aug 2003 01:49:01 +0000 (20:49 -0500)
committerStephen Lord <lord@jen.americas.sgi.com>
Tue, 12 Aug 2003 01:49:01 +0000 (20:49 -0500)
SGI Modid: 2.5.x-xfs:slinx:155553a

fs/xfs/linux/xfs_iops.c
fs/xfs/xfs_attr.c
fs/xfs/xfs_da_btree.c
fs/xfs/xfs_da_btree.h

index c66aff5b1609a741e170d2f5c7d6315e1dbbcb70..11eac5784afa696174f5384ae1c97827a21da1ab 100644 (file)
@@ -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;
 }
 
index 3514de27c85c3ae432d34e75003eb79eb499357b..90048386b3ab69553bdc700f9f491adc00dde9fe 100644 (file)
@@ -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;
index bd112587e784b3f4e5aca4c190ca5ff3b78a545e..76aadaa992e56c5682d9a17f3681833c1393925d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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)
index e575998a58ad237c22ddb86e6650b4f094c4ab28..86f286bdab63305b82376755051485d6cf223142 100644 (file)
@@ -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 */