From owner-freebsd-current@FreeBSD.ORG Wed Feb 20 07:37:10 2008 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3F66016A400; Wed, 20 Feb 2008 07:37:10 +0000 (UTC) (envelope-from delphij@delphij.net) Received: from tarsier.delphij.net (delphij-pt.tunnel.tserv2.fmt.ipv6.he.net [IPv6:2001:470:1f03:2c9::2]) by mx1.freebsd.org (Postfix) with ESMTP id E5B3A13C46A; Wed, 20 Feb 2008 07:36:36 +0000 (UTC) (envelope-from delphij@delphij.net) Received: from tarsier.geekcn.org (unknown [202.108.54.204]) (using TLSv1 with cipher ADH-CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by tarsier.delphij.net (Postfix) with ESMTP id B122028454; Wed, 20 Feb 2008 15:36:22 +0800 (CST) Received: from localhost (unknown [202.108.54.204]) by tarsier.geekcn.org (Postfix) with ESMTP id 75ECCEC4224; Wed, 20 Feb 2008 15:36:22 +0800 (CST) X-Virus-Scanned: amavisd-new at geekcn.org Received: from tarsier.geekcn.org ([202.108.54.204]) by localhost (mail.geekcn.org [202.108.54.204]) (amavisd-new, port 10024) with ESMTP id PKZE85EwkG3v; Wed, 20 Feb 2008 15:36:16 +0800 (CST) Received: from charlie.delphij.net (c-67-161-39-180.hsd1.ca.comcast.net [67.161.39.180]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by tarsier.geekcn.org (Postfix) with ESMTP id CE533EB662B; Wed, 20 Feb 2008 15:36:07 +0800 (CST) DomainKey-Signature: a=rsa-sha1; s=default; d=delphij.net; c=nofws; q=dns; h=message-id:date:from:reply-to:organization:user-agent: mime-version:to:subject:x-enigmail-version:openpgp:content-type; b=Z/aTHOBQkGOHWQgplsjRDtCaxct9R3V1OtctCUcfl4D+cLnaLDylw6HY/Q42IXCtU 97d5wULXFfxJIhTJIJ7xg== Message-ID: <47BBD864.3070905@delphij.net> Date: Tue, 19 Feb 2008 23:36:04 -0800 From: Xin LI Organization: The FreeBSD Project User-Agent: Thunderbird 2.0.0.9 (X11/20080122) MIME-Version: 1.0 To: freebsd-fs@freebsd.org, FreeBSD Current X-Enigmail-Version: 0.95.5 OpenPGP: id=18EDEBA0; url=http://www.delphij.net/delphij.asc Content-Type: multipart/mixed; boundary="------------080801040108060000080409" Cc: Subject: [PATCH FOR REVIEW] fsck_ffs: Recover from catastrophic damage X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: d@delphij.net List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 20 Feb 2008 07:37:10 -0000 This is a multi-part message in MIME format. --------------080801040108060000080409 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi, Here is a patch that will help fsck_ffs(8) to recover from certain types of damages which is caused by some catastrophic damage seen in some disk arrays that does not detect data errors in time. Change summary: fsutil.c: - Really update standard superblock. fsck_ffs -b used to update the backup superblock which does not recover file systems which have bad master superblocks. - Instead of coredump, zero out whole cg if its signature is bad. inode.c: - Instead of coredump, zero out whole cg if its signature is bad. pass1.c: - If cg gives insane initediblk, use a fallback one which will not cause allocation failure. setup.c: - Really sanity check the superblock's fs_sbsize. With these changes, fsck_ffs will be able to check file systems with heavily damaged cylinder group information, and have a better chance surviving. Comments? Cheers, - -- Xin LI http://www.delphij.net/ FreeBSD - The Power to Serve! -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.4 (FreeBSD) iD8DBQFHu9hji+vbBBjt66ARAqSyAJ49q4uEIANxr4/ccaVKeLTDomiFVQCfVB0i kLZsrSPTifwvItwC3WMq40E= =vvkQ -----END PGP SIGNATURE----- --------------080801040108060000080409 Content-Type: text/plain; name="fsck.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="fsck.diff" Index: fsutil.c =================================================================== RCS file: /home/ncvs/src/sbin/fsck_ffs/fsutil.c,v retrieving revision 1.26 diff -u -p -r1.26 fsutil.c --- fsutil.c 31 Oct 2006 22:06:56 -0000 1.26 +++ fsutil.c 20 Feb 2008 07:15:56 -0000 @@ -301,7 +301,7 @@ ckfini(int markclean) if (havesb && cursnapshot == 0 && sblock.fs_magic == FS_UFS2_MAGIC && sblk.b_bno != sblock.fs_sblockloc / dev_bsize && !preen && reply("UPDATE STANDARD SUPERBLOCK")) { - sblk.b_bno = sblock.fs_sblockloc / dev_bsize; + sblk.b_bno = SBLOCK_UFS2 / dev_bsize; sbdirty(); flush(fswritefd, &sblk); } @@ -441,8 +441,13 @@ allocblk(long frags) } cg = dtog(&sblock, i + j); getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize); - if (!cg_chkmagic(cgp)) - pfatal("CG %d: BAD MAGIC NUMBER\n", cg); + if (!cg_chkmagic(cgp)) { + pwarn("CG %d: BAD MAGIC NUMBER\n", cg); + memset(cgp, 0, (size_t)sblock.fs_cgsize); + cgp->cg_niblk = sblock.fs_ipg; + cgp->cg_ndblk = sblock.fs_size - cgbase(&sblock, cg); + cgp->cg_magic = CG_MAGIC; + } baseblk = dtogd(&sblock, i + j); for (k = 0; k < frags; k++) { setbmap(i + j + k); Index: inode.c =================================================================== RCS file: /home/ncvs/src/sbin/fsck_ffs/inode.c,v retrieving revision 1.38 diff -u -p -r1.38 inode.c --- inode.c 31 Oct 2006 22:06:56 -0000 1.38 +++ inode.c 20 Feb 2008 07:15:22 -0000 @@ -617,8 +617,13 @@ allocino(ino_t request, int type) return (0); cg = ino_to_cg(&sblock, ino); getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize); - if (!cg_chkmagic(cgp)) - pfatal("CG %d: BAD MAGIC NUMBER\n", cg); + if (!cg_chkmagic(cgp)) { + pwarn("CG %d: BAD MAGIC NUMBER\n", cg); + memset(cgp, 0, (size_t)sblock.fs_cgsize); + cgp->cg_niblk = sblock.fs_ipg; + cgp->cg_ndblk = sblock.fs_size - cgbase(&sblock, cg); + cgp->cg_magic = CG_MAGIC; + } setbit(cg_inosused(cgp), ino % sblock.fs_ipg); cgp->cg_cs.cs_nifree--; switch (type & IFMT) { Index: pass1.c =================================================================== RCS file: /home/ncvs/src/sbin/fsck_ffs/pass1.c,v retrieving revision 1.43 diff -u -p -r1.43 pass1.c --- pass1.c 8 Oct 2004 20:44:47 -0000 1.43 +++ pass1.c 20 Feb 2008 07:13:53 -0000 @@ -93,9 +93,11 @@ pass1(void) inumber = c * sblock.fs_ipg; setinodebuf(inumber); getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize); - if (sblock.fs_magic == FS_UFS2_MAGIC) + if (sblock.fs_magic == FS_UFS2_MAGIC) { inosused = cgrp.cg_initediblk; - else + if (inosused > sblock.fs_ipg) + inosused = sblock.fs_ipg; + } else inosused = sblock.fs_ipg; if (got_siginfo) { printf("%s: phase 1: cyl group %d of %d (%d%%)\n", Index: setup.c =================================================================== RCS file: /home/ncvs/src/sbin/fsck_ffs/setup.c,v retrieving revision 1.50 diff -u -p -r1.50 setup.c --- setup.c 31 Oct 2006 22:06:56 -0000 1.50 +++ setup.c 20 Feb 2008 07:13:27 -0000 @@ -349,7 +349,7 @@ readsb(int listerr) sblock.fs_sblockloc == sblock_try[i])) && sblock.fs_ncg >= 1 && sblock.fs_bsize >= MINBSIZE && - sblock.fs_bsize >= sizeof(struct fs)) + sblock.fs_sbsize >= roundup(sizeof(struct fs), dev_bsize)) break; } if (sblock_try[i] == -1) { --------------080801040108060000080409--