[PATCH] fs/jfs: Conversion to generic boolean
[powerpc.git] / fs / jfs / jfs_imap.c
index 4021d46..a45ee24 100644 (file)
 #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])
+#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
  */
-static int diAllocAG(struct inomap *, int, boolean_t, struct inode *);
-static int diAllocAny(struct inomap *, int, boolean_t, struct inode *);
+static int diAllocAG(struct inomap *, int, bool, struct inode *);
+static int diAllocAny(struct inomap *, int, bool, struct inode *);
 static int diAllocBit(struct inomap *, struct iag *, int);
 static int diAllocExt(struct inomap *, int, struct inode *);
 static int diAllocIno(struct inomap *, int, struct inode *);
@@ -259,8 +265,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);
 
@@ -491,6 +496,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);
 }
 
@@ -514,8 +521,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
@@ -559,8 +564,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);
 }
@@ -1257,7 +1261,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
@@ -1290,7 +1294,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);
@@ -1341,7 +1345,7 @@ diInitInode(struct inode *ip, int iagno, int ino, int extno, struct iag * iagp)
  *
  * PARAMETERS:
  *      pip    - pointer to incore inode for the parent inode.
- *      dir    - TRUE if the new disk inode is for a directory.
+ *      dir    - 'true' if the new disk inode is for a directory.
  *      ip     - pointer to a new inode
  *
  * RETURN VALUES:
@@ -1349,7 +1353,7 @@ diInitInode(struct inode *ip, int iagno, int ino, int extno, struct iag * iagp)
  *      -ENOSPC        - insufficient disk resources.
  *      -EIO   - i/o error.
  */
