]> err.no Git - linux-2.6/blobdiff - fs/xfs/xfs_attr.c
powerpc: Only make kernel text pages of linear mapping executable
[linux-2.6] / fs / xfs / xfs_attr.c
index 49fac8d6db129b00e6cadf0968721e1c1dee1691..f7cdc28aff413bb8b5d2fa866157a2e27c80cdcb 100644 (file)
@@ -16,8 +16,6 @@
  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include <linux/capability.h>
-
 #include "xfs.h"
 #include "xfs_fs.h"
 #include "xfs_types.h"
@@ -196,6 +194,46 @@ xfs_attr_get(
        return(error);
 }
 
+/*
+ * Calculate how many blocks we need for the new attribute,
+ */
+int
+xfs_attr_calc_size(
+       struct xfs_inode        *ip,
+       int                     namelen,
+       int                     valuelen,
+       int                     *local)
+{
+       struct xfs_mount        *mp = ip->i_mount;
+       int                     size;
+       int                     nblks;
+
+       /*
+        * Determine space new attribute will use, and if it would be
+        * "local" or "remote" (note: local != inline).
+        */
+       size = xfs_attr_leaf_newentsize(namelen, valuelen,
+                                       mp->m_sb.sb_blocksize, local);
+
+       nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
+       if (*local) {
+               if (size > (mp->m_sb.sb_blocksize >> 1)) {
+                       /* Double split possible */
+                       nblks *= 2;
+               }
+       } else {
+               /*
+                * Out of line attribute, cannot double split, but
+                * make room for the attribute value itself.
+                */
+               uint    dblocks = XFS_B_TO_FSB(mp, valuelen);
+               nblks += dblocks;
+               nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
+       }
+
+       return nblks;
+}
+
 STATIC int
 xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
                char *value, int valuelen, int flags)
@@ -204,10 +242,9 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
        xfs_fsblock_t   firstblock;
        xfs_bmap_free_t flist;
        int             error, err2, committed;
-       int             local, size;
-       uint            nblks;
        xfs_mount_t     *mp = dp->i_mount;
        int             rsvd = (flags & ATTR_ROOT) != 0;
+       int             local;
 
        /*
         * Attach the dquots to the inode.
@@ -243,30 +280,8 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
        args.whichfork = XFS_ATTR_FORK;
        args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
 
-       /*
-        * Determine space new attribute will use, and if it would be
-        * "local" or "remote" (note: local != inline).
-        */
-       size = xfs_attr_leaf_newentsize(name->len, valuelen,
-                                       mp->m_sb.sb_blocksize, &local);
-
-       nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
-       if (local) {
-               if (size > (mp->m_sb.sb_blocksize >> 1)) {
-                       /* Double split possible */
-                       nblks <<= 1;
-               }
-       } else {
-               uint    dblocks = XFS_B_TO_FSB(mp, valuelen);
-               /* Out of line attribute, cannot double split, but make
-                * room for the attribute value itself.
-                */
-               nblks += dblocks;
-               nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
-       }
-
        /* Size is now blocks for attribute data */
-       args.total = nblks;
+       args.total = xfs_attr_calc_size(dp, name->len, valuelen, &local);
 
        /*
         * Start our first transaction of the day.
@@ -288,18 +303,17 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
        if (rsvd)
                args.trans->t_flags |= XFS_TRANS_RESERVE;
 
-       if ((error = xfs_trans_reserve(args.trans, (uint) nblks,
-                                     XFS_ATTRSET_LOG_RES(mp, nblks),
-                                     0, XFS_TRANS_PERM_LOG_RES,
-                                     XFS_ATTRSET_LOG_COUNT))) {
+       if ((error = xfs_trans_reserve(args.trans, args.total,
+                       XFS_ATTRSET_LOG_RES(mp, args.total), 0,
+                       XFS_TRANS_PERM_LOG_RES, XFS_ATTRSET_LOG_COUNT))) {
                xfs_trans_cancel(args.trans, 0);
                return(error);
        }
        xfs_ilock(dp, XFS_ILOCK_EXCL);
 
-       error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, args.trans, dp, nblks, 0,
-                        rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
-                               XFS_QMOPT_RES_REGBLKS);
+       error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, args.trans, dp, args.total, 0,
+                               rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
+                                      XFS_QMOPT_RES_REGBLKS);
        if (error) {
                xfs_iunlock(dp, XFS_ILOCK_EXCL);
                xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES);
@@ -386,7 +400,9 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
                 * Commit the leaf transformation.  We'll need another (linked)
                 * transaction to add the new attribute to the leaf.
                 */
