Commit cf9e638b authored by Dave Kleikamp's avatar Dave Kleikamp

JFS: Move index table out of directory inode's address space

The metadata representing the directory entries' persistent index has been
mapped to the directory inode's address space.  This was the cause of much
ugliness in the code to avoid the inode being released from the inode cache
while there was still dirty metadata mapped to the inode.

This patch moves this metadata to the block device inode's address space,
which allows us to clean up the code somewhat.
parent a63e2f3d
......@@ -199,6 +199,28 @@ static void dtLinelockFreelist(dtpage_t * p, int m, struct dt_lock ** dtlock);
#define ciToUpper(c) UniStrupr((c)->name)
/*
* read_index_page()
*
* Reads a page of a directory's index table.
* Having metadata mapped into the directory inode's address space
* presents a multitude of problems. We avoid this by mapping to
* the absolute address space outside of the *_metapage routines
*/
static struct metapage *read_index_page(struct inode *inode, s64 blkno)
{
int rc;
s64 xaddr;
int xflag;
s32 xlen;
rc = xtLookup(inode, blkno, 1, &xflag, &xaddr, &xlen, 1);
if (rc || (xlen == 0))
return NULL;
return read_metapage(inode, xaddr, PSIZE, 1);
}
/*
* find_index()
*
......@@ -208,7 +230,7 @@ static void dtLinelockFreelist(dtpage_t * p, int m, struct dt_lock ** dtlock);
* mp must be released by caller.
*/
static struct dir_table_slot *find_index(struct inode *ip, u32 index,
struct metapage ** mp)
struct metapage ** mp, s64 *lblock)
{
struct jfs_inode_info *jfs_ip = JFS_IP(ip);
s64 blkno;
......@@ -243,12 +265,14 @@ static struct dir_table_slot *find_index(struct inode *ip, u32 index,
blkno = ((offset + 1) >> L2PSIZE) <<
JFS_SBI(ip->i_sb)->l2nbperpage;
if (*mp && ((*mp)->index != blkno)) {
if (*mp && (*lblock != blkno)) {
release_metapage(*mp);
*mp = 0;
}
if (*mp == 0)
*mp = read_metapage(ip, blkno, PSIZE, 0);
if (*mp == 0) {
*lblock = blkno;
*mp = read_index_page(ip, blkno);
}
if (*mp == 0) {
jERROR(1,
("free_index: error reading directory table\n"));
......@@ -368,7 +392,7 @@ static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot)
ip->i_size = PSIZE;
ip->i_blocks += LBLK2PBLK(sb, sbi->nbperpage);
if ((mp = get_metapage(ip, 0, ip->i_blksize, 0)) == 0) {
if ((mp = read_index_page(ip, 0)) == 0) {
jERROR(1, ("add_index: get_metapage failed!\n"));
xtTruncate(tid, ip, 0, COMMIT_PWMAP);
return -1;
......@@ -411,12 +435,12 @@ static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot)
ip->i_size += PSIZE;
ip->i_blocks += LBLK2PBLK(sb, sbi->nbperpage);
if ((mp = get_metapage(ip, blkno, PSIZE, 0)))
if ((mp = read_index_page(ip, blkno)))
memset(mp->data, 0, PSIZE); /* Just looks better */
else
xtTruncate(tid, ip, offset, COMMIT_PWMAP);
} else
mp = read_metapage(ip, blkno, PSIZE, 0);
mp = read_index_page(ip, blkno);
if (mp == 0) {
jERROR(1, ("add_index: get/read_metapage failed!\n"));
......@@ -445,9 +469,10 @@ static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot)
static void free_index(tid_t tid, struct inode *ip, u32 index, u32 next)
{
struct dir_table_slot *dirtab_slot;
s64 lblock;
struct metapage *mp = 0;
dirtab_slot = find_index(ip, index, &mp);
dirtab_slot = find_index(ip, index, &mp, &lblock);
if (dirtab_slot == 0)
return;
......@@ -470,11 +495,11 @@ static void free_index(tid_t tid, struct inode *ip, u32 index, u32 next)
* Changes an entry in the directory index table
*/
static void modify_index(tid_t tid, struct inode *ip, u32 index, s64 bn,
int slot, struct metapage ** mp)
int slot, struct metapage ** mp, u64 *lblock)
{
struct dir_table_slot *dirtab_slot;
dirtab_slot = find_index(ip, index, mp);
dirtab_slot = find_index(ip, index, mp, lblock);
if (dirtab_slot == 0)
return;
......@@ -497,10 +522,11 @@ static void modify_index(tid_t tid, struct inode *ip, u32 index, s64 bn,
static int read_index(struct inode *ip, u32 index,
struct dir_table_slot * dirtab_slot)
{
s64 lblock;
struct metapage *mp = 0;
struct dir_table_slot *slot;
slot = find_index(ip, index, &mp);
slot = find_index(ip, index, &mp, &lblock);
if (slot == 0) {
return -EIO;
}
......@@ -1491,12 +1517,14 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
* Update directory index table for entries now in right page
*/
if ((rp->header.flag & BT_LEAF) && DO_INDEX(ip)) {
s64 lblock;
mp = 0;
stbl = DT_GETSTBL(rp);
for (n = 0; n < rp->header.nextindex; n++) {
ldtentry = (struct ldtentry *) & rp->slot[stbl[n]];
modify_index(tid, ip, le32_to_cpu(ldtentry->index),
rbn, n, &mp);
rbn, n, &mp, &lblock);
}
if (mp)
release_metapage(mp);
......@@ -1616,6 +1644,8 @@ static int dtExtendPage(tid_t tid,
* Update directory index table to reflect new page address
*/
if (DO_INDEX(ip)) {
s64 lblock;
mp = 0;
stbl = DT_GETSTBL(sp);
for (n = 0; n < sp->header.nextindex; n++) {
......@@ -1623,7 +1653,7 @@ static int dtExtendPage(tid_t tid,
(struct ldtentry *) & sp->slot[stbl[n]];
modify_index(tid, ip,
le32_to_cpu(ldtentry->index),
xaddr, n, &mp);
xaddr, n, &mp, &lblock);
}
if (mp)
release_metapage(mp);
......@@ -1911,6 +1941,7 @@ static int dtSplitRoot(tid_t tid,
* Update directory index table for entries now in right page
*/
if ((rp->header.flag & BT_LEAF) && DO_INDEX(ip)) {
s64 lblock;
struct metapage *mp = 0;
struct ldtentry *ldtentry;
......@@ -1918,7 +1949,7 @@ static int dtSplitRoot(tid_t tid,
for (n = 0; n < rp->header.nextindex; n++) {
ldtentry = (struct ldtentry *) & rp->slot[stbl[n]];
modify_index(tid, ip, le32_to_cpu(ldtentry->index),
rbn, n, &mp);
rbn, n, &mp, &lblock);
}
if (mp)
release_metapage(mp);
......@@ -2120,6 +2151,8 @@ int dtDelete(tid_t tid,
* Update directory index table for entries moved in stbl
*/
if (DO_INDEX(ip) && index < p->header.nextindex) {
s64 lblock;
imp = 0;
stbl = DT_GETSTBL(p);
for (i = index; i < p->header.nextindex; i++) {
......@@ -2127,7 +2160,7 @@ int dtDelete(tid_t tid,
(struct ldtentry *) & p->slot[stbl[i]];
modify_index(tid, ip,
le32_to_cpu(ldtentry->index),
bn, i, &imp);
bn, i, &imp, &lblock);
}
if (imp)
release_metapage(imp);
......@@ -2769,12 +2802,6 @@ void dtInitRoot(tid_t tid, struct inode *ip, u32 idotdot)
set_cflag(COMMIT_Stale, ip);
tblk->xflag = xflag_save;
/*
* Tells jfs_metapage code that the metadata pages
* for the index table are no longer useful, and
* remove them from page cache.
*/
invalidate_inode_metapages(ip);
} else
ip->i_size = 1;
......@@ -3919,6 +3946,8 @@ static void dtInsertEntry(dtpage_t * p, int index, struct component_name * key,
memmove(stbl + index + 1, stbl + index, nextindex - index);
if ((p->header.flag & BT_LEAF) && data->leaf.ip) {
s64 lblock;
/*
* Need to update slot number for entries that moved
* in the stbl
......@@ -3928,7 +3957,7 @@ static void dtInsertEntry(dtpage_t * p, int index, struct component_name * key,
lh = (struct ldtentry *) & (p->slot[stbl[n]]);
modify_index(data->leaf.tid, data->leaf.ip,
le32_to_cpu(lh->index), bn, n,
&mp);
&mp, &lblock);
}
if (mp)
release_metapage(mp);
......
......@@ -1170,7 +1170,7 @@ int diFree(struct inode *ip)
* invalidate any page of the inode extent freed from buffer cache;
*/
freepxd = iagp->inoext[extno];
invalidate_pxd_metapages(ip->i_sb->s_bdev->bd_inode, freepxd);
invalidate_pxd_metapages(ip, freepxd);
/*
* update iag list(s) (careful update step 2)
......
......@@ -54,7 +54,6 @@ struct jfs_inode_info {
lid_t atlhead; /* anonymous tlock list head */
lid_t atltail; /* anonymous tlock list tail */
struct list_head anon_inode_list; /* inodes having anonymous txns */
struct list_head mp_list; /* metapages in inode's address space */
/*
* rdwrlock serializes xtree between reads & writes and synchronizes
* changes to special inodes. It's use would be redundant on
......
......@@ -317,8 +317,6 @@ struct metapage *__get_metapage(struct inode *inode, unsigned long lblock,
mp->page = 0;
mp->logical_size = size;
add_to_hash(mp, hash_ptr);
if (!absolute)
list_add(&mp->inode_list, &JFS_IP(inode)->mp_list);
spin_unlock(&meta_lock);
if (new) {
......@@ -351,8 +349,6 @@ struct metapage *__get_metapage(struct inode *inode, unsigned long lblock,
freeit:
spin_lock(&meta_lock);
remove_from_hash(mp, hash_ptr);
if (!absolute)
list_del(&mp->inode_list);
free_metapage(mp);
spin_unlock(&meta_lock);
return NULL;
......@@ -457,8 +453,6 @@ void release_metapage(struct metapage * mp)
spin_unlock(&meta_lock);
} else {
remove_from_hash(mp, meta_hash(mp->mapping, mp->index));
if (!test_bit(META_absolute, &mp->flag))
list_del(&mp->inode_list);
spin_unlock(&meta_lock);
if (mp->page) {
......@@ -505,7 +499,8 @@ void __invalidate_metapages(struct inode *ip, s64 addr, int len)
struct metapage **hash_ptr;
unsigned long lblock;
int l2BlocksPerPage = PAGE_CACHE_SHIFT - ip->i_blkbits;
struct address_space *mapping = ip->i_mapping;
/* All callers are interested in block device's mapping */
struct address_space *mapping = ip->i_sb->s_bdev->bd_inode->i_mapping;
struct metapage *mp;
struct page *page;
......@@ -535,26 +530,6 @@ void __invalidate_metapages(struct inode *ip, s64 addr, int len)
}
}
void invalidate_inode_metapages(struct inode *inode)
{
struct list_head *ptr;
struct metapage *mp;
spin_lock(&meta_lock);
list_for_each(ptr, &JFS_IP(inode)->mp_list) {
mp = list_entry(ptr, struct metapage, inode_list);
clear_bit(META_dirty, &mp->flag);
set_bit(META_discard, &mp->flag);
kunmap(mp->page);
page_cache_release(mp->page);
INCREMENT(mpStat.pagefree);
mp->data = 0;
mp->page = 0;
}
spin_unlock(&meta_lock);
truncate_inode_pages(inode->i_mapping, 0);
}
#ifdef CONFIG_JFS_STATISTICS
int jfs_mpstat_read(char *buffer, char **start, off_t offset, int length,
int *eof, void *data)
......
......@@ -38,7 +38,6 @@ struct metapage {
struct metapage *hash_prev;
struct metapage *hash_next; /* Also used for free list */
struct list_head inode_list; /* per-inode metapage list */
/*
* mapping & index become redundant, but we need these here to
* add the metapage to the hash before we have the real page
......@@ -109,9 +108,7 @@ extern void __invalidate_metapages(struct inode *, s64, int);
__invalidate_metapages((ip), addressPXD(&(pxd)), lengthPXD(&(pxd)))
#define invalidate_dxd_metapages(ip, dxd) \
__invalidate_metapages((ip), addressDXD(&(dxd)), lengthDXD(&(dxd)))
#define invalidate_xad_metapages(ip, xad) \
__invalidate_metapages((ip), addressXAD(&(xad)), lengthXAD(&(xad)))
/*
* This one uses mp_list to invalidate all pages for an inode
*/
extern void invalidate_inode_metapages(struct inode *inode);
#endif /* _H_JFS_METAPAGE */
......@@ -1513,10 +1513,6 @@ int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
{
struct metapage *mp;
pxd_t *pxd;
int rc;
s64 xaddr;
int xflag;
s32 xlen;
mp = tlck->mp;
......@@ -1541,13 +1537,7 @@ int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
return 0;
}
rc = xtLookup(tlck->ip, mp->index, 1, &xflag, &xaddr, &xlen, 1);
if (rc || (xlen == 0)) {
jERROR(1, ("dataLog: can't find physical address\n"));
return 0;
}
PXDaddress(pxd, xaddr);
PXDaddress(pxd, mp->index);
PXDlength(pxd, mp->logical_size >> tblk->sb->s_blocksize_bits);
lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck));
......
......@@ -3517,6 +3517,13 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag)
xlen = lengthXAD(xad);
xaddr = addressXAD(xad);
/*
* The "data" for a directory is indexed by the block
* device's address space. This metadata must be invalidated
* here
*/
if (S_ISDIR(ip->i_mode) && (teof == 0))
invalidate_xad_metapages(ip, *xad);
/*
* entry beyond eof: continue scan of current page
* xad
......
......@@ -412,7 +412,6 @@ static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
SLAB_CTOR_CONSTRUCTOR) {
INIT_LIST_HEAD(&jfs_ip->anon_inode_list);
INIT_LIST_HEAD(&jfs_ip->mp_list);
init_rwsem(&jfs_ip->rdwrlock);
init_MUTEX(&jfs_ip->commit_sem);
jfs_ip->atlhead = 0;
......
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