vserver 1.9.5.x5
[linux-2.6.git] / fs / jfs / jfs_imap.c
index 865334f..0c1cde9 100644 (file)
@@ -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,6 +44,8 @@
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
 #include <linux/pagemap.h>
+#include <linux/quotaops.h>
+#include <linux/vserver/xid.h>
 
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
@@ -130,7 +132,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 +155,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));
@@ -241,7 +243,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 +261,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));
@@ -504,6 +506,9 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
        ip->i_mapping->a_ops = &jfs_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);
@@ -1023,7 +1028,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 +1038,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] &=
@@ -1181,7 +1186,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 +1202,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 +1224,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 
@@ -1280,6 +1285,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);
 
        /* acquire tlock of the iag page of the freed ixad 
         * to force the page NOHOMEOK (even though no data is
@@ -1312,6 +1318,7 @@ int diFree(struct inode *ip)
        rc = txCommit(tid, 1, &iplist[0], COMMIT_FORCE);
 
        txEnd(tid);
+       up(&JFS_IP(ipimap)->commit_sem);
 
        /* unlock the AG inode map information */
        AG_UNLOCK(imap, agno);
@@ -2061,7 +2068,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 +2132,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 +2154,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 +2214,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 +2363,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 +2373,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 +2387,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;
        }
 
@@ -2586,9 +2593,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,36 +2603,28 @@ 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;
+                       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
+                */
+               set_bit(META_discard, &mp->flag);
                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 */
 
                /*
                 * start tyransaction of update of the inode map
                 * addressing structure pointing to the new iag page;
                 */
-#endif                         /*  _STILL_TO_PORT */
                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
                         */
@@ -2639,7 +2638,7 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
 
                /* update the inode map's inode to reflect the extension */
                ipimap->i_size += PSIZE;
-               ipimap->i_blocks += LBLK2PBLK(sb, xlen);
+               inode_add_bytes(ipimap, PSIZE);
 
                /*
                 * txCommit(COMMIT_FORCE) will synchronously write address 
@@ -2650,6 +2649,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);
 
                duplicateIXtree(sb, blkno, xlen, &xaddr);
 
@@ -2683,7 +2683,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;
@@ -2910,7 +2910,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 +2931,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 +2977,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 +3003,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 +3014,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 +3061,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 +3080,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 +3099,21 @@ 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);
+       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;
        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_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);
+
        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,6 +3164,8 @@ 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;
 
        dip->di_fileset = cpu_to_le32(jfs_ip->fileset);
        dip->di_inostamp = cpu_to_le32(JFS_SBI(ip->i_sb)->inostamp);
@@ -3164,8 +3174,11 @@ static void copy_to_dinode(struct dinode * dip, struct inode *ip)
        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);
+
+       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);
        /*
         * mode2 is only needed for storing the higher order bits.
         * Trust i_mode for the lower order ones