[XFS] Fix an infinite loop issue in bulkstat when a corrupt inode is
authorNathan Scott <nathans@sgi.com>
Fri, 17 Mar 2006 06:26:04 +0000 (17:26 +1100)
committerNathan Scott <nathans@sgi.com>
Fri, 17 Mar 2006 06:26:04 +0000 (17:26 +1100)
detected.  Thanks to Roger Willcocks.

SGI-PV: 951054
SGI-Modid: xfs-linux-melb:xfs-kern:25477a

Signed-off-by: Nathan Scott <nathans@sgi.com>
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_itable.c
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_vfsops.c

index 86a8451d10fc51d0ab2cb4caecfbdb30dbf1b897..b1e95707e7cf2e9a04ae5023624cd9a9f9ff3524 100644 (file)
@@ -253,7 +253,8 @@ xfs_itobp(
        xfs_inode_t     *ip,
        xfs_dinode_t    **dipp,
        xfs_buf_t       **bpp,
-       xfs_daddr_t     bno)
+       xfs_daddr_t     bno,
+       uint            imap_flags)
 {
        xfs_buf_t       *bp;
        int             error;
@@ -269,10 +270,9 @@ xfs_itobp(
                 * inode on disk.
                 */
                imap.im_blkno = bno;
-               error = xfs_imap(mp, tp, ip->i_ino, &imap, XFS_IMAP_LOOKUP);
-               if (error != 0) {
+               if ((error = xfs_imap(mp, tp, ip->i_ino, &imap,
+                                       XFS_IMAP_LOOKUP | imap_flags)))
                        return error;
-               }
 
                /*
                 * If the inode number maps to a block outside the bounds
@@ -336,9 +336,10 @@ xfs_itobp(
         * (if DEBUG kernel) or the first inode in the buffer, otherwise.
         */
 #ifdef DEBUG
-       ni = BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog;
+       ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 :
+               (BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog);
 #else
-       ni = 1;
+       ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : 1;
 #endif
        for (i = 0; i < ni; i++) {
                int             di_ok;
@@ -868,9 +869,8 @@ xfs_iread(
         * return NULL as well.  Set i_blkno to 0 so that xfs_itobp() will
         * know that this is a new incore inode.
         */
-       error = xfs_itobp(mp, tp, ip, &dip, &bp, bno);
-
-       if (error != 0) {
+       error = xfs_itobp(mp, tp, ip, &dip, &bp, bno, 0);
+       if (error) {
                kmem_zone_free(xfs_inode_zone, ip);
                return error;
        }
@@ -1895,7 +1895,7 @@ xfs_iunlink(
                 * Here we put the head pointer into our next pointer,
                 * and then we fall through to point the head at us.
                 */
-               error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0);
+               error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
                if (error) {
                        return error;
                }
@@ -2004,7 +2004,7 @@ xfs_iunlink_remove(
                 * of dealing with the buffer when there is no need to
                 * change it.
                 */
-               error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0);
+               error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
                if (error) {
                        cmn_err(CE_WARN,
                                "xfs_iunlink_remove: xfs_itobp()  returned an error %d on %s.  Returning error.",
@@ -2066,7 +2066,7 @@ xfs_iunlink_remove(
                 * Now last_ibp points to the buffer previous to us on
                 * the unlinked list.  Pull us from the list.
                 */
-               error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0);
+               error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
                if (error) {
                        cmn_err(CE_WARN,
                                "xfs_iunlink_remove: xfs_itobp()  returned an error %d on %s.  Returning error.",
@@ -3023,8 +3023,8 @@ xfs_iflush(
        /*
         * Get the buffer containing the on-disk inode.
         */
-       error = xfs_itobp(mp, NULL, ip, &dip, &bp, 0);
-       if (error != 0) {
+       error = xfs_itobp(mp, NULL, ip, &dip, &bp, 0, 0);
+       if (error) {
                xfs_ifunlock(ip);
                return error;
        }
index 006396764cbc1a2e9d85f53e07713a7390e4ac1f..39ef9c36ea55802fbe4dbd3efa114acbccdbcea2 100644 (file)
@@ -95,9 +95,10 @@ typedef struct xfs_ifork {
 #define        XFS_IFEXTIREC   0x08    /* Indirection array of extent blocks */
 
 /*
- * Flags for xfs_imap() and xfs_dilocate().
+ * Flags for xfs_itobp(), xfs_imap() and xfs_dilocate().
  */
-#define        XFS_IMAP_LOOKUP         0x1
+#define XFS_IMAP_LOOKUP                0x1
+#define XFS_IMAP_BULKSTAT      0x2
 
 #ifdef __KERNEL__
 struct bhv_desc;
@@ -421,7 +422,7 @@ int         xfs_finish_reclaim_all(struct xfs_mount *, int);
  */
 int            xfs_itobp(struct xfs_mount *, struct xfs_trans *,
                          xfs_inode_t *, xfs_dinode_t **, struct xfs_buf **,
-                         xfs_daddr_t);
+                         xfs_daddr_t, uint);
 int            xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
                          xfs_inode_t **, xfs_daddr_t);
 int            xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int);
index c59450e1be40a5af3758857267018eabb7b5f586..32247b6bfee73cca08e5d41a38e1ff485e72a2be 100644 (file)
@@ -562,7 +562,8 @@ xfs_bulkstat(
                                                if (bp)
                                                        xfs_buf_relse(bp);
                                                error = xfs_itobp(mp, NULL, ip,
-                                                                 &dip, &bp, bno);
+                                                               &dip, &bp, bno,
+                                                               XFS_IMAP_BULKSTAT);
                                                if (!error)
                                                        clustidx = ip->i_boffset / mp->m_sb.sb_inodesize;
                                                kmem_zone_free(xfs_inode_zone, ip);
@@ -570,6 +571,8 @@ xfs_bulkstat(
                                                                   mp, XFS_ERRTAG_BULKSTAT_READ_CHUNK,
                                                                   XFS_RANDOM_BULKSTAT_READ_CHUNK)) {
                                                        bp = NULL;
+                                                       ubleft = 0;
+                                                       rval = error;
                                                        break;
                                                }
                                        }
index 7d46cbd6a07ad448588c4fcc50c8695cc9008a66..add13f507ed2fd2f1915b6cbe7f8b5ec66bf345a 100644 (file)
@@ -3249,7 +3249,7 @@ xlog_recover_process_iunlinks(
                                         * next inode in the bucket.
                                         */
                                        error = xfs_itobp(mp, NULL, ip, &dip,
-                                                       &ibp, 0);
+                                                       &ibp, 0, 0);
                                        ASSERT(error || (dip != NULL));
                                }
 
index 5dd84fe609cc57ec084239eee204dc11749cba4c..811a4261fa2c88ccb4c83d5a8c2211d34659d3c1 100644 (file)
@@ -1229,7 +1229,7 @@ xfs_sync_inodes(
                                        xfs_iunlock(ip, XFS_ILOCK_SHARED);
 
                                        error = xfs_itobp(mp, NULL, ip,
-                                                         &dip, &bp, 0);
+                                                         &dip, &bp, 0, 0);
                                        if (!error) {
                                                xfs_buf_relse(bp);
                                        } else {
This page took 0.032824 seconds and 5 git commands to generate.