-int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
+int diAlloc(struct inode *pip, bool dir, struct inode *ip)
 {
        int rc, ino, iagno, addext, extno, bitno, sword;
        int nwords, rem, i, agno;
@@ -1371,7 +1375,7 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
        /* for a directory, the allocation policy is to start 
         * at the ag level using the preferred ag.
         */
-       if (dir == TRUE) {
+       if (dir) {
                agno = dbNextAG(JFS_SBI(pip->i_sb)->ipbmap);
                AG_LOCK(imap, agno);
                goto tryag;
@@ -1647,7 +1651,7 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
  * PARAMETERS:
  *      imap   - pointer to inode map control structure.
  *      agno   - allocation group to allocate from.
- *      dir    - TRUE if the new disk inode is for a directory.
+ *      dir    - 'true' if the new disk inode is for a directory.
  *      ip     - pointer to the new inode to be filled in on successful return
  *               with the disk inode number allocated, its extent address
  *               and the start of the ag.
@@ -1658,7 +1662,7 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
  *      -EIO   - i/o error.
  */
 static int
-diAllocAG(struct inomap * imap, int agno, boolean_t dir, struct inode *ip)
+diAllocAG(struct inomap * imap, int agno, bool dir, struct inode *ip)
 {
        int rc, addext, numfree, numinos;
 
@@ -1678,7 +1682,7 @@ diAllocAG(struct inomap * imap, int agno, boolean_t dir, struct inode *ip)
         * if there are a small number of free inodes or number of free
         * inodes is a small percentage of the number of backed inodes.
         */
-       if (dir == TRUE)
+       if (dir)
                addext = (numfree < 64 ||
                          (numfree < 256
                           && ((numfree * 100) / numinos) <= 20));
@@ -1717,7 +1721,7 @@ diAllocAG(struct inomap * imap, int agno, boolean_t dir, struct inode *ip)
  * PARAMETERS:
  *      imap   - pointer to inode map control structure.
  *      agno   - primary allocation group (to avoid).
- *      dir    - TRUE if the new disk inode is for a directory.
+ *      dir    - 'true' if the new disk inode is for a directory.
  *      ip     - pointer to a new inode to be filled in on successful return
  *               with the disk inode number allocated, its extent address
  *               and the start of the ag.
@@ -1728,7 +1732,7 @@ diAllocAG(struct inomap * imap, int agno, boolean_t dir, struct inode *ip)
  *      -EIO   - i/o error.
  */
 static int
-diAllocAny(struct inomap * imap, int agno, boolean_t dir, struct inode *ip)
+diAllocAny(struct inomap * imap, int agno, bool dir, struct inode *ip)
 {
        int ag, rc;
        int maxag = JFS_SBI(imap->im_ipimap->i_sb)->bmap->db_maxag;
@@ -2550,13 +2554,13 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
                 * addressing structure pointing to the new iag page;
                 */
                tid = txBegin(sb, COMMIT_FORCE);
-               down(&JFS_IP(ipimap)->commit_sem);
+               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);
-                       up(&JFS_IP(ipimap)->commit_sem);
+                       mutex_unlock(&JFS_IP(ipimap)->commit_mutex);
                        /* Free the blocks allocated for the iag since it was
                         * not successfully added to the inode map
                         */
@@ -2622,7 +2626,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);
 
@@ -2745,7 +2749,7 @@ static int diFindFree(u32 word, int start)
  * PARAMETERS:
  *     ipimap  - Incore inode map inode
  *     inum    - Number of inode to mark in permanent map
- *     is_free - If TRUE indicates inode should be marked freed, otherwise
+ *     is_free - If 'true' indicates inode should be marked freed, otherwise
  *               indicates inode should be marked allocated.
  *
  * RETURN VALUES: 
@@ -2753,7 +2757,7 @@ static int diFindFree(u32 word, int start)
  */
 int
 diUpdatePMap(struct inode *ipimap,
-            unsigned long inum, boolean_t is_free, struct tblock * tblk)
+            unsigned long inum, bool is_free, struct tblock * tblk)
 {
        int rc;
        struct iag *iagp;
@@ -2792,7 +2796,7 @@ diUpdatePMap(struct inode *ipimap,
        /* 
         * mark the inode free in persistent map:
         */
-       if (is_free == TRUE) {
+       if (is_free) {
                /* The inode should have been allocated both in working
                 * map and in persistent map;
                 * the inode will be freed from working map at the release
@@ -2840,11 +2844,11 @@ 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);
                logdiff(diffp, mp->lsn, log);
-               LOGSYNC_LOCK(log, flags);
                if (difft < diffp) {
                        mp->lsn = lsn;
                        /* move mp after tblock in logsync list */
@@ -2856,17 +2860,15 @@ diUpdatePMap(struct inode *ipimap,
                logdiff(diffp, mp->clsn, log);
                if (difft > diffp)
                        mp->clsn = tblk->clsn;
-               LOGSYNC_UNLOCK(log, flags);
        } else {
                mp->log = log;
                mp->lsn = lsn;
                /* insert mp after tblock in logsync list */
-               LOGSYNC_LOCK(log, flags);
                log->count++;
                list_add(&mp->synclist, &tblk->synclist);
                mp->clsn = tblk->clsn;
-               LOGSYNC_UNLOCK(log, flags);
        }
+       LOGSYNC_UNLOCK(log, flags);
        write_metapage(mp);
        return (0);
 }
@@ -3072,14 +3074,40 @@ 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);
 
        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);
+
+       jfs_ip->saved_uid = le32_to_cpu(dip->di_uid);
+       if (sbi->uid == -1)
+               ip->i_uid = jfs_ip->saved_uid;
+       else {
+               ip->i_uid = sbi->uid;
+       }
+
+       jfs_ip->saved_gid = le32_to_cpu(dip->di_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);
@@ -3087,7 +3115,6 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip)
        ip->i_mtime.tv_nsec = le32_to_cpu(dip->di_mtime.tv_nsec);
        ip->i_ctime.tv_sec = le32_to_cpu(dip->di_ctime.tv_sec);
        ip->i_ctime.tv_nsec = le32_to_cpu(dip->di_ctime.tv_nsec);
-       ip->i_blksize = ip->i_sb->s_blocksize;
        ip->i_blocks = LBLK2PBLK(ip->i_sb, le64_to_cpu(dip->di_nblocks));
        ip->i_generation = le32_to_cpu(dip->di_gen);
 
@@ -3130,21 +3157,33 @@ 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);
+       if (sbi->uid == -1)
+               dip->di_uid = cpu_to_le32(ip->i_uid);
+       else
+               dip->di_uid = cpu_to_le32(jfs_ip->saved_uid);
+       if (sbi->gid == -1)
+               dip->di_gid = cpu_to_le32(ip->i_gid);
+       else
+               dip->di_gid = cpu_to_le32(jfs_ip->saved_gid);
        /*
         * 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);