fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / fs / jfs / jfs_imap.c
index 848fbc8..dcd9f7e 100644 (file)
@@ -1,18 +1,18 @@
 /*
- *   Copyright (C) International Business Machines Corp., 2000-2003
+ *   Copyright (C) International Business Machines Corp., 2000-2004
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or 
+ *   the Free Software Foundation; either version 2 of the License, or
  *   (at your option) any later version.
- * 
+ *
  *   This program is distributed in the hope that it will be useful,
  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
  *   the GNU General Public License for more details.
  *
  *   You should have received a copy of the GNU General Public License
- *   along with this program;  if not, write to the Free Software 
+ *   along with this program;  if not, write to the Free Software
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
 #include <linux/pagemap.h>
-#include <linux/vserver/xid.h>
+#include <linux/quotaops.h>
+#include <linux/vs_tag.h>
 
 #include "jfs_incore.h"
+#include "jfs_inode.h"
 #include "jfs_filsys.h"
 #include "jfs_dinode.h"
 #include "jfs_dmap.h"
 #include "jfs_superblock.h"
 #include "jfs_debug.h"
 
+/*
+ * __mark_inode_dirty expects inodes to be hashed.  Since we don't want
+ * special inodes in the fileset inode space, we hash them to a dummy head
+ */
+static HLIST_HEAD(aggregate_hash);
+
 /*
  * imap locks
  */
 /* iag free list lock */
-#define IAGFREE_LOCK_INIT(imap)                init_MUTEX(&imap->im_freelock)
-#define IAGFREE_LOCK(imap)             down(&imap->im_freelock)
-#define IAGFREE_UNLOCK(imap)           up(&imap->im_freelock)
+#define IAGFREE_LOCK_INIT(imap)                mutex_init(&imap->im_freelock)
+#define IAGFREE_LOCK(imap)             mutex_lock(&imap->im_freelock)
+#define IAGFREE_UNLOCK(imap)           mutex_unlock(&imap->im_freelock)
 
 /* per ag iag list locks */
-#define AG_LOCK_INIT(imap,index)       init_MUTEX(&(imap->im_aglock[index]))
-#define AG_LOCK(imap,agno)             down(&imap->im_aglock[agno])
-#define AG_UNLOCK(imap,agno)           up(&imap->im_aglock[agno])
-
-/*
- * external references
- */
-extern struct address_space_operations jfs_aops;
+#define AG_LOCK_INIT(imap,index)       mutex_init(&(imap->im_aglock[index]))
+#define AG_LOCK(imap,agno)             mutex_lock(&imap->im_aglock[agno])
+#define AG_UNLOCK(imap,agno)           mutex_unlock(&imap->im_aglock[agno])
 
 /*
  * forward references
  */
-static int diAllocAG(struct inomap *, int, boolean_t, struct inode *);
-static int diAllocAny(struct inomap *, int, boolean_t, struct inode *);
+static int diAllocAG(struct inomap *, int, bool, struct inode *);
+static int diAllocAny(struct inomap *, int, bool, struct inode *);
 static int diAllocBit(struct inomap *, struct iag *, int);
 static int diAllocExt(struct inomap *, int, struct inode *);
 static int diAllocIno(struct inomap *, int, struct inode *);
@@ -90,32 +93,13 @@ static int diIAGRead(struct inomap * imap, int, struct metapage **);
 static int copy_from_dinode(struct dinode *, struct inode *);
 static void copy_to_dinode(struct dinode *, struct inode *);
 
-/*
- *     debug code for double-checking inode map
- */
-/* #define     _JFS_DEBUG_IMAP 1 */
-
-#ifdef _JFS_DEBUG_IMAP
-#define DBG_DIINIT(imap)       DBGdiInit(imap)
-#define DBG_DIALLOC(imap, ino) DBGdiAlloc(imap, ino)
-#define DBG_DIFREE(imap, ino)  DBGdiFree(imap, ino)
-
-static void *DBGdiInit(struct inomap * imap);
-static void DBGdiAlloc(struct inomap * imap, ino_t ino);
-static void DBGdiFree(struct inomap * imap, ino_t ino);
-#else
-#define DBG_DIINIT(imap)
-#define DBG_DIALLOC(imap, ino)
-#define DBG_DIFREE(imap, ino)
-#endif                         /* _JFS_DEBUG_IMAP */
-
 /*
  * NAME:        diMount()
  *
  * FUNCTION:    initialize the incore inode map control structures for
  *             a fileset or aggregate init time.
  *
- *              the inode map's control structure (dinomap) is 
+ *              the inode map's control structure (dinomap) is
  *              brought in from disk and placed in virtual memory.
  *
  * PARAMETERS:
@@ -124,20 +108,20 @@ static void DBGdiFree(struct inomap * imap, ino_t ino);
  * RETURN VALUES:
  *      0       - success
  *      -ENOMEM  - insufficient free virtual memory.
- *      -EIO   - i/o error.
+ *      -EIO   - i/o error.
  */
 int diMount(struct inode *ipimap)
 {
        struct inomap *imap;
        struct metapage *mp;
        int index;
-       struct dinomap *dinom_le;
+       struct dinomap_disk *dinom_le;
 
        /*
         * allocate/initialize the in-memory inode map control structure
         */
        /* allocate the in-memory inode map control structure. */
-       imap = (struct inomap *) kmalloc(sizeof(struct inomap), GFP_KERNEL);
+       imap = kmalloc(sizeof(struct inomap), GFP_KERNEL);
        if (imap == NULL) {
                jfs_err("diMount: kmalloc returned NULL!");
                return -ENOMEM;
@@ -154,7 +138,7 @@ int diMount(struct inode *ipimap)
        }
 
        /* copy the on-disk version to the in-memory version. */
-       dinom_le = (struct dinomap *) mp->data;
+       dinom_le = (struct dinomap_disk *) mp->data;
        imap->im_freeiag = le32_to_cpu(dinom_le->in_freeiag);
        imap->im_nextiag = le32_to_cpu(dinom_le->in_nextiag);
        atomic_set(&imap->im_numinos, le32_to_cpu(dinom_le->in_numinos));
@@ -192,8 +176,6 @@ int diMount(struct inode *ipimap)
        imap->im_ipimap = ipimap;
        JFS_IP(ipimap)->i_imap = imap;
 
-//      DBG_DIINIT(imap);
-
        return (0);
 }
 
@@ -210,7 +192,7 @@ int diMount(struct inode *ipimap)
  * RETURN VALUES:
  *      0       - success
  *      -ENOMEM  - insufficient free virtual memory.
