nfsd4: use list_move in move_to_confirmed
[safe/jmp/linux-2.6] / fs / jfs / jfs_imap.c
index 31b4aa1..f8332dc 100644 (file)
@@ -3,16 +3,16 @@
  *
  *   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
  */
 
@@ -45,6 +45,7 @@
 #include <linux/buffer_head.h>
 #include <linux/pagemap.h>
 #include <linux/quotaops.h>
+#include <linux/slab.h>
 
 #include "jfs_incore.h"
 #include "jfs_inode.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])
+#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 *);
@@ -93,21 +88,21 @@ static int copy_from_dinode(struct dinode *, struct inode *);
 static void copy_to_dinode(struct dinode *, struct inode *);
 
 /*
- * NAME:        diMount()
+ * NAME:       diMount()
  *
- * FUNCTION:    initialize the incore inode map control structures for
+ * FUNCTION:   initialize the incore inode map control structures for
  *             a fileset or aggregate init time.
  *
- *              the inode map's control structure (dinomap) is 
- *              brought in from disk and placed in virtual memory.
+ *             the inode map's control structure (dinomap) is
+ *             brought in from disk and placed in virtual memory.
  *
  * PARAMETERS:
- *      ipimap  - pointer to inode map inode for the aggregate or fileset.
+ *     ipimap  - pointer to inode map inode for the aggregate or fileset.
  *
  * RETURN VALUES:
- *      0       - success
- *      -ENOMEM  - insufficient free virtual memory.
- *      -EIO   - i/o error.
+ *     0       - success
+ *     -ENOMEM - insufficient free virtual memory.
+ *     -EIO    - i/o error.
  */
 int diMount(struct inode *ipimap)
 {
@@ -120,7 +115,7 @@ int diMount(struct inode *ipimap)
         * 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;
@@ -180,18 +175,18 @@ int diMount(struct inode *ipimap)
 
 
 /*
- * NAME:        diUnmount()
+ * NAME:       diUnmount()
  *
- * FUNCTION:    write to disk the incore inode map control structures for
+ * FUNCTION:   write to disk the incore inode map control structures for
  *             a fileset or aggregate at unmount time.
  *
  * PARAMETERS:
- *      ipimap  - pointer to inode map inode for the aggregate or fileset.
+ *     ipimap  - pointer to inode map inode for the aggregate or fileset.
  *
  * RETURN VALUES:
- *      0       - success
- *      -ENOMEM  - insufficient free virtual memory.
- *      -EIO   - i/o error.
+ *     0       - success
+ *     -ENOMEM - insufficient free virtual memory.
+ *     -EIO    - i/o error.
  */
 int diUnmount(struct inode *ipimap, int mounterror)
 {
@@ -274,22 +269,22 @@ int diSync(struct inode *ipimap)
 
 
 /*
- * NAME:        diRead()
+ * NAME:       diRead()
  *
- * FUNCTION:    initialize an incore inode from disk.
+ * FUNCTION:   initialize an incore inode from disk.
  *
  *             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
- *             require special handling since much of the file system
+ *             require special handling since much of the file system
  *             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
@@ -298,13 +293,13 @@ int diSync(struct inode *ipimap)
  *             incore inode.
  *
  * PARAMETERS:
- *      ip  -  pointer to incore inode to be initialized from disk.
+ *     ip      -  pointer to incore inode to be initialized from disk.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO   - i/o error.
- *      -ENOMEM        - insufficient memory
- *      
+ *     0       - success
+ *     -EIO    - i/o error.
+ *     -ENOMEM - insufficient memory
+ *
  */
 int diRead(struct inode *ip)
 {
@@ -318,7 +313,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);
@@ -331,7 +326,7 @@ int diRead(struct inode *ip)
 
        /* read the iag */
        imap = JFS_IP(ipimap)->i_imap;
-       IREAD_LOCK(ipimap);
+       IREAD_LOCK(ipimap, RDWRLOCK_IMAP);
        rc = diIAGRead(imap, iagno, &mp);
        IREAD_UNLOCK(ipimap);
        if (rc) {
@@ -381,12 +376,12 @@ int diRead(struct inode *ip)
 
        /* read the page of disk inode */
        mp = read_metapage(ipimap, pageno << sbi->l2nbperpage, PSIZE, 1);
-       if (mp == 0) {
+       if (!mp) {
                jfs_err("diRead: read_metapage failed");
                return -EIO;
        }
 
-       /* locate the the disk inode requested */
+       /* locate the disk inode requested */
        dp = (struct dinode *) mp->data;
        dp += rel_inode;
 
@@ -410,26 +405,26 @@ int diRead(struct inode *ip)
 
 
 /*
- * NAME:        diReadSpecial()
+ * NAME:       diReadSpecial()
  *
- * FUNCTION:    initialize a 'special' inode from disk.
+ * FUNCTION:   initialize a 'special' inode from disk.
  *
  *             this routines handles aggregate level inodes.  The
  *             inode cache cannot differentiate between the
  *             aggregate inodes and the filesystem inodes, so we
  *             handle these here.  We don't actually use the aggregate
- *             inode map, since these inodes are at a fixed location
+ *             inode map, since these inodes are at a fixed location
  *             and in some cases the aggregate inode map isn't initialized
  *             yet.
  *
  * PARAMETERS:
- *      sb - filesystem superblock
+ *     sb - filesystem superblock
  *     inum - aggregate inode number
  *     secondary - 1 if secondary aggregate inode table
  *
  * RETURN VALUES:
- *      new inode      - success
- *      NULL           - i/o error.
+ *     new inode       - success
+ *     NULL            - i/o error.
  */
 struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
 {
@@ -496,18 +491,24 @@ 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);
+       /*
+        * __mark_inode_dirty expects inodes to be hashed.  Since we don't
+        * want special inodes in the fileset inode space, we make them
+        * appear hashed, but do not put on any lists.  hlist_del()
+        * will work fine and require no locking.
+        */
+       ip->i_hash.pprev = &ip->i_hash.next;
 
        return (ip);
 }
 
 /*
- * NAME:        diWriteSpecial()
+ * NAME:       diWriteSpecial()
  *
- * FUNCTION:    Write the special inode to disk
+ * FUNCTION:   Write the special inode to disk
  *
  * PARAMETERS:
- *      ip - special inode
+ *     ip - special inode
  *     secondary - 1 if secondary aggregate inode table
  *
  * RETURN VALUES: none
@@ -554,9 +555,9 @@ void diWriteSpecial(struct inode *ip, int secondary)
 }
 
 /*
- * NAME:        diFreeSpecial()
+ * NAME:       diFreeSpecial()
  *
- * FUNCTION:    Free allocated space for special inode
+ * FUNCTION:   Free allocated space for special inode
  */
 void diFreeSpecial(struct inode *ip)
 {
@@ -572,9 +573,9 @@ void diFreeSpecial(struct inode *ip)
 
 
 /*
- * NAME:        diWrite()
+ * NAME:       diWrite()
  *
- * FUNCTION:    write the on-disk inode portion of the in-memory inode
+ * FUNCTION:   write the on-disk inode portion of the in-memory inode
  *             to its corresponding on-disk inode.
  *
  *             on entry, the specifed incore inode should itself
@@ -586,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.
+ *     ip  -  pointer to incore inode to be written to the inode extent.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO   - i/o error.
+ *     0       - success
+ *     -EIO    - i/o error.
  */
 int diWrite(tid_t tid, struct inode *ip)
 {
@@ -606,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;
@@ -654,7 +655,7 @@ int diWrite(tid_t tid, struct inode *ip)
        /* read the page of disk inode */
       retry:
        mp = read_metapage(ipimap, pageno << sbi->l2nbperpage, PSIZE, 1);
-       if (mp == 0)
+       if (!mp)
                return -EIO;
 
        /* get the pointer to the disk inode */
@@ -676,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;
         */
@@ -730,7 +731,7 @@ int diWrite(tid_t tid, struct inode *ip)
        ilinelock = (struct linelock *) & tlck->lock;
 
        /*
-        *      regular file: 16 byte (XAD slot) granularity
+        *      regular file: 16 byte (XAD slot) granularity
         */
        if (type & tlckXTREE) {
                xtpage_t *p, *xp;
@@ -755,7 +756,7 @@ int diWrite(tid_t tid, struct inode *ip)
                                xad->flag &= ~(XAD_NEW | XAD_EXTENDED);
        }
        /*
-        *      directory: 32 byte (directory entry slot) granularity
+        *      directory: 32 byte (directory entry slot) granularity
         */
        else if (type & tlckDTREE) {
                dtpage_t *p, *xp;
@@ -800,9 +801,8 @@ int diWrite(tid_t tid, struct inode *ip)
        }
 
        /*
-        *      lock/copy inode base: 128 byte slot granularity
+        *      lock/copy inode base: 128 byte slot granularity
         */
-// baseDinode:
        lv = & dilinelock->lv[dilinelock->index];
        lv->offset = dioffset >> L2INODESLOTSIZE;
        copy_to_dinode(dp, ip);
@@ -813,18 +813,7 @@ int diWrite(tid_t tid, struct inode *ip)
                lv->length = 1;
        dilinelock->index++;
 
-#ifdef _JFS_FASTDASD
-       /*
-        * We aren't logging changes to the DASD used in directory inodes,
-        * but we need to write them to disk.  If we don't unmount cleanly,
-        * mount will recalculate the DASD used.
-        */
-       if (S_ISDIR(ip->i_mode)
-           && (ip->i_ipmnt->i_mntflag & JFS_DASD_ENABLED))
-               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);
@@ -834,15 +823,15 @@ int diWrite(tid_t tid, struct inode *ip)
 
 
 /*
- * NAME:        diFree(ip)
+ * NAME:       diFree(ip)
  *
- * FUNCTION:    free a specified inode from the inode working map
+ * FUNCTION:   free a specified inode from the inode working map
  *             for a fileset or aggregate.
  *
  *             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
@@ -865,11 +854,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.
+ *     0       - success
+ *     -EIO    - i/o error.
  */
 int diFree(struct inode *ip)
 {
@@ -898,11 +887,12 @@ 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) {
-               dump_mem("imap", imap, 32);
+               print_hex_dump(KERN_ERR, "imap: ", DUMP_PREFIX_ADDRESS, 16, 4,
+                              imap, 32, 0);
                jfs_error(ip->i_sb,
                          "diFree: inum = %d, iagno = %d, nextiag = %d",
                          (uint) inum, iagno, imap->im_nextiag);
@@ -920,7 +910,7 @@ int diFree(struct inode *ip)
        /* Obtain read lock in imap inode.  Don't release it until we have
         * read all of the IAG's that we are going to.
         */
-       IREAD_LOCK(ipimap);
+       IREAD_LOCK(ipimap, RDWRLOCK_IMAP);
 
        /* read the iag.
         */
@@ -964,8 +954,8 @@ int diFree(struct inode *ip)
                return -EIO;
        }
        /*
-        *      inode extent still has some inodes or below low water mark:
-        *      keep the inode extent;
+        *      inode extent still has some inodes or below low water mark:
+        *      keep the inode extent;
         */
        if (bitmap ||
            imap->im_agctl[agno].numfree < 96 ||
@@ -1013,7 +1003,7 @@ int diFree(struct inode *ip)
 
                /* 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] == cpu_to_le32(ONES)) {
@@ -1030,8 +1020,7 @@ int diFree(struct inode *ip)
                /* update the free inode counts at the iag, ag and
                 * map level.
                 */
-               iagp->nfreeinos =
-                   cpu_to_le32(le32_to_cpu(iagp->nfreeinos) + 1);
+               le32_add_cpu(&iagp->nfreeinos, 1);
                imap->im_agctl[agno].numfree += 1;
                atomic_inc(&imap->im_numfree);
 
@@ -1047,12 +1036,12 @@ int diFree(struct inode *ip)
 
 
        /*
-        *      inode extent has become free and above low water mark:
-        *      free the inode extent;
+        *      inode extent has become free and above low water mark:
+        *      free the inode extent;
         */
 
        /*
-        *      prepare to update iag list(s) (careful update step 1)
+        *      prepare to update iag list(s) (careful update step 1)
         */
        amp = bmp = cmp = dmp = NULL;
        fwd = back = -1;
@@ -1152,7 +1141,7 @@ int diFree(struct inode *ip)
        invalidate_pxd_metapages(ip, freepxd);
 
        /*
-        *      update iag list(s) (careful update step 2)
+        *      update iag list(s) (careful update step 2)
         */
        /* add the iag to the ag extent free list if this is the
         * first free extent for the iag.
@@ -1204,9 +1193,9 @@ int diFree(struct inode *ip)
                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) {
@@ -1218,7 +1207,7 @@ int diFree(struct inode *ip)
 
        /* 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;
@@ -1230,9 +1219,8 @@ int diFree(struct inode *ip)
        /* update the number of free inodes and number of free extents
         * for the iag.
         */
-       iagp->nfreeinos = cpu_to_le32(le32_to_cpu(iagp->nfreeinos) -
-                                     (INOSPEREXT - 1));
-       iagp->nfreeexts = cpu_to_le32(le32_to_cpu(iagp->nfreeexts) + 1);
+       le32_add_cpu(&iagp->nfreeinos, -(INOSPEREXT - 1));
+       le32_add_cpu(&iagp->nfreeexts, 1);
 
        /* update the number of free inodes and backed inodes
         * at the ag and inode map level.
@@ -1255,17 +1243,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);
-       down(&JFS_IP(ipimap)->commit_sem);
+       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;
@@ -1284,8 +1272,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;
@@ -1294,7 +1282,7 @@ int diFree(struct inode *ip)
        rc = txCommit(tid, 1, &iplist[0], COMMIT_FORCE);
 
        txEnd(tid);
-       up(&JFS_IP(ipimap)->commit_sem);
+       mutex_unlock(&JFS_IP(ipimap)->commit_mutex);
 
        /* unlock the AG inode map information */
        AG_UNLOCK(imap, agno);
@@ -1338,22 +1326,22 @@ diInitInode(struct inode *ip, int iagno, int ino, int extno, struct iag * iagp)
 
 
 /*
- * NAME:        diAlloc(pip,dir,ip)
+ * 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.
+ *     0       - success.
+ *     -ENOSPC - insufficient disk resources.
+ *     -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;
@@ -1372,10 +1360,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;
@@ -1407,7 +1395,7 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
        inum = pip->i_ino + 1;
        ino = inum & (INOSPERIAG - 1);
 
-       /* back off the the hint if it is outside of the iag */
+       /* back off the hint if it is outside of the iag */
        if (ino == 0)
                inum = pip->i_ino;
 
@@ -1415,7 +1403,7 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
        AG_LOCK(imap, agno);
 
        /* Get read lock on imap inode */
-       IREAD_LOCK(ipimap);
+       IREAD_LOCK(ipimap, RDWRLOCK_IMAP);
 
        /* get the iag number and read the iag */
        iagno = INOTOIAG(inum);
@@ -1433,9 +1421,9 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
        addext = (imap->im_agctl[agno].numfree < 32 && iagp->nfreeexts);
 
        /*
-        *      try to allocate from the IAG
+        *      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) {
@@ -1490,7 +1478,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,
@@ -1533,7 +1521,7 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
                                        jfs_error(ip->i_sb,
                                                  "diAlloc: can't find free bit "
                                                  "in wmap");
-                                       return EIO;
+                                       return -EIO;
                                }
 
                                /* determine the inode number within the
@@ -1633,15 +1621,15 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
 
 
 /*
- * NAME:        diAllocAG(imap,agno,dir,ip)
+ * NAME:       diAllocAG(imap,agno,dir,ip)
  *
- * FUNCTION:    allocate a disk inode from the allocation group.
+ * FUNCTION:   allocate a disk inode from the allocation group.
  *
  *             this routine first determines if a new extent of free
  *             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.
@@ -1649,24 +1637,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.
+ *     0       - success.
+ *     -ENOSPC - insufficient disk resources.
+ *     -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;
@@ -1682,7 +1670,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));
@@ -1709,9 +1697,9 @@ diAllocAG(struct inomap * imap, int agno, boolean_t dir, struct inode *ip)
 
 
 /*
- * NAME:        diAllocAny(imap,agno,dir,iap)
+ * NAME:       diAllocAny(imap,agno,dir,iap)
  *
- * FUNCTION:    allocate a disk inode from any other allocation group.
+ * FUNCTION:   allocate a disk inode from any other allocation group.
  *
  *             this routine is called when an allocation attempt within
  *             the primary allocation group has failed. if attempts to
@@ -1719,26 +1707,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.
+ *     0       - success.
+ *     -ENOSPC - insufficient disk resources.
+ *     -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++) {
@@ -1772,29 +1760,29 @@ diAllocAny(struct inomap * imap, int agno, boolean_t dir, struct inode *ip)
 
 
 /*
- * NAME:        diAllocIno(imap,agno,ip)
+ * NAME:       diAllocIno(imap,agno,ip)
  *
- * FUNCTION:    allocate a disk inode from the allocation group's free
+ * FUNCTION:   allocate a disk inode from the allocation group's free
  *             inode list, returning an error if this free list is
  *             empty (i.e. no iags on the list).
  *
  *             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.
+ *     0       - success.
+ *     -ENOSPC - insufficient disk resources.
+ *     -EIO    - i/o error.
  */
 static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
 {
@@ -1808,7 +1796,7 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
                return -ENOSPC;
 
        /* obtain read lock on imap inode */
-       IREAD_LOCK(imap->im_ipimap);
+       IREAD_LOCK(imap->im_ipimap, RDWRLOCK_IMAP);
 
        /* read the iag at the head of the list.
         */
@@ -1867,7 +1855,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;
 
@@ -1890,19 +1878,19 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
 
 
 /*
- * NAME:        diAllocExt(imap,agno,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
@@ -1910,16 +1898,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.
+ *     0       - success.
+ *     -ENOSPC - insufficient disk resources.
+ *     -EIO    - i/o error.
  */
 static int diAllocExt(struct inomap * imap, int agno, struct inode *ip)
 {
@@ -1946,7 +1934,7 @@ static int diAllocExt(struct inomap * imap, int agno, struct inode *ip)
        } else {
                /* read the iag.
                 */
-               IREAD_LOCK(imap->im_ipimap);
+               IREAD_LOCK(imap->im_ipimap, RDWRLOCK_IMAP);
                if ((rc = diIAGRead(imap, iagno, &mp))) {
                        IREAD_UNLOCK(imap->im_ipimap);
                        jfs_error(ip->i_sb, "diAllocExt: error reading iag");
@@ -2010,9 +1998,9 @@ static int diAllocExt(struct inomap * imap, int agno, struct inode *ip)
 
 
 /*
- * NAME:        diAllocBit(imap,iagp,ino)
+ * 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.
@@ -2025,19 +2013,19 @@ 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.
+ *     0       - success.
+ *     -ENOSPC - insufficient disk resources.
+ *     -EIO    - i/o error.
  */
 static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino)
 {
@@ -2135,7 +2123,7 @@ static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino)
        /* update the free inode count at the iag, ag, inode
         * map levels.
         */
-       iagp->nfreeinos = cpu_to_le32(le32_to_cpu(iagp->nfreeinos) - 1);
+       le32_add_cpu(&iagp->nfreeinos, -1);
        imap->im_agctl[agno].numfree -= 1;
        atomic_dec(&imap->im_numfree);
 
@@ -2144,11 +2132,11 @@ static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino)
 
 
 /*
- * NAME:        diNewExt(imap,iagp,extno)
+ * NAME:       diNewExt(imap,iagp,extno)
  *
- * FUNCTION:    initialize a new extent of inodes for an iag, allocating
- *             the first inode of the extent for use for the current
- *             allocation request.
+ * FUNCTION:   initialize a new extent of inodes for an iag, allocating
+ *             the first inode of the extent for use for the current
+ *             allocation request.
  *
  *             disk resources are allocated for the new extent of inodes
  *             and the inodes themselves are initialized to reflect their
@@ -2172,19 +2160,19 @@ 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.
+ *     0       - success.
+ *     -ENOSPC - insufficient disk resources.
+ *     -EIO    - i/o error.
  */
 static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
 {
@@ -2389,9 +2377,8 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
        /* update the free inode and free extent counts for the
         * iag.
         */
-       iagp->nfreeinos = cpu_to_le32(le32_to_cpu(iagp->nfreeinos) +
-                                     (INOSPEREXT - 1));
-       iagp->nfreeexts = cpu_to_le32(le32_to_cpu(iagp->nfreeexts) - 1);
+       le32_add_cpu(&iagp->nfreeinos, (INOSPEREXT - 1));
+       le32_add_cpu(&iagp->nfreeexts, -1);
 
        /* update the free and backed inode counts for the ag.
         */
@@ -2430,38 +2417,38 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
 
 
 /*
- * NAME:        diNewIAG(imap,iagnop,agno)
+ * NAME:       diNewIAG(imap,iagnop,agno)
+ *
+ * FUNCTION:   allocate a new iag for an allocation group.
  *
- * 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 
+ *             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.
+ *     0       - success.
+ *     -ENOSPC - insufficient disk resources.
+ *     -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;
+ * . write log of xtree and inode of imap;
  * . commit;
  * . synchronous write of xtree (right to left, bottom to top);
  * . at start of logredo(): init in-memory imap with one additional iag page;
@@ -2481,9 +2468,6 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
        s64 xaddr = 0;
        s64 blkno;
        tid_t tid;
-#ifdef _STILL_TO_PORT
-       xad_t xad;
-#endif                         /*  _STILL_TO_PORT */
        struct inode *iplist[1];
 
        /* pick up pointers to the inode map and mount inodes */
@@ -2494,7 +2478,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) {
@@ -2509,7 +2493,7 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
                 */
 
                /* acquire inode map lock */
-               IWRITE_LOCK(ipimap);
+               IWRITE_LOCK(ipimap, RDWRLOCK_IMAP);
 
                if (ipimap->i_size >> L2PSIZE != imap->im_nextiag + 1) {
                        IWRITE_UNLOCK(ipimap);
@@ -2554,13 +2538,13 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
                 * addressing structure pointing to the new iag page;
                 */
                tid = txBegin(sb, COMMIT_FORCE);
-               down(&JFS_IP(ipimap)->commit_sem);
+               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);
-                       up(&JFS_IP(ipimap)->commit_sem);
+                       mutex_unlock(&JFS_IP(ipimap)->commit_mutex);
                        /* Free the blocks allocated for the iag since it was
                         * not successfully added to the inode map
                         */
@@ -2588,6 +2572,7 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
 
                        txAbort(tid, 0);
                        txEnd(tid);
+                       mutex_unlock(&JFS_IP(ipimap)->commit_mutex);
 
                        /* release the inode map lock */
                        IWRITE_UNLOCK(ipimap);
@@ -2618,15 +2603,15 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
                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);
-               up(&JFS_IP(ipimap)->commit_sem);
+               mutex_unlock(&JFS_IP(ipimap)->commit_mutex);
 
                duplicateIXtree(sb, blkno, xlen, &xaddr);
 
@@ -2648,7 +2633,7 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
        }
 
        /* obtain read lock on map */
-       IREAD_LOCK(ipimap);
+       IREAD_LOCK(ipimap, RDWRLOCK_IMAP);
 
        /* read the iag */
        if ((rc = diIAGRead(imap, iagno, &mp))) {
@@ -2674,15 +2659,15 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
 }
 
 /*
- * NAME:        diIAGRead()
+ * NAME:       diIAGRead()
  *
- * FUNCTION:    get the buffer for the specified iag within a fileset
+ * 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:
@@ -2691,8 +2676,8 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
  *      the read lock is unnecessary.)
  *
  * RETURN VALUES:
- *      0       - success.
- *      -EIO   - i/o error.
+ *     0       - success.
+ *     -EIO    - i/o error.
  */
 static int diIAGRead(struct inomap * imap, int iagno, struct metapage ** mpp)
 {
@@ -2712,17 +2697,17 @@ static int diIAGRead(struct inomap * imap, int iagno, struct metapage ** mpp)
 }
 
 /*
- * NAME:        diFindFree()
+ * NAME:       diFindFree()
  *
- * FUNCTION:    find the first free bit in a word starting at
+ * FUNCTION:   find the first free bit in a word starting at
  *             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
+ *     bit position of first free bit in the word or 32 if
  *     no free bits were found.
  */
 static int diFindFree(u32 word, int start)
@@ -2740,24 +2725,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;
@@ -2779,7 +2764,7 @@ diUpdatePMap(struct inode *ipimap,
                return -EIO;
        }
        /* read the iag */
-       IREAD_LOCK(ipimap);
+       IREAD_LOCK(ipimap, RDWRLOCK_IMAP);
        rc = diIAGRead(imap, iagno, &mp);
        IREAD_UNLOCK(ipimap);
        if (rc)
@@ -2793,17 +2778,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);
                }
@@ -2844,11 +2829,11 @@ 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);
                logdiff(diffp, mp->lsn, log);
-               LOGSYNC_LOCK(log, flags);
                if (difft < diffp) {
                        mp->lsn = lsn;
                        /* move mp after tblock in logsync list */
@@ -2860,17 +2845,15 @@ diUpdatePMap(struct inode *ipimap,
                logdiff(diffp, mp->clsn, log);
                if (difft > diffp)
                        mp->clsn = tblk->clsn;
-               LOGSYNC_UNLOCK(log, flags);
        } else {
                mp->log = log;
                mp->lsn = lsn;
                /* insert mp after tblock in logsync list */
-               LOGSYNC_LOCK(log, flags);
                log->count++;
                list_add(&mp->synclist, &tblk->synclist);
                mp->clsn = tblk->clsn;
-               LOGSYNC_UNLOCK(log, flags);
        }
+       LOGSYNC_UNLOCK(log, flags);
        write_metapage(mp);
        return (0);
 }
@@ -2879,8 +2862,8 @@ 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)
@@ -2899,7 +2882,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;
@@ -2915,7 +2898,7 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap)
        }
 
        /*
-        *      process each iag page of the map.
+        *      process each iag page of the map.
         *
         * rebuild AG Free Inode List, AG Free Inode Extent List;
         */
