Commit 7fab479b authored by Dave Kleikamp's avatar Dave Kleikamp Committed by Linus Torvalds

[PATCH] JFS: Support page sizes greater than 4K

jfs has never worked on architecutures where the page size was not 4K.
Signed-off-by: default avatarDave Kleikamp <shaggy@austin.ibm.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent dc5798d9
...@@ -175,31 +175,22 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks, ...@@ -175,31 +175,22 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks,
{ {
s64 lblock64 = lblock; s64 lblock64 = lblock;
int rc = 0; int rc = 0;
int take_locks;
xad_t xad; xad_t xad;
s64 xaddr; s64 xaddr;
int xflag; int xflag;
s32 xlen; s32 xlen;
/*
* If this is a special inode (imap, dmap)
* the lock should already be taken
*/
take_locks = (JFS_IP(ip)->fileset != AGGREGATE_I);
/* /*
* Take appropriate lock on inode * Take appropriate lock on inode
*/ */
if (take_locks) {
if (create) if (create)
IWRITE_LOCK(ip); IWRITE_LOCK(ip);
else else
IREAD_LOCK(ip); IREAD_LOCK(ip);
}
if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) && if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) &&
(xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, 0) (!xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, 0)) &&
== 0) && xlen) { xlen) {
if (xflag & XAD_NOTRECORDED) { if (xflag & XAD_NOTRECORDED) {
if (!create) if (!create)
/* /*
...@@ -258,12 +249,10 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks, ...@@ -258,12 +249,10 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks,
/* /*
* Release lock on inode * Release lock on inode
*/ */
if (take_locks) {
if (create) if (create)
IWRITE_UNLOCK(ip); IWRITE_UNLOCK(ip);
else else
IREAD_UNLOCK(ip); IREAD_UNLOCK(ip);
}
return rc; return rc;
} }
......
...@@ -471,6 +471,7 @@ dbUpdatePMap(struct inode *ipbmap, ...@@ -471,6 +471,7 @@ dbUpdatePMap(struct inode *ipbmap,
struct metapage *mp; struct metapage *mp;
struct jfs_log *log; struct jfs_log *log;
int lsn, difft, diffp; int lsn, difft, diffp;
unsigned long flags;
/* the blocks better be within the mapsize. */ /* the blocks better be within the mapsize. */
if (blkno + nblocks > bmp->db_mapsize) { if (blkno + nblocks > bmp->db_mapsize) {
...@@ -504,6 +505,7 @@ dbUpdatePMap(struct inode *ipbmap, ...@@ -504,6 +505,7 @@ dbUpdatePMap(struct inode *ipbmap,
0); 0);
if (mp == NULL) if (mp == NULL)
return -EIO; return -EIO;
metapage_wait_for_io(mp);
} }
dp = (struct dmap *) mp->data; dp = (struct dmap *) mp->data;
...@@ -578,34 +580,32 @@ dbUpdatePMap(struct inode *ipbmap, ...@@ -578,34 +580,32 @@ dbUpdatePMap(struct inode *ipbmap,
if (mp->lsn != 0) { if (mp->lsn != 0) {
/* inherit older/smaller lsn */ /* inherit older/smaller lsn */
logdiff(diffp, mp->lsn, log); logdiff(diffp, mp->lsn, log);
LOGSYNC_LOCK(log, flags);
if (difft < diffp) { if (difft < diffp) {
mp->lsn = lsn; mp->lsn = lsn;
/* move bp after tblock in logsync list */ /* move bp after tblock in logsync list */
LOGSYNC_LOCK(log);
list_move(&mp->synclist, &tblk->synclist); list_move(&mp->synclist, &tblk->synclist);
LOGSYNC_UNLOCK(log);
} }
/* inherit younger/larger clsn */ /* inherit younger/larger clsn */
LOGSYNC_LOCK(log);
logdiff(difft, tblk->clsn, log); logdiff(difft, tblk->clsn, log);
logdiff(diffp, mp->clsn, log); logdiff(diffp, mp->clsn, log);
if (difft > diffp) if (difft > diffp)
mp->clsn = tblk->clsn; mp->clsn = tblk->clsn;
LOGSYNC_UNLOCK(log); LOGSYNC_UNLOCK(log, flags);
} else { } else {
mp->log = log; mp->log = log;
mp->lsn = lsn; mp->lsn = lsn;
/* insert bp after tblock in logsync list */ /* insert bp after tblock in logsync list */
LOGSYNC_LOCK(log); LOGSYNC_LOCK(log, flags);
log->count++; log->count++;
list_add(&mp->synclist, &tblk->synclist); list_add(&mp->synclist, &tblk->synclist);
mp->clsn = tblk->clsn; mp->clsn = tblk->clsn;
LOGSYNC_UNLOCK(log); LOGSYNC_UNLOCK(log, flags);
} }
} }
......
...@@ -502,7 +502,7 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary) ...@@ -502,7 +502,7 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
} }
ip->i_mapping->a_ops = &jfs_aops; ip->i_mapping->a_ops = &jfs_metapage_aops;
mapping_set_gfp_mask(ip->i_mapping, GFP_NOFS); mapping_set_gfp_mask(ip->i_mapping, GFP_NOFS);
/* Allocations to metadata inodes should not affect quotas */ /* Allocations to metadata inodes should not affect quotas */
...@@ -2791,6 +2791,7 @@ diUpdatePMap(struct inode *ipimap, ...@@ -2791,6 +2791,7 @@ diUpdatePMap(struct inode *ipimap,
u32 mask; u32 mask;
struct jfs_log *log; struct jfs_log *log;
int lsn, difft, diffp; int lsn, difft, diffp;
unsigned long flags;
imap = JFS_IP(ipimap)->i_imap; imap = JFS_IP(ipimap)->i_imap;
/* get the iag number containing the inode */ /* get the iag number containing the inode */
...@@ -2807,6 +2808,7 @@ diUpdatePMap(struct inode *ipimap, ...@@ -2807,6 +2808,7 @@ diUpdatePMap(struct inode *ipimap,
IREAD_UNLOCK(ipimap); IREAD_UNLOCK(ipimap);
if (rc) if (rc)
return (rc); return (rc);
metapage_wait_for_io(mp);
iagp = (struct iag *) mp->data; iagp = (struct iag *) mp->data;
/* get the inode number and extent number of the inode within /* get the inode number and extent number of the inode within
* the iag and the inode number within the extent. * the iag and the inode number within the extent.
...@@ -2870,30 +2872,28 @@ diUpdatePMap(struct inode *ipimap, ...@@ -2870,30 +2872,28 @@ diUpdatePMap(struct inode *ipimap,
/* inherit older/smaller lsn */ /* inherit older/smaller lsn */
logdiff(difft, lsn, log); logdiff(difft, lsn, log);
logdiff(diffp, mp->lsn, log); logdiff(diffp, mp->lsn, log);
LOGSYNC_LOCK(log, flags);
if (difft < diffp) { if (difft < diffp) {
mp->lsn = lsn; mp->lsn = lsn;
/* move mp after tblock in logsync list */ /* move mp after tblock in logsync list */
LOGSYNC_LOCK(log);
list_move(&mp->synclist, &tblk->synclist); list_move(&mp->synclist, &tblk->synclist);
LOGSYNC_UNLOCK(log);
} }
/* inherit younger/larger clsn */ /* inherit younger/larger clsn */
LOGSYNC_LOCK(log);
assert(mp->clsn); assert(mp->clsn);
logdiff(difft, tblk->clsn, log); logdiff(difft, tblk->clsn, log);
logdiff(diffp, mp->clsn, log); logdiff(diffp, mp->clsn, log);
if (difft > diffp) if (difft > diffp)
mp->clsn = tblk->clsn; mp->clsn = tblk->clsn;
LOGSYNC_UNLOCK(log); LOGSYNC_UNLOCK(log, flags);
} else { } else {
mp->log = log; mp->log = log;
mp->lsn = lsn; mp->lsn = lsn;
/* insert mp after tblock in logsync list */ /* insert mp after tblock in logsync list */
LOGSYNC_LOCK(log); LOGSYNC_LOCK(log, flags);
log->count++; log->count++;
list_add(&mp->synclist, &tblk->synclist); list_add(&mp->synclist, &tblk->synclist);
mp->clsn = tblk->clsn; mp->clsn = tblk->clsn;
LOGSYNC_UNLOCK(log); LOGSYNC_UNLOCK(log, flags);
} }
write_metapage(mp); write_metapage(mp);
return (0); return (0);
......
...@@ -165,6 +165,7 @@ struct jfs_sb_info { ...@@ -165,6 +165,7 @@ struct jfs_sb_info {
/* Formerly in ipbmap */ /* Formerly in ipbmap */
struct bmap *bmap; /* incore bmap descriptor */ struct bmap *bmap; /* incore bmap descriptor */
struct nls_table *nls_tab; /* current codepage */ struct nls_table *nls_tab; /* current codepage */
struct inode *direct_inode; /* metadata inode */
uint state; /* mount/recovery state */ uint state; /* mount/recovery state */
unsigned long flag; /* mount time flags */ unsigned long flag; /* mount time flags */
uint p_state; /* state prior to going no integrity */ uint p_state; /* state prior to going no integrity */
......
...@@ -234,6 +234,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, ...@@ -234,6 +234,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
int lsn; int lsn;
int diffp, difft; int diffp, difft;
struct metapage *mp = NULL; struct metapage *mp = NULL;
unsigned long flags;
jfs_info("lmLog: log:0x%p tblk:0x%p, lrd:0x%p tlck:0x%p", jfs_info("lmLog: log:0x%p tblk:0x%p, lrd:0x%p tlck:0x%p",
log, tblk, lrd, tlck); log, tblk, lrd, tlck);
...@@ -254,7 +255,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, ...@@ -254,7 +255,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
*/ */
lsn = log->lsn; lsn = log->lsn;
LOGSYNC_LOCK(log); LOGSYNC_LOCK(log, flags);
/* /*
* initialize page lsn if first log write of the page * 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,7 +311,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
} }
} }
LOGSYNC_UNLOCK(log); LOGSYNC_UNLOCK(log, flags);
/* /*
* write the log record * write the log record
...@@ -334,7 +335,6 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, ...@@ -334,7 +335,6 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
return lsn; return lsn;
} }
/* /*
* NAME: lmWriteRecord() * NAME: lmWriteRecord()
* *
...@@ -945,6 +945,15 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait) ...@@ -945,6 +945,15 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
struct lrd lrd; struct lrd lrd;
int lsn; int lsn;
struct logsyncblk *lp; struct logsyncblk *lp;
struct jfs_sb_info *sbi;
unsigned long flags;
/* push dirty metapages out to disk */
list_for_each_entry(sbi, &log->sb_list, log_list) {
filemap_flush(sbi->ipbmap->i_mapping);
filemap_flush(sbi->ipimap->i_mapping);
filemap_flush(sbi->direct_inode->i_mapping);
}
/* /*
* forward syncpt * forward syncpt
...@@ -954,10 +963,7 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait) ...@@ -954,10 +963,7 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
*/ */
if (log->sync == log->syncpt) { if (log->sync == log->syncpt) {
LOGSYNC_LOCK(log); LOGSYNC_LOCK(log, flags);
/* ToDo: push dirty metapages out to disk */
// bmLogSync(log);
if (list_empty(&log->synclist)) if (list_empty(&log->synclist))
log->sync = log->lsn; log->sync = log->lsn;
else { else {
...@@ -965,7 +971,7 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait) ...@@ -965,7 +971,7 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
struct logsyncblk, synclist); struct logsyncblk, synclist);
log->sync = lp->lsn; log->sync = lp->lsn;
} }
LOGSYNC_UNLOCK(log); LOGSYNC_UNLOCK(log, flags);
} }
...@@ -974,27 +980,6 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait) ...@@ -974,27 +980,6 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
* reset syncpt = sync * reset syncpt = sync
*/ */
if (log->sync != log->syncpt) { if (log->sync != log->syncpt) {
struct jfs_sb_info *sbi;
/*
* We need to make sure all of the "written" metapages
* actually make it to disk
*/
list_for_each_entry(sbi, &log->sb_list, log_list) {
if (sbi->flag & JFS_NOINTEGRITY)
continue;
filemap_fdatawrite(sbi->ipbmap->i_mapping);
filemap_fdatawrite(sbi->ipimap->i_mapping);
filemap_fdatawrite(sbi->sb->s_bdev->bd_inode->i_mapping);
}
list_for_each_entry(sbi, &log->sb_list, log_list) {
if (sbi->flag & JFS_NOINTEGRITY)
continue;
filemap_fdatawait(sbi->ipbmap->i_mapping);
filemap_fdatawait(sbi->ipimap->i_mapping);
filemap_fdatawait(sbi->sb->s_bdev->bd_inode->i_mapping);
}
lrd.logtid = 0; lrd.logtid = 0;
lrd.backchain = 0; lrd.backchain = 0;
lrd.type = cpu_to_le16(LOG_SYNCPT); lrd.type = cpu_to_le16(LOG_SYNCPT);
...@@ -1547,6 +1532,7 @@ void jfs_flush_journal(struct jfs_log *log, int wait) ...@@ -1547,6 +1532,7 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
{ {
int i; int i;
struct tblock *target = NULL; struct tblock *target = NULL;
struct jfs_sb_info *sbi;
/* jfs_write_inode may call us during read-only mount */ /* jfs_write_inode may call us during read-only mount */
if (!log) if (!log)
...@@ -1608,12 +1594,18 @@ void jfs_flush_journal(struct jfs_log *log, int wait) ...@@ -1608,12 +1594,18 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
if (wait < 2) if (wait < 2)
return; return;
list_for_each_entry(sbi, &log->sb_list, log_list) {
filemap_fdatawrite(sbi->ipbmap->i_mapping);
filemap_fdatawrite(sbi->ipimap->i_mapping);
filemap_fdatawrite(sbi->direct_inode->i_mapping);
}
/* /*
* If there was recent activity, we may need to wait * If there was recent activity, we may need to wait
* for the lazycommit thread to catch up * for the lazycommit thread to catch up
*/ */
if ((!list_empty(&log->cqueue)) || !list_empty(&log->synclist)) { if ((!list_empty(&log->cqueue)) || !list_empty(&log->synclist)) {
for (i = 0; i < 800; i++) { /* Too much? */ for (i = 0; i < 200; i++) { /* Too much? */
msleep(250); msleep(250);
if (list_empty(&log->cqueue) && if (list_empty(&log->cqueue) &&
list_empty(&log->synclist)) list_empty(&log->synclist))
...@@ -1621,7 +1613,24 @@ void jfs_flush_journal(struct jfs_log *log, int wait) ...@@ -1621,7 +1613,24 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
} }
} }
assert(list_empty(&log->cqueue)); assert(list_empty(&log->cqueue));
assert(list_empty(&log->synclist)); if (!list_empty(&log->synclist)) {
struct logsyncblk *lp;
list_for_each_entry(lp, &log->synclist, synclist) {
if (lp->xflag & COMMIT_PAGE) {
struct metapage *mp = (struct metapage *)lp;
dump_mem("orphan metapage", lp,
sizeof(struct metapage));
dump_mem("page", mp->page, sizeof(struct page));
}
else
dump_mem("orphan tblock", lp,
sizeof(struct tblock));
}
// current->state = TASK_INTERRUPTIBLE;
// schedule();
}
//assert(list_empty(&log->synclist));
clear_bit(log_FLUSH, &log->flag); clear_bit(log_FLUSH, &log->flag);
} }
......
...@@ -490,8 +490,9 @@ struct logsyncblk { ...@@ -490,8 +490,9 @@ struct logsyncblk {
*/ */
#define LOGSYNC_LOCK_INIT(log) spin_lock_init(&(log)->synclock) #define LOGSYNC_LOCK_INIT(log) spin_lock_init(&(log)->synclock)
#define LOGSYNC_LOCK(log) spin_lock(&(log)->synclock) #define LOGSYNC_LOCK(log, flags) spin_lock_irqsave(&(log)->synclock, flags)
#define LOGSYNC_UNLOCK(log) spin_unlock(&(log)->synclock) #define LOGSYNC_UNLOCK(log, flags) \
spin_unlock_irqrestore(&(log)->synclock, flags)
/* compute the difference in bytes of lsn from sync point */ /* compute the difference in bytes of lsn from sync point */
#define logdiff(diff, lsn, log)\ #define logdiff(diff, lsn, log)\
......
This diff is collapsed.
...@@ -33,38 +33,27 @@ struct metapage { ...@@ -33,38 +33,27 @@ struct metapage {
unsigned long flag; /* See Below */ unsigned long flag; /* See Below */
unsigned long count; /* Reference count */ unsigned long count; /* Reference count */
void *data; /* Data pointer */ void *data; /* Data pointer */
sector_t index; /* block address of page */
/* list management stuff */
struct metapage *hash_prev;
struct metapage *hash_next; /* Also used for free list */
/*
* mapping & index become redundant, but we need these here to
* add the metapage to the hash before we have the real page
*/
struct address_space *mapping;
unsigned long index;
wait_queue_head_t wait; wait_queue_head_t wait;
/* implementation */ /* implementation */
struct page *page; struct page *page;
unsigned long logical_size; unsigned int logical_size;
/* Journal management */ /* Journal management */
int clsn; int clsn;
atomic_t nohomeok; int nohomeok;
struct jfs_log *log; struct jfs_log *log;
}; };
/* metapage flag */ /* metapage flag */
#define META_locked 0 #define META_locked 0
#define META_absolute 1 #define META_free 1
#define META_free 2 #define META_dirty 2
#define META_dirty 3 #define META_sync 3
#define META_sync 4 #define META_discard 4
#define META_discard 5 #define META_forcewrite 5
#define META_forced 6 #define META_io 6
#define META_stale 7
#define mark_metapage_dirty(mp) set_bit(META_dirty, &(mp)->flag) #define mark_metapage_dirty(mp) set_bit(META_dirty, &(mp)->flag)
...@@ -80,7 +69,16 @@ extern struct metapage *__get_metapage(struct inode *inode, ...@@ -80,7 +69,16 @@ extern struct metapage *__get_metapage(struct inode *inode,
__get_metapage(inode, lblock, size, absolute, TRUE) __get_metapage(inode, lblock, size, absolute, TRUE)
extern void release_metapage(struct metapage *); extern void release_metapage(struct metapage *);
extern void hold_metapage(struct metapage *, int); extern void grab_metapage(struct metapage *);
extern void force_metapage(struct metapage *);
/*
* hold_metapage and put_metapage are used in conjuction. The page lock
* is not dropped between the two, so no other threads can get or release
* the metapage
*/
extern void hold_metapage(struct metapage *);
extern void put_metapage(struct metapage *);
static inline void write_metapage(struct metapage *mp) static inline void write_metapage(struct metapage *mp)
{ {
...@@ -101,6 +99,46 @@ static inline void discard_metapage(struct metapage *mp) ...@@ -101,6 +99,46 @@ static inline void discard_metapage(struct metapage *mp)
release_metapage(mp); release_metapage(mp);
} }
static inline void metapage_nohomeok(struct metapage *mp)
{
struct page *page = mp->page;
lock_page(page);
if (!mp->nohomeok++) {
mark_metapage_dirty(mp);
page_cache_get(page);
wait_on_page_writeback(page);
}
unlock_page(page);
}
/*
* This serializes access to mp->lsn when metapages are added to logsynclist
* without setting nohomeok. i.e. updating imap & dmap
*/
static inline void metapage_wait_for_io(struct metapage *mp)
{
if (test_bit(META_io, &mp->flag))
wait_on_page_writeback(mp->page);
}
/*
* This is called when already holding the metapage
*/
static inline void _metapage_homeok(struct metapage *mp)
{
if (!--mp->nohomeok)
page_cache_release(mp->page);
}
static inline void metapage_homeok(struct metapage *mp)
{
hold_metapage(mp);
_metapage_homeok(mp);
put_metapage(mp);
}
extern struct address_space_operations jfs_metapage_aops;
/* /*
* This routines invalidate all pages for an extent. * This routines invalidate all pages for an extent.
*/ */
......
...@@ -285,11 +285,6 @@ int jfs_mount_rw(struct super_block *sb, int remount) ...@@ -285,11 +285,6 @@ int jfs_mount_rw(struct super_block *sb, int remount)
*/ */
logMOUNT(sb); logMOUNT(sb);
/*
* Set page cache allocation policy
*/
mapping_set_gfp_mask(sb->s_bdev->bd_inode->i_mapping, GFP_NOFS);
return rc; return rc;
} }
......
...@@ -227,6 +227,7 @@ static lid_t txLockAlloc(void) ...@@ -227,6 +227,7 @@ static lid_t txLockAlloc(void)
static void txLockFree(lid_t lid) static void txLockFree(lid_t lid)
{ {
TxLock[lid].tid = 0;
TxLock[lid].next = TxAnchor.freelock; TxLock[lid].next = TxAnchor.freelock;
TxAnchor.freelock = lid; TxAnchor.freelock = lid;
TxAnchor.tlocksInUse--; TxAnchor.tlocksInUse--;
...@@ -633,8 +634,10 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, ...@@ -633,8 +634,10 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
/* is page locked by the requester transaction ? */ /* is page locked by the requester transaction ? */
tlck = lid_to_tlock(lid); tlck = lid_to_tlock(lid);
if ((xtid = tlck->tid) == tid) if ((xtid = tlck->tid) == tid) {
TXN_UNLOCK();
goto grantLock; goto grantLock;
}
/* /*
* is page locked by anonymous transaction/lock ? * is page locked by anonymous transaction/lock ?
...@@ -649,6 +652,7 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, ...@@ -649,6 +652,7 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
*/ */
if (xtid == 0) { if (xtid == 0) {
tlck->tid = tid; tlck->tid = tid;
TXN_UNLOCK();
tblk = tid_to_tblock(tid); tblk = tid_to_tblock(tid);
/* /*
* The order of the tlocks in the transaction is important * 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,17 +710,18 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
*/ */
tlck->tid = tid; tlck->tid = tid;
TXN_UNLOCK();
/* mark tlock for meta-data page */ /* mark tlock for meta-data page */
if (mp->xflag & COMMIT_PAGE) { if (mp->xflag & COMMIT_PAGE) {
tlck->flag = tlckPAGELOCK; tlck->flag = tlckPAGELOCK;
/* mark the page dirty and nohomeok */ /* mark the page dirty and nohomeok */
mark_metapage_dirty(mp); metapage_nohomeok(mp);
atomic_inc(&mp->nohomeok);
jfs_info("locking mp = 0x%p, nohomeok = %d tid = %d tlck = 0x%p", jfs_info("locking mp = 0x%p, nohomeok = %d tid = %d tlck = 0x%p",
mp, atomic_read(&mp->nohomeok), tid, tlck); mp, mp->nohomeok, tid, tlck);
/* if anonymous transaction, and buffer is on the group /* if anonymous transaction, and buffer is on the group
* commit synclist, mark inode to show this. This will * 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,8 +767,10 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
if (tlck->next == 0) { if (tlck->next == 0) {
/* This inode's first anonymous transaction */ /* This inode's first anonymous transaction */
jfs_ip->atltail = lid; jfs_ip->atltail = lid;
TXN_LOCK();
list_add_tail(&jfs_ip->anon_inode_list, list_add_tail(&jfs_ip->anon_inode_list,
&TxAnchor.anon_list); &TxAnchor.anon_list);
TXN_UNLOCK();
} }
} }
...@@ -821,8 +828,6 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, ...@@ -821,8 +828,6 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
grantLock: grantLock:
tlck->type |= type; tlck->type |= type;
TXN_UNLOCK();
return tlck; return tlck;
/* /*
...@@ -841,11 +846,19 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, ...@@ -841,11 +846,19 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
BUG(); BUG();
} }
INCREMENT(stattx.waitlock); /* statistics */ INCREMENT(stattx.waitlock); /* statistics */
TXN_UNLOCK();
release_metapage(mp); release_metapage(mp);
TXN_LOCK();
xtid = tlck->tid; /* reaquire after dropping TXN_LOCK */
jfs_info("txLock: in waitLock, tid = %d, xtid = %d, lid = %d", jfs_info("txLock: in waitLock, tid = %d, xtid = %d, lid = %d",
tid, xtid, lid); tid, xtid, lid);
/* Recheck everything since dropping TXN_LOCK */
if (xtid && (tlck->mp == mp) && (mp->lid == lid))
TXN_SLEEP_DROP_LOCK(&tid_to_tblock(xtid)->waitor); TXN_SLEEP_DROP_LOCK(&tid_to_tblock(xtid)->waitor);
else
TXN_UNLOCK();
jfs_info("txLock: awakened tid = %d, lid = %d", tid, lid); jfs_info("txLock: awakened tid = %d, lid = %d", tid, lid);
return NULL; return NULL;
...@@ -906,6 +919,7 @@ static void txUnlock(struct tblock * tblk) ...@@ -906,6 +919,7 @@ static void txUnlock(struct tblock * tblk)
struct metapage *mp; struct metapage *mp;
struct jfs_log *log; struct jfs_log *log;
int difft, diffp; int difft, diffp;
unsigned long flags;
jfs_info("txUnlock: tblk = 0x%p", tblk); jfs_info("txUnlock: tblk = 0x%p", tblk);
log = JFS_SBI(tblk->sb)->log; log = JFS_SBI(tblk->sb)->log;
...@@ -925,19 +939,14 @@ static void txUnlock(struct tblock * tblk) ...@@ -925,19 +939,14 @@ static void txUnlock(struct tblock * tblk)
assert(mp->xflag & COMMIT_PAGE); assert(mp->xflag & COMMIT_PAGE);
/* hold buffer /* hold buffer
*
* It's possible that someone else has the metapage.
* The only things were changing are nohomeok, which
* is handled atomically, and clsn which is protected
* by the LOGSYNC_LOCK.
*/ */
hold_metapage(mp, 1); hold_metapage(mp);
assert(atomic_read(&mp->nohomeok) > 0); assert(mp->nohomeok > 0);
atomic_dec(&mp->nohomeok); _metapage_homeok(mp);
/* inherit younger/larger clsn */ /* inherit younger/larger clsn */
LOGSYNC_LOCK(log); LOGSYNC_LOCK(log, flags);
if (mp->clsn) { if (mp->clsn) {
logdiff(difft, tblk->clsn, log); logdiff(difft, tblk->clsn, log);
logdiff(diffp, mp->clsn, log); logdiff(diffp, mp->clsn, log);
...@@ -945,16 +954,11 @@ static void txUnlock(struct tblock * tblk) ...@@ -945,16 +954,11 @@ static void txUnlock(struct tblock * tblk)
mp->clsn = tblk->clsn; mp->clsn = tblk->clsn;
} else } else
mp->clsn = tblk->clsn; mp->clsn = tblk->clsn;
LOGSYNC_UNLOCK(log); LOGSYNC_UNLOCK(log, flags);
assert(!(tlck->flag & tlckFREEPAGE)); assert(!(tlck->flag & tlckFREEPAGE));
if (tlck->flag & tlckWRITEPAGE) { put_metapage(mp);
write_metapage(mp);
} else {
/* release page which has been forced */
release_metapage(mp);
}
} }
/* insert tlock, and linelock(s) of the tlock if any, /* insert tlock, and linelock(s) of the tlock if any,
...@@ -981,10 +985,10 @@ static void txUnlock(struct tblock * tblk) ...@@ -981,10 +985,10 @@ static void txUnlock(struct tblock * tblk)
* has been inserted in logsync list at txUpdateMap()) * has been inserted in logsync list at txUpdateMap())
*/ */
if (tblk->lsn) { if (tblk->lsn) {
LOGSYNC_LOCK(log); LOGSYNC_LOCK(log, flags);
log->count--; log->count--;
list_del(&tblk->synclist); list_del(&tblk->synclist);
LOGSYNC_UNLOCK(log); LOGSYNC_UNLOCK(log, flags);
} }
} }
...@@ -1573,8 +1577,8 @@ static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, ...@@ -1573,8 +1577,8 @@ static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
* the last entry, so don't bother logging this * the last entry, so don't bother logging this
*/ */
mp->lid = 0; mp->lid = 0;
hold_metapage(mp, 0); grab_metapage(mp);
atomic_dec(&mp->nohomeok); metapage_homeok(mp);
discard_metapage(mp); discard_metapage(mp);
tlck->mp = NULL; tlck->mp = NULL;
return 0; return 0;
...@@ -2270,7 +2274,8 @@ void txForce(struct tblock * tblk) ...@@ -2270,7 +2274,8 @@ void txForce(struct tblock * tblk)
tlck->flag &= ~tlckWRITEPAGE; tlck->flag &= ~tlckWRITEPAGE;
/* do not release page to freelist */ /* do not release page to freelist */
force_metapage(mp);
#if 0
/* /*
* The "right" thing to do here is to * The "right" thing to do here is to
* synchronously write the metadata. * synchronously write the metadata.
...@@ -2282,9 +2287,10 @@ void txForce(struct tblock * tblk) ...@@ -2282,9 +2287,10 @@ void txForce(struct tblock * tblk)
* we can get by with synchronously writing * we can get by with synchronously writing
* the pages when they are released. * the pages when they are released.
*/ */
assert(atomic_read(&mp->nohomeok)); assert(mp->nohomeok);
set_bit(META_dirty, &mp->flag); set_bit(META_dirty, &mp->flag);
set_bit(META_sync, &mp->flag); set_bit(META_sync, &mp->flag);
#endif
} }
} }
} }
...@@ -2344,7 +2350,7 @@ static void txUpdateMap(struct tblock * tblk) ...@@ -2344,7 +2350,7 @@ static void txUpdateMap(struct tblock * tblk)
*/ */
mp = tlck->mp; mp = tlck->mp;
ASSERT(mp->xflag & COMMIT_PAGE); ASSERT(mp->xflag & COMMIT_PAGE);
hold_metapage(mp, 0); grab_metapage(mp);
} }
/* /*
...@@ -2394,8 +2400,8 @@ static void txUpdateMap(struct tblock * tblk) ...@@ -2394,8 +2400,8 @@ static void txUpdateMap(struct tblock * tblk)
ASSERT(mp->lid == lid); ASSERT(mp->lid == lid);
tlck->mp->lid = 0; tlck->mp->lid = 0;
} }
assert(atomic_read(&mp->nohomeok) == 1); assert(mp->nohomeok == 1);
atomic_dec(&mp->nohomeok); metapage_homeok(mp);
discard_metapage(mp); discard_metapage(mp);
tlck->mp = NULL; tlck->mp = NULL;
} }
...@@ -2861,24 +2867,9 @@ static void LogSyncRelease(struct metapage * mp) ...@@ -2861,24 +2867,9 @@ static void LogSyncRelease(struct metapage * mp)
{ {
struct jfs_log *log = mp->log; struct jfs_log *log = mp->log;
assert(atomic_read(&mp->nohomeok)); assert(mp->nohomeok);
assert(log); assert(log);
atomic_dec(&mp->nohomeok); metapage_homeok(mp);
if (atomic_read(&mp->nohomeok))
return;
hold_metapage(mp, 0);
LOGSYNC_LOCK(log);
mp->log = NULL;
mp->lsn = 0;
mp->clsn = 0;
log->count--;
list_del_init(&mp->synclist);
LOGSYNC_UNLOCK(log);
release_metapage(mp);
} }
/* /*
......
...@@ -49,7 +49,6 @@ ...@@ -49,7 +49,6 @@
*/ */
int jfs_umount(struct super_block *sb) int jfs_umount(struct super_block *sb)
{ {
struct address_space *bdev_mapping = sb->s_bdev->bd_inode->i_mapping;
struct jfs_sb_info *sbi = JFS_SBI(sb); struct jfs_sb_info *sbi = JFS_SBI(sb);
struct inode *ipbmap = sbi->ipbmap; struct inode *ipbmap = sbi->ipbmap;
struct inode *ipimap = sbi->ipimap; struct inode *ipimap = sbi->ipimap;
...@@ -109,8 +108,8 @@ int jfs_umount(struct super_block *sb) ...@@ -109,8 +108,8 @@ int jfs_umount(struct super_block *sb)
* Make sure all metadata makes it to disk before we mark * Make sure all metadata makes it to disk before we mark
* the superblock as clean * the superblock as clean
*/ */
filemap_fdatawrite(bdev_mapping); filemap_fdatawrite(sbi->direct_inode->i_mapping);
filemap_fdatawait(bdev_mapping); filemap_fdatawait(sbi->direct_inode->i_mapping);
/* /*
* ensure all file system file pages are propagated to their * ensure all file system file pages are propagated to their
...@@ -123,9 +122,6 @@ int jfs_umount(struct super_block *sb) ...@@ -123,9 +122,6 @@ int jfs_umount(struct super_block *sb)
if (log) { /* log = NULL if read-only mount */ if (log) { /* log = NULL if read-only mount */
updateSuper(sb, FM_CLEAN); updateSuper(sb, FM_CLEAN);
/* Restore default gfp_mask for bdev */
mapping_set_gfp_mask(bdev_mapping, GFP_USER);
/* /*
* close log: * close log:
* *
...@@ -140,7 +136,6 @@ int jfs_umount(struct super_block *sb) ...@@ -140,7 +136,6 @@ int jfs_umount(struct super_block *sb)
int jfs_umount_rw(struct super_block *sb) int jfs_umount_rw(struct super_block *sb)
{ {
struct address_space *bdev_mapping = sb->s_bdev->bd_inode->i_mapping;
struct jfs_sb_info *sbi = JFS_SBI(sb); struct jfs_sb_info *sbi = JFS_SBI(sb);
struct jfs_log *log = sbi->log; struct jfs_log *log = sbi->log;
...@@ -166,13 +161,10 @@ int jfs_umount_rw(struct super_block *sb) ...@@ -166,13 +161,10 @@ int jfs_umount_rw(struct super_block *sb)
* mark the superblock clean before everything is flushed to * mark the superblock clean before everything is flushed to
* disk. * disk.
*/ */
filemap_fdatawrite(bdev_mapping); filemap_fdatawrite(sbi->direct_inode->i_mapping);
filemap_fdatawait(bdev_mapping); filemap_fdatawait(sbi->direct_inode->i_mapping);
updateSuper(sb, FM_CLEAN); updateSuper(sb, FM_CLEAN);
/* Restore default gfp_mask for bdev */
mapping_set_gfp_mask(bdev_mapping, GFP_USER);
return lmLogClose(sb); return lmLogClose(sb);
} }
...@@ -209,6 +209,9 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize) ...@@ -209,6 +209,9 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
*/ */
txQuiesce(sb); txQuiesce(sb);
/* Reset size of direct inode */
sbi->direct_inode->i_size = sb->s_bdev->bd_inode->i_size;
if (sbi->mntflag & JFS_INLINELOG) { if (sbi->mntflag & JFS_INLINELOG) {
/* /*
* deactivate old inline log * deactivate old inline log
......
...@@ -210,6 +210,10 @@ static void jfs_put_super(struct super_block *sb) ...@@ -210,6 +210,10 @@ static void jfs_put_super(struct super_block *sb)
unload_nls(sbi->nls_tab); unload_nls(sbi->nls_tab);
sbi->nls_tab = NULL; sbi->nls_tab = NULL;
truncate_inode_pages(sbi->direct_inode->i_mapping, 0);
iput(sbi->direct_inode);
sbi->direct_inode = NULL;
kfree(sbi); kfree(sbi);
} }
...@@ -358,6 +362,12 @@ static int jfs_remount(struct super_block *sb, int *flags, char *data) ...@@ -358,6 +362,12 @@ static int jfs_remount(struct super_block *sb, int *flags, char *data)
} }
if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
/*
* Invalidate any previously read metadata. fsck may have
* changed the on-disk data since we mounted r/o
*/
truncate_inode_pages(JFS_SBI(sb)->direct_inode->i_mapping, 0);
JFS_SBI(sb)->flag = flag; JFS_SBI(sb)->flag = flag;
return jfs_mount_rw(sb, 1); return jfs_mount_rw(sb, 1);
} }
...@@ -428,12 +438,26 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -428,12 +438,26 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_op = &jfs_super_operations; sb->s_op = &jfs_super_operations;
sb->s_export_op = &jfs_export_operations; sb->s_export_op = &jfs_export_operations;
/*
* Initialize direct-mapping inode/address-space
*/
inode = new_inode(sb);
if (inode == NULL)
goto out_kfree;
inode->i_ino = 0;
inode->i_nlink = 1;
inode->i_size = sb->s_bdev->bd_inode->i_size;
inode->i_mapping->a_ops = &jfs_metapage_aops;
mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
sbi->direct_inode = inode;
rc = jfs_mount(sb); rc = jfs_mount(sb);
if (rc) { if (rc) {
if (!silent) { if (!silent) {
jfs_err("jfs_mount failed w/return code = %d", rc); jfs_err("jfs_mount failed w/return code = %d", rc);
} }
goto out_kfree; goto out_mount_failed;
} }
if (sb->s_flags & MS_RDONLY) if (sb->s_flags & MS_RDONLY)
sbi->log = NULL; sbi->log = NULL;
...@@ -482,6 +506,13 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -482,6 +506,13 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
if (rc) { if (rc) {
jfs_err("jfs_umount failed with return code %d", rc); jfs_err("jfs_umount failed with return code %d", rc);
} }
out_mount_failed:
filemap_fdatawrite(sbi->direct_inode->i_mapping);
filemap_fdatawait(sbi->direct_inode->i_mapping);
truncate_inode_pages(sbi->direct_inode->i_mapping, 0);
make_bad_inode(sbi->direct_inode);
iput(sbi->direct_inode);
sbi->direct_inode = NULL;
out_kfree: out_kfree:
if (sbi->nls_tab) if (sbi->nls_tab)
unload_nls(sbi->nls_tab); unload_nls(sbi->nls_tab);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment