X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fjfs%2Fjfs_imap.c;h=d88cf0b1bff2ecfb0002350cd6c6bf7ad7f5e098;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=0c1cde98c6ade01c784baee11b1f5b0fd53bf51a;hpb=6a77f38946aaee1cd85eeec6cf4229b204c15071;p=linux-2.6.git diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index 0c1cde98c..d88cf0b1b 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -48,6 +48,7 @@ #include #include "jfs_incore.h" +#include "jfs_inode.h" #include "jfs_filsys.h" #include "jfs_dinode.h" #include "jfs_dmap.h" @@ -56,23 +57,24 @@ #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 */ /* iag free list lock */ -#define IAGFREE_LOCK_INIT(imap) init_MUTEX(&imap->im_freelock) -#define IAGFREE_LOCK(imap) down(&imap->im_freelock) -#define IAGFREE_UNLOCK(imap) up(&imap->im_freelock) +#define IAGFREE_LOCK_INIT(imap) mutex_init(&imap->im_freelock) +#define IAGFREE_LOCK(imap) mutex_lock(&imap->im_freelock) +#define IAGFREE_UNLOCK(imap) mutex_unlock(&imap->im_freelock) /* per ag iag list locks */ -#define AG_LOCK_INIT(imap,index) init_MUTEX(&(imap->im_aglock[index])) -#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; +#define AG_LOCK_INIT(imap,index) mutex_init(&(imap->im_aglock[index])) +#define AG_LOCK(imap,agno) mutex_lock(&imap->im_aglock[agno]) +#define AG_UNLOCK(imap,agno) mutex_unlock(&imap->im_aglock[agno]) /* * forward references @@ -91,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() * @@ -193,8 +176,6 @@ int diMount(struct inode *ipimap) imap->im_ipimap = ipimap; JFS_IP(ipimap)->i_imap = imap; -// DBG_DIINIT(imap); - return (0); } @@ -285,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); @@ -503,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 */ @@ -517,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); } @@ -540,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 @@ -585,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); } @@ -1048,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. @@ -1236,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); @@ -1285,7 +1262,7 @@ int diFree(struct inode *ip) * to be freed by the transaction; */ tid = txBegin(ipimap->i_sb, COMMIT_FORCE); - down(&JFS_IP(ipimap)->commit_sem); + mutex_lock(&JFS_IP(ipimap)->commit_mutex); /* acquire tlock of the iag page of the freed ixad * to force the page NOHOMEOK (even though no data is @@ -1318,7 +1295,7 @@ int diFree(struct inode *ip) rc = txCommit(tid, 1, &iplist[0], COMMIT_FORCE); txEnd(tid); - up(&JFS_IP(ipimap)->commit_sem); + mutex_unlock(&JFS_IP(ipimap)->commit_mutex); /* unlock the AG inode map information */ AG_UNLOCK(imap, agno); @@ -1355,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; @@ -2574,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); + mutex_lock(&JFS_IP(ipimap)->commit_mutex); + + /* update the inode map addressing structure to point to it */ + if ((rc = + xtInsert(tid, ipimap, 0, blkno, xlen, &xaddr, 0))) { + txEnd(tid); + mutex_unlock(&JFS_IP(ipimap)->commit_mutex); /* Free the blocks allocated for the iag since it was * not successfully added to the inode map */ @@ -2585,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; } @@ -2606,40 +2614,10 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) iagp->inosmap[i] = cpu_to_le32(ONES); /* - * Invalidate the page after writing and syncing it. - * After it's initialized, we access it in a different - * address space + * Write and sync the metapage */ - set_bit(META_discard, &mp->flag); flush_metapage(mp); - /* - * start tyransaction 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 - */ - 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); - /* * txCommit(COMMIT_FORCE) will synchronously write address * index pages and inode after commit in careful update order @@ -2649,7 +2627,7 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) rc = txCommit(tid, 1, &iplist[0], COMMIT_FORCE); txEnd(tid); - up(&JFS_IP(ipimap)->commit_sem); + mutex_unlock(&JFS_IP(ipimap)->commit_mutex); duplicateIXtree(sb, blkno, xlen, &xaddr); @@ -2790,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 */ @@ -2806,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. @@ -2865,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); @@ -2872,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); } @@ -3099,6 +3075,7 @@ static void duplicateIXtree(struct super_block *sb, s64 blkno, static int copy_from_dinode(struct dinode * dip, struct inode *ip) { struct jfs_inode_info *jfs_ip = JFS_IP(ip); + struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb); uid_t uid; gid_t gid; @@ -3106,14 +3083,38 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip) jfs_ip->mode2 = le32_to_cpu(dip->di_mode); ip->i_mode = le32_to_cpu(dip->di_mode) & 0xffff; + if (sbi->umask != -1) { + ip->i_mode = (ip->i_mode & ~0777) | (0777 & ~sbi->umask); + /* For directories, add x permission if r is allowed by umask */ + if (S_ISDIR(ip->i_mode)) { + if (ip->i_mode & 0400) + ip->i_mode |= 0100; + if (ip->i_mode & 0040) + ip->i_mode |= 0010; + if (ip->i_mode & 0004) + ip->i_mode |= 0001; + } + } ip->i_nlink = le32_to_cpu(dip->di_nlink); uid = le32_to_cpu(dip->di_uid); gid = le32_to_cpu(dip->di_gid); - ip->i_uid = INOXID_UID(XID_TAG(ip), uid, gid); - ip->i_gid = INOXID_GID(XID_TAG(ip), uid, gid); ip->i_xid = INOXID_XID(XID_TAG(ip), uid, gid, 0); + jfs_ip->saved_uid = INOXID_UID(XID_TAG(ip), uid, gid); + if (sbi->uid == -1) + ip->i_uid = jfs_ip->saved_uid; + else { + ip->i_uid = sbi->uid; + } + + jfs_ip->saved_gid = INOXID_GID(XID_TAG(ip), uid, gid); + if (sbi->gid == -1) + ip->i_gid = jfs_ip->saved_gid; + else { + ip->i_gid = sbi->gid; + } + ip->i_size = le64_to_cpu(dip->di_size); ip->i_atime.tv_sec = le32_to_cpu(dip->di_atime.tv_sec); ip->i_atime.tv_nsec = le32_to_cpu(dip->di_atime.tv_nsec); @@ -3164,26 +3165,31 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip) static void copy_to_dinode(struct dinode * dip, struct inode *ip) { struct jfs_inode_info *jfs_ip = JFS_IP(ip); - uid_t uid; - gid_t gid; + struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb); dip->di_fileset = cpu_to_le32(jfs_ip->fileset); - dip->di_inostamp = cpu_to_le32(JFS_SBI(ip->i_sb)->inostamp); + dip->di_inostamp = cpu_to_le32(sbi->inostamp); dip->di_number = cpu_to_le32(ip->i_ino); dip->di_gen = cpu_to_le32(ip->i_generation); dip->di_size = cpu_to_le64(ip->i_size); dip->di_nblocks = cpu_to_le64(PBLK2LBLK(ip->i_sb, ip->i_blocks)); dip->di_nlink = cpu_to_le32(ip->i_nlink); - uid = XIDINO_UID(XID_TAG(ip), ip->i_uid, ip->i_xid); - gid = XIDINO_GID(XID_TAG(ip), ip->i_gid, ip->i_xid); - dip->di_uid = cpu_to_le32(uid); - dip->di_gid = cpu_to_le32(gid); + dip->di_uid = cpu_to_le32(XIDINO_UID(XID_TAG(ip), + (sbi->uid == -1) ? ip->i_uid : jfs_ip->saved_uid, ip->i_xid)); + dip->di_gid = cpu_to_le32(XIDINO_GID(XID_TAG(ip), + (sbi->gid == -1) ? ip->i_gid : jfs_ip->saved_gid, ip->i_xid)); + /* * mode2 is only needed for storing the higher order bits. * Trust i_mode for the lower order ones */ - dip->di_mode = cpu_to_le32((jfs_ip->mode2 & 0xffff0000) | ip->i_mode); + if (sbi->umask == -1) + dip->di_mode = cpu_to_le32((jfs_ip->mode2 & 0xffff0000) | + ip->i_mode); + else /* Leave the original permissions alone */ + dip->di_mode = cpu_to_le32(jfs_ip->mode2); + dip->di_atime.tv_sec = cpu_to_le32(ip->i_atime.tv_sec); dip->di_atime.tv_nsec = cpu_to_le32(ip->i_atime.tv_nsec); dip->di_ctime.tv_sec = cpu_to_le32(ip->i_ctime.tv_sec); @@ -3200,84 +3206,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 */