summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/jfs/jfs_imap.c70
1 files changed, 36 insertions, 34 deletions
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index 783831301625..6a0aa7e2cbef 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -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);