-               if ((error = xfs_attr_rolltrans(&args.trans, dp)))
+
+               error = xfs_trans_roll(&args.trans, dp);
+               if (error)
                        goto out;
 
        }
@@ -607,12 +623,20 @@ xfs_attr_remove(
        return xfs_attr_remove_int(dp, &xname, flags);
 }
 
-STATIC int
+int
 xfs_attr_list_int(xfs_attr_list_context_t *context)
 {
        int error;
        xfs_inode_t *dp = context->dp;
 
+       XFS_STATS_INC(xs_attr_list);
+
+       if (XFS_FORCED_SHUTDOWN(dp->i_mount))
+               return EIO;
+
+       xfs_ilock(dp, XFS_ILOCK_SHARED);
+       xfs_attr_trace_l_c("syscall start", context);
+
        /*
         * Decide on what work routines to call based on the inode size.
         */
@@ -625,6 +649,10 @@ xfs_attr_list_int(xfs_attr_list_context_t *context)
        } else {
                error = xfs_attr_node_list(context);
        }
+
+       xfs_iunlock(dp, XFS_ILOCK_SHARED);
+       xfs_attr_trace_l_c("syscall end", context);
+
        return error;
 }
 
@@ -641,74 +669,50 @@ xfs_attr_list_int(xfs_attr_list_context_t *context)
  */
 /*ARGSUSED*/
 STATIC int
