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,
{
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
/*
* 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);
......
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