- *      -EIO   - i/o error.
+ *      -EIO   - i/o error.
  */
 int diUnmount(struct inode *ipimap, int mounterror)
 {
@@ -242,7 +224,7 @@ int diUnmount(struct inode *ipimap, int mounterror)
  */
 int diSync(struct inode *ipimap)
 {
-       struct dinomap *dinom_le;
+       struct dinomap_disk *dinom_le;
        struct inomap *imp = JFS_IP(ipimap)->i_imap;
        struct metapage *mp;
        int index;
@@ -260,7 +242,7 @@ int diSync(struct inode *ipimap)
        }
 
        /* copy the in-memory version to the on-disk version */
-       dinom_le = (struct dinomap *) mp->data;
+       dinom_le = (struct dinomap_disk *) mp->data;
        dinom_le->in_freeiag = cpu_to_le32(imp->im_freeiag);
        dinom_le->in_nextiag = cpu_to_le32(imp->im_nextiag);
        dinom_le->in_numinos = cpu_to_le32(atomic_read(&imp->im_numinos));
@@ -284,8 +266,7 @@ int diSync(struct inode *ipimap)
        /*
         * write out dirty pages of imap
         */
-       filemap_fdatawrite(ipimap->i_mapping);
-       filemap_fdatawait(ipimap->i_mapping);
+       filemap_write_and_wait(ipimap->i_mapping);
 
        diWriteSpecial(ipimap, 0);
 
@@ -301,7 +282,7 @@ int diSync(struct inode *ipimap)
  *             on entry, the specifed incore inode should itself
  *             specify the disk inode number corresponding to the
  *             incore inode (i.e. i_number should be initialized).
- *             
+ *
  *             this routine handles incore inode initialization for
  *             both "special" and "regular" inodes.  special inodes
  *             are those required early in the mount process and
@@ -309,7 +290,7 @@ int diSync(struct inode *ipimap)
  *             is not yet initialized.  these "special" inodes are
  *             identified by a NULL inode map inode pointer and are
  *             actually initialized by a call to diReadSpecial().
- *             
+ *
  *             for regular inodes, the iag describing the disk inode
  *             is read from disk to determine the inode extent address
  *             for the disk inode.  with the inode extent address in
@@ -322,9 +303,9 @@ int diSync(struct inode *ipimap)
  *
  * RETURN VALUES:
  *      0       - success
- *      -EIO   - i/o error.
+ *      -EIO   - i/o error.
  *      -ENOMEM        - insufficient memory
- *      
+ *
  */
 int diRead(struct inode *ip)
 {
@@ -338,7 +319,7 @@ int diRead(struct inode *ip)
        struct inomap *imap;
        int block_offset;
        int inodes_left;
-       uint pageno;
+       unsigned long pageno;
        int rel_inode;
 
        jfs_info("diRead: ino = %ld", ip->i_ino);
@@ -502,9 +483,12 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
 
        }
 
-       ip->i_mapping->a_ops = &jfs_aops;
+       ip->i_mapping->a_ops = &jfs_metapage_aops;
        mapping_set_gfp_mask(ip->i_mapping, GFP_NOFS);
 
+       /* Allocations to metadata inodes should not affect quotas */
+       ip->i_flags |= S_NOQUOTA;
+
        if ((inum == FILESYSTEM_I) && (JFS_IP(ip)->ipimap == sbi->ipaimap)) {
                sbi->gengen = le32_to_cpu(dp->di_gengen);
                sbi->inostamp = le32_to_cpu(dp->di_inostamp);
@@ -513,6 +497,8 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
        /* release the page */
        release_metapage(mp);
 
+       hlist_add_head(&ip->i_hash, &aggregate_hash);
+
        return (ip);
 }
 
@@ -536,8 +522,6 @@ void diWriteSpecial(struct inode *ip, int secondary)
        ino_t inum = ip->i_ino;
        struct metapage *mp;
 
-       ip->i_state &= ~I_DIRTY;
-
        if (secondary)
                address = addressPXD(&sbi->ait2) >> sbi->l2nbperpage;
        else
@@ -581,8 +565,7 @@ void diFreeSpecial(struct inode *ip)
                jfs_err("diFreeSpecial called with NULL ip!");
                return;
        }
-       filemap_fdatawrite(ip->i_mapping);
-       filemap_fdatawait(ip->i_mapping);
+       filemap_write_and_wait(ip->i_mapping);
        truncate_inode_pages(ip->i_mapping, 0);
        iput(ip);
 }
@@ -604,14 +587,14 @@ void diFreeSpecial(struct inode *ip)
  *             page of the extent that contains the disk inode is
  *             read and the disk inode portion of the incore inode
  *             is copied to the disk inode.
- *             
+ *
  * PARAMETERS:
  *     tid -  transacation id
  *      ip  -  pointer to incore inode to be written to the inode extent.
  *
  * RETURN VALUES:
  *      0       - success
