xfs
[Top] [All Lists]

review: fsblock zero - don't panic

To: xfs@xxxxxxxxxxx
Subject: review: fsblock zero - don't panic
From: Nathan Scott <nathans@xxxxxxx>
Date: Thu, 10 Aug 2006 15:58:51 +1000
Sender: xfs-bounce@xxxxxxxxxxx
User-agent: Mutt/1.2.5i
As part of attempting to understand what happened in a corruption
problem awhile back, and generally be a bit more defensive of our
precious primary superblock, some code was added to XFS to detect
(and panic) on any inode extents that start at block zero.

This has happened once or twice now, and when it does, we panic the
kernel.  This is not at all nice, as it means we take out the whole
system due to ondisk corruption.  This patch makes that code issue
a warning now, and fail whatever operation was in progress.

cheers.

-- 
Nathan


Index: xfs-linux/xfs_bmap.c
===================================================================
--- xfs-linux.orig/xfs_bmap.c   2006-08-08 15:59:14.396022750 +1000
+++ xfs-linux/xfs_bmap.c        2006-08-08 16:08:34.790988750 +1000
@@ -3722,16 +3722,19 @@ xfs_bmap_search_extents(
 
        rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
        if (unlikely(!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,
+               cmn_err(CE_WARN, "Access to block zero: fs: <%s> inode: %lld "
+                                "start_block : %llx start_off : %llx "
+                                "blkcnt : %llx extent-state : %x lastx : %x\n",
+                       ip->i_mount->m_fsname, (long long)ip->i_ino,
                        (unsigned long long)gotp->br_startblock,
                        (unsigned long long)gotp->br_startoff,
                        (unsigned long long)gotp->br_blockcount,
-                       gotp->br_state);
-        }
-        return ep;
+                       gotp->br_state, *lastxp);
+               ASSERT(0);
+               *eofp = 1;
+               return NULL;
+       }
+       return ep;
 }
 
 
Index: xfs-linux/xfs_iomap.c
===================================================================
--- xfs-linux.orig/xfs_iomap.c  2006-08-08 15:59:14.428024750 +1000
+++ xfs-linux/xfs_iomap.c       2006-08-08 16:18:40.116068500 +1000
@@ -536,23 +536,28 @@ xfs_iomap_write_direct(
         * Copy any maps to caller's array and return any error.
         */
        if (nimaps == 0) {
-               error = (ENOSPC);
+               error = ENOSPC;
                goto error_out;
        }
 
-       *ret_imap = imap;
-       *nmaps = 1;
-       if ( !(io->io_flags & XFS_IOCORE_RT)  && !ret_imap->br_startblock) {
-                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,
-                        (unsigned long long)ret_imap->br_startblock,
+       if (unlikely(
+           !(io->io_flags & XFS_IOCORE_RT) && !ret_imap->br_startblock)) {
+               cmn_err(CE_WARN, "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,
+                       (unsigned long long)ret_imap->br_startblock,
                        (unsigned long long)ret_imap->br_startoff,
-                        (unsigned long long)ret_imap->br_blockcount,
+                       (unsigned long long)ret_imap->br_blockcount,
                        ret_imap->br_state);
-        }
+               ASSERT(0);
+               error = EFSCORRUPTED;
+               goto error_out;
+       }
+
+       *ret_imap = imap;
+       *nmaps = 1;
        return 0;
 
 error0:        /* Cancel bmap, unlock inode, unreserve quota blocks, cancel 
trans */
@@ -715,16 +720,19 @@ retry:
                goto retry;
        }
 
-       if (!(io->io_flags & XFS_IOCORE_RT)  && !ret_imap->br_startblock) {
-               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,
-                        (unsigned long long)ret_imap->br_startblock,
-                       (unsigned long long)ret_imap->br_startoff,
-                        (unsigned long long)ret_imap->br_blockcount,
-                       ret_imap->br_state);
+       if (unlikely(
+           !(io->io_flags & XFS_IOCORE_RT) && !ret_imap->br_startblock)) {
+               cmn_err(CE_WARN, "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,
+                               (unsigned long long)ret_imap->br_startblock,
+                               (unsigned long long)ret_imap->br_startoff,
+                               (unsigned long long)ret_imap->br_blockcount,
+                               ret_imap->br_state);
+               ASSERT(0);
+               return XFS_ERROR(EFSCORRUPTED);
        }
 
        *ret_imap = imap[0];
@@ -855,15 +863,15 @@ xfs_iomap_write_allocate(
                 * See if we were able to allocate an extent that
                 * covers at least part of the callers request
                 */
-
                for (i = 0; i < nimaps; i++) {
-                       if (!(io->io_flags & XFS_IOCORE_RT)  &&
-                           !imap[i].br_startblock) {
-                               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,
+                       if (unlikely(!(io->io_flags & XFS_IOCORE_RT) &&
+                                    !imap[i].br_startblock)) {
+                               cmn_err(CE_WARN,
+                                       "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,
                                        (unsigned long long)
                                                imap[i].br_startblock,
@@ -872,7 +880,9 @@ xfs_iomap_write_allocate(
                                        (unsigned long long)
                                                imap[i].br_blockcount,
                                        imap[i].br_state);
-                        }
+                               ASSERT(0);
+                               return XFS_ERROR(EFSCORRUPTED);
+                       }
                        if ((offset_fsb >= imap[i].br_startoff) &&
                            (offset_fsb < (imap[i].br_startoff +
                                           imap[i].br_blockcount))) {
@@ -951,7 +961,7 @@ xfs_iomap_write_unwritten(
                }
                if (error) {
                        xfs_trans_cancel(tp, 0);
-                       goto error0;
+                       return XFS_ERROR(error);
                }
 
                xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -977,18 +987,22 @@ xfs_iomap_write_unwritten(
                error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
                xfs_iunlock(ip, XFS_ILOCK_EXCL);
                if (error)
-                       goto error0;
+                       return XFS_ERROR(error);
 
-               if ( !(io->io_flags & XFS_IOCORE_RT)  && !imap.br_startblock) {
-                       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,
+               if (unlikely(
+                   !(io->io_flags & XFS_IOCORE_RT) && !imap.br_startblock)) {
+                       cmn_err(CE_WARN, "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,
                                (unsigned long long)imap.br_startblock,
                                (unsigned long long)imap.br_startoff,
                                (unsigned long long)imap.br_blockcount,
                                imap.br_state);
+                       ASSERT(0);
+                       return XFS_ERROR(EFSCORRUPTED);
                }
 
                if ((numblks_fsb = imap.br_blockcount) == 0) {
@@ -1009,6 +1023,5 @@ error_on_bmapi_transaction:
        xfs_bmap_cancel(&free_list);
        xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT));
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
-error0:
        return XFS_ERROR(error);
 }


<Prev in Thread] Current Thread [Next in Thread>