vserver 1.9.3
[linux-2.6.git] / fs / xfs / xfs_bmap.c
index d797f40..4b07382 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -203,8 +203,6 @@ STATIC void
 xfs_bmap_check_extents(
        xfs_inode_t             *ip,            /* incore inode pointer */
        int                     whichfork);     /* data or attr fork */
-#else
-#define        xfs_bmap_check_extents(ip,w)
 #endif
 
 /*
@@ -3429,6 +3427,20 @@ xfs_bmap_do_search_extents(
        int             high;           /* high index of binary search */
        int             low;            /* low index of binary search */
 
+       /*
+        * Initialize the extent entry structure to catch access to
+        * uninitialized br_startblock field.
+        */
+       got.br_startoff = 0xffa5a5a5a5a5a5a5LL;
+       got.br_blockcount = 0xa55a5a5a5a5a5a5aLL;
+       got.br_state = XFS_EXT_INVALID;
+
+#if XFS_BIG_BLKNOS
+       got.br_startblock = 0xffffa5a5a5a5a5a5LL;
+#else
+       got.br_startblock = 0xffffa5a5;
+#endif
+
        if (lastx != NULLEXTNUM && lastx < nextents)
                ep = base + lastx;
        else
@@ -3527,6 +3539,8 @@ xfs_bmap_search_extents(
        xfs_bmbt_rec_t  *base;          /* base of extent list */
        xfs_extnum_t    lastx;          /* last extent index used */
        xfs_extnum_t    nextents;       /* extent list size */
+       xfs_bmbt_rec_t  *ep;            /* extent list entry pointer */
+       int             rt;             /* realtime flag    */
 
        XFS_STATS_INC(xs_look_exlist);
        ifp = XFS_IFORK_PTR(ip, whichfork);
@@ -3534,8 +3548,18 @@ xfs_bmap_search_extents(
        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
        base = &ifp->if_u1.if_extents[0];
 
-       return xfs_bmap_do_search_extents(base, lastx, nextents, bno, eofp,
+       ep = xfs_bmap_do_search_extents(base, lastx, nextents, bno, eofp,
                                          lastxp, gotp, prevp);
+       rt = ip->i_d.di_flags & XFS_DIFLAG_REALTIME;
+       if(!rt && !gotp->br_startblock && (*lastxp != NULLEXTNUM)) {
+                cmn_err(CE_PANIC,"Access to block zero: fs: <%s> inode: %lld "
+                       "start_block : %llx start_off : %llx blkcnt : %llx "
+                       "extent-state : %x \n",
+                       (ip->i_mount)->m_fsname,(long long)ip->i_ino,
+                       gotp->br_startblock, gotp->br_startoff,
+                       gotp->br_blockcount,gotp->br_state);
+        }
+        return ep;
 }
 
 
@@ -4689,8 +4713,41 @@ xfs_bmapi(
                                        }
                                        break;
                                }
+
+                               /*
+                                * Split changing sb for alen and indlen since
+                                * they could be coming from different places.
+                                */
+                               if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) {
+                                       xfs_extlen_t    extsz;
+                                       xfs_extlen_t    ralen;
+                                       if (!(extsz = ip->i_d.di_extsize))
+                                               extsz = mp->m_sb.sb_rextsize;
+                                       ralen = roundup(alen, extsz);
+                                       ralen = ralen / mp->m_sb.sb_rextsize;
+                                       if (xfs_mod_incore_sb(mp,
+                                               XFS_SBS_FREXTENTS,
+                                               -(ralen), rsvd)) {
+                                               if (XFS_IS_QUOTA_ON(ip->i_mount))
+                                                       XFS_TRANS_UNRESERVE_BLKQUOTA(
+                                                               mp, NULL, ip,
+                                                               (long)alen);
+                                               break;
+                                       }
+                               } else {
+                                       if (xfs_mod_incore_sb(mp,
+                                                             XFS_SBS_FDBLOCKS,
+                                                             -(alen), rsvd)) {
+                                               if (XFS_IS_QUOTA_ON(ip->i_mount))
+                                                       XFS_TRANS_UNRESERVE_BLKQUOTA(
+                                                               mp, NULL, ip,
+                                                               (long)alen);
+                                               break;
+                                       }
+                               }
+
                                if (xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
-                                               -(alen + indlen), rsvd)) {
+                                               -(indlen), rsvd)) {
                                        XFS_TRANS_UNRESERVE_BLKQUOTA(
                                                mp, NULL, ip, (long)alen);
                                        break;
@@ -5445,7 +5502,7 @@ int                                               /* error code */
 xfs_getbmap(
        bhv_desc_t              *bdp,           /* XFS behavior descriptor*/
        struct getbmap          *bmv,           /* user bmap structure */
-       void                    *ap,            /* pointer to user's array */
+       void                    __user *ap,     /* pointer to user's array */
        int                     interface)      /* interface flags */
 {
        __int64_t               bmvend;         /* last block requested */
@@ -5634,8 +5691,10 @@ xfs_getbmap(
                                        (__int64_t)(bmvend - bmv->bmv_offset));
                                bmv->bmv_entries++;
                                ap = (interface & BMV_IF_EXTENDED) ?
-                                       (void *)((struct getbmapx *)ap + 1) :
-                                       (void *)((struct getbmap *)ap + 1);
+                                               (void __user *)
+                                       ((struct getbmapx __user *)ap + 1) :
+                                               (void __user *)
+                                       ((struct getbmap __user *)ap + 1);
                        }
                }
        } while (nmap && nexleft && bmv->bmv_length);