vserver 2.0 rc7
[linux-2.6.git] / fs / xfs / xfs_inode.c
index 8a821fe..6e523ea 100644 (file)
@@ -67,6 +67,7 @@
 #include "xfs_mac.h"
 #include "xfs_acl.h"
 
+#include <linux/vserver/xid.h>
 
 kmem_zone_t *xfs_ifork_zone;
 kmem_zone_t *xfs_inode_zone;
@@ -135,11 +136,11 @@ xfs_inobp_check(
        for (i = 0; i < j; i++) {
                dip = (xfs_dinode_t *)xfs_buf_offset(bp,
                                        i * mp->m_sb.sb_inodesize);
-               if (INT_ISZERO(dip->di_next_unlinked, ARCH_CONVERT))  {
+               if (!dip->di_next_unlinked)  {
                        xfs_fs_cmn_err(CE_ALERT, mp,
                                "Detected a bogus zero next_unlinked field in incore inode buffer 0x%p.  About to pop an ASSERT.",
                                bp);
-                       ASSERT(!INT_ISZERO(dip->di_next_unlinked, ARCH_CONVERT));
+                       ASSERT(dip->di_next_unlinked);
                }
        }
 }
@@ -176,7 +177,7 @@ xfs_inobp_bwcheck(xfs_buf_t *bp)
                        xfs_fs_cmn_err(CE_WARN, mp,
                                "corrupt, unmount and run xfs_repair");
                }
