[PATCH] JFS: Simplify creation of new iag
Dave Kleikamp [Mon, 2 May 2005 18:24:51 +0000 (12:24 -0600)]
JFS was creating a new IAG (inode aggregate group) in one address
space, and afterwards, accessing it from another.  This could lead to
complications when cache pages contain more than one page of jfs
metadata.  This patch causes the IAG to be initialized in the same
address space that it is subsequently accessed with.

This also elimitates an I/O, but IAG's aren't created too often.

Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

fs/jfs/jfs_imap.c

index 7838313..6a0aa7e 100644 (file)
@@ -2573,9 +2573,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);
+               down(&JFS_IP(ipimap)->commit_sem);
+
+               /* 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);
                        /* Free the blocks allocated for the iag since it was
                         * not successfully added to the inode map
                         */
@@ -2584,6 +2593,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;
                }
@@ -2605,41 +2637,11 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
                        iagp->inosmap[i] = cpu_to_le32(ONES);
 
                /*
-                * Invalidate the page after writing and syncing it.
-                * After it's initialized, we access it in a different
-                * address space
+                * Write and sync the metapage
                 */
-               set_bit(META_discard, &mp->flag);
                flush_metapage(mp);
 
                /*
-                * start tyransaction of update of the inode map
-                * addressing structure pointing to the new iag page;
-                */
-               tid = txBegin(sb, COMMIT_FORCE);
-               down(&JFS_IP(ipimap)->commit_sem);
-
-               /* 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);
-                       /* 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;
-               inode_add_bytes(ipimap, PSIZE);
-
-               /*
                 * 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);