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

[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,
{
s64 lblock64 = lblock;
int rc = 0;
int take_locks;
xad_t xad;
s64 xaddr;
int xflag;
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
*/
if (take_locks) {
if (create)
IWRITE_LOCK(ip);
else
IREAD_LOCK(ip);
}
if (create)
IWRITE_LOCK(ip);
else
IREAD_LOCK(ip);
if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) &&
(xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, 0)
== 0) && xlen) {
(!xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, 0)) &&
xlen) {
if (xflag & XAD_NOTRECORDED) {
if (!create)
/*
......@@ -258,12 +249,10 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks,
/*
* Release lock on inode
*/
if (take_locks) {
if (create)
IWRITE_UNLOCK(ip);
else
IREAD_UNLOCK(ip);
}
if (create)
IWRITE_UNLOCK(ip);
else
IREAD_UNLOCK(ip);
return rc;
}
......
......@@ -471,6 +471,7 @@ dbUpdatePMap(struct inode *ipbmap,
struct metapage *mp;
struct jfs_log *log;
int lsn, difft, diffp;
unsigned long flags;
/* the blocks better be within the mapsize. */
if (blkno + nblocks > bmp->db_mapsize) {
......@@ -504,6 +505,7 @@ dbUpdatePMap(struct inode *ipbmap,
0);
if (mp == NULL)
return -EIO;
metapage_wait_for_io(mp);
}
dp = (struct dmap *) mp->data;
......@@ -578,34 +580,32 @@ dbUpdatePMap(struct inode *ipbmap,
if (mp->lsn != 0) {
/* inherit older/smaller lsn */
logdiff(diffp, mp->lsn, log);
LOGSYNC_LOCK(log, flags);
if (difft < diffp) {
mp->lsn = lsn;
/* move bp after tblock in logsync list */
LOGSYNC_LOCK(log);
list_move(&mp->synclist, &tblk->synclist);
LOGSYNC_UNLOCK(log);
}
/* inherit younger/larger clsn */
LOGSYNC_LOCK(log);
logdiff(difft, tblk->clsn, log);
logdiff(diffp, mp->clsn, log);
if (difft > diffp)
mp->clsn = tblk->clsn;
LOGSYNC_UNLOCK(log);
LOGSYNC_UNLOCK(log, flags);
} else {
mp->log = log;
mp->lsn = lsn;
/* insert bp after tblock in logsync list */
LOGSYNC_LOCK(log);
LOGSYNC_LOCK(log, flags);
log->count++;
list_add(&mp->synclist, &tblk->synclist);
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)
}
ip->i_mapping->a_ops = &jfs_aops;
ip->i_mapping->a_ops = &jfs_metapage_aops;
mapping_set_gfp_mask(ip->i_mapping, GFP_NOFS);
/* Allocations to metadata inodes should not affect quotas */
......@@ -2791,6 +2791,7 @@ diUpdatePMap(struct inode *ipimap,
u32 mask;
struct jfs_log *log;
int lsn, difft, diffp;
unsigned long flags;
imap = JFS_IP(ipimap)->i_imap;
/* get the iag number containing the inode */
......@@ -2807,6 +2808,7 @@ diUpdatePMap(struct inode *ipimap,
IREAD_UNLOCK(ipimap);
if (rc)
return (rc);
metapage_wait_for_io(mp);
iagp = (struct iag *) mp->data;
/* get the inode number and extent number of the inode within
* the iag and the inode number within the extent.
......@@ -2870,30 +2872,28 @@ diUpdatePMap(struct inode *ipimap,
/* inherit older/smaller lsn */
logdiff(difft, lsn, log);
logdiff(diffp, mp->lsn, log);
LOGSYNC_LOCK(log, flags);
if (difft < diffp) {
mp->lsn = lsn;
/* move mp after tblock in logsync list */
LOGSYNC_LOCK(log);
list_move(&mp->synclist, &tblk->synclist);
LOGSYNC_UNLOCK(log);
}
/* inherit younger/larger clsn */
LOGSYNC_LOCK(log);
assert(mp->clsn);
logdiff(difft, tblk->clsn, log);
logdiff(diffp, mp->clsn, log);
if (difft > diffp)
mp->clsn = tblk->clsn;
LOGSYNC_UNLOCK(log);
LOGSYNC_UNLOCK(log, flags);
} else {
mp->log = log;
mp->lsn = lsn;
/* insert mp after tblock in logsync list */
LOGSYNC_LOCK(log);
LOGSYNC_LOCK(log, flags);
log->count++;
list_add(&mp->synclist, &tblk->synclist);
mp->clsn = tblk->clsn;
LOGSYNC_UNLOCK(log);
LOGSYNC_UNLOCK(log, flags);
}
write_metapage(mp);
return (0);
......
......@@ -165,6 +165,7 @@ struct jfs_sb_info {
/* Formerly in ipbmap */
struct bmap *bmap; /* incore bmap descriptor */
struct nls_table *nls_tab; /* current codepage */
struct inode *direct_inode; /* metadata inode */
uint state; /* mount/recovery state */
unsigned long flag; /* mount time flags */
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,
int lsn;
int diffp, difft;
struct metapage *mp = NULL;
unsigned long flags;
jfs_info("lmLog: log:0x%p tblk:0x%p, lrd:0x%p tlck:0x%p",
log, tblk, lrd, tlck);
......@@ -254,7 +255,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
*/
lsn = log->lsn;
LOGSYNC_LOCK(log);
LOGSYNC_LOCK(log, flags);
/*
* 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,
}
}
LOGSYNC_UNLOCK(log);
LOGSYNC_UNLOCK(log, flags);
/*
* write the log record
......@@ -334,7 +335,6 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
return lsn;
}
/*
* NAME: lmWriteRecord()
*
......@@ -945,6 +945,15 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
struct lrd lrd;
int lsn;
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
......@@ -954,10 +963,7 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
*/
if (log->sync == log->syncpt) {
LOGSYNC_LOCK(log);
/* ToDo: push dirty metapages out to disk */
// bmLogSync(log);
LOGSYNC_LOCK(log, flags);
if (list_empty(&log->synclist))
log->sync = log->lsn;
else {
......@@ -965,7 +971,7 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
struct logsyncblk, synclist);
log->sync = lp->lsn;
}
LOGSYNC_UNLOCK(log);
LOGSYNC_UNLOCK(log, flags);
}
......@@ -974,27 +980,6 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait)
* reset syncpt = sync
*/
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.backchain = 0;
lrd.type = cpu_to_le16(LOG_SYNCPT);
......@@ -1547,6 +1532,7 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
{
int i;
struct tblock *target = NULL;
struct jfs_sb_info *sbi;
/* jfs_write_inode may call us during read-only mount */
if (!log)
......@@ -1608,12 +1594,18 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
if (wait < 2)
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
* for the lazycommit thread to catch up
*/
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);
if (list_empty(&log->cqueue) &&
list_empty(&log->synclist))
......@@ -1621,7 +1613,24 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
}
}
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);
}
......
......@@ -490,8 +490,9 @@ struct logsyncblk {
*/
#define LOGSYNC_LOCK_INIT(log) spin_lock_init(&(log)->synclock)
#define LOGSYNC_LOCK(log) spin_lock(&(log)->synclock)
#define LOGSYNC_UNLOCK(log) spin_unlock(&(log)->synclock)
#define LOGSYNC_LOCK(log, flags) spin_lock_irqsave(&(log)->synclock, flags)
#define LOGSYNC_UNLOCK(log, flags) \
spin_unlock_irqrestore(&(log)->synclock, flags)
/* compute the difference in bytes of lsn from sync point */
#define logdiff(diff, lsn, log)\
......
This diff is collapsed.
......@@ -33,38 +33,27 @@ struct metapage {
unsigned long flag; /* See Below */
unsigned long count; /* Reference count */
void *data; /* Data pointer */
/* 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;
sector_t index; /* block address of page */
wait_queue_head_t wait;
/* implementation */
struct page *page;
unsigned long logical_size;
unsigned int logical_size;
/* Journal management */
int clsn;
atomic_t nohomeok;
int nohomeok;
struct jfs_log *log;
};
/* metapage flag */
#define META_locked 0
#define META_absolute 1
#define META_free 2
#define META_dirty 3
#define META_sync 4
#define META_discard 5
#define META_forced 6
#define META_stale 7
#define META_free 1
#define META_dirty 2
#define META_sync 3
#define META_discard 4
#define META_forcewrite 5
#define META_io 6
#define mark_metapage_dirty(mp) set_bit(META_dirty, &(mp)->flag)
......@@ -80,7 +69,16 @@ extern struct metapage *__get_metapage(struct inode *inode,
__get_metapage(inode, lblock, size, absolute, TRUE)
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)
{
......@@ -101,6 +99,46 @@ static inline void discard_metapage(struct 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.
*/
......
......@@ -285,11 +285,6 @@ int jfs_mount_rw(struct super_block *sb, int remount)
*/
logMOUNT(sb);
/*
* Set page cache allocation policy
*/
mapping_set_gfp_mask(sb->s_bdev->bd_inode->i_mapping, GFP_NOFS);
return rc;
}
......
......@@ -227,6 +227,7 @@ static lid_t txLockAlloc(void)
static void txLockFree(lid_t lid)
{
TxLock[lid].tid = 0;
TxLock[lid].next = TxAnchor.freelock;
TxAnchor.freelock = lid;
TxAnchor.tlocksInUse--;
......@@ -633,8 +634,10 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
/* is page locked by the requester transaction ? */
tlck = lid_to_tlock(lid);
if ((xtid = tlck->tid) == tid)
if ((xtid = tlck->tid) == tid) {
TXN_UNLOCK();
goto grantLock;
}
/*
* is page locked by anonymous transaction/lock ?
......@@ -649,6 +652,7 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
*/
if (xtid == 0) {
tlck->tid = tid;
TXN_UNLOCK();
tblk = tid_to_tblock(tid);
/*
* 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,
*/
tlck->tid = tid;
TXN_UNLOCK();
/* mark tlock for meta-data page */
if (mp->xflag & COMMIT_PAGE) {
tlck->flag = tlckPAGELOCK;
/* mark the page dirty and nohomeok */
mark_metapage_dirty(mp);
atomic_inc(&mp->nohomeok);
metapage_nohomeok(mp);
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
* 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,
if (tlck->next == 0) {
/* This inode's first anonymous transaction */
jfs_ip->atltail = lid;
TXN_LOCK();
list_add_tail(&jfs_ip->anon_inode_list,
&TxAnchor.anon_list);
TXN_UNLOCK();
}
}
......@@ -821,8 +828,6 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
grantLock:
tlck->type |= type;
TXN_UNLOCK();
return tlck;
/*
......@@ -841,11 +846,19 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
BUG();
}
INCREMENT(stattx.waitlock); /* statistics */
TXN_UNLOCK();
release_metapage(mp);
TXN_LOCK();
xtid = tlck->tid; /* reaquire after dropping TXN_LOCK */
jfs_info("txLock: in waitLock, tid = %d, xtid = %d, lid = %d",
tid, xtid, lid);
TXN_SLEEP_DROP_LOCK(&tid_to_tblock(xtid)->waitor);
/* Recheck everything since dropping TXN_LOCK */
if (xtid && (tlck->mp == mp) && (mp->lid == lid))
TXN_SLEEP_DROP_LOCK(&tid_to_tblock(xtid)->waitor);
else
TXN_UNLOCK();
jfs_info("txLock: awakened tid = %d, lid = %d", tid, lid);
return NULL;
......@@ -906,6 +919,7 @@ static void txUnlock(struct tblock * tblk)
struct metapage *mp;
struct jfs_log *log;
int difft, diffp;
unsigned long flags;
jfs_info("txUnlock: tblk = 0x%p", tblk);
log = JFS_SBI(tblk->sb)->log;
......@@ -925,19 +939,14 @@ static void txUnlock(struct tblock * tblk)
assert(mp->xflag & COMMIT_PAGE);
/* 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);
atomic_dec(&mp->nohomeok);
assert(mp->nohomeok > 0);
_metapage_homeok(mp);
/* inherit younger/larger clsn */
LOGSYNC_LOCK(log);
LOGSYNC_LOCK(log, flags);
if (mp->clsn) {
logdiff(difft, tblk->clsn, log);
logdiff(diffp, mp->clsn, log);
......@@ -945,16 +954,11 @@ static void txUnlock(struct tblock * tblk)
mp->clsn = tblk->clsn;
} else
mp->clsn = tblk->clsn;
LOGSYNC_UNLOCK(log);
LOGSYNC_UNLOCK(log, flags);
assert(!(tlck->flag & tlckFREEPAGE));
if (tlck->flag & tlckWRITEPAGE) {
write_metapage(mp);
} else {
/* release page which has been forced */
release_metapage(mp);
}
put_metapage(mp);
}
/* insert tlock, and linelock(s) of the tlock if any,
......@@ -981,10 +985,10 @@ static void txUnlock(struct tblock * tblk)
* has been inserted in logsync list at txUpdateMap())
*/
if (tblk->lsn) {
LOGSYNC_LOCK(log);
LOGSYNC_LOCK(log, flags);
log->count--;
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,
* the last entry, so don't bother logging this
*/
mp->lid = 0;
hold_metapage(mp, 0);
atomic_dec(&mp->nohomeok);
grab_metapage(mp);
metapage_homeok(mp);
discard_metapage(mp);
tlck->mp = NULL;
return 0;
......@@ -2270,7 +2274,8 @@ void txForce(struct tblock * tblk)
tlck->flag &= ~tlckWRITEPAGE;
/* do not release page to freelist */
force_metapage(mp);
#if 0
/*