-               if (INT_ISZERO(dip->di_next_unlinked, ARCH_CONVERT))  {
+               if (!dip->di_next_unlinked)  {
                        cmn_err(CE_WARN,
 "Bad next_unlinked field (0) in XFS inode buffer 0x%p, starting blockno %Ld, offset 0x%x",
                                (__uint64_t)(__psunsigned_t) bp,
@@ -520,8 +521,7 @@ xfs_iformat(
                        }
 
                        di_size = INT_GET(dip->di_core.di_size, ARCH_CONVERT);
-                       if (unlikely(di_size >
-                           XFS_DFORK_DSIZE_ARCH(dip, ip->i_mount, ARCH_CONVERT))) {
+                       if (unlikely(di_size > XFS_DFORK_DSIZE(dip, ip->i_mount))) {
                                xfs_fs_cmn_err(CE_WARN, ip->i_mount,
                                        "corrupt inode %Lu (bad size %Ld for local inode).  Unmount and run xfs_repair.",
                                        (unsigned long long) ip->i_ino,
@@ -555,7 +555,7 @@ xfs_iformat(
        if (error) {
                return error;
        }
-       if (!XFS_DFORK_Q_ARCH(dip, ARCH_CONVERT))
+       if (!XFS_DFORK_Q(dip))
                return 0;
        ASSERT(ip->i_afp == NULL);
        ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP);
@@ -563,7 +563,7 @@ xfs_iformat(
                XFS_IFORK_ASIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
        switch (INT_GET(dip->di_core.di_aformat, ARCH_CONVERT)) {
        case XFS_DINODE_FMT_LOCAL:
-               atp = (xfs_attr_shortform_t *)XFS_DFORK_APTR_ARCH(dip, ARCH_CONVERT);
+               atp = (xfs_attr_shortform_t *)XFS_DFORK_APTR(dip);
                size = (int)INT_GET(atp->hdr.totsize, ARCH_CONVERT);
                error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK, size);
                break;
@@ -610,11 +610,11 @@ xfs_iformat_local(
         * is wrong and we just bail out rather than crash in
         * kmem_alloc() or memcpy() below.
         */
-       if (unlikely(size > XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT))) {
+       if (unlikely(size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) {
                xfs_fs_cmn_err(CE_WARN, ip->i_mount,
                        "corrupt inode %Lu (bad size %d for local fork, size = %d).  Unmount and run xfs_repair.",
                        (unsigned long long) ip->i_ino, size,
-                       XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT));
+                       XFS_DFORK_SIZE(dip, ip->i_mount, whichfork));
                XFS_CORRUPTION_ERROR("xfs_iformat_local", XFS_ERRLEVEL_LOW,
                                     ip->i_mount, dip);
                return XFS_ERROR(EFSCORRUPTED);
@@ -632,8 +632,7 @@ xfs_iformat_local(
        ifp->if_bytes = size;
        ifp->if_real_bytes = real_size;
        if (size)
-               memcpy(ifp->if_u1.if_data,
-                       XFS_DFORK_PTR_ARCH(dip, whichfork, ARCH_CONVERT), size);
+               memcpy(ifp->if_u1.if_data, XFS_DFORK_PTR(dip, whichfork), size);
        ifp->if_flags &= ~XFS_IFEXTENTS;
        ifp->if_flags |= XFS_IFINLINE;
        return 0;
@@ -662,7 +661,7 @@ xfs_iformat_extents(
        int             i;
 
        ifp = XFS_IFORK_PTR(ip, whichfork);
-       nex = XFS_DFORK_NEXTENTS_ARCH(dip, whichfork, ARCH_CONVERT);
+       nex = XFS_DFORK_NEXTENTS(dip, whichfork);
        size = nex * (uint)sizeof(xfs_bmbt_rec_t);
 
        /*
@@ -670,7 +669,7 @@ xfs_iformat_extents(
         * is wrong and we just bail out rather than crash in
         * kmem_alloc() or memcpy() below.
         */
-       if (unlikely(size < 0 || size > XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT))) {
+       if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) {
                xfs_fs_cmn_err(CE_WARN, ip->i_mount,
                        "corrupt inode %Lu ((a)extents = %d).  Unmount and run xfs_repair.",
                        (unsigned long long) ip->i_ino, nex);
@@ -692,8 +691,7 @@ xfs_iformat_extents(
        ifp->if_bytes = size;
        ifp->if_real_bytes = real_size;
        if (size) {
-               dp = (xfs_bmbt_rec_t *)
-                       XFS_DFORK_PTR_ARCH(dip, whichfork, ARCH_CONVERT);
+               dp = (xfs_bmbt_rec_t *) XFS_DFORK_PTR(dip, whichfork);
                xfs_validate_extents(dp, nex, 1, XFS_EXTFMT_INODE(ip));
                ep = ifp->if_u1.if_extents;
                for (i = 0; i < nex; i++, ep++, dp++) {
@@ -739,7 +737,7 @@ xfs_iformat_btree(
        int                     size;
 
        ifp = XFS_IFORK_PTR(ip, whichfork);
-       dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR_ARCH(dip, whichfork, ARCH_CONVERT);
+       dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork);
        size = XFS_BMAP_BROOT_SPACE(dfp);
        nrecs = XFS_BMAP_BROOT_NUMRECS(dfp);
 
@@ -752,7 +750,7 @@ xfs_iformat_btree(
         */
        if (unlikely(XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max
            || XFS_BMDR_SPACE_CALC(nrecs) >
-                       XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT)
+                       XFS_DFORK_SIZE(dip, ip->i_mount, whichfork)
            || XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks)) {
                xfs_fs_cmn_err(CE_WARN, ip->i_mount,
                        "corrupt inode %Lu (btree).  Unmount and run xfs_repair.",
@@ -769,7 +767,7 @@ xfs_iformat_btree(
         * Copy and convert from the on-disk structure
         * to the in-memory structure.
         */
-       xfs_bmdr_to_bmbt(dfp, XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT),
+       xfs_bmdr_to_bmbt(dfp, XFS_DFORK_SIZE(dip, ip->i_mount, whichfork),
                ifp->if_broot, size);
        ifp->if_flags &= ~XFS_IFEXTENTS;
        ifp->if_flags |= XFS_IFBROOT;
@@ -785,28 +783,26 @@ xfs_iformat_btree(
  * dip  = native representation
  * dir  = direction - +ve -> disk to native
  *                    -ve -> native to disk
- * arch = on-disk architecture
  */
 void
 xfs_xlate_dinode_core(
        xfs_caddr_t             buf,
        xfs_dinode_core_t       *dip,
-       int                     dir,
-       xfs_arch_t              arch)
+       int                     dir)
 {
        xfs_dinode_core_t       *buf_core = (xfs_dinode_core_t *)buf;
        xfs_dinode_core_t       *mem_core = (xfs_dinode_core_t *)dip;
+       xfs_arch_t              arch = ARCH_CONVERT;
+       uint32_t                uid = 0, gid = 0;
+       uint16_t                xid = 0;
 
        ASSERT(dir);
-       if (arch == ARCH_NOCONVERT) {
-               if (dir > 0) {
-                       memcpy((xfs_caddr_t)mem_core, (xfs_caddr_t)buf_core,
-                               sizeof(xfs_dinode_core_t));
-               } else {
-                       memcpy((xfs_caddr_t)buf_core, (xfs_caddr_t)mem_core,
-                               sizeof(xfs_dinode_core_t));
-               }
-               return;
+
+       if (dir < 0) {
+               /* FIXME make that conditional on some flag */
+               xid = mem_core->di_xid;
+               uid = XIDINO_UID(1, mem_core->di_uid, xid);
+               gid = XIDINO_GID(1, mem_core->di_gid, xid);
        }
 
        INT_XLATE(buf_core->di_magic, mem_core->di_magic, dir, arch);
@@ -814,12 +810,17 @@ xfs_xlate_dinode_core(
        INT_XLATE(buf_core->di_version, mem_core->di_version, dir, arch);
        INT_XLATE(buf_core->di_format, mem_core->di_format, dir, arch);
        INT_XLATE(buf_core->di_onlink, mem_core->di_onlink, dir, arch);
-       INT_XLATE(buf_core->di_uid, mem_core->di_uid, dir, arch);
-       INT_XLATE(buf_core->di_gid, mem_core->di_gid, dir, arch);
+       INT_XLATE(buf_core->di_uid, uid, dir, arch);
+       INT_XLATE(buf_core->di_gid, gid, dir, arch);
+       INT_XLATE(buf_core->di_xid, xid, dir, arch);
        INT_XLATE(buf_core->di_nlink, mem_core->di_nlink, dir, arch);
        INT_XLATE(buf_core->di_projid, mem_core->di_projid, dir, arch);
 
        if (dir > 0) {
+               /* FIXME make that conditional on some flag */
+               mem_core->di_uid = INOXID_UID(1, uid, gid);
+               mem_core->di_gid = INOXID_GID(1, uid, gid);
+               mem_core->di_xid = INOXID_XID(1, uid, gid, xid);
                memcpy(mem_core->di_pad, buf_core->di_pad,
                        sizeof(buf_core->di_pad));
        } else {
@@ -854,34 +855,61 @@ xfs_xlate_dinode_core(
        INT_XLATE(buf_core->di_gen, mem_core->di_gen, dir, arch);
 }
 
-uint
-xfs_dic2xflags(
+STATIC uint
+_xfs_dic2xflags(
        xfs_dinode_core_t       *dic,
-       xfs_arch_t              arch)
+       __uint16_t              di_flags)
 {
-       __uint16_t              di_flags;
        uint                    flags = 0;
 
-       di_flags = INT_GET(dic->di_flags, arch);
-       if (di_flags & XFS_DIFLAG_REALTIME)
-               flags |= XFS_XFLAG_REALTIME;
-       if (di_flags & XFS_DIFLAG_PREALLOC)
-               flags |= XFS_XFLAG_PREALLOC;
-       if (di_flags & XFS_DIFLAG_IMMUTABLE)
-               flags |= XFS_XFLAG_IMMUTABLE;
-       if (di_flags & XFS_DIFLAG_APPEND)
-               flags |= XFS_XFLAG_APPEND;
-       if (di_flags & XFS_DIFLAG_SYNC)
-               flags |= XFS_XFLAG_SYNC;
-       if (di_flags & XFS_DIFLAG_NOATIME)
-               flags |= XFS_XFLAG_NOATIME;
-       if (di_flags & XFS_DIFLAG_NODUMP)
-               flags |= XFS_XFLAG_NODUMP;
-       if (XFS_CFORK_Q_ARCH(dic, arch))
-               flags |= XFS_XFLAG_HASATTR;
+       if (di_flags & XFS_DIFLAG_ANY) {
+               if (di_flags & XFS_DIFLAG_REALTIME)
+                       flags |= XFS_XFLAG_REALTIME;
+               if (di_flags & XFS_DIFLAG_PREALLOC)
+                       flags |= XFS_XFLAG_PREALLOC;
+               if (di_flags & XFS_DIFLAG_IMMUTABLE)
+                       flags |= XFS_XFLAG_IMMUTABLE;
+               if (di_flags & XFS_DIFLAG_IUNLINK)
+                       flags |= XFS_XFLAG_IUNLINK;
+               if (di_flags & XFS_DIFLAG_BARRIER)
+                       flags |= XFS_XFLAG_BARRIER;
+               if (di_flags & XFS_DIFLAG_APPEND)
+                       flags |= XFS_XFLAG_APPEND;
+               if (di_flags & XFS_DIFLAG_SYNC)
+                       flags |= XFS_XFLAG_SYNC;
+               if (di_flags & XFS_DIFLAG_NOATIME)
+                       flags |= XFS_XFLAG_NOATIME;
+               if (di_flags & XFS_DIFLAG_NODUMP)
+                       flags |= XFS_XFLAG_NODUMP;
+               if (di_flags & XFS_DIFLAG_RTINHERIT)
+                       flags |= XFS_XFLAG_RTINHERIT;
+               if (di_flags & XFS_DIFLAG_PROJINHERIT)
+                       flags |= XFS_XFLAG_PROJINHERIT;
+               if (di_flags & XFS_DIFLAG_NOSYMLINKS)
+                       flags |= XFS_XFLAG_NOSYMLINKS;
+       }
+
        return flags;
 }
 
+uint
+xfs_ip2xflags(
+       xfs_inode_t             *ip)
+{
+       xfs_dinode_core_t       *dic = &ip->i_d;
+
+       return _xfs_dic2xflags(dic, dic->di_flags) |
+               (XFS_CFORK_Q(dic) ? XFS_XFLAG_HASATTR : 0);
+}
+
+uint
+xfs_dic2xflags(
+       xfs_dinode_core_t       *dic)
+{
+       return _xfs_dic2xflags(dic, INT_GET(dic->di_flags, ARCH_CONVERT)) |
+               (XFS_CFORK_Q_DISK(dic) ? XFS_XFLAG_HASATTR : 0);
+}
+
 /*
  * Given a mount structure and an inode number, return a pointer
  * to a newly allocated in-core inode coresponding to the given
@@ -967,9 +995,9 @@ xfs_iread(
         * specific information.
         * Otherwise, just get the truly permanent information.
         */
-       if (!INT_ISZERO(dip->di_core.di_mode, ARCH_CONVERT)) {
+       if (dip->di_core.di_mode) {
                xfs_xlate_dinode_core((xfs_caddr_t)&dip->di_core,
-                    &(ip->i_d), 1, ARCH_CONVERT);
+                    &(ip->i_d), 1);
                error = xfs_iformat(ip, dip);
                if (error)  {
                        kmem_zone_free(xfs_inode_zone, ip);
@@ -1121,7 +1149,7 @@ xfs_ialloc(
        xfs_trans_t     *tp,
        xfs_inode_t     *pip,
        mode_t          mode,
-       nlink_t         nlink,
+       xfs_nlink_t     nlink,
        xfs_dev_t       rdev,
        cred_t          *cr,
        xfs_prid_t      prid,
@@ -1156,7 +1184,8 @@ xfs_ialloc(
         * This is because we're setting fields here we need
         * to prevent others from looking at until we're done.
         */
-       error = xfs_trans_iget(tp->t_mountp, tp, ino, XFS_ILOCK_EXCL, &ip);
+       error = xfs_trans_iget(tp->t_mountp, tp, ino,
+                       IGET_CREATE, XFS_ILOCK_EXCL, &ip);
        if (error != 0) {
                return error;
        }
@@ -1170,6 +1199,7 @@ xfs_ialloc(
        ASSERT(ip->i_d.di_nlink == nlink);
        ip->i_d.di_uid = current_fsuid(cr);
        ip->i_d.di_gid = current_fsgid(cr);
+       ip->i_d.di_xid = current_fsxid(cr, vp);
        ip->i_d.di_projid = prid;
        memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
 
@@ -1236,8 +1266,15 @@ xfs_ialloc(
                break;
        case S_IFREG:
        case S_IFDIR:
-               if (pip->i_d.di_flags &
-                   (XFS_DIFLAG_NOATIME|XFS_DIFLAG_NODUMP|XFS_DIFLAG_SYNC)) {
+               if (unlikely(pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
+                       if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) {
+                               if ((mode & S_IFMT) == S_IFDIR) {
+                                       ip->i_d.di_flags |= XFS_DIFLAG_RTINHERIT;
+                               } else {
+                                       ip->i_d.di_flags |= XFS_DIFLAG_REALTIME;
+                                       ip->i_iocore.io_flags |= XFS_IOCORE_RT;
+                               }
+                       }
                        if ((pip->i_d.di_flags & XFS_DIFLAG_NOATIME) &&
                            xfs_inherit_noatime)
                                ip->i_d.di_flags |= XFS_DIFLAG_NOATIME;
@@ -1247,7 +1284,11 @@ xfs_ialloc(
                        if ((pip->i_d.di_flags & XFS_DIFLAG_SYNC) &&
                            xfs_inherit_sync)
                                ip->i_d.di_flags |= XFS_DIFLAG_SYNC;
+                       if ((pip->i_d.di_flags & XFS_DIFLAG_NOSYMLINKS) &&
+                           xfs_inherit_nosymlinks)
+                               ip->i_d.di_flags |= XFS_DIFLAG_NOSYMLINKS;
                }
+               /* FALLTHROUGH */
        case S_IFLNK:
                ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
                ip->i_df.if_flags = XFS_IFEXTENTS;
@@ -1912,7 +1953,7 @@ xfs_iunlink(
        agino = XFS_INO_TO_AGINO(mp, ip->i_ino);
        ASSERT(agino != 0);
        bucket_index = agino % XFS_AGI_UNLINKED_BUCKETS;
-       ASSERT(!INT_ISZERO(agi->agi_unlinked[bucket_index], ARCH_CONVERT));
+       ASSERT(agi->agi_unlinked[bucket_index]);
        ASSERT(INT_GET(agi->agi_unlinked[bucket_index], ARCH_CONVERT) != agino);
 
        if (INT_GET(agi->agi_unlinked[bucket_index], ARCH_CONVERT) != NULLAGINO) {
@@ -1927,7 +1968,7 @@ xfs_iunlink(
                        return error;
                }
                ASSERT(INT_GET(dip->di_next_unlinked, ARCH_CONVERT) == NULLAGINO);
-               ASSERT(!INT_ISZERO(dip->di_next_unlinked, ARCH_CONVERT));
+               ASSERT(dip->di_next_unlinked);
                /* both on-disk, don't endian flip twice */
                dip->di_next_unlinked = agi->agi_unlinked[bucket_index];
                offset = ip->i_boffset +
@@ -2020,7 +2061,7 @@ xfs_iunlink_remove(
        ASSERT(agino != 0);
        bucket_index = agino % XFS_AGI_UNLINKED_BUCKETS;
        ASSERT(INT_GET(agi->agi_unlinked[bucket_index], ARCH_CONVERT) != NULLAGINO);
-       ASSERT(!INT_ISZERO(agi->agi_unlinked[bucket_index], ARCH_CONVERT));
+       ASSERT(agi->agi_unlinked[bucket_index]);
 
        if (INT_GET(agi->agi_unlinked[bucket_index], ARCH_CONVERT) == agino) {
                /*
@@ -2996,7 +3037,7 @@ xfs_iflush_fork(
                ASSERT(whichfork == XFS_ATTR_FORK);
                return 0;
        }
-       cp = XFS_DFORK_PTR_ARCH(dip, whichfork, ARCH_CONVERT);
+       cp = XFS_DFORK_PTR(dip, whichfork);
        mp = ip->i_mount;
        switch (XFS_IFORK_FORMAT(ip, whichfork)) {
        case XFS_DINODE_FMT_LOCAL:
@@ -3037,7 +3078,7 @@ xfs_iflush_fork(
                                XFS_BROOT_SIZE_ADJ));
                        xfs_bmbt_to_bmdr(ifp->if_broot, ifp->if_broot_bytes,
                                (xfs_bmdr_block_t *)cp,
-                               XFS_DFORK_SIZE_ARCH(dip, mp, whichfork, ARCH_CONVERT));
+                               XFS_DFORK_SIZE(dip, mp, whichfork));
                }
                break;
 
@@ -3455,8 +3496,7 @@ xfs_iflush_int(
         * because if the inode is dirty at all the core must
         * be.
         */
-       xfs_xlate_dinode_core((xfs_caddr_t)&(dip->di_core), &(ip->i_d),
-               -1, ARCH_CONVERT);
+       xfs_xlate_dinode_core((xfs_caddr_t)&(dip->di_core), &(ip->i_d), -1);
 
        /* Wrap, we never let the log put out DI_MAX_FLUSH */
        if (ip->i_d.di_flushiter == DI_MAX_FLUSH)
@@ -3486,7 +3526,7 @@ xfs_iflush_int(
                        ip->i_d.di_version = XFS_DINODE_VERSION_2;
                        INT_SET(dip->di_core.di_version, ARCH_CONVERT, XFS_DINODE_VERSION_2);
                        ip->i_d.di_onlink = 0;
-                       INT_ZERO(dip->di_core.di_onlink, ARCH_CONVERT);
+                       dip->di_core.di_onlink = 0;
                        memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
                        memset(&(dip->di_core.di_pad[0]), 0,
                              sizeof(dip->di_core.di_pad));
@@ -3579,6 +3619,7 @@ corrupt_out:
        return XFS_ERROR(EFSCORRUPTED);
 }
 
+
 /*
  * Flush all inactive inodes in mp.  Return true if no user references
  * were found, false otherwise.
@@ -3634,7 +3675,6 @@ xfs_iflush_all(
                                        continue;
                                }
                                if (!(flag & XFS_FLUSH_ALL)) {
-                                       ASSERT(0);
                                        busy = 1;
                                        done = 1;
                                        break;
@@ -3851,6 +3891,6 @@ xfs_ilock_trace(xfs_inode_t *ip, int lock, unsigned int lockflags, inst_t *ra)
                     (void *)ra,                /* caller of ilock */
                     (void *)(unsigned long)current_cpu(),
                     (void *)(unsigned long)current_pid(),
-                    0,0,0,0,0,0,0,0,0,0);
+                    NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
 }
 #endif