@@ -2933,8 +2916,8 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap)
                }
 
                /* leave free iag in the free iag list */
-               if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) {  
-                       release_metapage(bp);
+               if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) {
+                       release_metapage(bp);
                        continue;
                }
 
@@ -3065,25 +3048,52 @@ static void duplicateIXtree(struct super_block *sb, s64 blkno,
 }
 
 /*
- * NAME:        copy_from_dinode()
+ * NAME:       copy_from_dinode()
  *
- * FUNCTION:    Copies inode info from disk inode to in-memory inode
+ * FUNCTION:   Copies inode info from disk inode to in-memory inode
  *
  * RETURN VALUES:
- *      0       - success
- *      -ENOMEM        - insufficient memory
+ *     0       - success
+ *     -ENOMEM - insufficient memory
  */
 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);
 
        jfs_ip->fileset = le32_to_cpu(dip->di_fileset);
        jfs_ip->mode2 = le32_to_cpu(dip->di_mode);
+       jfs_set_inode_flags(ip);
 
        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);
-       ip->i_uid = le32_to_cpu(dip->di_uid);
-       ip->i_gid = le32_to_cpu(dip->di_gid);
+
+       jfs_ip->saved_uid = le32_to_cpu(dip->di_uid);
+       if (sbi->uid == -1)
+               ip->i_uid = jfs_ip->saved_uid;
+       else {
+               ip->i_uid = sbi->uid;
+       }
+
+       jfs_ip->saved_gid = le32_to_cpu(dip->di_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);
@@ -3091,7 +3101,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);
 
@@ -3127,28 +3136,41 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip)
 }
 
 /*
- * NAME:        copy_to_dinode()
+ * NAME:       copy_to_dinode()
  *
- * FUNCTION:    Copies inode info from in-memory inode to disk inode
+ * FUNCTION:   Copies inode info from in-memory inode to disk inode
  */
 static void copy_to_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);
 
        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);
-       dip->di_uid = cpu_to_le32(ip->i_uid);
-       dip->di_gid = cpu_to_le32(ip->i_gid);
+       if (sbi->uid == -1)
+               dip->di_uid = cpu_to_le32(ip->i_uid);
+       else
+               dip->di_uid = cpu_to_le32(jfs_ip->saved_uid);
+       if (sbi->gid == -1)
+               dip->di_gid = cpu_to_le32(ip->i_gid);
+       else
+               dip->di_gid = cpu_to_le32(jfs_ip->saved_gid);
+       jfs_get_inode_flags(jfs_ip);
        /*
         * 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);