From owner-svn-src-all@FreeBSD.ORG Mon Jan 11 20:05:39 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 4931B106566B; Mon, 11 Jan 2010 20:05:39 +0000 (UTC) (envelope-from mckusick@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 379D18FC0C; Mon, 11 Jan 2010 20:05:39 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o0BK5dKM062428; Mon, 11 Jan 2010 20:05:39 GMT (envelope-from mckusick@svn.freebsd.org) Received: (from mckusick@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0BK5dCQ062426; Mon, 11 Jan 2010 20:05:39 GMT (envelope-from mckusick@svn.freebsd.org) Message-Id: <201001112005.o0BK5dCQ062426@svn.freebsd.org> From: Kirk McKusick Date: Mon, 11 Jan 2010 20:05:39 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r202109 - head/sbin/fsck_ffs X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 11 Jan 2010 20:05:39 -0000 Author: mckusick Date: Mon Jan 11 20:05:38 2010 New Revision: 202109 URL: http://svn.freebsd.org/changeset/base/202109 Log: This update utilizes new fsck sysctl commands that allow fsck running in background mode to correct expected inconsistencies that arise during directory rename (see immediately previous update to this file for details). If run on a kernel without the new functionality, background fsck will simply ignore these inconsistencies rather than fail. Reported by: jeff Modified: head/sbin/fsck_ffs/pass2.c Modified: head/sbin/fsck_ffs/pass2.c ============================================================================== --- head/sbin/fsck_ffs/pass2.c Mon Jan 11 19:59:12 2010 (r202108) +++ head/sbin/fsck_ffs/pass2.c Mon Jan 11 20:05:38 2010 (r202109) @@ -36,12 +36,14 @@ static const char sccsid[] = "@(#)pass2. __FBSDID("$FreeBSD$"); #include +#include #include #include #include #include +#include #include #include @@ -214,9 +216,48 @@ pass2(void) inoinfo(inp->i_parent)->ino_linkcnt--; continue; } - fileerror(inp->i_parent, inp->i_number, - "BAD INODE NUMBER FOR '..'"); - if (reply("FIX") == 0) + /* + * Here we have: + * inp->i_number is directory with bad ".." in it. + * inp->i_dotdot is current value of "..". + * inp->i_parent is directory to which ".." should point. + */ + getpathname(pathbuf, inp->i_parent, inp->i_number); + printf("BAD INODE NUMBER FOR '..' in DIR I=%d (%s)\n", + inp->i_number, pathbuf); + getpathname(pathbuf, inp->i_dotdot, inp->i_dotdot); + printf("CURRENTLY POINTS TO I=%d (%s), ", inp->i_dotdot, + pathbuf); + getpathname(pathbuf, inp->i_parent, inp->i_parent); + printf("SHOULD POINT TO I=%d (%s)", inp->i_parent, pathbuf); + if (cursnapshot != 0) { + /* + * We need to: + * setcwd(inp->i_number); + * setdotdot(inp->i_dotdot, inp->i_parent); + */ + cmd.value = inp->i_number; + if (sysctlbyname("vfs.ffs.setcwd", 0, 0, + &cmd, sizeof cmd) == -1) { + /* kernel lacks support for these functions */ + printf(" (IGNORED)\n"); + continue; + } + cmd.value = inp->i_dotdot; /* verify same value */ + cmd.size = inp->i_parent; /* new parent */ + if (sysctlbyname("vfs.ffs.setdotdot", 0, 0, + &cmd, sizeof cmd) == -1) { + printf(" (FIX FAILED: %s)\n", strerror(errno)); + continue; + } + printf(" (FIXED)\n"); + inoinfo(inp->i_parent)->ino_linkcnt--; + inp->i_dotdot = inp->i_parent; + continue; + } + if (preen) + printf(" (FIXED)\n"); + else if (reply("FIX") == 0) continue; inoinfo(inp->i_dotdot)->ino_linkcnt++; inoinfo(inp->i_parent)->ino_linkcnt--; @@ -450,6 +491,7 @@ again: static int fix_extraneous(struct inoinfo *inp, struct inodesc *idesc) { + char *cp; struct inodesc dotdesc; char oldname[MAXPATHLEN + 1]; char newname[MAXPATHLEN + 1]; @@ -491,7 +533,7 @@ fix_extraneous(struct inoinfo *inp, stru strcat (newname, "/"); strcat(newname, idesc->id_dirp->d_name); getpathname(oldname, inp->i_number, inp->i_number); - pwarn("%s IS AN EXTRANEOUS HARD LINK TO DIRECTORY %s\n", + pwarn("%s IS AN EXTRANEOUS HARD LINK TO DIRECTORY %s", newname, oldname); if (cursnapshot != 0) { /* @@ -499,7 +541,21 @@ fix_extraneous(struct inoinfo *inp, stru * setcwd(idesc->id_number); * unlink(idesc->id_dirp->d_name); */ - printf(" (IGNORED)\n"); + cmd.value = idesc->id_number; + if (sysctlbyname("vfs.ffs.setcwd", 0, 0, + &cmd, sizeof cmd) == -1) { + printf(" (IGNORED)\n"); + return (0); + } + cmd.value = (int)idesc->id_dirp->d_name; + cmd.size = inp->i_number; /* verify same name */ + if (sysctlbyname("vfs.ffs.unlink", 0, 0, + &cmd, sizeof cmd) == -1) { + printf(" (UNLINK FAILED: %s)\n", + strerror(errno)); + return (0); + } + printf(" (REMOVED)\n"); return (0); } if (preen) { @@ -514,7 +570,7 @@ fix_extraneous(struct inoinfo *inp, stru */ getpathname(oldname, inp->i_parent, inp->i_number); getpathname(newname, inp->i_number, inp->i_number); - pwarn("%s IS AN EXTRANEOUS HARD LINK TO DIRECTORY %s\n", oldname, + pwarn("%s IS AN EXTRANEOUS HARD LINK TO DIRECTORY %s", oldname, newname); if (cursnapshot != 0) { /* @@ -522,7 +578,26 @@ fix_extraneous(struct inoinfo *inp, stru * setcwd(inp->i_parent); * unlink(last component of oldname pathname); */ - printf(" (IGNORED)\n"); + cmd.value = inp->i_parent; + if (sysctlbyname("vfs.ffs.setcwd", 0, 0, + &cmd, sizeof cmd) == -1) { + printf(" (IGNORED)\n"); + return (0); + } + if ((cp = rindex(oldname, '/')) == NULL) { + printf(" (IGNORED)\n"); + return (0); + } + cmd.value = (int)(cp + 1); + cmd.size = inp->i_number; /* verify same name */ + if (sysctlbyname("vfs.ffs.unlink", 0, 0, + &cmd, sizeof cmd) == -1) { + printf(" (UNLINK FAILED: %s)\n", + strerror(errno)); + return (0); + } + printf(" (REMOVED)\n"); + inp->i_parent = idesc->id_number; /* reparent to correct dir */ return (0); } if (!preen && !reply("REMOVE"))