[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>
This commit is contained in:
parent
dc5798d9a7
commit
7fab479beb
@ -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)\
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
/*
|
||||
* The "right" thing to do here is to
|
||||
* synchronously write the metadata.
|
||||
@ -2282,9 +2287,10 @@ void txForce(struct tblock * tblk)
|
||||
* we can get by with synchronously writing
|
||||
* the pages when they are released.
|
||||
*/
|
||||
assert(atomic_read(&mp->nohomeok));
|
||||
assert(mp->nohomeok);
|
||||
set_bit(META_dirty, &mp->flag);
|
||||
set_bit(META_sync, &mp->flag);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2344,7 +2350,7 @@ static void txUpdateMap(struct tblock * tblk)
|
||||
*/
|
||||
mp = tlck->mp;
|
||||
ASSERT(mp->xflag & COMMIT_PAGE);
|
||||
hold_metapage(mp, 0);
|
||||
grab_metapage(mp);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2394,8 +2400,8 @@ static void txUpdateMap(struct tblock * tblk)
|
||||
ASSERT(mp->lid == lid);
|
||||
tlck->mp->lid = 0;
|
||||
}
|
||||
assert(atomic_read(&mp->nohomeok) == 1);
|
||||
atomic_dec(&mp->nohomeok);
|
||||
assert(mp->nohomeok == 1);
|
||||
metapage_homeok(mp);
|
||||
discard_metapage(mp);
|
||||
tlck->mp = NULL;
|
||||
}
|
||||
@ -2861,24 +2867,9 @@ static void LogSyncRelease(struct metapage * mp)
|
||||
{
|
||||
struct jfs_log *log = mp->log;
|
||||
|
||||
assert(atomic_read(&mp->nohomeok));
|
||||
assert(mp->nohomeok);
|
||||
assert(log);
|
||||
atomic_dec(&mp->nohomeok);
|
||||
|
||||
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);
|
||||
metapage_homeok(mp);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -49,7 +49,6 @@
|
||||
*/
|
||||
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 inode *ipbmap = sbi->ipbmap;
|
||||
struct inode *ipimap = sbi->ipimap;
|
||||
@ -109,8 +108,8 @@ int jfs_umount(struct super_block *sb)
|
||||
* Make sure all metadata makes it to disk before we mark
|
||||
* the superblock as clean
|
||||
*/
|
||||
filemap_fdatawrite(bdev_mapping);
|
||||
filemap_fdatawait(bdev_mapping);
|
||||
filemap_fdatawrite(sbi->direct_inode->i_mapping);
|
||||
filemap_fdatawait(sbi->direct_inode->i_mapping);
|
||||
|
||||
/*
|
||||
* ensure all file system file pages are propagated to their
|
||||
@ -123,9 +122,6 @@ int jfs_umount(struct super_block *sb)
|
||||
if (log) { /* log = NULL if read-only mount */
|
||||
updateSuper(sb, FM_CLEAN);
|
||||
|
||||
/* Restore default gfp_mask for bdev */
|
||||
mapping_set_gfp_mask(bdev_mapping, GFP_USER);
|
||||
|
||||
/*
|
||||
* close log:
|
||||
*
|
||||
@ -140,7 +136,6 @@ int jfs_umount(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_log *log = sbi->log;
|
||||
|
||||
@ -166,13 +161,10 @@ int jfs_umount_rw(struct super_block *sb)
|
||||
* mark the superblock clean before everything is flushed to
|
||||
* disk.
|
||||
*/
|
||||
filemap_fdatawrite(bdev_mapping);
|
||||
filemap_fdatawait(bdev_mapping);
|
||||
filemap_fdatawrite(sbi->direct_inode->i_mapping);
|
||||
filemap_fdatawait(sbi->direct_inode->i_mapping);
|
||||
|
||||
updateSuper(sb, FM_CLEAN);
|
||||
|
||||
/* Restore default gfp_mask for bdev */
|
||||
mapping_set_gfp_mask(bdev_mapping, GFP_USER);
|
||||
|
||||
return lmLogClose(sb);
|
||||
}
|
||||
|
@ -209,6 +209,9 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
|
||||
*/
|
||||
txQuiesce(sb);
|
||||
|
||||
/* Reset size of direct inode */
|
||||
sbi->direct_inode->i_size = sb->s_bdev->bd_inode->i_size;
|
||||
|
||||
if (sbi->mntflag & JFS_INLINELOG) {
|
||||
/*
|
||||
* deactivate old inline log
|
||||
|
@ -210,6 +210,10 @@ static void jfs_put_super(struct super_block *sb)
|
||||
unload_nls(sbi->nls_tab);
|
||||
sbi->nls_tab = NULL;
|
||||
|
||||
truncate_inode_pages(sbi->direct_inode->i_mapping, 0);
|
||||
iput(sbi->direct_inode);
|
||||
sbi->direct_inode = NULL;
|
||||
|
||||
kfree(sbi);
|
||||
}
|
||||
|
||||
@ -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)) {
|
||||
/*
|
||||
* 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;
|
||||
return jfs_mount_rw(sb, 1);
|
||||
}
|
||||
@ -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_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);
|
||||
if (rc) {
|
||||
if (!silent) {
|
||||
jfs_err("jfs_mount failed w/return code = %d", rc);
|
||||
}
|
||||
goto out_kfree;
|
||||
goto out_mount_failed;
|
||||
}
|
||||
if (sb->s_flags & MS_RDONLY)
|
||||
sbi->log = NULL;
|
||||
@ -482,6 +506,13 @@ out_no_rw:
|
||||
if (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:
|
||||
if (sbi->nls_tab)
|
||||
unload_nls(sbi->nls_tab);
|
||||
|
Loading…
Reference in New Issue
Block a user