- *      -EIO   - i/o error.
+ *      -EIO   - i/o error.
  */
 int diWrite(tid_t tid, struct inode *ip)
 {
@@ -624,7 +607,7 @@ int diWrite(tid_t tid, struct inode *ip)
        int block_offset;
        int inodes_left;
        struct metapage *mp;
-       uint pageno;
+       unsigned long pageno;
        int rel_inode;
        int dioffset;
        struct inode *ipimap;
@@ -694,11 +677,11 @@ int diWrite(tid_t tid, struct inode *ip)
         * copy btree root from in-memory inode to on-disk inode
         *
         * (tlock is taken from inline B+-tree root in in-memory
-        * inode when the B+-tree root is updated, which is pointed 
+        * inode when the B+-tree root is updated, which is pointed
         * by jfs_ip->blid as well as being on tx tlock list)
         *
-        * further processing of btree root is based on the copy 
-        * in in-memory inode, where txLog() will log from, and, 
+        * further processing of btree root is based on the copy
+        * in in-memory inode, where txLog() will log from, and,
         * for xtree root, txUpdateMap() will update map and reset
         * XAD_NEW bit;
         */
@@ -842,7 +825,7 @@ int diWrite(tid_t tid, struct inode *ip)
                memcpy(&dp->di_DASD, &ip->i_DASD, sizeof(struct dasd));
 #endif                         /*  _JFS_FASTDASD */
 
-       /* release the buffer holding the updated on-disk inode. 
+       /* release the buffer holding the updated on-disk inode.
         * the buffer will be later written by commit processing.
         */
        write_metapage(mp);
@@ -860,7 +843,7 @@ int diWrite(tid_t tid, struct inode *ip)
  *             if the inode to be freed represents the first (only)
  *             free inode within the iag, the iag will be placed on
  *             the ag free inode list.
- *     
+ *
  *             freeing the inode will cause the inode extent to be
  *             freed if the inode is the only allocated inode within
  *             the extent.  in this case all the disk resource backing
@@ -883,11 +866,11 @@ int diWrite(tid_t tid, struct inode *ip)
  *             any updates and are held until all updates are complete.
  *
  * PARAMETERS:
- *      ip     - inode to be freed.
+ *      ip     - inode to be freed.
  *
  * RETURN VALUES:
  *      0       - success
- *      -EIO   - i/o error.
+ *      -EIO   - i/o error.
  */
 int diFree(struct inode *ip)
 {
@@ -916,7 +899,7 @@ int diFree(struct inode *ip)
         */
        iagno = INOTOIAG(inum);
 
-       /* make sure that the iag is contained within 
+       /* make sure that the iag is contained within
         * the map.
         */
        if (iagno >= imap->im_nextiag) {
@@ -1024,17 +1007,17 @@ int diFree(struct inode *ip)
                         */
                        iagp->inofreefwd =
                            cpu_to_le32(imap->im_agctl[agno].inofree);
-                       iagp->inofreeback = -1;
+                       iagp->inofreeback = cpu_to_le32(-1);
                        imap->im_agctl[agno].inofree = iagno;
                }
                IREAD_UNLOCK(ipimap);
 
                /* update the free inode summary map for the extent if
                 * freeing the inode means the extent will now have free
-                * inodes (i.e., the inode being freed is the first free 
+                * inodes (i.e., the inode being freed is the first free
                 * inode of extent),
                 */
-               if (iagp->wmap[extno] == ONES) {
+               if (iagp->wmap[extno] == cpu_to_le32(ONES)) {
                        sword = extno >> L2EXTSPERSUM;
                        bitno = extno & (EXTSPERSUM - 1);
                        iagp->inosmap[sword] &=
@@ -1044,7 +1027,6 @@ int diFree(struct inode *ip)
                /* update the bitmap.
                 */
                iagp->wmap[extno] = cpu_to_le32(bitmap);
-               DBG_DIFREE(imap, inum);
 
                /* update the free inode counts at the iag, ag and
                 * map level.
@@ -1182,7 +1164,7 @@ int diFree(struct inode *ip)
 
                iagp->extfreefwd =
                    cpu_to_le32(imap->im_agctl[agno].extfree);
-               iagp->extfreeback = -1;
+               iagp->extfreeback = cpu_to_le32(-1);
                imap->im_agctl[agno].extfree = iagno;
        } else {
                /* remove the iag from the ag extent list if all extents
@@ -1198,7 +1180,7 @@ int diFree(struct inode *ip)
                                imap->im_agctl[agno].extfree =
                                    le32_to_cpu(iagp->extfreefwd);
 
-                       iagp->extfreefwd = iagp->extfreeback = -1;
+                       iagp->extfreefwd = iagp->extfreeback = cpu_to_le32(-1);
 
                        IAGFREE_LOCK(imap);
                        iagp->iagfree = cpu_to_le32(imap->im_freeiag);
@@ -1220,25 +1202,24 @@ int diFree(struct inode *ip)
                        imap->im_agctl[agno].inofree =
                            le32_to_cpu(iagp->inofreefwd);
 
-               iagp->inofreefwd = iagp->inofreeback = -1;
+               iagp->inofreefwd = iagp->inofreeback = cpu_to_le32(-1);
        }
 
-       /* update the inode extent address and working map 
+       /* update the inode extent address and working map
         * to reflect the free extent.
-        * the permanent map should have been updated already 
+        * the permanent map should have been updated already
         * for the inode being freed.
         */
        if (iagp->pmap[extno] != 0) {
                jfs_error(ip->i_sb, "diFree: the pmap does not show inode free");
        }
        iagp->wmap[extno] = 0;
-       DBG_DIFREE(imap, inum);
        PXDlength(&iagp->inoext[extno], 0);
        PXDaddress(&iagp->inoext[extno], 0);
 
        /* update the free extent and free inode summary maps
         * to reflect the freed extent.
-        * the inode summary map is marked to indicate no inodes 
+        * the inode summary map is marked to indicate no inodes
         * available for the freed extent.
         */
        sword = extno >> L2EXTSPERSUM;
@@ -1275,16 +1256,17 @@ int diFree(struct inode *ip)
         * start transaction to update block allocation map
         * for the inode extent freed;
         *
-        * N.B. AG_LOCK is released and iag will be released below, and 
+        * N.B. AG_LOCK is released and iag will be released below, and
         * other thread may allocate inode from/reusing the ixad freed
-        * BUT with new/different backing inode extent from the extent 
-        * to be freed by the transaction;  
+        * BUT with new/different backing inode extent from the extent
+        * to be freed by the transaction;
         */
        tid = txBegin(ipimap->i_sb, COMMIT_FORCE);
+       mutex_lock(&JFS_IP(ipimap)->commit_mutex);
 
-       /* acquire tlock of the iag page of the freed ixad 
+       /* acquire tlock of the iag page of the freed ixad
         * to force the page NOHOMEOK (even though no data is
-        * logged from the iag page) until NOREDOPAGE|FREEXTENT log 
+        * logged from the iag page) until NOREDOPAGE|FREEXTENT log
         * for the free of the extent is committed;
         * write FREEXTENT|NOREDOPAGE log record
         * N.B. linelock is overlaid as freed extent descriptor;
@@ -1303,8 +1285,8 @@ int diFree(struct inode *ip)
         * logredo needs the IAG number and IAG extent index in order
         * to ensure that the IMap is consistent.  The least disruptive
         * way to pass these values through  to the transaction manager
-        * is in the iplist array.  
-        * 
+        * is in the iplist array.
+        *
         * It's not pretty, but it works.
         */
        iplist[1] = (struct inode *) (size_t)iagno;
@@ -1313,6 +1295,7 @@ int diFree(struct inode *ip)
        rc = txCommit(tid, 1, &iplist[0], COMMIT_FORCE);
 
        txEnd(tid);
+       mutex_unlock(&JFS_IP(ipimap)->commit_mutex);
 
        /* unlock the AG inode map information */
        AG_UNLOCK(imap, agno);
@@ -1349,7 +1332,6 @@ diInitInode(struct inode *ip, int iagno, int ino, int extno, struct iag * iagp)
        struct jfs_inode_info *jfs_ip = JFS_IP(ip);
 
        ip->i_ino = (iagno << L2INOSPERIAG) + ino;
-       DBG_DIALLOC(JFS_IP(ipimap)->i_imap, ip->i_ino);
        jfs_ip->ixpxd = iagp->inoext[extno];
        jfs_ip->agno = BLKTOAG(le64_to_cpu(iagp->agstart), sbi);
        jfs_ip->active_ag = -1;
@@ -1359,20 +1341,20 @@ diInitInode(struct inode *ip, int iagno, int ino, int extno, struct iag * iagp)
 /*
  * NAME:        diAlloc(pip,dir,ip)
  *
- * FUNCTION:    allocate a disk inode from the inode working map 
+ * FUNCTION:    allocate a disk inode from the inode working map
  *             for a fileset or aggregate.
  *
  * PARAMETERS:
- *      pip    - pointer to incore inode for the parent inode.
- *      dir    - TRUE if the new disk inode is for a directory.
- *      ip     - pointer to a new inode
+ *      pip    - pointer to incore inode for the parent inode.
+ *      dir    - 'true' if the new disk inode is for a directory.
+ *      ip     - pointer to a new inode
  *
  * RETURN VALUES:
  *      0       - success.
  *      -ENOSPC        - insufficient disk resources.
- *      -EIO   - i/o error.
+ *      -EIO   - i/o error.
  */
-int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
+int diAlloc(struct inode *pip, bool dir, struct inode *ip)
 {
        int rc, ino, iagno, addext, extno, bitno, sword;
        int nwords, rem, i, agno;
@@ -1391,10 +1373,10 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
        JFS_IP(ip)->ipimap = ipimap;
        JFS_IP(ip)->fileset = FILESYSTEM_I;
 
-       /* for a directory, the allocation policy is to start 
+       /* for a directory, the allocation policy is to start
         * at the ag level using the preferred ag.
         */
-       if (dir == TRUE) {
+       if (dir) {
                agno = dbNextAG(JFS_SBI(pip->i_sb)->ipbmap);
                AG_LOCK(imap, agno);
                goto tryag;
@@ -1454,7 +1436,7 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
        /*
         *      try to allocate from the IAG
         */
-       /* check if the inode may be allocated from the iag 
+       /* check if the inode may be allocated from the iag
         * (i.e. the inode has free inodes or new extent can be added).
         */
        if (iagp->nfreeinos || addext) {
@@ -1509,7 +1491,7 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
                 * hint or, if appropriate (i.e. addext is true), allocate
                 * an extent of free inodes at or following the extent
                 * containing the hint.
-                * 
+                *
                 * the free inode and free extent summary maps are used
                 * here, so determine the starting summary map position
                 * and the number of words we'll have to examine.  again,
@@ -1660,7 +1642,7 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
  *             inodes should be added for the allocation group, with
  *             the current request satisfied from this extent. if this
  *             is the case, an attempt will be made to do just that.  if
- *             this attempt fails or it has been determined that a new 
+ *             this attempt fails or it has been determined that a new
  *             extent should not be added, an attempt is made to satisfy
  *             the request by allocating an existing (backed) free inode
  *             from the allocation group.
@@ -1668,24 +1650,24 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
  * PRE CONDITION: Already have the AG lock for this AG.
  *
  * PARAMETERS:
- *      imap   - pointer to inode map control structure.
- *      agno   - allocation group to allocate from.
- *      dir    - TRUE if the new disk inode is for a directory.
- *      ip     - pointer to the new inode to be filled in on successful return
+ *      imap   - pointer to inode map control structure.
+ *      agno   - allocation group to allocate from.
+ *      dir    - 'true' if the new disk inode is for a directory.
+ *      ip     - pointer to the new inode to be filled in on successful return
  *               with the disk inode number allocated, its extent address
  *               and the start of the ag.
  *
  * RETURN VALUES:
  *      0       - success.
  *      -ENOSPC        - insufficient disk resources.
- *      -EIO   - i/o error.
+ *      -EIO   - i/o error.
  */
 static int
-diAllocAG(struct inomap * imap, int agno, boolean_t dir, struct inode *ip)
+diAllocAG(struct inomap * imap, int agno, bool dir, struct inode *ip)
 {
        int rc, addext, numfree, numinos;
 
-       /* get the number of free and the number of backed disk 
+       /* get the number of free and the number of backed disk
         * inodes currently within the ag.
         */
        numfree = imap->im_agctl[agno].numfree;
@@ -1701,7 +1683,7 @@ diAllocAG(struct inomap * imap, int agno, boolean_t dir, struct inode *ip)
         * if there are a small number of free inodes or number of free
         * inodes is a small percentage of the number of backed inodes.
         */
-       if (dir == TRUE)
+       if (dir)
                addext = (numfree < 64 ||
                          (numfree < 256
                           && ((numfree * 100) / numinos) <= 20));
@@ -1738,26 +1720,26 @@ diAllocAG(struct inomap * imap, int agno, boolean_t dir, struct inode *ip)
  *             specified primary group.
  *
  * PARAMETERS:
- *      imap   - pointer to inode map control structure.
- *      agno   - primary allocation group (to avoid).
- *      dir    - TRUE if the new disk inode is for a directory.
- *      ip     - pointer to a new inode to be filled in on successful return
+ *      imap   - pointer to inode map control structure.
+ *      agno   - primary allocation group (to avoid).
+ *      dir    - 'true' if the new disk inode is for a directory.
+ *      ip     - pointer to a new inode to be filled in on successful return
  *               with the disk inode number allocated, its extent address
  *               and the start of the ag.
  *
  * RETURN VALUES:
  *      0       - success.
  *      -ENOSPC        - insufficient disk resources.
- *      -EIO   - i/o error.
+ *      -EIO   - i/o error.
  */
 static int
-diAllocAny(struct inomap * imap, int agno, boolean_t dir, struct inode *ip)
+diAllocAny(struct inomap * imap, int agno, bool dir, struct inode *ip)
 {
        int ag, rc;
        int maxag = JFS_SBI(imap->im_ipimap->i_sb)->bmap->db_maxag;
 
 
-       /* try to allocate from the ags following agno up to 
+       /* try to allocate from the ags following agno up to
         * the maximum ag number.
         */
        for (ag = agno + 1; ag <= maxag; ag++) {
@@ -1799,21 +1781,21 @@ diAllocAny(struct inomap * imap, int agno, boolean_t dir, struct inode *ip)
  *
  *             allocation occurs from the first iag on the list using
  *             the iag's free inode summary map to find the leftmost
- *             free inode in the iag. 
- *             
+ *             free inode in the iag.
+ *
  * PRE CONDITION: Already have AG lock for this AG.
- *             
+ *
  * PARAMETERS:
- *      imap   - pointer to inode map control structure.
- *      agno   - allocation group.
- *      ip     - pointer to new inode to be filled in on successful return
+ *      imap   - pointer to inode map control structure.
+ *      agno   - allocation group.
+ *      ip     - pointer to new inode to be filled in on successful return
  *               with the disk inode number allocated, its extent address
  *               and the start of the ag.
  *
  * RETURN VALUES:
  *      0       - success.
  *      -ENOSPC        - insufficient disk resources.
- *      -EIO   - i/o error.
+ *      -EIO   - i/o error.
  */
 static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
 {
@@ -1886,7 +1868,7 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
                return -EIO;
        }
 
-       /* compute the inode number within the iag. 
+       /* compute the inode number within the iag.
         */
        ino = (extno << L2INOSPEREXT) + rem;
 
@@ -1911,17 +1893,17 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
 /*
  * NAME:        diAllocExt(imap,agno,ip)
  *
- * FUNCTION:           add a new extent of free inodes to an iag, allocating
- *             an inode from this extent to satisfy the current allocation
- *             request.
- *             
+ * FUNCTION:   add a new extent of free inodes to an iag, allocating
+ *             an inode from this extent to satisfy the current allocation
+ *             request.
+ *
  *             this routine first tries to find an existing iag with free
  *             extents through the ag free extent list.  if list is not
  *             empty, the head of the list will be selected as the home
  *             of the new extent of free inodes.  otherwise (the list is
  *             empty), a new iag will be allocated for the ag to contain
  *             the extent.
- *             
+ *
  *             once an iag has been selected, the free extent summary map
  *             is used to locate a free extent within the iag and diNewExt()
  *             is called to initialize the extent, with initialization
@@ -1929,16 +1911,16 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
  *             for the purpose of satisfying this request.
  *
  * PARAMETERS:
- *      imap   - pointer to inode map control structure.
- *      agno   - allocation group number.
- *      ip     - pointer to new inode to be filled in on successful return
+ *      imap   - pointer to inode map control structure.
+ *      agno   - allocation group number.
+ *      ip     - pointer to new inode to be filled in on successful return
  *               with the disk inode number allocated, its extent address
  *               and the start of the ag.
  *
  * RETURN VALUES:
  *      0       - success.
  *      -ENOSPC        - insufficient disk resources.
- *      -EIO   - i/o error.
+ *      -EIO   - i/o error.
  */
 static int diAllocExt(struct inomap * imap, int agno, struct inode *ip)
 {
@@ -2031,7 +2013,7 @@ static int diAllocExt(struct inomap * imap, int agno, struct inode *ip)
 /*
  * NAME:        diAllocBit(imap,iagp,ino)
  *
- * FUNCTION:           allocate a backed inode from an iag.
+ * FUNCTION:   allocate a backed inode from an iag.
  *
  *             this routine performs the mechanics of allocating a
  *             specified inode from a backed extent.
@@ -2044,25 +2026,25 @@ static int diAllocExt(struct inomap * imap, int agno, struct inode *ip)
  *             in the face of updates to multiple buffers.  under this
  *             approach, all required buffers are obtained before making
  *             any updates and are held all are updates are complete.
- *             
+ *
  * PRE CONDITION: Already have buffer lock on iagp.  Already have AG lock on
  *     this AG.  Must have read lock on imap inode.
  *
  * PARAMETERS:
- *      imap   - pointer to inode map control structure.
- *      iagp   - pointer to iag. 
- *      ino    - inode number to be allocated within the iag.
+ *      imap   - pointer to inode map control structure.
+ *      iagp   - pointer to iag.
+ *      ino    - inode number to be allocated within the iag.
  *
  * RETURN VALUES:
  *      0       - success.
  *      -ENOSPC        - insufficient disk resources.
- *      -EIO   - i/o error.
+ *      -EIO   - i/o error.
  */
 static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino)
 {
        int extno, bitno, agno, sword, rc;
        struct metapage *amp = NULL, *bmp = NULL;
-       struct iag *aiagp = 0, *biagp = 0;
+       struct iag *aiagp = NULL, *biagp = NULL;
        u32 mask;
 
        /* check if this is the last free inode within the iag.
@@ -2126,7 +2108,7 @@ static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino)
         * allocated.  if so, update the free inode summary
         * map to reflect this.
         */
-       if (iagp->wmap[extno] == ONES) {
+       if (iagp->wmap[extno] == cpu_to_le32(ONES)) {
                sword = extno >> L2EXTSPERSUM;
                bitno = extno & (EXTSPERSUM - 1);
                iagp->inosmap[sword] |= cpu_to_le32(HIGHORDER >> bitno);
@@ -2148,7 +2130,7 @@ static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino)
                        imap->im_agctl[agno].inofree =
                            le32_to_cpu(iagp->inofreefwd);
                }
-               iagp->inofreefwd = iagp->inofreeback = -1;
+               iagp->inofreefwd = iagp->inofreeback = cpu_to_le32(-1);
        }
 
        /* update the free inode count at the iag, ag, inode
@@ -2191,24 +2173,24 @@ static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino)
  *             buffers.  under this approach, all required buffers are
  *             obtained before making any updates and are held until all
  *             updates are complete.
- *             
+ *
  * PRE CONDITION: Already have buffer lock on iagp.  Already have AG lock on
  *     this AG.  Must have read lock on imap inode.
  *
  * PARAMETERS:
- *      imap   - pointer to inode map control structure.
- *      iagp   - pointer to iag. 
- *      extno          - extent number.
+ *      imap   - pointer to inode map control structure.
+ *      iagp   - pointer to iag.
+ *      extno  - extent number.
  *
  * RETURN VALUES:
  *      0       - success.
  *      -ENOSPC        - insufficient disk resources.
- *      -EIO   - i/o error.
+ *      -EIO   - i/o error.
  */
 static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
 {
        int agno, iagno, fwd, back, freei = 0, sword, rc;
-       struct iag *aiagp = 0, *biagp = 0, *ciagp = 0;
+       struct iag *aiagp = NULL, *biagp = NULL, *ciagp = NULL;
        struct metapage *amp, *bmp, *cmp, *dmp;
        struct inode *ipimap;
        s64 blkno, hint;
@@ -2357,7 +2339,7 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
                        imap->im_agctl[agno].extfree =
                            le32_to_cpu(iagp->extfreefwd);
 
-               iagp->extfreefwd = iagp->extfreeback = -1;
+               iagp->extfreefwd = iagp->extfreeback = cpu_to_le32(-1);
        } else {
                /* if the iag has all free extents (newly allocated iag),
                 * add the iag to the ag free extent list.
@@ -2367,7 +2349,7 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
                                aiagp->extfreeback = cpu_to_le32(iagno);
 
                        iagp->extfreefwd = cpu_to_le32(fwd);
-                       iagp->extfreeback = -1;
+                       iagp->extfreeback = cpu_to_le32(-1);
                        imap->im_agctl[agno].extfree = iagno;
                }
        }
@@ -2381,7 +2363,7 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
 
                iagp->inofreefwd =
                    cpu_to_le32(imap->im_agctl[agno].inofree);
-               iagp->inofreeback = -1;
+               iagp->inofreeback = cpu_to_le32(-1);
                imap->im_agctl[agno].inofree = iagno;
        }
 
@@ -2451,34 +2433,34 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
 /*
  * NAME:        diNewIAG(imap,iagnop,agno)
  *
- * FUNCTION:           allocate a new iag for an allocation group.
- *             
- *             first tries to allocate the iag from the inode map 
- *             iagfree list:  
- *             if the list has free iags, the head of the list is removed 
+ * FUNCTION:   allocate a new iag for an allocation group.
+ *
+ *             first tries to allocate the iag from the inode map
+ *             iagfree list:
+ *             if the list has free iags, the head of the list is removed
  *             and returned to satisfy the request.
  *             if the inode map's iag free list is empty, the inode map
  *             is extended to hold a new iag. this new iag is initialized
  *             and returned to satisfy the request.
  *
  * PARAMETERS:
- *      imap   - pointer to inode map control structure.
- *      iagnop         - pointer to an iag number set with the number of the
+ *      imap   - pointer to inode map control structure.
+ *      iagnop - pointer to an iag number set with the number of the
  *               newly allocated iag upon successful return.
- *      agno   - allocation group number.
+ *      agno   - allocation group number.
  *     bpp     - Buffer pointer to be filled in with new IAG's buffer
  *
  * RETURN VALUES:
  *      0       - success.
  *      -ENOSPC        - insufficient disk resources.
- *      -EIO   - i/o error.
+ *      -EIO   - i/o error.
  *
- * serialization: 
+ * serialization:
  *     AG lock held on entry/exit;
  *     write lock on the map is held inside;
  *     read lock on the map is held on successful completion;
  *
- * note: new iag transaction: 
+ * note: new iag transaction:
  * . synchronously write iag;
  * . write log of xtree and inode  of imap;
  * . commit;
@@ -2513,7 +2495,7 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
        /* acquire the free iag lock */
        IAGFREE_LOCK(imap);
 
-       /* if there are any iags on the inode map free iag list, 
+       /* if there are any iags on the inode map free iag list,
         * allocate the iag from the head of the list.
         */
        if (imap->im_freeiag >= 0) {
@@ -2568,9 +2550,18 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
                        goto out;
                }
 
-               /* assign a buffer for the page */
-               mp = get_metapage(ipimap, xaddr, PSIZE, 1);
-               if (!mp) {
+               /*
+                * start transaction of update of the inode map
+                * addressing structure pointing to the new iag page;
+                */
+               tid = txBegin(sb, COMMIT_FORCE);
+               mutex_lock(&JFS_IP(ipimap)->commit_mutex);
+
+               /* update the inode map addressing structure to point to it */
+               if ((rc =
+                    xtInsert(tid, ipimap, 0, blkno, xlen, &xaddr, 0))) {
+                       txEnd(tid);
+                       mutex_unlock(&JFS_IP(ipimap)->commit_mutex);
                        /* Free the blocks allocated for the iag since it was
                         * not successfully added to the inode map
                         */
@@ -2579,6 +2570,29 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
                        /* release the inode map lock */
                        IWRITE_UNLOCK(ipimap);
 
+                       goto out;
+               }
+
+               /* update the inode map's inode to reflect the extension */
+               ipimap->i_size += PSIZE;
+               inode_add_bytes(ipimap, PSIZE);
+
+               /* assign a buffer for the page */
+               mp = get_metapage(ipimap, blkno, PSIZE, 0);
+               if (!mp) {
+                       /*
+                        * This is very unlikely since we just created the
+                        * extent, but let's try to handle it correctly
+                        */
+                       xtTruncate(tid, ipimap, ipimap->i_size - PSIZE,
+                                  COMMIT_PWMAP);
+
+                       txAbort(tid, 0);
+                       txEnd(tid);
+
+                       /* release the inode map lock */
+                       IWRITE_UNLOCK(ipimap);
+
                        rc = -EIO;
                        goto out;
                }
@@ -2587,9 +2601,9 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
                /* init the iag */
                memset(iagp, 0, sizeof(struct iag));
                iagp->iagnum = cpu_to_le32(iagno);
-               iagp->inofreefwd = iagp->inofreeback = -1;
-               iagp->extfreefwd = iagp->extfreeback = -1;
-               iagp->iagfree = -1;
+               iagp->inofreefwd = iagp->inofreeback = cpu_to_le32(-1);
+               iagp->extfreefwd = iagp->extfreeback = cpu_to_le32(-1);
+               iagp->iagfree = cpu_to_le32(-1);
                iagp->nfreeinos = 0;
                iagp->nfreeexts = cpu_to_le32(EXTSPERIAG);
 
@@ -2597,60 +2611,23 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
                 * summary map initialization handled by bzero).
                 */
                for (i = 0; i < SMAPSZ; i++)
-                       iagp->inosmap[i] = ONES;
-
-               flush_metapage(mp);
-#ifdef _STILL_TO_PORT
-               /* synchronously write the iag page */
-               if (bmWrite(bp)) {
-                       /* Free the blocks allocated for the iag since it was
-                        * not successfully added to the inode map
-                        */
-                       dbFree(ipimap, xaddr, (s64) xlen);
-
-                       /* release the inode map lock */
-                       IWRITE_UNLOCK(ipimap);
-
-                       rc = -EIO;
-                       goto out;
-               }
-
-               /* Now the iag is on disk */
+                       iagp->inosmap[i] = cpu_to_le32(ONES);
 
                /*
-                * start tyransaction of update of the inode map
-                * addressing structure pointing to the new iag page;
+                * Write and sync the metapage
                 */
-#endif                         /*  _STILL_TO_PORT */
-               tid = txBegin(sb, COMMIT_FORCE);
-
-               /* update the inode map addressing structure to point to it */
-               if ((rc =
-                    xtInsert(tid, ipimap, 0, blkno, xlen, &xaddr, 0))) {
-                       /* Free the blocks allocated for the iag since it was
-                        * not successfully added to the inode map
-                        */
-                       dbFree(ipimap, xaddr, (s64) xlen);
-
-                       /* release the inode map lock */
-                       IWRITE_UNLOCK(ipimap);
-
-                       goto out;
-               }
-
-               /* update the inode map's inode to reflect the extension */
-               ipimap->i_size += PSIZE;
-               ipimap->i_blocks += LBLK2PBLK(sb, xlen);
+               flush_metapage(mp);
 
                /*
-                * txCommit(COMMIT_FORCE) will synchronously write address 
-                * index pages and inode after commit in careful update order 
+                * txCommit(COMMIT_FORCE) will synchronously write address
+                * index pages and inode after commit in careful update order
                 * of address index pages (right to left, bottom up);
                 */
                iplist[0] = ipimap;
                rc = txCommit(tid, 1, &iplist[0], COMMIT_FORCE);
 
                txEnd(tid);
+               mutex_unlock(&JFS_IP(ipimap)->commit_mutex);
 
                duplicateIXtree(sb, blkno, xlen, &xaddr);
 
@@ -2684,7 +2661,7 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
 
        /* remove the iag from the iag free list */
        imap->im_freeiag = le32_to_cpu(iagp->iagfree);
-       iagp->iagfree = -1;
+       iagp->iagfree = cpu_to_le32(-1);
 
        /* set the return iag number and buffer pointer */
        *iagnop = iagno;
@@ -2702,11 +2679,11 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
  *
  * FUNCTION:    get the buffer for the specified iag within a fileset
  *             or aggregate inode map.
- *             
+ *
  * PARAMETERS:
- *      imap   - pointer to inode map control structure.
- *      iagno          - iag number.
- *      bpp    - point to buffer pointer to be filled in on successful
+ *      imap   - pointer to inode map control structure.
+ *      iagno  - iag number.
+ *      bpp    - point to buffer pointer to be filled in on successful
  *               exit.
  *
  * SERIALIZATION:
@@ -2716,7 +2693,7 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
  *
  * RETURN VALUES:
  *      0       - success.
- *      -EIO   - i/o error.
+ *      -EIO   - i/o error.
  */
 static int diIAGRead(struct inomap * imap, int iagno, struct metapage ** mpp)
 {
@@ -2742,8 +2719,8 @@ static int diIAGRead(struct inomap * imap, int iagno, struct metapage ** mpp)
  *             the specified bit position.
  *
  * PARAMETERS:
- *      word   - word to be examined.
- *      start          - starting bit position.
+ *      word   - word to be examined.
+ *      start  - starting bit position.
  *
  * RETURN VALUES:
  *      bit position of first free bit in the word or 32 if
@@ -2764,24 +2741,24 @@ static int diFindFree(u32 word, int start)
 
 /*
  * NAME:       diUpdatePMap()
- *                                                                    
- * FUNCTION: Update the persistent map in an IAG for the allocation or 
+ *
+ * FUNCTION: Update the persistent map in an IAG for the allocation or
  *     freeing of the specified inode.
- *                                                                    
+ *
  * PRE CONDITIONS: Working map has already been updated for allocate.
  *
  * PARAMETERS:
  *     ipimap  - Incore inode map inode
  *     inum    - Number of inode to mark in permanent map
- *     is_free - If TRUE indicates inode should be marked freed, otherwise
+ *     is_free - If 'true' indicates inode should be marked freed, otherwise
  *               indicates inode should be marked allocated.
  *
- * RETURN VALUES: 
+ * RETURN VALUES:
  *             0 for success
  */
 int
 diUpdatePMap(struct inode *ipimap,
-            unsigned long inum, boolean_t is_free, struct tblock * tblk)
+            unsigned long inum, bool is_free, struct tblock * tblk)
 {
        int rc;
        struct iag *iagp;
@@ -2791,6 +2768,7 @@ diUpdatePMap(struct inode *ipimap,
        u32 mask;
        struct jfs_log *log;
        int lsn, difft, diffp;
+       unsigned long flags;
 
        imap = JFS_IP(ipimap)->i_imap;
        /* get the iag number containing the inode */
@@ -2807,6 +2785,7 @@ diUpdatePMap(struct inode *ipimap,
        IREAD_UNLOCK(ipimap);
        if (rc)
                return (rc);
+       metapage_wait_for_io(mp);
        iagp = (struct iag *) mp->data;
        /* get the inode number and extent number of the inode within
         * the iag and the inode number within the extent.
@@ -2815,17 +2794,17 @@ diUpdatePMap(struct inode *ipimap,
        extno = ino >> L2INOSPEREXT;
        bitno = ino & (INOSPEREXT - 1);
        mask = HIGHORDER >> bitno;
-       /* 
+       /*
         * mark the inode free in persistent map:
         */
-       if (is_free == TRUE) {
+       if (is_free) {
                /* The inode should have been allocated both in working
                 * map and in persistent map;
                 * the inode will be freed from working map at the release
                 * of last reference release;
                 */
                if (!(le32_to_cpu(iagp->wmap[extno]) & mask)) {
-                       jfs_error(ipimap->i_sb, 
+                       jfs_error(ipimap->i_sb,
                                  "diUpdatePMap: inode %ld not marked as "
                                  "allocated in wmap!", inum);
                }
@@ -2866,6 +2845,7 @@ diUpdatePMap(struct inode *ipimap,
         */
        lsn = tblk->lsn;
        log = JFS_SBI(tblk->sb)->log;
+       LOGSYNC_LOCK(log, flags);
        if (mp->lsn != 0) {
                /* inherit older/smaller lsn */
                logdiff(difft, lsn, log);
@@ -2873,28 +2853,23 @@ diUpdatePMap(struct inode *ipimap,
                if (difft < diffp) {
                        mp->lsn = lsn;
                        /* move mp after tblock in logsync list */
-                       LOGSYNC_LOCK(log);
                        list_move(&mp->synclist, &tblk->synclist);
-                       LOGSYNC_UNLOCK(log);
                }
                /* inherit younger/larger clsn */
-               LOGSYNC_LOCK(log);
                assert(mp->clsn);
                logdiff(difft, tblk->clsn, log);
                logdiff(diffp, mp->clsn, log);
                if (difft > diffp)
                        mp->clsn = tblk->clsn;
-               LOGSYNC_UNLOCK(log);
        } else {
                mp->log = log;
                mp->lsn = lsn;
                /* insert mp after tblock in logsync list */
-               LOGSYNC_LOCK(log);
                log->count++;
                list_add(&mp->synclist, &tblk->synclist);
                mp->clsn = tblk->clsn;
-               LOGSYNC_UNLOCK(log);
        }
+       LOGSYNC_UNLOCK(log, flags);
        write_metapage(mp);
        return (0);
 }
@@ -2903,15 +2878,15 @@ diUpdatePMap(struct inode *ipimap,
  *     diExtendFS()
  *
  * function: update imap for extendfs();
- * 
- * note: AG size has been increased s.t. each k old contiguous AGs are 
+ *
+ * note: AG size has been increased s.t. each k old contiguous AGs are
  * coalesced into a new AG;
  */
 int diExtendFS(struct inode *ipimap, struct inode *ipbmap)
 {
        int rc, rcx = 0;
        struct inomap *imap = JFS_IP(ipimap)->i_imap;
-       struct iag *iagp = 0, *hiagp = 0;
+       struct iag *iagp = NULL, *hiagp = NULL;
        struct bmap *mp = JFS_SBI(ipbmap->i_sb)->bmap;
        struct metapage *bp, *hbp;
        int i, n, head;
@@ -2923,7 +2898,7 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap)
                   atomic_read(&imap->im_numfree));
 
        /*
-        *      reconstruct imap 
+        *      reconstruct imap
         *
         * coalesce contiguous k (newAGSize/oldAGSize) AGs;
         * i.e., (AGi, ..., AGj) where i = k*n and j = k*(n+1) - 1 to AGn;
@@ -2932,8 +2907,8 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap)
 
        /* init per AG control information im_agctl[] */
        for (i = 0; i < MAXAG; i++) {
-               imap->im_agctl[i].inofree = -1; /* free inode list */
-               imap->im_agctl[i].extfree = -1; /* free extent list */
+               imap->im_agctl[i].inofree = -1;
+               imap->im_agctl[i].extfree = -1;
                imap->im_agctl[i].numinos = 0;  /* number of backed inodes */
                imap->im_agctl[i].numfree = 0;  /* number of free backed inodes */
        }
@@ -2957,7 +2932,7 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap)
                }
 
                /* leave free iag in the free iag list */
-               if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) {  
+               if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) {
                        release_metapage(bp);
                        continue;
                }
@@ -2978,18 +2953,18 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap)
 
                /* if any backed free inodes, insert at AG free inode list */
                if ((int) le32_to_cpu(iagp->nfreeinos) > 0) {
-                       if ((head = imap->im_agctl[n].inofree) == -1)
-                               iagp->inofreefwd = iagp->inofreeback = -1;
-                       else {
+                       if ((head = imap->im_agctl[n].inofree) == -1) {
+                               iagp->inofreefwd = cpu_to_le32(-1);
+                               iagp->inofreeback = cpu_to_le32(-1);
+                       } else {
                                if ((rc = diIAGRead(imap, head, &hbp))) {
                                        rcx = rc;
                                        goto nextiag;
                                }
                                hiagp = (struct iag *) hbp->data;
-                               hiagp->inofreeback =
-                                   le32_to_cpu(iagp->iagnum);
+                               hiagp->inofreeback = iagp->iagnum;
                                iagp->inofreefwd = cpu_to_le32(head);
-                               iagp->inofreeback = -1;
+                               iagp->inofreeback = cpu_to_le32(-1);
                                write_metapage(hbp);
                        }
 
@@ -3004,9 +2979,10 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap)
 
                /* if any free extents, insert at AG free extent list */
                if (le32_to_cpu(iagp->nfreeexts) > 0) {
-                       if ((head = imap->im_agctl[n].extfree) == -1)
-                               iagp->extfreefwd = iagp->extfreeback = -1;
-                       else {
+                       if ((head = imap->im_agctl[n].extfree) == -1) {
+                               iagp->extfreefwd = cpu_to_le32(-1);
+                               iagp->extfreeback = cpu_to_le32(-1);
+                       } else {
                                if ((rc = diIAGRead(imap, head, &hbp))) {
                                        rcx = rc;
                                        goto nextiag;
@@ -3014,7 +2990,7 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap)
                                hiagp = (struct iag *) hbp->data;
                                hiagp->extfreeback = iagp->iagnum;
                                iagp->extfreefwd = cpu_to_le32(head);
-                               iagp->extfreeback = -1;
+                               iagp->extfreeback = cpu_to_le32(-1);
                                write_metapage(hbp);
                        }
 
@@ -3061,7 +3037,7 @@ static void duplicateIXtree(struct super_block *sb, s64 blkno,
                if (readSuper(sb, &bh))
                        return;
                j_sb = (struct jfs_superblock *)bh->b_data;
-               j_sb->s_flag |= JFS_BAD_SAIT;
+               j_sb->s_flag |= cpu_to_le32(JFS_BAD_SAIT);
 
                mark_buffer_dirty(bh);
                sync_dirty_buffer(bh);
@@ -3080,7 +3056,7 @@ static void duplicateIXtree(struct super_block *sb, s64 blkno,
        }
        /* update the inode map's inode to reflect the extension */
        ip->i_size += PSIZE;
-       ip->i_blocks += LBLK2PBLK(sb, xlen);
+       inode_add_bytes(ip, PSIZE);
        txCommit(tid, 1, &ip, COMMIT_FORCE);
       cleanup:
        txEnd(tid);
@@ -3099,6 +3075,7 @@ static void duplicateIXtree(struct super_block *sb, s64 blkno,
 static int copy_from_dinode(struct dinode * dip, struct inode *ip)
 {
        struct jfs_inode_info *jfs_ip = JFS_IP(ip);
+       struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
        uid_t uid;
        gid_t gid;
 
@@ -3106,14 +3083,38 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip)
        jfs_ip->mode2 = le32_to_cpu(dip->di_mode);
 
        ip->i_mode = le32_to_cpu(dip->di_mode) & 0xffff;
+       if (sbi->umask != -1) {
+               ip->i_mode = (ip->i_mode & ~0777) | (0777 & ~sbi->umask);
+               /* For directories, add x permission if r is allowed by umask */
+               if (S_ISDIR(ip->i_mode)) {
+                       if (ip->i_mode & 0400)
+                               ip->i_mode |= 0100;
+                       if (ip->i_mode & 0040)
+                               ip->i_mode |= 0010;
+                       if (ip->i_mode & 0004)
+                               ip->i_mode |= 0001;
+               }
+       }
        ip->i_nlink = le32_to_cpu(dip->di_nlink);
 
        uid = le32_to_cpu(dip->di_uid);
        gid = le32_to_cpu(dip->di_gid);
-       ip->i_uid = INOXID_UID(uid, gid);
-       ip->i_gid = INOXID_GID(uid, gid);
-       ip->i_xid = INOXID_XID(uid, gid, 0);
-       
+       ip->i_tag = INOTAG_TAG(DX_TAG(ip), uid, gid, 0);
+
+       jfs_ip->saved_uid = INOTAG_UID(DX_TAG(ip), uid, gid);
+       if (sbi->uid == -1)
+               ip->i_uid = jfs_ip->saved_uid;
+       else {
+               ip->i_uid = sbi->uid;
+       }
+
+       jfs_ip->saved_gid = INOTAG_GID(DX_TAG(ip), uid, gid);
+       if (sbi->gid == -1)
+               ip->i_gid = jfs_ip->saved_gid;
+       else {
+               ip->i_gid = sbi->gid;
+       }
+
        ip->i_size = le64_to_cpu(dip->di_size);
        ip->i_atime.tv_sec = le32_to_cpu(dip->di_atime.tv_sec);
        ip->i_atime.tv_nsec = le32_to_cpu(dip->di_atime.tv_nsec);
@@ -3121,7 +3122,6 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip)
        ip->i_mtime.tv_nsec = le32_to_cpu(dip->di_mtime.tv_nsec);
        ip->i_ctime.tv_sec = le32_to_cpu(dip->di_ctime.tv_sec);
        ip->i_ctime.tv_nsec = le32_to_cpu(dip->di_ctime.tv_nsec);
-       ip->i_blksize = ip->i_sb->s_blocksize;
        ip->i_blocks = LBLK2PBLK(ip->i_sb, le64_to_cpu(dip->di_nblocks));
        ip->i_generation = le32_to_cpu(dip->di_gen);
 
@@ -3164,26 +3164,31 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip)
 static void copy_to_dinode(struct dinode * dip, struct inode *ip)
 {
        struct jfs_inode_info *jfs_ip = JFS_IP(ip);
-       uid_t uid;
-       gid_t gid;
+       struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
 
        dip->di_fileset = cpu_to_le32(jfs_ip->fileset);
-       dip->di_inostamp = cpu_to_le32(JFS_SBI(ip->i_sb)->inostamp);
+       dip->di_inostamp = cpu_to_le32(sbi->inostamp);
        dip->di_number = cpu_to_le32(ip->i_ino);
        dip->di_gen = cpu_to_le32(ip->i_generation);
        dip->di_size = cpu_to_le64(ip->i_size);
        dip->di_nblocks = cpu_to_le64(PBLK2LBLK(ip->i_sb, ip->i_blocks));
        dip->di_nlink = cpu_to_le32(ip->i_nlink);
 
-       uid = XIDINO_UID(ip->i_uid, ip->i_xid);
-       gid = XIDINO_GID(ip->i_gid, ip->i_xid);
-       dip->di_uid = cpu_to_le32(uid);
-       dip->di_gid = cpu_to_le32(gid);
+       dip->di_uid = cpu_to_le32(TAGINO_UID(DX_TAG(ip),
+               (sbi->uid == -1) ? ip->i_uid : jfs_ip->saved_uid, ip->i_tag));
+       dip->di_gid = cpu_to_le32(TAGINO_GID(DX_TAG(ip),
+               (sbi->gid == -1) ? ip->i_gid : jfs_ip->saved_gid, ip->i_tag));
+
        /*
         * mode2 is only needed for storing the higher order bits.
         * Trust i_mode for the lower order ones
         */
-       dip->di_mode = cpu_to_le32((jfs_ip->mode2 & 0xffff0000) | ip->i_mode);
+       if (sbi->umask == -1)
+               dip->di_mode = cpu_to_le32((jfs_ip->mode2 & 0xffff0000) |
+                                          ip->i_mode);
+       else /* Leave the original permissions alone */
+               dip->di_mode = cpu_to_le32(jfs_ip->mode2);
+
        dip->di_atime.tv_sec = cpu_to_le32(ip->i_atime.tv_sec);
        dip->di_atime.tv_nsec = cpu_to_le32(ip->i_atime.tv_nsec);
        dip->di_ctime.tv_sec = cpu_to_le32(ip->i_ctime.tv_sec);
@@ -3200,84 +3205,3 @@ static void copy_to_dinode(struct dinode * dip, struct inode *ip)
        if (S_ISCHR(ip->i_mode) || S_ISBLK(ip->i_mode))
                dip->di_rdev = cpu_to_le32(jfs_ip->dev);
 }
-
-#ifdef _JFS_DEBUG_IMAP
-/*
- *     DBGdiInit()
- */
-static void *DBGdiInit(struct inomap * imap)
-{
-       u32 *dimap;
-       int size;
-       size = 64 * 1024;
-       if ((dimap = (u32 *) xmalloc(size, L2PSIZE, kernel_heap)) == NULL)
-               assert(0);
-       bzero((void *) dimap, size);
-       imap->im_DBGdimap = dimap;
-}
-
-/*
- *     DBGdiAlloc()
- */
-static void DBGdiAlloc(struct inomap * imap, ino_t ino)
-{
-       u32 *dimap = imap->im_DBGdimap;
-       int w, b;
-       u32 m;
-       w = ino >> 5;
-       b = ino & 31;
-       m = 0x80000000 >> b;
-       assert(w < 64 * 256);
-       if (dimap[w] & m) {
-               printk("DEBUG diAlloc: duplicate alloc ino:0x%x\n", ino);
-       }
-       dimap[w] |= m;
-}
-
-/*
- *     DBGdiFree()
- */
-static void DBGdiFree(struct inomap * imap, ino_t ino)
-{
-       u32 *dimap = imap->im_DBGdimap;
-       int w, b;
-       u32 m;
-       w = ino >> 5;
-       b = ino & 31;
-       m = 0x80000000 >> b;
-       assert(w < 64 * 256);
-       if ((dimap[w] & m) == 0) {
-               printk("DEBUG diFree: duplicate free ino:0x%x\n", ino);
-       }
-       dimap[w] &= ~m;
-}
-
-static void dump_cp(struct inomap * ipimap, char *function, int line)
-{
-       printk("\n* ********* *\nControl Page %s %d\n", function, line);
-       printk("FreeIAG %d\tNextIAG %d\n", ipimap->im_freeiag,
-              ipimap->im_nextiag);
-       printk("NumInos %d\tNumFree %d\n",
-              atomic_read(&ipimap->im_numinos),
-              atomic_read(&ipimap->im_numfree));
-       printk("AG InoFree %d\tAG ExtFree %d\n",
-              ipimap->im_agctl[0].inofree, ipimap->im_agctl[0].extfree);
-       printk("AG NumInos %d\tAG NumFree %d\n",
-              ipimap->im_agctl[0].numinos, ipimap->im_agctl[0].numfree);
-}
-
-static void dump_iag(struct iag * iag, char *function, int line)
-{
-       printk("\n* ********* *\nIAG %s %d\n", function, line);
-       printk("IagNum %d\tIAG Free %d\n", le32_to_cpu(iag->iagnum),
-              le32_to_cpu(iag->iagfree));
-       printk("InoFreeFwd %d\tInoFreeBack %d\n",
-              le32_to_cpu(iag->inofreefwd),
-              le32_to_cpu(iag->inofreeback));
-       printk("ExtFreeFwd %d\tExtFreeBack %d\n",
-              le32_to_cpu(iag->extfreefwd),
-              le32_to_cpu(iag->extfreeback));
-       printk("NFreeInos %d\tNFreeExts %d\n", le32_to_cpu(iag->nfreeinos),
-              le32_to_cpu(iag->nfreeexts));
-}
-#endif                         /* _JFS_DEBUG_IMAP */