-xfs_attr_put_listent(xfs_attr_list_context_t *context, attrnames_t *namesp,
+xfs_attr_put_listent(xfs_attr_list_context_t *context, int flags,
                     char *name, int namelen,
                     int valuelen, char *value)
 {
+       struct attrlist *alist = (struct attrlist *)context->alist;
        attrlist_ent_t *aep;
        int arraytop;
 
        ASSERT(!(context->flags & ATTR_KERNOVAL));
        ASSERT(context->count >= 0);
        ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
-       ASSERT(context->firstu >= sizeof(*context->alist));
+       ASSERT(context->firstu >= sizeof(*alist));
        ASSERT(context->firstu <= context->bufsize);
 
-       arraytop = sizeof(*context->alist) +
-                       context->count * sizeof(context->alist->al_offset[0]);
+       /*
+        * Only list entries in the right namespace.
+        */
+       if (((context->flags & ATTR_SECURE) == 0) !=
+           ((flags & XFS_ATTR_SECURE) == 0))
+               return 0;
+       if (((context->flags & ATTR_ROOT) == 0) !=
+           ((flags & XFS_ATTR_ROOT) == 0))
+               return 0;
+
+       arraytop = sizeof(*alist) +
+                       context->count * sizeof(alist->al_offset[0]);
        context->firstu -= ATTR_ENTSIZE(namelen);
        if (context->firstu < arraytop) {
                xfs_attr_trace_l_c("buffer full", context);
-               context->alist->al_more = 1;
+               alist->al_more = 1;
                context->seen_enough = 1;
                return 1;
        }
 
-       aep = (attrlist_ent_t *)&(((char *)context->alist)[ context->firstu ]);
+       aep = (attrlist_ent_t *)&context->alist[context->firstu];
        aep->a_valuelen = valuelen;
        memcpy(aep->a_name, name, namelen);
-       aep->a_name[ namelen ] = 0;
-       context->alist->al_offset[ context->count++ ] = context->firstu;
-       context->alist->al_count = context->count;
+       aep->a_name[namelen] = 0;
+       alist->al_offset[context->count++] = context->firstu;
+       alist->al_count = context->count;
        xfs_attr_trace_l_c("add", context);
        return 0;
 }
 
-STATIC int
-xfs_attr_kern_list(xfs_attr_list_context_t *context, attrnames_t *namesp,
-                    char *name, int namelen,
-                    int valuelen, char *value)
-{
-       char *offset;
-       int arraytop;
-
-       ASSERT(context->count >= 0);
-
-       arraytop = context->count + namesp->attr_namelen + namelen + 1;
-       if (arraytop > context->firstu) {
-               context->count = -1;    /* insufficient space */
-               return 1;
-       }
-       offset = (char *)context->alist + context->count;
-       strncpy(offset, namesp->attr_name, namesp->attr_namelen);
-       offset += namesp->attr_namelen;
-       strncpy(offset, name, namelen);                 /* real name */
-       offset += namelen;
-       *offset = '\0';
-       context->count += namesp->attr_namelen + namelen + 1;
-       return 0;
-}
-
-/*ARGSUSED*/
-STATIC int
-xfs_attr_kern_list_sizes(xfs_attr_list_context_t *context, attrnames_t *namesp,
-                    char *name, int namelen,
-                    int valuelen, char *value)
-{
-       context->count += namesp->attr_namelen + namelen + 1;
-       return 0;
-}
-
 /*
  * Generate a list of extended attribute names and optionally
  * also value lengths.  Positive return value follows the XFS
@@ -725,10 +729,9 @@ xfs_attr_list(
        attrlist_cursor_kern_t *cursor)
 {
        xfs_attr_list_context_t context;
+       struct attrlist *alist;
        int error;
 
-       XFS_STATS_INC(xs_attr_list);
-
        /*
         * Validate the cursor.
         */
@@ -749,52 +752,23 @@ xfs_attr_list(
        /*
         * Initialize the output buffer.
         */
+       memset(&context, 0, sizeof(context));
        context.dp = dp;
        context.cursor = cursor;
-       context.count = 0;
-       context.dupcnt = 0;
        context.resynch = 1;
        context.flags = flags;
-       context.seen_enough = 0;
-       context.alist = (attrlist_t *)buffer;
-       context.put_value = 0;
-
-       if (flags & ATTR_KERNAMELS) {
-               context.bufsize = bufsize;
-               context.firstu = context.bufsize;
-               if (flags & ATTR_KERNOVAL)
-                       context.put_listent = xfs_attr_kern_list_sizes;
-               else
-                       context.put_listent = xfs_attr_kern_list;
-       } else {
-               context.bufsize = (bufsize & ~(sizeof(int)-1));  /* align */
-               context.firstu = context.bufsize;
-               context.alist->al_count = 0;
-               context.alist->al_more = 0;
-               context.alist->al_offset[0] = context.bufsize;
-               context.put_listent = xfs_attr_put_listent;
-       }
-
-       if (XFS_FORCED_SHUTDOWN(dp->i_mount))
-               return EIO;
+       context.alist = buffer;
+       context.bufsize = (bufsize & ~(sizeof(int)-1));  /* align */
+       context.firstu = context.bufsize;
+       context.put_listent = xfs_attr_put_listent;
 
-       xfs_ilock(dp, XFS_ILOCK_SHARED);
-       xfs_attr_trace_l_c("syscall start", &context);
+       alist = (struct attrlist *)context.alist;
+       alist->al_count = 0;
+       alist->al_more = 0;
+       alist->al_offset[0] = context.bufsize;
 
        error = xfs_attr_list_int(&context);
-
-       xfs_iunlock(dp, XFS_ILOCK_SHARED);
-       xfs_attr_trace_l_c("syscall end", &context);
-
-       if (context.flags & (ATTR_KERNOVAL|ATTR_KERNAMELS)) {
-               /* must return negated buffer size or the error */
-               if (context.count < 0)
-                       error = XFS_ERROR(ERANGE);
-               else
-                       error = -context.count;
-       } else
-               ASSERT(error >= 0);
-
+       ASSERT(error >= 0);
        return error;
 }
 
@@ -1008,7 +982,8 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
                 * Commit the current trans (including the inode) and start
                 * a new one.
                 */
-               if ((error = xfs_attr_rolltrans(&args->trans, dp)))
+               error = xfs_trans_roll(&args->trans, dp);
+               if (error)
                        return (error);
 
                /*
@@ -1022,7 +997,8 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
         * Commit the transaction that added the attr name so that
         * later routines can manage their own transactions.
         */
-       if ((error = xfs_attr_rolltrans(&args->trans, dp)))
+       error = xfs_trans_roll(&args->trans, dp);
+       if (error)
                return (error);
 
        /*
@@ -1111,7 +1087,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
                /*
                 * Commit the remove and start the next trans in series.
                 */
-               error = xfs_attr_rolltrans(&args->trans, dp);
+               error = xfs_trans_roll(&args->trans, dp);
 
        } else if (args->rmtblkno > 0) {
                /*
@@ -1342,7 +1318,8 @@ restart:
                         * Commit the node conversion and start the next
                         * trans in the chain.
                         */
-                       if ((error = xfs_attr_rolltrans(&args->trans, dp)))
+                       error = xfs_trans_roll(&args->trans, dp);
+                       if (error)
                                goto out;
 
                        goto restart;
@@ -1393,7 +1370,8 @@ restart:
         * Commit the leaf addition or btree split and start the next
         * trans in the chain.
         */
-       if ((error = xfs_attr_rolltrans(&args->trans, dp)))
+       error = xfs_trans_roll(&args->trans, dp);
+       if (error)
                goto out;
 
        /*
@@ -1493,7 +1471,8 @@ restart:
                /*
                 * Commit and start the next trans in the chain.
                 */
-               if ((error = xfs_attr_rolltrans(&args->trans, dp)))
+               error = xfs_trans_roll(&args->trans, dp);
+               if (error)
                        goto out;
 
        } else if (args->rmtblkno > 0) {
@@ -1625,7 +1604,8 @@ xfs_attr_node_removename(xfs_da_args_t *args)
                /*
                 * Commit the Btree join operation and start a new trans.
                 */
-               if ((error = xfs_attr_rolltrans(&args->trans, dp)))
+               error = xfs_trans_roll(&args->trans, dp);
+               if (error)
                        goto out;
        }
 
@@ -2126,7 +2106,8 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)
                /*
                 * Start the next trans in the chain.
                 */
-               if ((error = xfs_attr_rolltrans(&args->trans, dp)))
+               error = xfs_trans_roll(&args->trans, dp);
+               if (error)
                        return (error);
        }
 
@@ -2276,7 +2257,8 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
                /*
                 * Close out trans and start the next one in the chain.
                 */
-               if ((error = xfs_attr_rolltrans(&args->trans, args->dp)))
+               error = xfs_trans_roll(&args->trans, args->dp);
+               if (error)
                        return (error);
        }
        return(0);
@@ -2357,12 +2339,7 @@ xfs_attr_trace_enter(int type, char *where,
                (void *)((__psunsigned_t)context->bufsize),
                (void *)((__psunsigned_t)context->count),
                (void *)((__psunsigned_t)context->firstu),
-               (void *)((__psunsigned_t)
-                       (((context->count > 0) &&
-                       !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))
-                               ? (ATTR_ENTRY(context->alist,
-                                             context->count-1)->a_valuelen)
-                               : 0)),
+               NULL,
                (void *)((__psunsigned_t)context->dupcnt),
                (void *)((__psunsigned_t)context->flags),
                (void *)a13, (void *)a14, (void *)a15);