X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fjfs%2Fjfs_imap.c;h=d88cf0b1bff2ecfb0002350cd6c6bf7ad7f5e098;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=865334f6c8afce4e1a1685700e0e4dea5f9b21de;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index 865334f6c..d88cf0b1b 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -1,5 +1,5 @@ /* - * Copyright (C) International Business Machines Corp., 2000-2003 + * Copyright (C) International Business Machines Corp., 2000-2004 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -44,8 +44,11 @@ #include #include #include +#include +#include #include "jfs_incore.h" +#include "jfs_inode.h" #include "jfs_filsys.h" #include "jfs_dinode.h" #include "jfs_dmap.h" @@ -54,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 @@ -89,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() * @@ -130,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 @@ -153,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)); @@ -191,8 +176,6 @@ int diMount(struct inode *ipimap) imap->im_ipimap = ipimap; JFS_IP(ipimap)->i_imap = imap; -// DBG_DIINIT(imap); - return (0); } @@ -241,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; @@ -259,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)); @@ -283,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); @@ -501,9 +483,12 @@ 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 */ + ip->i_flags |= S_NOQUOTA; + if ((inum == FILESYSTEM_I) && (JFS_IP(ip)->ipimap == sbi->ipaimap)) { sbi->gengen = le32_to_cpu(dp->di_gengen); sbi->inostamp = le32_to_cpu(dp->di_inostamp); @@ -512,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); } @@ -535,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 @@ -580,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); } @@ -1023,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); @@ -1033,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] &= @@ -1043,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. @@ -1181,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 @@ -1197,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); @@ -1219,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 @@ -1231,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); @@ -1280,6 +1262,7 @@ int diFree(struct inode *ip) * to be freed by the transaction; */ tid = txBegin(ipimap->i_sb, COMMIT_FORCE); + 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 @@ -1312,6 +1295,7 @@ int diFree(struct inode *ip) rc = txCommit(tid, 1, &iplist[0], COMMIT_FORCE); txEnd(tid); + mutex_unlock(&JFS_IP(ipimap)->commit_mutex); /* unlock the AG inode map information */ AG_UNLOCK(imap, agno); @@ -1348,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; @@ -2061,7 +2044,7 @@ static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino) { int extno, bitno, agno, sword, rc; struct metapage *amp = NULL, *bmp = NULL; - struct iag *aiagp = 0, *biagp = 0; + struct iag *aiagp = NULL, *biagp = NULL; u32 mask; /* check if this is the last free inode within the iag. @@ -2125,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); @@ -2147,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 @@ -2207,7 +2190,7 @@ static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino) static int diNewExt(struct inomap * imap, struct iag * iagp, int extno) { int agno, iagno, fwd, back, freei = 0, sword, rc; - struct iag *aiagp = 0, *biagp = 0, *ciagp = 0; + struct iag *aiagp = NULL, *biagp = NULL, *ciagp = NULL; struct metapage *amp, *bmp, *cmp, *dmp; struct inode *ipimap; s64 blkno, hint; @@ -2356,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. @@ -2366,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; } } @@ -2380,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; } @@ -2567,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 */ @@ -2578,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; } @@ -2586,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); @@ -2596,50 +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); -#ifdef _STILL_TO_PORT - /* synchronously write the iag page */ - if (bmWrite(bp)) { - /* 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); - - rc = -EIO; - goto out; - } - - /* Now the iag is on disk */ + 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 */ -#endif /* _STILL_TO_PORT */ - tid = txBegin(sb, COMMIT_FORCE); - - /* update the inode map addressing structure to point to it */ - if ((rc = - xtInsert(tid, ipimap, 0, blkno, xlen, &xaddr, 0))) { - /* 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; - ipimap->i_blocks += LBLK2PBLK(sb, xlen); + flush_metapage(mp); /* * txCommit(COMMIT_FORCE) will synchronously write address @@ -2650,6 +2627,7 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) rc = txCommit(tid, 1, &iplist[0], COMMIT_FORCE); txEnd(tid); + mutex_unlock(&JFS_IP(ipimap)->commit_mutex); duplicateIXtree(sb, blkno, xlen, &xaddr); @@ -2683,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; @@ -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); } @@ -2910,7 +2886,7 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap) { int rc, rcx = 0; struct inomap *imap = JFS_IP(ipimap)->i_imap; - struct iag *iagp = 0, *hiagp = 0; + struct iag *iagp = NULL, *hiagp = NULL; struct bmap *mp = JFS_SBI(ipbmap->i_sb)->bmap; struct metapage *bp, *hbp; int i, n, head; @@ -2931,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 */ } @@ -2977,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); } @@ -3003,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; @@ -3013,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); } @@ -3060,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); @@ -3079,7 +3056,7 @@ static void duplicateIXtree(struct super_block *sb, s64 blkno, } /* update the inode map's inode to reflect the extension */ ip->i_size += PSIZE; - ip->i_blocks += LBLK2PBLK(sb, xlen); + inode_add_bytes(ip, PSIZE); txCommit(tid, 1, &ip, COMMIT_FORCE); cleanup: txEnd(tid); @@ -3098,14 +3075,46 @@ 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; jfs_ip->fileset = le32_to_cpu(dip->di_fileset); 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); - ip->i_uid = le32_to_cpu(dip->di_uid); - ip->i_gid = le32_to_cpu(dip->di_gid); + + uid = le32_to_cpu(dip->di_uid); + gid = le32_to_cpu(dip->di_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); @@ -3156,21 +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); + 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); - dip->di_uid = cpu_to_le32(ip->i_uid); - dip->di_gid = cpu_to_le32(ip->i_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); @@ -3187,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 */