[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:
committed by
Linus Torvalds
parent
dc5798d9a7
commit
7fab479beb
@@ -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,
|
|||||||
/*
|
/*
|
||||||
* 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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
/* 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 {
|
|||||||
/* 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,
|
|||||||
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,
|
|||||||
*/
|
*/
|
||||||
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,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
return lsn;
|
return lsn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NAME: lmWriteRecord()
|
* NAME: lmWriteRecord()
|
||||||
*
|
*
|
||||||
@@ -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)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#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)\
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -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,
|
|||||||
__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)
|
|||||||
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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
|
|
||||||
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,
|
|||||||
|
|
||||||
/* 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,
|
|||||||
*/
|
*/
|
||||||
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,
|
|||||||
*/
|
*/
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
* 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,
|
|||||||
* 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)
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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 @@
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
* 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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
* 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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
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 @@ out_no_rw:
|
|||||||
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);
|
||||||
|
Reference in New Issue
Block a user