aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDave Kleikamp <shaggy@austin.ibm.com>2005-05-02 14:25:02 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-03 01:23:53 -0400
commit7fab479bebb96b1b4888bdae9b42e1fa9c5d3f38 (patch)
tree3d47de90cf39002e576df02f474bc17342ff0f4a /fs
parentdc5798d9a7b656550533a5c0177dba17d4ef4990 (diff)
[PATCH] JFS: Support page sizes greater than 4K
jfs has never worked on architecutures where the page size was not 4K. Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/jfs/inode.c31
-rw-r--r--fs/jfs/jfs_dmap.c12
-rw-r--r--fs/jfs/jfs_imap.c14
-rw-r--r--fs/jfs/jfs_incore.h1
-rw-r--r--fs/jfs/jfs_logmgr.c71
-rw-r--r--fs/jfs/jfs_logmgr.h5
-rw-r--r--fs/jfs/jfs_metapage.c908
-rw-r--r--fs/jfs/jfs_metapage.h80
-rw-r--r--fs/jfs/jfs_mount.c5
-rw-r--r--fs/jfs/jfs_txnmgr.c89
-rw-r--r--fs/jfs/jfs_umount.c16
-rw-r--r--fs/jfs/resize.c3
-rw-r--r--fs/jfs/super.c33
13 files changed, 806 insertions, 462 deletions
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 7bc906677b0d..6c04f5eda135 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -175,31 +175,22 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks,
175{ 175{
176 s64 lblock64 = lblock; 176 s64 lblock64 = lblock;
177 int rc = 0; 177 int rc = 0;
178 int take_locks;
179 xad_t xad; 178 xad_t xad;
180 s64 xaddr; 179 s64 xaddr;
181 int xflag; 180 int xflag;
182 s32 xlen; 181 s32 xlen;
183 182
184 /* 183 /*
185 * If this is a special inode (imap, dmap)
186 * the lock should already be taken
187 */
188 take_locks = (JFS_IP(ip)->fileset != AGGREGATE_I);
189
190 /*
191 * Take appropriate lock on inode 184 * Take appropriate lock on inode
192 */ 185 */
193 if (take_locks) { 186 if (create)
194 if (create) 187 IWRITE_LOCK(ip);
195 IWRITE_LOCK(ip); 188 else
196 else 189 IREAD_LOCK(ip);
197 IREAD_LOCK(ip);
198 }
199 190
200 if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) && 191 if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) &&
201 (xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, 0) 192 (!xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, 0)) &&
202 == 0) && xlen) { 193 xlen) {
203 if (xflag & XAD_NOTRECORDED) { 194 if (xflag & XAD_NOTRECORDED) {
204 if (!create) 195 if (!create)
205 /* 196 /*
@@ -258,12 +249,10 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks,
258 /* 249 /*
259 * Release lock on inode 250 * Release lock on inode
260 */ 251 */
261 if (take_locks) { 252 if (create)
262 if (create) 253 IWRITE_UNLOCK(ip);
263 IWRITE_UNLOCK(ip); 254 else
264 else 255 IREAD_UNLOCK(ip);
265 IREAD_UNLOCK(ip);
266 }
267 return rc; 256 return rc;
268} 257}
269 258
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
index d86e467c6e42..69007fd546ef 100644
--- a/fs/jfs/jfs_dmap.c
+++ b/fs/jfs/jfs_dmap.c
@@ -471,6 +471,7 @@ dbUpdatePMap(struct inode *ipbmap,
471 struct metapage *mp; 471 struct metapage *mp;
472 struct jfs_log *log; 472 struct jfs_log *log;
473 int lsn, difft, diffp; 473 int lsn, difft, diffp;
474 unsigned long flags;
474 475
475 /* the blocks better be within the mapsize. */ 476 /* the blocks better be within the mapsize. */
476 if (blkno + nblocks > bmp->db_mapsize) { 477 if (blkno + nblocks > bmp->db_mapsize) {
@@ -504,6 +505,7 @@ dbUpdatePMap(struct inode *ipbmap,
504 0); 505 0);
505 if (mp == NULL) 506 if (mp == NULL)
506 return -EIO; 507 return -EIO;
508 metapage_wait_for_io(mp);
507 } 509 }
508 dp = (struct dmap *) mp->data; 510 dp = (struct dmap *) mp->data;
509 511
@@ -578,34 +580,32 @@ dbUpdatePMap(struct inode *ipbmap,
578 if (mp->lsn != 0) { 580 if (mp->lsn != 0) {
579 /* inherit older/smaller lsn */ 581 /* inherit older/smaller lsn */
580 logdiff(diffp, mp->lsn, log); 582 logdiff(diffp, mp->lsn, log);
583 LOGSYNC_LOCK(log, flags);
581 if (difft < diffp) { 584 if (difft < diffp) {
582 mp->lsn = lsn; 585 mp->lsn = lsn;
583 586
584 /* move bp after tblock in logsync list */ 587 /* move bp after tblock in logsync list */
585 LOGSYNC_LOCK(log);
586 list_move(&mp->synclist, &tblk->synclist); 588 list_move(&mp->synclist, &tblk->synclist);
587 LOGSYNC_UNLOCK(log);
588 } 589 }
589 590
590 /* inherit younger/larger clsn */ 591 /* inherit younger/larger clsn */
591 LOGSYNC_LOCK(log);
592 logdiff(difft, tblk->clsn, log); 592 logdiff(difft, tblk->clsn, log);
593 logdiff(diffp, mp->clsn, log); 593 logdiff(diffp, mp->clsn, log);
594 if (difft > diffp) 594 if (difft > diffp)
595 mp->clsn = tblk->clsn; 595 mp->clsn = tblk->clsn;
596 LOGSYNC_UNLOCK(log); 596 LOGSYNC_UNLOCK(log, flags);
597 } else { 597 } else {
598 mp->log = log; 598 mp->log = log;
599 mp->lsn = lsn; 599 mp->lsn = lsn;
600 600
601 /* insert bp after tblock in logsync list */ 601 /* insert bp after tblock in logsync list */
602 LOGSYNC_LOCK(log); 602 LOGSYNC_LOCK(log, flags);
603 603
604 log->count++; 604 log->count++;
605 list_add(&mp->synclist, &tblk->synclist); 605 list_add(&mp->synclist, &tblk->synclist);
606 606
607 mp->clsn = tblk->clsn; 607 mp->clsn = tblk->clsn;
608 LOGSYNC_UNLOCK(log); 608 LOGSYNC_UNLOCK(log, flags);
609 } 609 }
610 } 610 }
611 611
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index 6a0aa7e2cbef..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 */
@@ -2791,6 +2791,7 @@ diUpdatePMap(struct inode *ipimap,
2791 u32 mask; 2791 u32 mask;
2792 struct jfs_log *log; 2792 struct jfs_log *log;
2793 int lsn, difft, diffp; 2793 int lsn, difft, diffp;
2794 unsigned long flags;
2794 2795
2795 imap = JFS_IP(ipimap)->i_imap; 2796 imap = JFS_IP(ipimap)->i_imap;
2796 /* get the iag number containing the inode */ 2797 /* get the iag number containing the inode */
@@ -2807,6 +2808,7 @@ diUpdatePMap(struct inode *ipimap,
2807 IREAD_UNLOCK(ipimap); 2808 IREAD_UNLOCK(ipimap);
2808 if (rc) 2809 if (rc)
2809 return (rc); 2810 return (rc);
2811 metapage_wait_for_io(mp);
2810 iagp = (struct iag *) mp->data; 2812 iagp = (struct iag *) mp->data;
2811 /* get the inode number and extent number of the inode within 2813 /* get the inode number and extent number of the inode within
2812 * the iag and the inode number within the extent. 2814 * the iag and the inode number within the extent.
@@ -2870,30 +2872,28 @@ diUpdatePMap(struct inode *ipimap,
2870 /* inherit older/smaller lsn */ 2872 /* inherit older/smaller lsn */
2871 logdiff(difft, lsn, log); 2873 logdiff(difft, lsn, log);
2872 logdiff(diffp, mp->lsn, log); 2874 logdiff(diffp, mp->lsn, log);
2875 LOGSYNC_LOCK(log, flags);
2873 if (difft < diffp) { 2876 if (difft < diffp) {
2874 mp->lsn = lsn; 2877 mp->lsn = lsn;
2875 /* move mp after tblock in logsync list */ 2878 /* move mp after tblock in logsync list */
2876 LOGSYNC_LOCK(log);
2877 list_move(&mp->synclist, &tblk->synclist); 2879 list_move(&mp->synclist, &tblk->synclist);
2878 LOGSYNC_UNLOCK(log);
2879 } 2880 }
2880 /* inherit younger/larger clsn */ 2881 /* inherit younger/larger clsn */
2881 LOGSYNC_LOCK(log);
2882 assert(mp->clsn); 2882 assert(mp->clsn);
2883 logdiff(difft, tblk->clsn, log); 2883 logdiff(difft, tblk->clsn, log);
2884 logdiff(diffp, mp->clsn, log); 2884 logdiff(diffp, mp->clsn, log);
2885 if (difft > diffp) 2885 if (difft > diffp)
2886 mp->clsn = tblk->clsn; 2886 mp->clsn = tblk->clsn;
2887 LOGSYNC_UNLOCK(log); 2887 LOGSYNC_UNLOCK(log, flags);
2888 } else { 2888 } else {
2889 mp->log = log; 2889 mp->log = log;
2890 mp->lsn = lsn; 2890 mp->lsn = lsn;
2891 /* insert mp after tblock in logsync list */ 2891 /* insert mp after tblock in logsync list */
2892 LOGSYNC_LOCK(log); 2892 LOGSYNC_LOCK(log, flags);
2893 log->count++; 2893 log->count++;
2894 list_add(&mp->synclist, &tblk->synclist); 2894 list_add(&mp->synclist, &tblk->synclist);
2895 mp->clsn = tblk->clsn; 2895 mp->clsn = tblk->clsn;
2896 LOGSYNC_UNLOCK(log); 2896 LOGSYNC_UNLOCK(log, flags);
2897 } 2897 }
2898 write_metapage(mp); 2898 write_metapage(mp);
2899 return (0); 2899 return (0);
diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h
index ebd77c1bed66..c0fd7b3eadc6 100644
--- a/fs/jfs/jfs_incore.h
+++ b/fs/jfs/jfs_incore.h
@@ -165,6 +165,7 @@ struct jfs_sb_info {
165 /* Formerly in ipbmap */ 165 /* Formerly in ipbmap */
166 struct bmap *bmap; /* incore bmap descriptor */ 166 struct bmap *bmap; /* incore bmap descriptor */
167 struct nls_table *nls_tab; /* current codepage */ 167 struct nls_table *nls_tab; /* current codepage */
168 struct inode *direct_inode; /* metadata inode */
168 uint state; /* mount/recovery state */ 169 uint state; /* mount/recovery state */
169 unsigned long flag; /* mount time flags */ 170 unsigned long flag; /* mount time flags */
170 uint p_state; /* state prior to going no integrity */ 171 uint p_state; /* state prior to going no integrity */
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index e0f867ddfd10..cfcdad3459dd 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -234,6 +234,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
234 int lsn; 234 int lsn;
235 int diffp, difft; 235 int diffp, difft;
236 struct metapage *mp = NULL; 236 struct metapage *mp = NULL;
237 unsigned long flags;
237 238
238 jfs_info("lmLog: log:0x%p tblk:0x%p, lrd:0x%p tlck:0x%p", 239 jfs_info("lmLog: log:0x%p tblk:0x%p, lrd:0x%p tlck:0x%p",
239 log, tblk, lrd, tlck); 240 log, tblk, lrd, tlck);
@@ -254,7 +255,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
254 */ 255 */
255 lsn = log->lsn; 256 lsn = log->lsn;
256 257
257 LOGSYNC_LOCK(log); 258 LOGSYNC_LOCK(log, flags);
258 259
259 /* 260 /*
260 * initialize page lsn if first log write of the page 261 * initialize page lsn if first log write of the page
@@ -310,7 +311,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
310 } 311 }
311 } 312 }
312 313
313 LOGSYNC_UNLOCK(log); 314 LOGSYNC_UNLOCK(log, flags);
314 315
315 /* 316 /*
316 * write the log record 317 * write the log record
@@ -334,7 +335,6 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
334 return lsn; 335 return lsn;
335} 336}
336 337
337
338/* 338/*
339 * NAME: lmWriteRecord() 339 * NAME: lmWriteRecord()
340 * 340 *
@@ -945,6 +945,15 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
945 struct lrd lrd; 945 struct lrd lrd;
946 int lsn; 946 int lsn;
947 struct logsyncblk *lp; 947 struct logsyncblk *lp;
948 struct jfs_sb_info *sbi;
949 unsigned long flags;
950
951 /* push dirty metapages out to disk */
952 list_for_each_entry(sbi, &log->sb_list, log_list) {
953 filemap_flush(sbi->ipbmap->i_mapping);
954 filemap_flush(sbi->ipimap->i_mapping);
955 filemap_flush(sbi->direct_inode->i_mapping);
956 }
948 957
949 /* 958 /*
950 * forward syncpt 959 * forward syncpt
@@ -954,10 +963,7 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
954 */ 963 */
955 964
956 if (log->sync == log->syncpt) { 965 if (log->sync == log->syncpt) {
957 LOGSYNC_LOCK(log); 966 LOGSYNC_LOCK(log, flags);
958 /* ToDo: push dirty metapages out to disk */
959// bmLogSync(log);
960
961 if (list_empty(&log->synclist)) 967 if (list_empty(&log->synclist))
962 log->sync = log->lsn; 968 log->sync = log->lsn;
963 else { 969 else {
@@ -965,7 +971,7 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
965 struct logsyncblk, synclist); 971 struct logsyncblk, synclist);
966 log->sync = lp->lsn; 972 log->sync = lp->lsn;
967 } 973 }
968 LOGSYNC_UNLOCK(log); 974 LOGSYNC_UNLOCK(log, flags);
969 975
970 } 976 }
971 977
@@ -974,27 +980,6 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
974 * reset syncpt = sync 980 * reset syncpt = sync
975 */ 981 */
976 if (log->sync != log->syncpt) { 982 if (log->sync != log->syncpt) {
977 struct jfs_sb_info *sbi;
978
979 /*
980 * We need to make sure all of the "written" metapages
981 * actually make it to disk
982 */
983 list_for_each_entry(sbi, &log->sb_list, log_list) {
984 if (sbi->flag & JFS_NOINTEGRITY)
985 continue;
986 filemap_fdatawrite(sbi->ipbmap->i_mapping);
987 filemap_fdatawrite(sbi->ipimap->i_mapping);
988 filemap_fdatawrite(sbi->sb->s_bdev->bd_inode->i_mapping);
989 }
990 list_for_each_entry(sbi, &log->sb_list, log_list) {
991 if (sbi->flag & JFS_NOINTEGRITY)
992 continue;
993 filemap_fdatawait(sbi->ipbmap->i_mapping);
994 filemap_fdatawait(sbi->ipimap->i_mapping);
995 filemap_fdatawait(sbi->sb->s_bdev->bd_inode->i_mapping);
996 }
997
998 lrd.logtid = 0; 983 lrd.logtid = 0;
999 lrd.backchain = 0; 984 lrd.backchain = 0;
1000 lrd.type = cpu_to_le16(LOG_SYNCPT); 985 lrd.type = cpu_to_le16(LOG_SYNCPT);
@@ -1547,6 +1532,7 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
1547{ 1532{
1548 int i; 1533 int i;
1549 struct tblock *target = NULL; 1534 struct tblock *target = NULL;
1535 struct jfs_sb_info *sbi;
1550 1536
1551 /* jfs_write_inode may call us during read-only mount */ 1537 /* jfs_write_inode may call us during read-only mount */
1552 if (!log) 1538 if (!log)
@@ -1608,12 +1594,18 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
1608 if (wait < 2) 1594 if (wait < 2)
1609 return; 1595 return;
1610 1596
1597 list_for_each_entry(sbi, &log->sb_list, log_list) {
1598 filemap_fdatawrite(sbi->ipbmap->i_mapping);
1599 filemap_fdatawrite(sbi->ipimap->i_mapping);
1600 filemap_fdatawrite(sbi->direct_inode->i_mapping);
1601 }
1602
1611 /* 1603 /*
1612 * If there was recent activity, we may need to wait 1604 * If there was recent activity, we may need to wait
1613 * for the lazycommit thread to catch up 1605 * for the lazycommit thread to catch up
1614 */ 1606 */
1615 if ((!list_empty(&log->cqueue)) || !list_empty(&log->synclist)) { 1607 if ((!list_empty(&log->cqueue)) || !list_empty(&log->synclist)) {
1616 for (i = 0; i < 800; i++) { /* Too much? */ 1608 for (i = 0; i < 200; i++) { /* Too much? */
1617 msleep(250); 1609 msleep(250);
1618 if (list_empty(&log->cqueue) && 1610 if (list_empty(&log->cqueue) &&
1619 list_empty(&log->synclist)) 1611 list_empty(&log->synclist))
@@ -1621,7 +1613,24 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
1621 } 1613 }
1622 } 1614 }
1623 assert(list_empty(&log->cqueue)); 1615 assert(list_empty(&log->cqueue));
1624 assert(list_empty(&log->synclist)); 1616 if (!list_empty(&log->synclist)) {
1617 struct logsyncblk *lp;
1618
1619 list_for_each_entry(lp, &log->synclist, synclist) {
1620 if (lp->xflag & COMMIT_PAGE) {
1621 struct metapage *mp = (struct metapage *)lp;
1622 dump_mem("orphan metapage", lp,
1623 sizeof(struct metapage));
1624 dump_mem("page", mp->page, sizeof(struct page));
1625 }
1626 else
1627 dump_mem("orphan tblock", lp,
1628 sizeof(struct tblock));
1629 }
1630// current->state = TASK_INTERRUPTIBLE;
1631// schedule();
1632 }
1633 //assert(list_empty(&log->synclist));
1625 clear_bit(log_FLUSH, &log->flag); 1634 clear_bit(log_FLUSH, &log->flag);
1626} 1635}
1627 1636
diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h
index f67146684b7f..f4c121098d4f 100644
--- a/fs/jfs/jfs_logmgr.h
+++ b/fs/jfs/jfs_logmgr.h
@@ -490,8 +490,9 @@ struct logsyncblk {
490 */ 490 */
491 491
492#define LOGSYNC_LOCK_INIT(log) spin_lock_init(&(log)->synclock) 492#define LOGSYNC_LOCK_INIT(log) spin_lock_init(&(log)->synclock)
493#define LOGSYNC_LOCK(log) spin_lock(&(log)->synclock) 493#define LOGSYNC_LOCK(log, flags) spin_lock_irqsave(&(log)->synclock, flags)
494#define LOGSYNC_UNLOCK(log) spin_unlock(&(log)->synclock) 494#define LOGSYNC_UNLOCK(log, flags) \
495 spin_unlock_irqrestore(&(log)->synclock, flags)
495 496
496/* compute the difference in bytes of lsn from sync point */ 497/* compute the difference in bytes of lsn from sync point */
497#define logdiff(diff, lsn, log)\ 498#define logdiff(diff, lsn, log)\
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 4c0a3ac75c08..41bf078dce05 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) International Business Machines Corp., 2000-2003 2 * Copyright (C) International Business Machines Corp., 2000-2005
3 * Portions Copyright (C) Christoph Hellwig, 2001-2002 3 * Portions Copyright (C) Christoph Hellwig, 2001-2002
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
@@ -18,10 +18,11 @@
18 */ 18 */
19 19
20#include <linux/fs.h> 20#include <linux/fs.h>
21#include <linux/mm.h>
22#include <linux/bio.h>
21#include <linux/init.h> 23#include <linux/init.h>
22#include <linux/buffer_head.h> 24#include <linux/buffer_head.h>
23#include <linux/mempool.h> 25#include <linux/mempool.h>
24#include <linux/delay.h>
25#include "jfs_incore.h" 26#include "jfs_incore.h"
26#include "jfs_superblock.h" 27#include "jfs_superblock.h"
27#include "jfs_filsys.h" 28#include "jfs_filsys.h"
@@ -29,8 +30,6 @@
29#include "jfs_txnmgr.h" 30#include "jfs_txnmgr.h"
30#include "jfs_debug.h" 31#include "jfs_debug.h"
31 32
32static DEFINE_SPINLOCK(meta_lock);
33
34#ifdef CONFIG_JFS_STATISTICS 33#ifdef CONFIG_JFS_STATISTICS
35static struct { 34static struct {
36 uint pagealloc; /* # of page allocations */ 35 uint pagealloc; /* # of page allocations */
@@ -39,22 +38,8 @@ static struct {
39} mpStat; 38} mpStat;
40#endif 39#endif
41 40
42 41#define metapage_locked(mp) test_bit(META_locked, &(mp)->flag)
43#define HASH_BITS 10 /* This makes hash_table 1 4K page */ 42#define trylock_metapage(mp) test_and_set_bit(META_locked, &(mp)->flag)
44#define HASH_SIZE (1 << HASH_BITS)
45static struct metapage **hash_table = NULL;
46static unsigned long hash_order;
47
48
49static inline int metapage_locked(struct metapage *mp)
50{
51 return test_bit(META_locked, &mp->flag);
52}
53
54static inline int trylock_metapage(struct metapage *mp)
55{
56 return test_and_set_bit(META_locked, &mp->flag);
57}
58 43
59static inline void unlock_metapage(struct metapage *mp) 44static inline void unlock_metapage(struct metapage *mp)
60{ 45{
@@ -62,26 +47,26 @@ static inline void unlock_metapage(struct metapage *mp)
62 wake_up(&mp->wait); 47 wake_up(&mp->wait);
63} 48}
64 49
65static void __lock_metapage(struct metapage *mp) 50static inline void __lock_metapage(struct metapage *mp)
66{ 51{
67 DECLARE_WAITQUEUE(wait, current); 52 DECLARE_WAITQUEUE(wait, current);
68
69 INCREMENT(mpStat.lockwait); 53 INCREMENT(mpStat.lockwait);
70
71 add_wait_queue_exclusive(&mp->wait, &wait); 54 add_wait_queue_exclusive(&mp->wait, &wait);
72 do { 55 do {
73 set_current_state(TASK_UNINTERRUPTIBLE); 56 set_current_state(TASK_UNINTERRUPTIBLE);
74 if (metapage_locked(mp)) { 57 if (metapage_locked(mp)) {
75 spin_unlock(&meta_lock); 58 unlock_page(mp->page);
76 schedule(); 59 schedule();
77 spin_lock(&meta_lock); 60 lock_page(mp->page);
78 } 61 }
79 } while (trylock_metapage(mp)); 62 } while (trylock_metapage(mp));
80 __set_current_state(TASK_RUNNING); 63 __set_current_state(TASK_RUNNING);
81 remove_wait_queue(&mp->wait, &wait); 64 remove_wait_queue(&mp->wait, &wait);
82} 65}
83 66
84/* needs meta_lock */ 67/*
68 * Must have mp->page locked
69 */
85static inline void lock_metapage(struct metapage *mp) 70static inline void lock_metapage(struct metapage *mp)
86{ 71{
87 if (trylock_metapage(mp)) 72 if (trylock_metapage(mp))
@@ -92,6 +77,110 @@ static inline void lock_metapage(struct metapage *mp)
92static kmem_cache_t *metapage_cache; 77static kmem_cache_t *metapage_cache;
93static mempool_t *metapage_mempool; 78static mempool_t *metapage_mempool;
94 79
80#define MPS_PER_PAGE (PAGE_CACHE_SIZE >> L2PSIZE)
81
82#if MPS_PER_PAGE > 1
83
84struct meta_anchor {
85 int mp_count;
86 atomic_t io_count;
87 struct metapage *mp[MPS_PER_PAGE];
88};
89#define mp_anchor(page) ((struct meta_anchor *)page->private)
90
91static inline struct metapage *page_to_mp(struct page *page, uint offset)
92{
93 if (!PagePrivate(page))
94 return NULL;
95 return mp_anchor(page)->mp[offset >> L2PSIZE];
96}
97
98static inline int insert_metapage(struct page *page, struct metapage *mp)
99{
100 struct meta_anchor *a;
101 int index;
102 int l2mp_blocks; /* log2 blocks per metapage */
103
104 if (PagePrivate(page))
105 a = mp_anchor(page);
106 else {
107 a = kmalloc(sizeof(struct meta_anchor), GFP_NOFS);
108 if (!a)
109 return -ENOMEM;
110 memset(a, 0, sizeof(struct meta_anchor));
111 page->private = (unsigned long)a;
112 SetPagePrivate(page);
113 kmap(page);
114 }
115
116 if (mp) {
117 l2mp_blocks = L2PSIZE - page->mapping->host->i_blkbits;
118 index = (mp->index >> l2mp_blocks) & (MPS_PER_PAGE - 1);
119 a->mp_count++;
120 a->mp[index] = mp;
121 }
122
123 return 0;
124}
125
126static inline void remove_metapage(struct page *page, struct metapage *mp)
127{
128 struct meta_anchor *a = mp_anchor(page);
129 int l2mp_blocks = L2PSIZE - page->mapping->host->i_blkbits;
130 int index;
131
132 index = (mp->index >> l2mp_blocks) & (MPS_PER_PAGE - 1);
133
134 BUG_ON(a->mp[index] != mp);
135
136 a->mp[index] = NULL;
137 if (--a->mp_count == 0) {
138 kfree(a);
139 page->private = 0;
140 ClearPagePrivate(page);
141 kunmap(page);
142 }
143}
144
145static inline void inc_io(struct page *page)
146{
147 atomic_inc(&mp_anchor(page)->io_count);
148}
149
150static inline void dec_io(struct page *page, void (*handler) (struct page *))
151{
152 if (atomic_dec_and_test(&mp_anchor(page)->io_count))
153 handler(page);
154}
155
156#else
157static inline struct metapage *page_to_mp(struct page *page, uint offset)
158{
159 return PagePrivate(page) ? (struct metapage *)page->private : NULL;
160}
161
162static inline int insert_metapage(struct page *page, struct metapage *mp)
163{
164 if (mp) {
165 page->private = (unsigned long)mp;
166 SetPagePrivate(page);
167 kmap(page);
168 }
169 return 0;
170}
171
172static inline void remove_metapage(struct page *page, struct metapage *mp)
173{
174 page->private = 0;
175 ClearPagePrivate(page);
176 kunmap(page);
177}
178
179#define inc_io(page) do {} while(0)
180#define dec_io(page, handler) handler(page)
181
182#endif
183
95static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags) 184static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
96{ 185{
97 struct metapage *mp = (struct metapage *)foo; 186 struct metapage *mp = (struct metapage *)foo;
@@ -139,16 +228,6 @@ int __init metapage_init(void)
139 kmem_cache_destroy(metapage_cache); 228 kmem_cache_destroy(metapage_cache);
140 return -ENOMEM; 229 return -ENOMEM;
141 } 230 }
142 /*
143 * Now the hash list
144 */
145 for (hash_order = 0;
146 ((PAGE_SIZE << hash_order) / sizeof(void *)) < HASH_SIZE;
147 hash_order++);
148 hash_table =
149 (struct metapage **) __get_free_pages(GFP_KERNEL, hash_order);
150 assert(hash_table);
151 memset(hash_table, 0, PAGE_SIZE << hash_order);
152 231
153 return 0; 232 return 0;
154} 233}
@@ -159,73 +238,388 @@ void metapage_exit(void)
159 kmem_cache_destroy(metapage_cache); 238 kmem_cache_destroy(metapage_cache);
160} 239}
161 240
241static inline void drop_metapage(struct page *page, struct metapage *mp)
242{
243 if (mp->count || mp->nohomeok || test_bit(META_dirty, &mp->flag) ||
244 test_bit(META_io, &mp->flag))
245 return;
246 remove_metapage(page, mp);
247 INCREMENT(mpStat.pagefree);
248 free_metapage(mp);
249}
250
162/* 251/*
163 * Basically same hash as in pagemap.h, but using our hash table 252 * Metapage address space operations
164 */ 253 */
165static struct metapage **meta_hash(struct address_space *mapping, 254
166 unsigned long index) 255static sector_t metapage_get_blocks(struct inode *inode, sector_t lblock,
256 unsigned int *len)
167{ 257{
168#define i (((unsigned long)mapping)/ \ 258 int rc = 0;
169 (sizeof(struct inode) & ~(sizeof(struct inode) -1 ))) 259 int xflag;
170#define s(x) ((x) + ((x) >> HASH_BITS)) 260 s64 xaddr;
171 return hash_table + (s(i + index) & (HASH_SIZE - 1)); 261 sector_t file_blocks = (inode->i_size + inode->i_blksize - 1) >>
172#undef i 262 inode->i_blkbits;
173#undef s 263
264 if (lblock >= file_blocks)
265 return 0;
266 if (lblock + *len > file_blocks)
267 *len = file_blocks - lblock;
268
269 if (inode->i_ino) {
270 rc = xtLookup(inode, (s64)lblock, *len, &xflag, &xaddr, len, 0);
271 if ((rc == 0) && *len)
272 lblock = (sector_t)xaddr;
273 else
274 lblock = 0;
275 } /* else no mapping */
276
277 return lblock;
174} 278}
175 279
176static struct metapage *search_hash(struct metapage ** hash_ptr, 280static void last_read_complete(struct page *page)
177 struct address_space *mapping,
178 unsigned long index)
179{ 281{
180 struct metapage *ptr; 282 if (!PageError(page))
283 SetPageUptodate(page);
284 unlock_page(page);
285}
286
287static int metapage_read_end_io(struct bio *bio, unsigned int bytes_done,
288 int err)
289{
290 struct page *page = bio->bi_private;
291
292 if (bio->bi_size)
293 return 1;
181 294
182 for (ptr = *hash_ptr; ptr; ptr = ptr->hash_next) { 295 if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) {
183 if ((ptr->mapping == mapping) && (ptr->index == index)) 296 printk(KERN_ERR "metapage_read_end_io: I/O error\n");
184 return ptr; 297 SetPageError(page);
185 } 298 }
186 299
187 return NULL; 300 dec_io(page, last_read_complete);
301 bio_put(bio);
302
303 return 0;
188} 304}
189 305
190static void add_to_hash(struct metapage * mp, struct metapage ** hash_ptr) 306static void remove_from_logsync(struct metapage *mp)
191{ 307{
192 if (*hash_ptr) 308 struct jfs_log *log = mp->log;
193 (*hash_ptr)->hash_prev = mp; 309 unsigned long flags;
310/*
311 * This can race. Recheck that log hasn't been set to null, and after
312 * acquiring logsync lock, recheck lsn
313 */
314 if (!log)
315 return;
316
317 LOGSYNC_LOCK(log, flags);
318 if (mp->lsn) {
319 mp->log = NULL;
320 mp->lsn = 0;
321 mp->clsn = 0;
322 log->count--;
323 list_del(&mp->synclist);
324 }
325 LOGSYNC_UNLOCK(log, flags);
326}
194 327
195 mp->hash_prev = NULL; 328static void last_write_complete(struct page *page)
196 mp->hash_next = *hash_ptr; 329{
197 *hash_ptr = mp; 330 struct metapage *mp;
331 unsigned int offset;
332
333 for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) {
334 mp = page_to_mp(page, offset);
335 if (mp && test_bit(META_io, &mp->flag)) {
336 if (mp->lsn)
337 remove_from_logsync(mp);
338 clear_bit(META_io, &mp->flag);
339 }
340 /*
341 * I'd like to call drop_metapage here, but I don't think it's
342 * safe unless I have the page locked
343 */
344 }
345 end_page_writeback(page);
198} 346}
199 347
200static void remove_from_hash(struct metapage * mp, struct metapage ** hash_ptr) 348static int metapage_write_end_io(struct bio *bio, unsigned int bytes_done,
349 int err)
201{ 350{
202 if (mp->hash_prev) 351 struct page *page = bio->bi_private;
203 mp->hash_prev->hash_next = mp->hash_next; 352
204 else { 353 BUG_ON(!PagePrivate(page));
205 assert(*hash_ptr == mp); 354
206 *hash_ptr = mp->hash_next; 355 if (bio->bi_size)
356 return 1;
357
358 if (! test_bit(BIO_UPTODATE, &bio->bi_flags)) {
359 printk(KERN_ERR "metapage_write_end_io: I/O error\n");
360 SetPageError(page);
361 }
362 dec_io(page, last_write_complete);
363 bio_put(bio);
364 return 0;
365}
366
367static int metapage_writepage(struct page *page, struct writeback_control *wbc)
368{
369 struct bio *bio = NULL;
370 unsigned int block_offset; /* block offset of mp within page */
371 struct inode *inode = page->mapping->host;
372 unsigned int blocks_per_mp = JFS_SBI(inode->i_sb)->nbperpage;
373 unsigned int len;
374 unsigned int xlen;
375 struct metapage *mp;
376 int redirty = 0;
377 sector_t lblock;
378 sector_t pblock;
379 sector_t next_block = 0;
380 sector_t page_start;
381 unsigned long bio_bytes = 0;
382 unsigned long bio_offset = 0;
383 unsigned int offset;
384
385 page_start = (sector_t)page->index <<
386 (PAGE_CACHE_SHIFT - inode->i_blkbits);
387 BUG_ON(!PageLocked(page));
388 BUG_ON(PageWriteback(page));
389
390 for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) {
391 mp = page_to_mp(page, offset);
392
393 if (!mp || !test_bit(META_dirty, &mp->flag))
394 continue;
395
396 if (mp->nohomeok && !test_bit(META_forcewrite, &mp->flag)) {
397 redirty = 1;
398 continue;
399 }
400
401 clear_bit(META_dirty, &mp->flag);
402 block_offset = offset >> inode->i_blkbits;
403 lblock = page_start + block_offset;
404 if (bio) {
405 if (xlen && lblock == next_block) {
406 /* Contiguous, in memory & on disk */
407 len = min(xlen, blocks_per_mp);
408 xlen -= len;
409 bio_bytes += len << inode->i_blkbits;
410 set_bit(META_io, &mp->flag);
411 continue;
412 }
413 /* Not contiguous */
414 if (bio_add_page(bio, page, bio_bytes, bio_offset) <
415 bio_bytes)
416 goto add_failed;
417 /*
418 * Increment counter before submitting i/o to keep
419 * count from hitting zero before we're through
420 */
421 inc_io(page);
422 if (!bio->bi_size)
423 goto dump_bio;
424 submit_bio(WRITE, bio);
425 bio = NULL;
426 } else {
427 set_page_writeback(page);
428 inc_io(page);
429 }
430 xlen = (PAGE_CACHE_SIZE - offset) >> inode->i_blkbits;
431 pblock = metapage_get_blocks(inode, lblock, &xlen);
432 if (!pblock) {
433 /* Need better error handling */
434 printk(KERN_ERR "JFS: metapage_get_blocks failed\n");
435 dec_io(page, last_write_complete);
436 continue;
437 }
438 set_bit(META_io, &mp->flag);
439 len = min(xlen, (uint) JFS_SBI(inode->i_sb)->nbperpage);
440
441 bio = bio_alloc(GFP_NOFS, 1);
442 bio->bi_bdev = inode->i_sb->s_bdev;
443 bio->bi_sector = pblock << (inode->i_blkbits - 9);
444 bio->bi_end_io = metapage_write_end_io;
445 bio->bi_private = page;
446
447 /* Don't call bio_add_page yet, we may add to this vec */
448 bio_offset = offset;
449 bio_bytes = len << inode->i_blkbits;
450
451 xlen -= len;
452 next_block = lblock + len;
453 }
454 if (bio) {
455 if (bio_add_page(bio, page, bio_bytes, bio_offset) < bio_bytes)
456 goto add_failed;
457 if (!bio->bi_size)
458 goto dump_bio;
459
460 submit_bio(WRITE, bio);
461 }
462 if (redirty)
463 redirty_page_for_writepage(wbc, page);
464
465 unlock_page(page);
466
467 return 0;
468add_failed:
469 /* We should never reach here, since we're only adding one vec */
470 printk(KERN_ERR "JFS: bio_add_page failed unexpectedly\n");
471 goto skip;
472dump_bio:
473 dump_mem("bio", bio, sizeof(*bio));
474skip:
475 bio_put(bio);
476 unlock_page(page);
477 dec_io(page, last_write_complete);
478
479 return -EIO;
480}
481
482static int metapage_readpage(struct file *fp, struct page *page)
483{
484 struct inode *inode = page->mapping->host;
485 struct bio *bio = NULL;
486 unsigned int block_offset;
487 unsigned int blocks_per_page = PAGE_CACHE_SIZE >> inode->i_blkbits;
488 sector_t page_start; /* address of page in fs blocks */
489 sector_t pblock;
490 unsigned int xlen;
491 unsigned int len;
492 unsigned int offset;
493
494 BUG_ON(!PageLocked(page));
495 page_start = (sector_t)page->index <<
496 (PAGE_CACHE_SHIFT - inode->i_blkbits);
497
498 block_offset = 0;
499 while (block_offset < blocks_per_page) {
500 xlen = blocks_per_page - block_offset;
501 pblock = metapage_get_blocks(inode, page_start + block_offset,
502 &xlen);
503 if (pblock) {
504 if (!PagePrivate(page))
505 insert_metapage(page, NULL);
506 inc_io(page);
507 if (bio)
508 submit_bio(READ, bio);
509
510 bio = bio_alloc(GFP_NOFS, 1);
511 bio->bi_bdev = inode->i_sb->s_bdev;
512 bio->bi_sector = pblock << (inode->i_blkbits - 9);
513 bio->bi_end_io = metapage_read_end_io;
514 bio->bi_private = page;
515 len = xlen << inode->i_blkbits;
516 offset = block_offset << inode->i_blkbits;
517 if (bio_add_page(bio, page, len, offset) < len)
518 goto add_failed;
519 block_offset += xlen;
520 } else
521 block_offset++;
207 } 522 }
523 if (bio)
524 submit_bio(READ, bio);
525 else
526 unlock_page(page);
527
528 return 0;
208 529
209 if (mp->hash_next) 530add_failed:
210 mp->hash_next->hash_prev = mp->hash_prev; 531 printk(KERN_ERR "JFS: bio_add_page failed unexpectedly\n");
532 bio_put(bio);
533 dec_io(page, last_read_complete);
534 return -EIO;
211} 535}
212 536
537static int metapage_releasepage(struct page *page, int gfp_mask)
538{
539 struct metapage *mp;
540 int busy = 0;
541 unsigned int offset;
542
543 for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) {
544 mp = page_to_mp(page, offset);
545
546 if (!mp)
547 continue;
548
549 jfs_info("metapage_releasepage: mp = 0x%p", mp);
550 if (mp->count || mp->nohomeok) {
551 jfs_info("count = %ld, nohomeok = %d", mp->count,
552 mp->nohomeok);
553 busy = 1;
554 continue;
555 }
556 wait_on_page_writeback(page);
557 //WARN_ON(test_bit(META_dirty, &mp->flag));
558 if (test_bit(META_dirty, &mp->flag)) {
559 dump_mem("dirty mp in metapage_releasepage", mp,
560 sizeof(struct metapage));
561 dump_mem("page", page, sizeof(struct page));
562 dump_stack();
563 }
564 WARN_ON(mp->lsn);
565 if (mp->lsn)
566 remove_from_logsync(mp);
567 remove_metapage(page, mp);
568 INCREMENT(mpStat.pagefree);
569 free_metapage(mp);
570 }
571 if (busy)
572 return -1;
573
574 return 0;
575}
576
577static int metapage_invalidatepage(struct page *page, unsigned long offset)
578{
579 BUG_ON(offset);
580
581 if (PageWriteback(page))
582 return 0;
583
584 return metapage_releasepage(page, 0);
585}
586
587struct address_space_operations jfs_metapage_aops = {
588 .readpage = metapage_readpage,
589 .writepage = metapage_writepage,
590 .sync_page = block_sync_page,
591 .releasepage = metapage_releasepage,
592 .invalidatepage = metapage_invalidatepage,
593 .set_page_dirty = __set_page_dirty_nobuffers,
594};
595
213struct metapage *__get_metapage(struct inode *inode, unsigned long lblock, 596struct metapage *__get_metapage(struct inode *inode, unsigned long lblock,
214 unsigned int size, int absolute, 597 unsigned int size, int absolute,
215 unsigned long new) 598 unsigned long new)
216{ 599{
217 struct metapage **hash_ptr;
218 int l2BlocksPerPage; 600 int l2BlocksPerPage;
219 int l2bsize; 601 int l2bsize;
220 struct address_space *mapping; 602 struct address_space *mapping;
221 struct metapage *mp; 603 struct metapage *mp = NULL;
604 struct page *page;
222 unsigned long page_index; 605 unsigned long page_index;
223 unsigned long page_offset; 606 unsigned long page_offset;
224 607
225 jfs_info("__get_metapage: inode = 0x%p, lblock = 0x%lx", inode, lblock); 608 jfs_info("__get_metapage: ino = %ld, lblock = 0x%lx, abs=%d",
226 609 inode->i_ino, lblock, absolute);
610
611 l2bsize = inode->i_blkbits;
612 l2BlocksPerPage = PAGE_CACHE_SHIFT - l2bsize;
613 page_index = lblock >> l2BlocksPerPage;
614 page_offset = (lblock - (page_index << l2BlocksPerPage)) << l2bsize;
615 if ((page_offset + size) > PAGE_CACHE_SIZE) {
616 jfs_err("MetaData crosses page boundary!!");
617 jfs_err("lblock = %lx, size = %d", lblock, size);
618 dump_stack();
619 return NULL;
620 }
227 if (absolute) 621 if (absolute)
228 mapping = inode->i_sb->s_bdev->bd_inode->i_mapping; 622 mapping = JFS_SBI(inode->i_sb)->direct_inode->i_mapping;
229 else { 623 else {
230 /* 624 /*
231 * If an nfs client tries to read an inode that is larger 625 * If an nfs client tries to read an inode that is larger
@@ -237,312 +631,212 @@ struct metapage *__get_metapage(struct inode *inode, unsigned long lblock,
237 mapping = inode->i_mapping; 631 mapping = inode->i_mapping;
238 } 632 }
239 633
240 hash_ptr = meta_hash(mapping, lblock); 634 if (new && (PSIZE == PAGE_CACHE_SIZE)) {
241again: 635 page = grab_cache_page(mapping, page_index);
242 spin_lock(&meta_lock); 636 if (!page) {
243 mp = search_hash(hash_ptr, mapping, lblock); 637 jfs_err("grab_cache_page failed!");
638 return NULL;
639 }
640 SetPageUptodate(page);
641 } else {
642 page = read_cache_page(mapping, page_index,
643 (filler_t *)mapping->a_ops->readpage, NULL);
644 if (IS_ERR(page)) {
645 jfs_err("read_cache_page failed!");
646 return NULL;
647 }
648 lock_page(page);
649 }
650
651 mp = page_to_mp(page, page_offset);
244 if (mp) { 652 if (mp) {
245 page_found: 653 if (mp->logical_size != size) {
246 if (test_bit(META_stale, &mp->flag)) { 654 jfs_error(inode->i_sb,
247 spin_unlock(&meta_lock); 655 "__get_metapage: mp->logical_size != size");
248 msleep(1); 656 jfs_err("logical_size = %d, size = %d",
249 goto again; 657 mp->logical_size, size);
658 dump_stack();
659 goto unlock;
250 } 660 }
251 mp->count++; 661 mp->count++;
252 lock_metapage(mp); 662 lock_metapage(mp);
253 spin_unlock(&meta_lock);
254 if (test_bit(META_discard, &mp->flag)) { 663 if (test_bit(META_discard, &mp->flag)) {
255 if (!new) { 664 if (!new) {
256 jfs_error(inode->i_sb, 665 jfs_error(inode->i_sb,
257 "__get_metapage: using a " 666 "__get_metapage: using a "
258 "discarded metapage"); 667 "discarded metapage");
259 release_metapage(mp); 668 discard_metapage(mp);
260 return NULL; 669 goto unlock;
261 } 670 }
262 clear_bit(META_discard, &mp->flag); 671 clear_bit(META_discard, &mp->flag);
263 } 672 }
264 jfs_info("__get_metapage: found 0x%p, in hash", mp);
265 if (mp->logical_size != size) {
266 jfs_error(inode->i_sb,
267 "__get_metapage: mp->logical_size != size");
268 release_metapage(mp);
269 return NULL;
270 }
271 } else { 673 } else {
272 l2bsize = inode->i_blkbits; 674 INCREMENT(mpStat.pagealloc);
273 l2BlocksPerPage = PAGE_CACHE_SHIFT - l2bsize; 675 mp = alloc_metapage(GFP_NOFS);
274 page_index = lblock >> l2BlocksPerPage; 676 mp->page = page;
275 page_offset = (lblock - (page_index << l2BlocksPerPage)) <<
276 l2bsize;
277 if ((page_offset + size) > PAGE_CACHE_SIZE) {
278 spin_unlock(&meta_lock);
279 jfs_err("MetaData crosses page boundary!!");
280 return NULL;
281 }
282
283 /*
284 * Locks held on aggregate inode pages are usually
285 * not held long, and they are taken in critical code
286 * paths (committing dirty inodes, txCommit thread)
287 *
288 * Attempt to get metapage without blocking, tapping into
289 * reserves if necessary.
290 */
291 mp = NULL;
292 if (JFS_IP(inode)->fileset == AGGREGATE_I) {
293 mp = alloc_metapage(GFP_ATOMIC);
294 if (!mp) {
295 /*
296 * mempool is supposed to protect us from
297 * failing here. We will try a blocking
298 * call, but a deadlock is possible here
299 */
300 printk(KERN_WARNING
301 "__get_metapage: atomic call to mempool_alloc failed.\n");
302 printk(KERN_WARNING
303 "Will attempt blocking call\n");
304 }
305 }
306 if (!mp) {
307 struct metapage *mp2;
308
309 spin_unlock(&meta_lock);
310 mp = alloc_metapage(GFP_NOFS);
311 spin_lock(&meta_lock);
312
313 /* we dropped the meta_lock, we need to search the
314 * hash again.
315 */
316 mp2 = search_hash(hash_ptr, mapping, lblock);
317 if (mp2) {
318 free_metapage(mp);
319 mp = mp2;
320 goto page_found;
321 }
322 }
323 mp->flag = 0; 677 mp->flag = 0;
324 lock_metapage(mp);
325 if (absolute)
326 set_bit(META_absolute, &mp->flag);
327 mp->xflag = COMMIT_PAGE; 678 mp->xflag = COMMIT_PAGE;
328 mp->count = 1; 679 mp->count = 1;
329 atomic_set(&mp->nohomeok,0); 680 mp->nohomeok = 0;
330 mp->mapping = mapping;
331 mp->index = lblock;
332 mp->page = NULL;
333 mp->logical_size = size; 681 mp->logical_size = size;
334 add_to_hash(mp, hash_ptr); 682 mp->data = page_address(page) + page_offset;
335 spin_unlock(&meta_lock); 683 mp->index = lblock;
336 684 if (unlikely(insert_metapage(page, mp))) {
337 if (new) { 685 free_metapage(mp);
338 jfs_info("__get_metapage: Calling grab_cache_page"); 686 goto unlock;
339 mp->page = grab_cache_page(mapping, page_index);
340 if (!mp->page) {
341 jfs_err("grab_cache_page failed!");
342 goto freeit;
343 } else {
344 INCREMENT(mpStat.pagealloc);
345 unlock_page(mp->page);
346 }
347 } else {
348 jfs_info("__get_metapage: Calling read_cache_page");
349 mp->page = read_cache_page(mapping, lblock,
350 (filler_t *)mapping->a_ops->readpage, NULL);
351 if (IS_ERR(mp->page)) {
352 jfs_err("read_cache_page failed!");
353 goto freeit;
354 } else
355 INCREMENT(mpStat.pagealloc);
356 } 687 }
357 mp->data = kmap(mp->page) + page_offset; 688 lock_metapage(mp);
358 } 689 }
359 690
360 if (new) 691 if (new) {
692 jfs_info("zeroing mp = 0x%p", mp);
361 memset(mp->data, 0, PSIZE); 693 memset(mp->data, 0, PSIZE);
694 }
362 695
363 jfs_info("__get_metapage: returning = 0x%p", mp); 696 unlock_page(page);
697 jfs_info("__get_metapage: returning = 0x%p data = 0x%p", mp, mp->data);
364 return mp; 698 return mp;
365 699
366freeit: 700unlock:
367 spin_lock(&meta_lock); 701 unlock_page(page);
368 remove_from_hash(mp, hash_ptr);
369 free_metapage(mp);
370 spin_unlock(&meta_lock);
371 return NULL; 702 return NULL;
372} 703}
373 704
374void hold_metapage(struct metapage * mp, int force) 705void grab_metapage(struct metapage * mp)
375{ 706{
376 spin_lock(&meta_lock); 707 jfs_info("grab_metapage: mp = 0x%p", mp);
377 708 page_cache_get(mp->page);
709 lock_page(mp->page);
378 mp->count++; 710 mp->count++;
379 711 lock_metapage(mp);
380 if (force) { 712 unlock_page(mp->page);
381 ASSERT (!(test_bit(META_forced, &mp->flag)));
382 if (trylock_metapage(mp))
383 set_bit(META_forced, &mp->flag);
384 } else
385 lock_metapage(mp);
386
387 spin_unlock(&meta_lock);
388} 713}
389 714
390static void __write_metapage(struct metapage * mp) 715void force_metapage(struct metapage *mp)
391{ 716{
392 int l2bsize = mp->mapping->host->i_blkbits; 717 struct page *page = mp->page;
393 int l2BlocksPerPage = PAGE_CACHE_SHIFT - l2bsize; 718 jfs_info("force_metapage: mp = 0x%p", mp);
394 unsigned long page_index; 719 set_bit(META_forcewrite, &mp->flag);
395 unsigned long page_offset; 720 clear_bit(META_sync, &mp->flag);
396 int rc; 721 page_cache_get(page);
397 722 lock_page(page);
398 jfs_info("__write_metapage: mp = 0x%p", mp); 723 set_page_dirty(page);
399 724 write_one_page(page, 1);
400 page_index = mp->page->index; 725 clear_bit(META_forcewrite, &mp->flag);
401 page_offset = 726 page_cache_release(page);
402 (mp->index - (page_index << l2BlocksPerPage)) << l2bsize; 727}
403 728
729extern void hold_metapage(struct metapage *mp)
730{
404 lock_page(mp->page); 731 lock_page(mp->page);
405 rc = mp->mapping->a_ops->prepare_write(NULL, mp->page, page_offset, 732}
406 page_offset + 733
407 mp->logical_size); 734extern void put_metapage(struct metapage *mp)
408 if (rc) { 735{
409 jfs_err("prepare_write return %d!", rc); 736 if (mp->count || mp->nohomeok) {
410 ClearPageUptodate(mp->page); 737 /* Someone else will release this */
411 unlock_page(mp->page); 738 unlock_page(mp->page);
412 clear_bit(META_dirty, &mp->flag);
413 return; 739 return;
414 } 740 }
415 rc = mp->mapping->a_ops->commit_write(NULL, mp->page, page_offset, 741 page_cache_get(mp->page);
416 page_offset + 742 mp->count++;
417 mp->logical_size); 743 lock_metapage(mp);
418 if (rc) {
419 jfs_err("commit_write returned %d", rc);
420 }
421
422 unlock_page(mp->page); 744 unlock_page(mp->page);
423 clear_bit(META_dirty, &mp->flag); 745 release_metapage(mp);
424
425 jfs_info("__write_metapage done");
426}
427
428static inline void sync_metapage(struct metapage *mp)
429{
430 struct page *page = mp->page;
431
432 page_cache_get(page);
433 lock_page(page);
434
435 /* we're done with this page - no need to check for errors */
436 if (page_has_buffers(page))
437 write_one_page(page, 1);
438 else
439 unlock_page(page);
440 page_cache_release(page);
441} 746}
442 747
443void release_metapage(struct metapage * mp) 748void release_metapage(struct metapage * mp)
444{ 749{
445 struct jfs_log *log; 750 struct page *page = mp->page;
446
447 jfs_info("release_metapage: mp = 0x%p, flag = 0x%lx", mp, mp->flag); 751 jfs_info("release_metapage: mp = 0x%p, flag = 0x%lx", mp, mp->flag);
448 752
449 spin_lock(&meta_lock); 753 BUG_ON(!page);
450 if (test_bit(META_forced, &mp->flag)) { 754
451 clear_bit(META_forced, &mp->flag); 755 lock_page(page);
452 mp->count--; 756 unlock_metapage(mp);
453 spin_unlock(&meta_lock);
454 return;
455 }
456 757
457 assert(mp->count); 758 assert(mp->count);
458 if (--mp->count || atomic_read(&mp->nohomeok)) { 759 if (--mp->count || mp->nohomeok) {
459 unlock_metapage(mp); 760 unlock_page(page);
460 spin_unlock(&meta_lock); 761 page_cache_release(page);
461 return; 762 return;
462 } 763 }
463 764
464 if (mp->page) { 765 if (test_bit(META_dirty, &mp->flag)) {
465 set_bit(META_stale, &mp->flag); 766 set_page_dirty(page);
466 spin_unlock(&meta_lock);
467 kunmap(mp->page);
468 mp->data = NULL;
469 if (test_bit(META_dirty, &mp->flag))
470 __write_metapage(mp);
471 if (test_bit(META_sync, &mp->flag)) { 767 if (test_bit(META_sync, &mp->flag)) {
472 sync_metapage(mp);
473 clear_bit(META_sync, &mp->flag); 768 clear_bit(META_sync, &mp->flag);
769 write_one_page(page, 1);
770 lock_page(page); /* write_one_page unlocks the page */
474 } 771 }
772 } else if (mp->lsn) /* discard_metapage doesn't remove it */
773 remove_from_logsync(mp);
475 774
476 if (test_bit(META_discard, &mp->flag)) { 775#if MPS_PER_PAGE == 1
477 lock_page(mp->page); 776 /*
478 block_invalidatepage(mp->page, 0); 777 * If we know this is the only thing in the page, we can throw
479 unlock_page(mp->page); 778 * the page out of the page cache. If pages are larger, we
480 } 779 * don't want to do this.
481 780 */
482 page_cache_release(mp->page);
483 mp->page = NULL;
484 INCREMENT(mpStat.pagefree);
485 spin_lock(&meta_lock);
486 }
487 781
488 if (mp->lsn) { 782 /* Retest mp->count since we may have released page lock */
489 /* 783 if (test_bit(META_discard, &mp->flag) && !mp->count) {
490 * Remove metapage from logsynclist. 784 clear_page_dirty(page);
491 */ 785 ClearPageUptodate(page);
492 log = mp->log; 786#ifdef _NOT_YET
493 LOGSYNC_LOCK(log); 787 if (page->mapping) {
494 mp->log = NULL; 788 /* Remove from page cache and page cache reference */
495 mp->lsn = 0; 789 remove_from_page_cache(page);
496 mp->clsn = 0; 790 page_cache_release(page);
497 log->count--; 791 metapage_releasepage(page, 0);
498 list_del(&mp->synclist); 792 }
499 LOGSYNC_UNLOCK(log); 793#endif
500 } 794 }
501 remove_from_hash(mp, meta_hash(mp->mapping, mp->index)); 795#else
502 spin_unlock(&meta_lock); 796 /* Try to keep metapages from using up too much memory */
503 797 drop_metapage(page, mp);
504 free_metapage(mp); 798#endif
799 unlock_page(page);
800 page_cache_release(page);
505} 801}
506 802
507void __invalidate_metapages(struct inode *ip, s64 addr, int len) 803void __invalidate_metapages(struct inode *ip, s64 addr, int len)
508{ 804{
509 struct metapage **hash_ptr; 805 sector_t lblock;
510 unsigned long lblock;
511 int l2BlocksPerPage = PAGE_CACHE_SHIFT - ip->i_blkbits; 806 int l2BlocksPerPage = PAGE_CACHE_SHIFT - ip->i_blkbits;
807 int BlocksPerPage = 1 << l2BlocksPerPage;
512 /* All callers are interested in block device's mapping */ 808 /* All callers are interested in block device's mapping */
513 struct address_space *mapping = ip->i_sb->s_bdev->bd_inode->i_mapping; 809 struct address_space *mapping =
810 JFS_SBI(ip->i_sb)->direct_inode->i_mapping;
514 struct metapage *mp; 811 struct metapage *mp;
515 struct page *page; 812 struct page *page;
813 unsigned int offset;
516 814
517 /* 815 /*
518 * First, mark metapages to discard. They will eventually be 816 * Mark metapages to discard. They will eventually be
519 * released, but should not be written. 817 * released, but should not be written.
520 */ 818 */
521 for (lblock = addr; lblock < addr + len; 819 for (lblock = addr & ~(BlocksPerPage - 1); lblock < addr + len;
522 lblock += 1 << l2BlocksPerPage) { 820 lblock += BlocksPerPage) {
523 hash_ptr = meta_hash(mapping, lblock); 821 page = find_lock_page(mapping, lblock >> l2BlocksPerPage);
524again: 822 if (!page)
525 spin_lock(&meta_lock); 823 continue;
526 mp = search_hash(hash_ptr, mapping, lblock); 824 for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) {
527 if (mp) { 825 mp = page_to_mp(page, offset);
528 if (test_bit(META_stale, &mp->flag)) { 826 if (!mp)
529 spin_unlock(&meta_lock); 827 continue;
530 msleep(1); 828 if (mp->index < addr)
531 goto again; 829 continue;
532 } 830 if (mp->index >= addr + len)
831 break;
533 832
534 clear_bit(META_dirty, &mp->flag); 833 clear_bit(META_dirty, &mp->flag);
535 set_bit(META_discard, &mp->flag); 834 set_bit(META_discard, &mp->flag);
536 spin_unlock(&meta_lock); 835 if (mp->lsn)
537 } else { 836 remove_from_logsync(mp);
538 spin_unlock(&meta_lock);
539 page = find_lock_page(mapping, lblock>>l2BlocksPerPage);
540 if (page) {
541 block_invalidatepage(page, 0);
542 unlock_page(page);
543 page_cache_release(page);
544 }
545 } 837 }
838 unlock_page(page);
839 page_cache_release(page);
546 } 840 }
547} 841}
548 842
diff --git a/fs/jfs/jfs_metapage.h b/fs/jfs/jfs_metapage.h
index 0e58aba58c37..991e9fb84c75 100644
--- a/fs/jfs/jfs_metapage.h
+++ b/fs/jfs/jfs_metapage.h
@@ -33,38 +33,27 @@ struct metapage {
33 unsigned long flag; /* See Below */ 33 unsigned long flag; /* See Below */
34 unsigned long count; /* Reference count */ 34 unsigned long count; /* Reference count */
35 void *data; /* Data pointer */ 35 void *data; /* Data pointer */
36 36 sector_t index; /* block address of page */
37 /* list management stuff */
38 struct metapage *hash_prev;
39 struct metapage *hash_next; /* Also used for free list */
40
41 /*
42 * mapping & index become redundant, but we need these here to
43 * add the metapage to the hash before we have the real page
44 */
45 struct address_space *mapping;
46 unsigned long index;
47 wait_queue_head_t wait; 37 wait_queue_head_t wait;
48 38
49 /* implementation */ 39 /* implementation */
50 struct page *page; 40 struct page *page;
51 unsigned long logical_size; 41 unsigned int logical_size;
52 42
53 /* Journal management */ 43 /* Journal management */
54 int clsn; 44 int clsn;
55 atomic_t nohomeok; 45 int nohomeok;
56 struct jfs_log *log; 46 struct jfs_log *log;
57}; 47};
58 48
59/* metapage flag */ 49/* metapage flag */
60#define META_locked 0 50#define META_locked 0
61#define META_absolute 1 51#define META_free 1
62#define META_free 2 52#define META_dirty 2
63#define META_dirty 3 53#define META_sync 3
64#define META_sync 4 54#define META_discard 4
65#define META_discard 5 55#define META_forcewrite 5
66#define META_forced 6 56#define META_io 6
67#define META_stale 7
68 57
69#define mark_metapage_dirty(mp) set_bit(META_dirty, &(mp)->flag) 58#define mark_metapage_dirty(mp) set_bit(META_dirty, &(mp)->flag)
70 59
@@ -80,7 +69,16 @@ extern struct metapage *__get_metapage(struct inode *inode,
80 __get_metapage(inode, lblock, size, absolute, TRUE) 69 __get_metapage(inode, lblock, size, absolute, TRUE)
81 70
82extern void release_metapage(struct metapage *); 71extern void release_metapage(struct metapage *);
83extern void hold_metapage(struct metapage *, int); 72extern void grab_metapage(struct metapage *);
73extern void force_metapage(struct metapage *);
74
75/*
76 * hold_metapage and put_metapage are used in conjuction. The page lock
77 * is not dropped between the two, so no other threads can get or release
78 * the metapage
79 */
80extern void hold_metapage(struct metapage *);
81extern void put_metapage(struct metapage *);
84 82
85static inline void write_metapage(struct metapage *mp) 83static inline void write_metapage(struct metapage *mp)
86{ 84{
@@ -101,6 +99,46 @@ static inline void discard_metapage(struct metapage *mp)
101 release_metapage(mp); 99 release_metapage(mp);
102} 100}
103 101
102static inline void metapage_nohomeok(struct metapage *mp)
103{
104 struct page *page = mp->page;
105 lock_page(page);
106 if (!mp->nohomeok++) {
107 mark_metapage_dirty(mp);
108 page_cache_get(page);
109 wait_on_page_writeback(page);
110 }
111 unlock_page(page);
112}
113
114/*
115 * This serializes access to mp->lsn when metapages are added to logsynclist
116 * without setting nohomeok. i.e. updating imap & dmap
117 */
118static inline void metapage_wait_for_io(struct metapage *mp)
119{
120 if (test_bit(META_io, &mp->flag))
121 wait_on_page_writeback(mp->page);
122}
123
124/*
125 * This is called when already holding the metapage
126 */
127static inline void _metapage_homeok(struct metapage *mp)
128{
129 if (!--mp->nohomeok)
130 page_cache_release(mp->page);
131}
132
133static inline void metapage_homeok(struct metapage *mp)
134{
135 hold_metapage(mp);
136 _metapage_homeok(mp);
137 put_metapage(mp);
138}
139
140extern struct address_space_operations jfs_metapage_aops;
141
104/* 142/*
105 * This routines invalidate all pages for an extent. 143 * This routines invalidate all pages for an extent.
106 */ 144 */
diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c
index c535ffd638e8..032d111bc330 100644
--- a/fs/jfs/jfs_mount.c
+++ b/fs/jfs/jfs_mount.c
@@ -285,11 +285,6 @@ int jfs_mount_rw(struct super_block *sb, int remount)
285 */ 285 */
286 logMOUNT(sb); 286 logMOUNT(sb);
287 287
288 /*
289 * Set page cache allocation policy
290 */
291 mapping_set_gfp_mask(sb->s_bdev->bd_inode->i_mapping, GFP_NOFS);
292
293 return rc; 288 return rc;
294} 289}
295 290
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index 98e16d93e146..bbc9c1407b55 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -227,6 +227,7 @@ static lid_t txLockAlloc(void)
227 227
228static void txLockFree(lid_t lid) 228static void txLockFree(lid_t lid)
229{ 229{
230 TxLock[lid].tid = 0;
230 TxLock[lid].next = TxAnchor.freelock; 231 TxLock[lid].next = TxAnchor.freelock;
231 TxAnchor.freelock = lid; 232 TxAnchor.freelock = lid;
232 TxAnchor.tlocksInUse--; 233 TxAnchor.tlocksInUse--;
@@ -633,8 +634,10 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
633 634
634 /* is page locked by the requester transaction ? */ 635 /* is page locked by the requester transaction ? */
635 tlck = lid_to_tlock(lid); 636 tlck = lid_to_tlock(lid);
636 if ((xtid = tlck->tid) == tid) 637 if ((xtid = tlck->tid) == tid) {
638 TXN_UNLOCK();
637 goto grantLock; 639 goto grantLock;
640 }
638 641
639 /* 642 /*
640 * is page locked by anonymous transaction/lock ? 643 * is page locked by anonymous transaction/lock ?
@@ -649,6 +652,7 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
649 */ 652 */
650 if (xtid == 0) { 653 if (xtid == 0) {
651 tlck->tid = tid; 654 tlck->tid = tid;
655 TXN_UNLOCK();
652 tblk = tid_to_tblock(tid); 656 tblk = tid_to_tblock(tid);
653 /* 657 /*
654 * The order of the tlocks in the transaction is important 658 * The order of the tlocks in the transaction is important
@@ -706,17 +710,18 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
706 */ 710 */
707 tlck->tid = tid; 711 tlck->tid = tid;
708 712
713 TXN_UNLOCK();
714
709 /* mark tlock for meta-data page */ 715 /* mark tlock for meta-data page */
710 if (mp->xflag & COMMIT_PAGE) { 716 if (mp->xflag & COMMIT_PAGE) {
711 717
712 tlck->flag = tlckPAGELOCK; 718 tlck->flag = tlckPAGELOCK;
713 719
714 /* mark the page dirty and nohomeok */ 720 /* mark the page dirty and nohomeok */
715 mark_metapage_dirty(mp); 721 metapage_nohomeok(mp);
716 atomic_inc(&mp->nohomeok);
717 722
718 jfs_info("locking mp = 0x%p, nohomeok = %d tid = %d tlck = 0x%p", 723 jfs_info("locking mp = 0x%p, nohomeok = %d tid = %d tlck = 0x%p",
719 mp, atomic_read(&mp->nohomeok), tid, tlck); 724 mp, mp->nohomeok, tid, tlck);
720 725
721 /* if anonymous transaction, and buffer is on the group 726 /* if anonymous transaction, and buffer is on the group
722 * commit synclist, mark inode to show this. This will 727 * commit synclist, mark inode to show this. This will
@@ -762,8 +767,10 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
762 if (tlck->next == 0) { 767 if (tlck->next == 0) {
763 /* This inode's first anonymous transaction */ 768 /* This inode's first anonymous transaction */
764 jfs_ip->atltail = lid; 769 jfs_ip->atltail = lid;
770 TXN_LOCK();
765 list_add_tail(&jfs_ip->anon_inode_list, 771 list_add_tail(&jfs_ip->anon_inode_list,
766 &TxAnchor.anon_list); 772 &TxAnchor.anon_list);
773 TXN_UNLOCK();
767 } 774 }
768 } 775 }
769 776
@@ -821,8 +828,6 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
821 grantLock: 828 grantLock:
822 tlck->type |= type; 829 tlck->type |= type;
823 830
824 TXN_UNLOCK();
825
826 return tlck; 831 return tlck;
827 832
828 /* 833 /*
@@ -841,11 +846,19 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
841 BUG(); 846 BUG();
842 } 847 }
843 INCREMENT(stattx.waitlock); /* statistics */ 848 INCREMENT(stattx.waitlock); /* statistics */
849 TXN_UNLOCK();
844 release_metapage(mp); 850 release_metapage(mp);
851 TXN_LOCK();
852 xtid = tlck->tid; /* reaquire after dropping TXN_LOCK */
845 853
846 jfs_info("txLock: in waitLock, tid = %d, xtid = %d, lid = %d", 854 jfs_info("txLock: in waitLock, tid = %d, xtid = %d, lid = %d",
847 tid, xtid, lid); 855 tid, xtid, lid);
848 TXN_SLEEP_DROP_LOCK(&tid_to_tblock(xtid)->waitor); 856
857 /* Recheck everything since dropping TXN_LOCK */
858 if (xtid && (tlck->mp == mp) && (mp->lid == lid))
859 TXN_SLEEP_DROP_LOCK(&tid_to_tblock(xtid)->waitor);
860 else
861 TXN_UNLOCK();
849 jfs_info("txLock: awakened tid = %d, lid = %d", tid, lid); 862 jfs_info("txLock: awakened tid = %d, lid = %d", tid, lid);
850 863
851 return NULL; 864 return NULL;
@@ -906,6 +919,7 @@ static void txUnlock(struct tblock * tblk)
906 struct metapage *mp; 919 struct metapage *mp;
907 struct jfs_log *log; 920 struct jfs_log *log;
908 int difft, diffp; 921 int difft, diffp;
922 unsigned long flags;
909 923
910 jfs_info("txUnlock: tblk = 0x%p", tblk); 924 jfs_info("txUnlock: tblk = 0x%p", tblk);
911 log = JFS_SBI(tblk->sb)->log; 925 log = JFS_SBI(tblk->sb)->log;
@@ -925,19 +939,14 @@ static void txUnlock(struct tblock * tblk)
925 assert(mp->xflag & COMMIT_PAGE); 939 assert(mp->xflag & COMMIT_PAGE);
926 940
927 /* hold buffer 941 /* hold buffer
928 *
929 * It's possible that someone else has the metapage.
930 * The only things were changing are nohomeok, which
931 * is handled atomically, and clsn which is protected
932 * by the LOGSYNC_LOCK.
933 */ 942 */
934 hold_metapage(mp, 1); 943 hold_metapage(mp);
935 944
936 assert(atomic_read(&mp->nohomeok) > 0); 945 assert(mp->nohomeok > 0);
937 atomic_dec(&mp->nohomeok); 946 _metapage_homeok(mp);
938 947
939 /* inherit younger/larger clsn */ 948 /* inherit younger/larger clsn */
940 LOGSYNC_LOCK(log); 949 LOGSYNC_LOCK(log, flags);
941 if (mp->clsn) { 950 if (mp->clsn) {
942 logdiff(difft, tblk->clsn, log); 951 logdiff(difft, tblk->clsn, log);
943 logdiff(diffp, mp->clsn, log); 952 logdiff(diffp, mp->clsn, log);
@@ -945,16 +954,11 @@ static void txUnlock(struct tblock * tblk)
945 mp->clsn = tblk->clsn; 954 mp->clsn = tblk->clsn;
946 } else 955 } else
947 mp->clsn = tblk->clsn; 956 mp->clsn = tblk->clsn;
948 LOGSYNC_UNLOCK(log); 957 LOGSYNC_UNLOCK(log, flags);
949 958
950 assert(!(tlck->flag & tlckFREEPAGE)); 959 assert(!(tlck->flag & tlckFREEPAGE));
951 960
952 if (tlck->flag & tlckWRITEPAGE) { 961 put_metapage(mp);
953 write_metapage(mp);
954 } else {
955 /* release page which has been forced */
956 release_metapage(mp);
957 }
958 } 962 }
959 963
960 /* insert tlock, and linelock(s) of the tlock if any, 964 /* insert tlock, and linelock(s) of the tlock if any,
@@ -981,10 +985,10 @@ static void txUnlock(struct tblock * tblk)
981 * has been inserted in logsync list at txUpdateMap()) 985 * has been inserted in logsync list at txUpdateMap())
982 */ 986 */
983 if (tblk->lsn) { 987 if (tblk->lsn) {
984 LOGSYNC_LOCK(log); 988 LOGSYNC_LOCK(log, flags);
985 log->count--; 989 log->count--;
986 list_del(&tblk->synclist); 990 list_del(&tblk->synclist);
987 LOGSYNC_UNLOCK(log); 991 LOGSYNC_UNLOCK(log, flags);
988 } 992 }
989} 993}
990 994
@@ -1573,8 +1577,8 @@ static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
1573 * the last entry, so don't bother logging this 1577 * the last entry, so don't bother logging this
1574 */ 1578 */
1575 mp->lid = 0; 1579 mp->lid = 0;
1576 hold_metapage(mp, 0); 1580 grab_metapage(mp);
1577 atomic_dec(&mp->nohomeok); 1581 metapage_homeok(mp);
1578 discard_metapage(mp); 1582 discard_metapage(mp);
1579 tlck->mp = NULL; 1583 tlck->mp = NULL;
1580 return 0; 1584 return 0;
@@ -2270,7 +2274,8 @@ void txForce(struct tblock * tblk)
2270 tlck->flag &= ~tlckWRITEPAGE; 2274 tlck->flag &= ~tlckWRITEPAGE;
2271 2275
2272 /* do not release page to freelist */ 2276 /* do not release page to freelist */
2273 2277 force_metapage(mp);
2278#if 0
2274 /* 2279 /*
2275 * The "right" thing to do here is to 2280 * The "right" thing to do here is to
2276 * synchronously write the metadata. 2281 * synchronously write the metadata.
@@ -2282,9 +2287,10 @@ void txForce(struct tblock * tblk)
2282 * we can get by with synchronously writing 2287 * we can get by with synchronously writing
2283 * the pages when they are released. 2288 * the pages when they are released.
2284 */ 2289 */
2285 assert(atomic_read(&mp->nohomeok)); 2290 assert(mp->nohomeok);
2286 set_bit(META_dirty, &mp->flag); 2291 set_bit(META_dirty, &mp->flag);
2287 set_bit(META_sync, &mp->flag); 2292 set_bit(META_sync, &mp->flag);
2293#endif
2288 } 2294 }
2289 } 2295 }
2290 } 2296 }
@@ -2344,7 +2350,7 @@ static void txUpdateMap(struct tblock * tblk)
2344 */ 2350 */
2345 mp = tlck->mp; 2351 mp = tlck->mp;
2346 ASSERT(mp->xflag & COMMIT_PAGE); 2352 ASSERT(mp->xflag & COMMIT_PAGE);
2347 hold_metapage(mp, 0); 2353 grab_metapage(mp);
2348 } 2354 }
2349 2355
2350 /* 2356 /*
@@ -2394,8 +2400,8 @@ static void txUpdateMap(struct tblock * tblk)
2394 ASSERT(mp->lid == lid); 2400 ASSERT(mp->lid == lid);
2395 tlck->mp->lid = 0; 2401 tlck->mp->lid = 0;
2396 } 2402 }
2397 assert(atomic_read(&mp->nohomeok) == 1); 2403 assert(mp->nohomeok == 1);
2398 atomic_dec(&mp->nohomeok); 2404 metapage_homeok(mp);
2399 discard_metapage(mp); 2405 discard_metapage(mp);
2400 tlck->mp = NULL; 2406 tlck->mp = NULL;
2401 } 2407 }
@@ -2861,24 +2867,9 @@ static void LogSyncRelease(struct metapage * mp)
2861{ 2867{
2862 struct jfs_log *log = mp->log; 2868 struct jfs_log *log = mp->log;
2863 2869
2864 assert(atomic_read(&mp->nohomeok)); 2870 assert(mp->nohomeok);
2865 assert(log); 2871 assert(log);
2866 atomic_dec(&mp->nohomeok); 2872 metapage_homeok(mp);
2867
2868 if (atomic_read(&mp->nohomeok))
2869 return;
2870
2871 hold_metapage(mp, 0);
2872
2873 LOGSYNC_LOCK(log);
2874 mp->log = NULL;
2875 mp->lsn = 0;
2876 mp->clsn = 0;
2877 log->count--;
2878 list_del_init(&mp->synclist);
2879 LOGSYNC_UNLOCK(log);
2880
2881 release_metapage(mp);
2882} 2873}
2883 2874
2884/* 2875/*
diff --git a/fs/jfs/jfs_umount.c b/fs/jfs/jfs_umount.c
index f31a9e3f3fec..5cf91785b541 100644
--- a/fs/jfs/jfs_umount.c
+++ b/fs/jfs/jfs_umount.c
@@ -49,7 +49,6 @@
49 */ 49 */
50int jfs_umount(struct super_block *sb) 50int jfs_umount(struct super_block *sb)
51{ 51{
52 struct address_space *bdev_mapping = sb->s_bdev->bd_inode->i_mapping;
53 struct jfs_sb_info *sbi = JFS_SBI(sb); 52 struct jfs_sb_info *sbi = JFS_SBI(sb);
54 struct inode *ipbmap = sbi->ipbmap; 53 struct inode *ipbmap = sbi->ipbmap;
55 struct inode *ipimap = sbi->ipimap; 54 struct inode *ipimap = sbi->ipimap;
@@ -109,8 +108,8 @@ int jfs_umount(struct super_block *sb)
109 * Make sure all metadata makes it to disk before we mark 108 * Make sure all metadata makes it to disk before we mark
110 * the superblock as clean 109 * the superblock as clean
111 */ 110 */
112 filemap_fdatawrite(bdev_mapping); 111 filemap_fdatawrite(sbi->direct_inode->i_mapping);
113 filemap_fdatawait(bdev_mapping); 112 filemap_fdatawait(sbi->direct_inode->i_mapping);
114 113
115 /* 114 /*
116 * ensure all file system file pages are propagated to their 115 * ensure all file system file pages are propagated to their
@@ -123,9 +122,6 @@ int jfs_umount(struct super_block *sb)
123 if (log) { /* log = NULL if read-only mount */ 122 if (log) { /* log = NULL if read-only mount */
124 updateSuper(sb, FM_CLEAN); 123 updateSuper(sb, FM_CLEAN);
125 124
126 /* Restore default gfp_mask for bdev */
127 mapping_set_gfp_mask(bdev_mapping, GFP_USER);
128
129 /* 125 /*
130 * close log: 126 * close log:
131 * 127 *
@@ -140,7 +136,6 @@ int jfs_umount(struct super_block *sb)
140 136
141int jfs_umount_rw(struct super_block *sb) 137int jfs_umount_rw(struct super_block *sb)
142{ 138{
143 struct address_space *bdev_mapping = sb->s_bdev->bd_inode->i_mapping;
144 struct jfs_sb_info *sbi = JFS_SBI(sb); 139 struct jfs_sb_info *sbi = JFS_SBI(sb);
145 struct jfs_log *log = sbi->log; 140 struct jfs_log *log = sbi->log;
146 141
@@ -166,13 +161,10 @@ int jfs_umount_rw(struct super_block *sb)
166 * mark the superblock clean before everything is flushed to 161 * mark the superblock clean before everything is flushed to
167 * disk. 162 * disk.
168 */ 163 */
169 filemap_fdatawrite(bdev_mapping); 164 filemap_fdatawrite(sbi->direct_inode->i_mapping);
170 filemap_fdatawait(bdev_mapping); 165 filemap_fdatawait(sbi->direct_inode->i_mapping);
171 166
172 updateSuper(sb, FM_CLEAN); 167 updateSuper(sb, FM_CLEAN);
173 168
174 /* Restore default gfp_mask for bdev */
175 mapping_set_gfp_mask(bdev_mapping, GFP_USER);
176
177 return lmLogClose(sb); 169 return lmLogClose(sb);
178} 170}
diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c
index 2eb6869b6e72..c6dc254d3253 100644
--- a/fs/jfs/resize.c
+++ b/fs/jfs/resize.c
@@ -209,6 +209,9 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
209 */ 209 */
210 txQuiesce(sb); 210 txQuiesce(sb);
211 211
212 /* Reset size of direct inode */
213 sbi->direct_inode->i_size = sb->s_bdev->bd_inode->i_size;
214
212 if (sbi->mntflag & JFS_INLINELOG) { 215 if (sbi->mntflag & JFS_INLINELOG) {
213 /* 216 /*
214 * deactivate old inline log 217 * deactivate old inline log
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 5856866e24fc..0812005364a1 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -210,6 +210,10 @@ static void jfs_put_super(struct super_block *sb)
210 unload_nls(sbi->nls_tab); 210 unload_nls(sbi->nls_tab);
211 sbi->nls_tab = NULL; 211 sbi->nls_tab = NULL;
212 212
213 truncate_inode_pages(sbi->direct_inode->i_mapping, 0);
214 iput(sbi->direct_inode);
215 sbi->direct_inode = NULL;
216
213 kfree(sbi); 217 kfree(sbi);
214} 218}
215 219
@@ -358,6 +362,12 @@ static int jfs_remount(struct super_block *sb, int *flags, char *data)
358 } 362 }
359 363
360 if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { 364 if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
365 /*
366 * Invalidate any previously read metadata. fsck may have
367 * changed the on-disk data since we mounted r/o
368 */
369 truncate_inode_pages(JFS_SBI(sb)->direct_inode->i_mapping, 0);
370
361 JFS_SBI(sb)->flag = flag; 371 JFS_SBI(sb)->flag = flag;
362 return jfs_mount_rw(sb, 1); 372 return jfs_mount_rw(sb, 1);
363 } 373 }
@@ -428,12 +438,26 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
428 sb->s_op = &jfs_super_operations; 438 sb->s_op = &jfs_super_operations;
429 sb->s_export_op = &jfs_export_operations; 439 sb->s_export_op = &jfs_export_operations;
430 440
441 /*
442 * Initialize direct-mapping inode/address-space
443 */
444 inode = new_inode(sb);
445 if (inode == NULL)
446 goto out_kfree;
447 inode->i_ino = 0;
448 inode->i_nlink = 1;
449 inode->i_size = sb->s_bdev->bd_inode->i_size;
450 inode->i_mapping->a_ops = &jfs_metapage_aops;
451 mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
452
453 sbi->direct_inode = inode;
454
431 rc = jfs_mount(sb); 455 rc = jfs_mount(sb);
432 if (rc) { 456 if (rc) {
433 if (!silent) { 457 if (!silent) {
434 jfs_err("jfs_mount failed w/return code = %d", rc); 458 jfs_err("jfs_mount failed w/return code = %d", rc);
435 } 459 }
436 goto out_kfree; 460 goto out_mount_failed;
437 } 461 }
438 if (sb->s_flags & MS_RDONLY) 462 if (sb->s_flags & MS_RDONLY)
439 sbi->log = NULL; 463 sbi->log = NULL;
@@ -482,6 +506,13 @@ out_no_rw:
482 if (rc) { 506 if (rc) {
483 jfs_err("jfs_umount failed with return code %d", rc); 507 jfs_err("jfs_umount failed with return code %d", rc);
484 } 508 }
509out_mount_failed:
510 filemap_fdatawrite(sbi->direct_inode->i_mapping);
511 filemap_fdatawait(sbi->direct_inode->i_mapping);
512 truncate_inode_pages(sbi->direct_inode->i_mapping, 0);
513 make_bad_inode(sbi->direct_inode);
514 iput(sbi->direct_inode);
515 sbi->direct_inode = NULL;
485out_kfree: 516out_kfree:
486 if (sbi->nls_tab) 517 if (sbi->nls_tab)
487 unload_nls(sbi->nls_tab); 518 unload_nls(sbi->nls_tab);