X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fjfs%2Fjfs_imap.c;h=5384cac3bc829435f52901c4c93d84b6b81d95b5;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=1c77abca0eb4e64fff96bbd6d439fb6c334e3a0c;hpb=ec9397bab20a628530ce3051167d3d0fcc2c1af7;p=linux-2.6.git diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index 1c77abca0..5384cac3b 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -46,9 +46,9 @@ #include #include #include -#include #include "jfs_incore.h" +#include "jfs_inode.h" #include "jfs_filsys.h" #include "jfs_dinode.h" #include "jfs_dmap.h" @@ -57,6 +57,12 @@ #include "jfs_superblock.h" #include "jfs_debug.h" +/* + * __mark_inode_dirty expects inodes to be hashed. Since we don't want + * special inodes in the fileset inode space, we hash them to a dummy head + */ +static HLIST_HEAD(aggregate_hash); + /* * imap locks */ @@ -70,11 +76,6 @@ #define AG_LOCK(imap,agno) down(&imap->im_aglock[agno]) #define AG_UNLOCK(imap,agno) up(&imap->im_aglock[agno]) -/* - * external references - */ -extern struct address_space_operations jfs_aops; - /* * forward references */ @@ -92,25 +93,6 @@ static int diIAGRead(struct inomap * imap, int, struct metapage **); static int copy_from_dinode(struct dinode *, struct inode *); static void copy_to_dinode(struct dinode *, struct inode *); -/* - * debug code for double-checking inode map - */ -/* #define _JFS_DEBUG_IMAP 1 */ - -#ifdef _JFS_DEBUG_IMAP -#define DBG_DIINIT(imap) DBGdiInit(imap) -#define DBG_DIALLOC(imap, ino) DBGdiAlloc(imap, ino) -#define DBG_DIFREE(imap, ino) DBGdiFree(imap, ino) - -static void *DBGdiInit(struct inomap * imap); -static void DBGdiAlloc(struct inomap * imap, ino_t ino); -static void DBGdiFree(struct inomap * imap, ino_t ino); -#else -#define DBG_DIINIT(imap) -#define DBG_DIALLOC(imap, ino) -#define DBG_DIFREE(imap, ino) -#endif /* _JFS_DEBUG_IMAP */ - /* * NAME: diMount() * @@ -133,7 +115,7 @@ int diMount(struct inode *ipimap) struct inomap *imap; struct metapage *mp; int index; - struct dinomap *dinom_le; + struct dinomap_disk *dinom_le; /* * allocate/initialize the in-memory inode map control structure @@ -156,7 +138,7 @@ int diMount(struct inode *ipimap) } /* copy the on-disk version to the in-memory version. */ - dinom_le = (struct dinomap *) mp->data; + dinom_le = (struct dinomap_disk *) mp->data; imap->im_freeiag = le32_to_cpu(dinom_le->in_freeiag); imap->im_nextiag = le32_to_cpu(dinom_le->in_nextiag); atomic_set(&imap->im_numinos, le32_to_cpu(dinom_le->in_numinos)); @@ -194,8 +176,6 @@ int diMount(struct inode *ipimap) imap->im_ipimap = ipimap; JFS_IP(ipimap)->i_imap = imap; -// DBG_DIINIT(imap); - return (0); } @@ -244,7 +224,7 @@ int diUnmount(struct inode *ipimap, int mounterror) */ int diSync(struct inode *ipimap) { - struct dinomap *dinom_le; + struct dinomap_disk *dinom_le; struct inomap *imp = JFS_IP(ipimap)->i_imap; struct metapage *mp; int index; @@ -262,7 +242,7 @@ int diSync(struct inode *ipimap) } /* copy the in-memory version to the on-disk version */ - dinom_le = (struct dinomap *) mp->data; + dinom_le = (struct dinomap_disk *) mp->data; dinom_le->in_freeiag = cpu_to_le32(imp->im_freeiag); dinom_le->in_nextiag = cpu_to_le32(imp->im_nextiag); dinom_le->in_numinos = cpu_to_le32(atomic_read(&imp->im_numinos)); @@ -286,8 +266,7 @@ int diSync(struct inode *ipimap) /* * write out dirty pages of imap */ - filemap_fdatawrite(ipimap->i_mapping); - filemap_fdatawait(ipimap->i_mapping); + filemap_write_and_wait(ipimap->i_mapping); diWriteSpecial(ipimap, 0); @@ -340,7 +319,7 @@ int diRead(struct inode *ip) struct inomap *imap; int block_offset; int inodes_left; - uint pageno; + unsigned long pageno; int rel_inode; jfs_info("diRead: ino = %ld", ip->i_ino); @@ -504,7 +483,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 */ @@ -518,6 +497,8 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary) /* release the page */ release_metapage(mp); + hlist_add_head(&ip->i_hash, &aggregate_hash); + return (ip); } @@ -541,8 +522,6 @@ void diWriteSpecial(struct inode *ip, int secondary) ino_t inum = ip->i_ino; struct metapage *mp; - ip->i_state &= ~I_DIRTY; - if (secondary) address = addressPXD(&sbi->ait2) >> sbi->l2nbperpage; else @@ -586,8 +565,7 @@ void diFreeSpecial(struct inode *ip) jfs_err("diFreeSpecial called with NULL ip!"); return; } - filemap_fdatawrite(ip->i_mapping); - filemap_fdatawait(ip->i_mapping); + filemap_write_and_wait(ip->i_mapping); truncate_inode_pages(ip->i_mapping, 0); iput(ip); } @@ -629,7 +607,7 @@ int diWrite(tid_t tid, struct inode *ip) int block_offset; int inodes_left; struct metapage *mp; - uint pageno; + unsigned long pageno; int rel_inode; int dioffset; struct inode *ipimap; @@ -1029,7 +1007,7 @@ int diFree(struct inode *ip) */ iagp->inofreefwd = cpu_to_le32(imap->im_agctl[agno].inofree); - iagp->inofreeback = -1; + iagp->inofreeback = cpu_to_le32(-1); imap->im_agctl[agno].inofree = iagno; } IREAD_UNLOCK(ipimap); @@ -1039,7 +1017,7 @@ int diFree(struct inode *ip) * inodes (i.e., the inode being freed is the first free * inode of extent), */ - if (iagp->wmap[extno] == ONES) { + if (iagp->wmap[extno] == cpu_to_le32(ONES)) { sword = extno >> L2EXTSPERSUM; bitno = extno & (EXTSPERSUM - 1); iagp->inosmap[sword] &= @@ -1049,7 +1027,6 @@ int diFree(struct inode *ip) /* update the bitmap. */ iagp->wmap[extno] = cpu_to_le32(bitmap); - DBG_DIFREE(imap, inum); /* update the free inode counts at the iag, ag and * map level. @@ -1187,7 +1164,7 @@ int diFree(struct inode *ip) iagp->extfreefwd = cpu_to_le32(imap->im_agctl[agno].extfree); - iagp->extfreeback = -1; + iagp->extfreeback = cpu_to_le32(-1); imap->im_agctl[agno].extfree = iagno; } else { /* remove the iag from the ag extent list if all extents @@ -1203,7 +1180,7 @@ int diFree(struct inode *ip) imap->im_agctl[agno].extfree = le32_to_cpu(iagp->extfreefwd); - iagp->extfreefwd = iagp->extfreeback = -1; + iagp->extfreefwd = iagp->extfreeback = cpu_to_le32(-1); IAGFREE_LOCK(imap); iagp->iagfree = cpu_to_le32(imap->im_freeiag); @@ -1225,7 +1202,7 @@ int diFree(struct inode *ip) imap->im_agctl[agno].inofree = le32_to_cpu(iagp->inofreefwd); - iagp->inofreefwd = iagp->inofreeback = -1; + iagp->inofreefwd = iagp->inofreeback = cpu_to_le32(-1); } /* update the inode extent address and working map @@ -1237,7 +1214,6 @@ int diFree(struct inode *ip) jfs_error(ip->i_sb, "diFree: the pmap does not show inode free"); } iagp->wmap[extno] = 0; - DBG_DIFREE(imap, inum); PXDlength(&iagp->inoext[extno], 0); PXDaddress(&iagp->inoext[extno], 0); @@ -1356,7 +1332,6 @@ diInitInode(struct inode *ip, int iagno, int ino, int extno, struct iag * iagp) struct jfs_inode_info *jfs_ip = JFS_IP(ip); ip->i_ino = (iagno << L2INOSPERIAG) + ino; - DBG_DIALLOC(JFS_IP(ipimap)->i_imap, ip->i_ino); jfs_ip->ixpxd = iagp->inoext[extno]; jfs_ip->agno = BLKTOAG(le64_to_cpu(iagp->agstart), sbi); jfs_ip->active_ag = -1; @@ -2133,7 +2108,7 @@ static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino) * allocated. if so, update the free inode summary * map to reflect this. */ - if (iagp->wmap[extno] == ONES) { + if (iagp->wmap[extno] == cpu_to_le32(ONES)) { sword = extno >> L2EXTSPERSUM; bitno = extno & (EXTSPERSUM - 1); iagp->inosmap[sword] |= cpu_to_le32(HIGHORDER >> bitno); @@ -2155,7 +2130,7 @@ static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino) imap->im_agctl[agno].inofree = le32_to_cpu(iagp->inofreefwd); } - iagp->inofreefwd = iagp->inofreeback = -1; + iagp->inofreefwd = iagp->inofreeback = cpu_to_le32(-1); } /* update the free inode count at the iag, ag, inode @@ -2364,7 +2339,7 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno) imap->im_agctl[agno].extfree = le32_to_cpu(iagp->extfreefwd); - iagp->extfreefwd = iagp->extfreeback = -1; + iagp->extfreefwd = iagp->extfreeback = cpu_to_le32(-1); } else { /* if the iag has all free extents (newly allocated iag), * add the iag to the ag free extent list. @@ -2374,7 +2349,7 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno) aiagp->extfreeback = cpu_to_le32(iagno); iagp->extfreefwd = cpu_to_le32(fwd); - iagp->extfreeback = -1; + iagp->extfreeback = cpu_to_le32(-1); imap->im_agctl[agno].extfree = iagno; } } @@ -2388,7 +2363,7 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno) iagp->inofreefwd = cpu_to_le32(imap->im_agctl[agno].inofree); - iagp->inofreeback = -1; + iagp->inofreeback = cpu_to_le32(-1); imap->im_agctl[agno].inofree = iagno; } @@ -2575,9 +2550,18 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) goto out; } - /* assign a buffer for the page */ - mp = get_metapage(ipimap, xaddr, PSIZE, 1); - if (!mp) { + /* + * start transaction of update of the inode map + * addressing structure pointing to the new iag page; + */ + tid = txBegin(sb, COMMIT_FORCE); + down(&JFS_IP(ipimap)->commit_sem); + + /* update the inode map addressing structure to point to it */ + if ((rc = + xtInsert(tid, ipimap, 0, blkno, xlen, &xaddr, 0))) { + txEnd(tid); + up(&JFS_IP(ipimap)->commit_sem); /* Free the blocks allocated for the iag since it was * not successfully added to the inode map */ @@ -2586,6 +2570,29 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) /* release the inode map lock */ IWRITE_UNLOCK(ipimap); + goto out; + } + + /* update the inode map's inode to reflect the extension */ + ipimap->i_size += PSIZE; + inode_add_bytes(ipimap, PSIZE); + + /* assign a buffer for the page */ + mp = get_metapage(ipimap, blkno, PSIZE, 0); + if (!mp) { + /* + * This is very unlikely since we just created the + * extent, but let's try to handle it correctly + */ + xtTruncate(tid, ipimap, ipimap->i_size - PSIZE, + COMMIT_PWMAP); + + txAbort(tid, 0); + txEnd(tid); + + /* release the inode map lock */ + IWRITE_UNLOCK(ipimap); + rc = -EIO; goto out; } @@ -2594,9 +2601,9 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) /* init the iag */ memset(iagp, 0, sizeof(struct iag)); iagp->iagnum = cpu_to_le32(iagno); - iagp->inofreefwd = iagp->inofreeback = -1; - iagp->extfreefwd = iagp->extfreeback = -1; - iagp->iagfree = -1; + iagp->inofreefwd = iagp->inofreeback = cpu_to_le32(-1); + iagp->extfreefwd = iagp->extfreeback = cpu_to_le32(-1); + iagp->iagfree = cpu_to_le32(-1); iagp->nfreeinos = 0; iagp->nfreeexts = cpu_to_le32(EXTSPERIAG); @@ -2604,36 +2611,12 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) * summary map initialization handled by bzero). */ for (i = 0; i < SMAPSZ; i++) - iagp->inosmap[i] = ONES; - - flush_metapage(mp); + iagp->inosmap[i] = cpu_to_le32(ONES); /* - * start tyransaction of update of the inode map - * addressing structure pointing to the new iag page; + * Write and sync the metapage */ - tid = txBegin(sb, COMMIT_FORCE); - down(&JFS_IP(ipimap)->commit_sem); - - /* update the inode map addressing structure to point to it */ - if ((rc = - xtInsert(tid, ipimap, 0, blkno, xlen, &xaddr, 0))) { - txEnd(tid); - up(&JFS_IP(ipimap)->commit_sem); - /* Free the blocks allocated for the iag since it was - * not successfully added to the inode map - */ - dbFree(ipimap, xaddr, (s64) xlen); - - /* release the inode map lock */ - IWRITE_UNLOCK(ipimap); - - goto out; - } - - /* update the inode map's inode to reflect the extension */ - ipimap->i_size += PSIZE; - inode_add_bytes(ipimap, PSIZE); + flush_metapage(mp); /* * txCommit(COMMIT_FORCE) will synchronously write address @@ -2678,7 +2661,7 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) /* remove the iag from the iag free list */ imap->im_freeiag = le32_to_cpu(iagp->iagfree); - iagp->iagfree = -1; + iagp->iagfree = cpu_to_le32(-1); /* set the return iag number and buffer pointer */ *iagnop = iagno; @@ -2785,6 +2768,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 */ @@ -2801,6 +2785,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. @@ -2860,6 +2845,7 @@ diUpdatePMap(struct inode *ipimap, */ lsn = tblk->lsn; log = JFS_SBI(tblk->sb)->log; + LOGSYNC_LOCK(log, flags); if (mp->lsn != 0) { /* inherit older/smaller lsn */ logdiff(difft, lsn, log); @@ -2867,28 +2853,23 @@ diUpdatePMap(struct inode *ipimap, 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); } else { mp->log = log; mp->lsn = lsn; /* insert mp after tblock in logsync list */ - LOGSYNC_LOCK(log); log->count++; list_add(&mp->synclist, &tblk->synclist); mp->clsn = tblk->clsn; - LOGSYNC_UNLOCK(log); } + LOGSYNC_UNLOCK(log, flags); write_metapage(mp); return (0); } @@ -2926,8 +2907,8 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap) /* init per AG control information im_agctl[] */ for (i = 0; i < MAXAG; i++) { - imap->im_agctl[i].inofree = -1; /* free inode list */ - imap->im_agctl[i].extfree = -1; /* free extent list */ + imap->im_agctl[i].inofree = -1; + imap->im_agctl[i].extfree = -1; imap->im_agctl[i].numinos = 0; /* number of backed inodes */ imap->im_agctl[i].numfree = 0; /* number of free backed inodes */ } @@ -2972,18 +2953,18 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap) /* if any backed free inodes, insert at AG free inode list */ if ((int) le32_to_cpu(iagp->nfreeinos) > 0) { - if ((head = imap->im_agctl[n].inofree) == -1) - iagp->inofreefwd = iagp->inofreeback = -1; - else { + if ((head = imap->im_agctl[n].inofree) == -1) { + iagp->inofreefwd = cpu_to_le32(-1); + iagp->inofreeback = cpu_to_le32(-1); + } else { if ((rc = diIAGRead(imap, head, &hbp))) { rcx = rc; goto nextiag; } hiagp = (struct iag *) hbp->data; - hiagp->inofreeback = - le32_to_cpu(iagp->iagnum); + hiagp->inofreeback = iagp->iagnum; iagp->inofreefwd = cpu_to_le32(head); - iagp->inofreeback = -1; + iagp->inofreeback = cpu_to_le32(-1); write_metapage(hbp); } @@ -2998,9 +2979,10 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap) /* if any free extents, insert at AG free extent list */ if (le32_to_cpu(iagp->nfreeexts) > 0) { - if ((head = imap->im_agctl[n].extfree) == -1) - iagp->extfreefwd = iagp->extfreeback = -1; - else { + if ((head = imap->im_agctl[n].extfree) == -1) { + iagp->extfreefwd = cpu_to_le32(-1); + iagp->extfreeback = cpu_to_le32(-1); + } else { if ((rc = diIAGRead(imap, head, &hbp))) { rcx = rc; goto nextiag; @@ -3008,7 +2990,7 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap) hiagp = (struct iag *) hbp->data; hiagp->extfreeback = iagp->iagnum; iagp->extfreefwd = cpu_to_le32(head); - iagp->extfreeback = -1; + iagp->extfreeback = cpu_to_le32(-1); write_metapage(hbp); } @@ -3055,7 +3037,7 @@ static void duplicateIXtree(struct super_block *sb, s64 blkno, if (readSuper(sb, &bh)) return; j_sb = (struct jfs_superblock *)bh->b_data; - j_sb->s_flag |= JFS_BAD_SAIT; + j_sb->s_flag |= cpu_to_le32(JFS_BAD_SAIT); mark_buffer_dirty(bh); sync_dirty_buffer(bh); @@ -3194,84 +3176,3 @@ static void copy_to_dinode(struct dinode * dip, struct inode *ip) if (S_ISCHR(ip->i_mode) || S_ISBLK(ip->i_mode)) dip->di_rdev = cpu_to_le32(jfs_ip->dev); } - -#ifdef _JFS_DEBUG_IMAP -/* - * DBGdiInit() - */ -static void *DBGdiInit(struct inomap * imap) -{ - u32 *dimap; - int size; - size = 64 * 1024; - if ((dimap = (u32 *) xmalloc(size, L2PSIZE, kernel_heap)) == NULL) - assert(0); - bzero((void *) dimap, size); - imap->im_DBGdimap = dimap; -} - -/* - * DBGdiAlloc() - */ -static void DBGdiAlloc(struct inomap * imap, ino_t ino) -{ - u32 *dimap = imap->im_DBGdimap; - int w, b; - u32 m; - w = ino >> 5; - b = ino & 31; - m = 0x80000000 >> b; - assert(w < 64 * 256); - if (dimap[w] & m) { - printk("DEBUG diAlloc: duplicate alloc ino:0x%x\n", ino); - } - dimap[w] |= m; -} - -/* - * DBGdiFree() - */ -static void DBGdiFree(struct inomap * imap, ino_t ino) -{ - u32 *dimap = imap->im_DBGdimap; - int w, b; - u32 m; - w = ino >> 5; - b = ino & 31; - m = 0x80000000 >> b; - assert(w < 64 * 256); - if ((dimap[w] & m) == 0) { - printk("DEBUG diFree: duplicate free ino:0x%x\n", ino); - } - dimap[w] &= ~m; -} - -static void dump_cp(struct inomap * ipimap, char *function, int line) -{ - printk("\n* ********* *\nControl Page %s %d\n", function, line); - printk("FreeIAG %d\tNextIAG %d\n", ipimap->im_freeiag, - ipimap->im_nextiag); - printk("NumInos %d\tNumFree %d\n", - atomic_read(&ipimap->im_numinos), - atomic_read(&ipimap->im_numfree)); - printk("AG InoFree %d\tAG ExtFree %d\n", - ipimap->im_agctl[0].inofree, ipimap->im_agctl[0].extfree); - printk("AG NumInos %d\tAG NumFree %d\n", - ipimap->im_agctl[0].numinos, ipimap->im_agctl[0].numfree); -} - -static void dump_iag(struct iag * iag, char *function, int line) -{ - printk("\n* ********* *\nIAG %s %d\n", function, line); - printk("IagNum %d\tIAG Free %d\n", le32_to_cpu(iag->iagnum), - le32_to_cpu(iag->iagfree)); - printk("InoFreeFwd %d\tInoFreeBack %d\n", - le32_to_cpu(iag->inofreefwd), - le32_to_cpu(iag->inofreeback)); - printk("ExtFreeFwd %d\tExtFreeBack %d\n", - le32_to_cpu(iag->extfreefwd), - le32_to_cpu(iag->extfreeback)); - printk("NFreeInos %d\tNFreeExts %d\n", le32_to_cpu(iag->nfreeinos), - le32_to_cpu(iag->nfreeexts)); -} -#endif /* _JFS_DEBUG_IMAP */