diff options
Diffstat (limited to 'fs/jfs/jfs_imap.c')
-rw-r--r-- | fs/jfs/jfs_imap.c | 84 |
1 files changed, 43 insertions, 41 deletions
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index 783831301625..7acff2ce3c80 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c | |||
@@ -502,7 +502,7 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary) | |||
502 | 502 | ||
503 | } | 503 | } |
504 | 504 | ||
505 | ip->i_mapping->a_ops = &jfs_aops; | 505 | ip->i_mapping->a_ops = &jfs_metapage_aops; |
506 | mapping_set_gfp_mask(ip->i_mapping, GFP_NOFS); | 506 | mapping_set_gfp_mask(ip->i_mapping, GFP_NOFS); |
507 | 507 | ||
508 | /* Allocations to metadata inodes should not affect quotas */ | 508 | /* Allocations to metadata inodes should not affect quotas */ |
@@ -2573,9 +2573,18 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) | |||
2573 | goto out; | 2573 | goto out; |
2574 | } | 2574 | } |
2575 | 2575 | ||
2576 | /* assign a buffer for the page */ | 2576 | /* |
2577 | mp = get_metapage(ipimap, xaddr, PSIZE, 1); | 2577 | * start transaction of update of the inode map |
2578 | if (!mp) { | 2578 | * addressing structure pointing to the new iag page; |
2579 | */ | ||
2580 | tid = txBegin(sb, COMMIT_FORCE); | ||
2581 | down(&JFS_IP(ipimap)->commit_sem); | ||
2582 | |||
2583 | /* update the inode map addressing structure to point to it */ | ||
2584 | if ((rc = | ||
2585 | xtInsert(tid, ipimap, 0, blkno, xlen, &xaddr, 0))) { | ||
2586 | txEnd(tid); | ||
2587 | up(&JFS_IP(ipimap)->commit_sem); | ||
2579 | /* Free the blocks allocated for the iag since it was | 2588 | /* Free the blocks allocated for the iag since it was |
2580 | * not successfully added to the inode map | 2589 | * not successfully added to the inode map |
2581 | */ | 2590 | */ |
@@ -2584,6 +2593,29 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) | |||
2584 | /* release the inode map lock */ | 2593 | /* release the inode map lock */ |
2585 | IWRITE_UNLOCK(ipimap); | 2594 | IWRITE_UNLOCK(ipimap); |
2586 | 2595 | ||
2596 | goto out; | ||
2597 | } | ||
2598 | |||
2599 | /* update the inode map's inode to reflect the extension */ | ||
2600 | ipimap->i_size += PSIZE; | ||
2601 | inode_add_bytes(ipimap, PSIZE); | ||
2602 | |||
2603 | /* assign a buffer for the page */ | ||
2604 | mp = get_metapage(ipimap, blkno, PSIZE, 0); | ||
2605 | if (!mp) { | ||
2606 | /* | ||
2607 | * This is very unlikely since we just created the | ||
2608 | * extent, but let's try to handle it correctly | ||
2609 | */ | ||
2610 | xtTruncate(tid, ipimap, ipimap->i_size - PSIZE, | ||
2611 | COMMIT_PWMAP); | ||
2612 | |||
2613 | txAbort(tid, 0); | ||
2614 | txEnd(tid); | ||
2615 | |||
2616 | /* release the inode map lock */ | ||
2617 | IWRITE_UNLOCK(ipimap); | ||
2618 | |||
2587 | rc = -EIO; | 2619 | rc = -EIO; |
2588 | goto out; | 2620 | goto out; |
2589 | } | 2621 | } |
@@ -2605,41 +2637,11 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) | |||
2605 | iagp->inosmap[i] = cpu_to_le32(ONES); | 2637 | iagp->inosmap[i] = cpu_to_le32(ONES); |
2606 | 2638 | ||
2607 | /* | 2639 | /* |
2608 | * Invalidate the page after writing and syncing it. | 2640 | * Write and sync the metapage |
2609 | * After it's initialized, we access it in a different | ||
2610 | * address space | ||
2611 | */ | 2641 | */ |
2612 | set_bit(META_discard, &mp->flag); | ||
2613 | flush_metapage(mp); | 2642 | flush_metapage(mp); |
2614 | 2643 | ||
2615 | /* | 2644 | /* |
2616 | * start tyransaction of update of the inode map | ||
2617 | * addressing structure pointing to the new iag page; | ||
2618 | */ | ||
2619 | tid = txBegin(sb, COMMIT_FORCE); | ||
2620 | down(&JFS_IP(ipimap)->commit_sem); | ||
2621 | |||
2622 | /* update the inode map addressing structure to point to it */ | ||
2623 | if ((rc = | ||
2624 | xtInsert(tid, ipimap, 0, blkno, xlen, &xaddr, 0))) { | ||
2625 | txEnd(tid); | ||
2626 | up(&JFS_IP(ipimap)->commit_sem); | ||
2627 | /* Free the blocks allocated for the iag since it was | ||
2628 | * not successfully added to the inode map | ||
2629 | */ | ||
2630 | dbFree(ipimap, xaddr, (s64) xlen); | ||
2631 | |||
2632 | /* release the inode map lock */ | ||
2633 | IWRITE_UNLOCK(ipimap); | ||
2634 | |||
2635 | goto out; | ||
2636 | } | ||
2637 | |||
2638 | /* update the inode map's inode to reflect the extension */ | ||
2639 | ipimap->i_size += PSIZE; | ||
2640 | inode_add_bytes(ipimap, PSIZE); | ||
2641 | |||
2642 | /* | ||
2643 | * txCommit(COMMIT_FORCE) will synchronously write address | 2645 | * txCommit(COMMIT_FORCE) will synchronously write address |
2644 | * index pages and inode after commit in careful update order | 2646 | * index pages and inode after commit in careful update order |
2645 | * of address index pages (right to left, bottom up); | 2647 | * of address index pages (right to left, bottom up); |
@@ -2789,6 +2791,7 @@ diUpdatePMap(struct inode *ipimap, | |||
2789 | u32 mask; | 2791 | u32 mask; |
2790 | struct jfs_log *log; | 2792 | struct jfs_log *log; |
2791 | int lsn, difft, diffp; | 2793 | int lsn, difft, diffp; |
2794 | unsigned long flags; | ||
2792 | 2795 | ||
2793 | imap = JFS_IP(ipimap)->i_imap; | 2796 | imap = JFS_IP(ipimap)->i_imap; |
2794 | /* get the iag number containing the inode */ | 2797 | /* get the iag number containing the inode */ |
@@ -2805,6 +2808,7 @@ diUpdatePMap(struct inode *ipimap, | |||
2805 | IREAD_UNLOCK(ipimap); | 2808 | IREAD_UNLOCK(ipimap); |
2806 | if (rc) | 2809 | if (rc) |
2807 | return (rc); | 2810 | return (rc); |
2811 | metapage_wait_for_io(mp); | ||
2808 | iagp = (struct iag *) mp->data; | 2812 | iagp = (struct iag *) mp->data; |
2809 | /* get the inode number and extent number of the inode within | 2813 | /* get the inode number and extent number of the inode within |
2810 | * the iag and the inode number within the extent. | 2814 | * the iag and the inode number within the extent. |
@@ -2868,30 +2872,28 @@ diUpdatePMap(struct inode *ipimap, | |||
2868 | /* inherit older/smaller lsn */ | 2872 | /* inherit older/smaller lsn */ |
2869 | logdiff(difft, lsn, log); | 2873 | logdiff(difft, lsn, log); |
2870 | logdiff(diffp, mp->lsn, log); | 2874 | logdiff(diffp, mp->lsn, log); |
2875 | LOGSYNC_LOCK(log, flags); | ||
2871 | if (difft < diffp) { | 2876 | if (difft < diffp) { |
2872 | mp->lsn = lsn; | 2877 | mp->lsn = lsn; |
2873 | /* move mp after tblock in logsync list */ | 2878 | /* move mp after tblock in logsync list */ |
2874 | LOGSYNC_LOCK(log); | ||
2875 | list_move(&mp->synclist, &tblk->synclist); | 2879 | list_move(&mp->synclist, &tblk->synclist); |
2876 | LOGSYNC_UNLOCK(log); | ||
2877 | } | 2880 | } |
2878 | /* inherit younger/larger clsn */ | 2881 | /* inherit younger/larger clsn */ |
2879 | LOGSYNC_LOCK(log); | ||
2880 | assert(mp->clsn); | 2882 | assert(mp->clsn); |
2881 | logdiff(difft, tblk->clsn, log); | 2883 | logdiff(difft, tblk->clsn, log); |
2882 | logdiff(diffp, mp->clsn, log); | 2884 | logdiff(diffp, mp->clsn, log); |
2883 | if (difft > diffp) | 2885 | if (difft > diffp) |
2884 | mp->clsn = tblk->clsn; | 2886 | mp->clsn = tblk->clsn; |
2885 | LOGSYNC_UNLOCK(log); | 2887 | LOGSYNC_UNLOCK(log, flags); |
2886 | } else { | 2888 | } else { |
2887 | mp->log = log; | 2889 | mp->log = log; |
2888 | mp->lsn = lsn; | 2890 | mp->lsn = lsn; |
2889 | /* insert mp after tblock in logsync list */ | 2891 | /* insert mp after tblock in logsync list */ |
2890 | LOGSYNC_LOCK(log); | 2892 | LOGSYNC_LOCK(log, flags); |
2891 | log->count++; | 2893 | log->count++; |
2892 | list_add(&mp->synclist, &tblk->synclist); | 2894 | list_add(&mp->synclist, &tblk->synclist); |
2893 | mp->clsn = tblk->clsn; | 2895 | mp->clsn = tblk->clsn; |
2894 | LOGSYNC_UNLOCK(log); | 2896 | LOGSYNC_UNLOCK(log, flags); |
2895 | } | 2897 | } |
2896 | write_metapage(mp); | 2898 | write_metapage(mp); |
2897 | return (0); | 2899 | return (0); |