From owner-freebsd-current Mon Jan 20 14:15: 5 2003 Delivered-To: freebsd-current@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 73CFE37B401 for ; Mon, 20 Jan 2003 14:15:02 -0800 (PST) Received: from HAL9000.homeunix.com (12-233-57-224.client.attbi.com [12.233.57.224]) by mx1.FreeBSD.org (Postfix) with ESMTP id 9379A43ED8 for ; Mon, 20 Jan 2003 14:15:01 -0800 (PST) (envelope-from dschultz@uclink.Berkeley.EDU) Received: from HAL9000.homeunix.com (localhost [127.0.0.1]) by HAL9000.homeunix.com (8.12.6/8.12.5) with ESMTP id h0KMEx0L004039; Mon, 20 Jan 2003 14:14:59 -0800 (PST) (envelope-from dschultz@uclink.Berkeley.EDU) Received: (from das@localhost) by HAL9000.homeunix.com (8.12.6/8.12.5/Submit) id h0KMEx3k004038; Mon, 20 Jan 2003 14:14:59 -0800 (PST) (envelope-from dschultz@uclink.Berkeley.EDU) Date: Mon, 20 Jan 2003 14:14:59 -0800 From: David Schultz To: Matthew Dillon Cc: Jan Srzednicki , current@FreeBSD.ORG Subject: Re: background fsck did not create lost+found Message-ID: <20030120221459.GA3668@HAL9000.homeunix.com> Mail-Followup-To: Matthew Dillon , Jan Srzednicki , current@FreeBSD.ORG References: <20030120183442.GA2778@HAL9000.homeunix.com> <200301201911.h0KJBZ4g065531@apollo.backplane.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <200301201911.h0KJBZ4g065531@apollo.backplane.com> Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG Thus spake Matthew Dillon : > :However, when you are saving a new version of an important file, > :you need to be careful that the new version (and its directory > :entry) hits the disk before the old one goes away. I know that vi > :saves files in a safe way, whereas ee and emacs do not. (Emacs > :introduces only a small race, though.) Also, mv will DTRT only if > :the source and destination files live on the same filesystem. > : > > I think you have that reversed. vi just overwrites the destination > file (O_CREAT|O_TRUNC, try ktrace'ing a vi session and you will see). > I believe emacs defaults to a mode where it creates a new file and > renames it over the original. > > This means that there is a period of time where a crash may result in > the loss of the file if the vi session cannot be recovered (with vi -r) > after the fact. vi writes and fsyncs a recovery file when it opens a file for editing, and it fsyncs the real file before removing the recovery file. (I don't know how reliable vi's recovery mechanism is because I don't use vi, but at least it's ensuring that the recovery file is written to disk when it should be.) In Emacs, if 'make-backup-files' is non-nil (the default), the original file ${FILE} is renamed to ${FILE}~. Then it writes out and fsyncs a new file, which is perfectly safe. If 'make-backup-files' is nil, emacs simply omits the renaming part, unsafely overwriting the original file. The behavior in the latter case appears to be a bug, or at least an undocumented feature. Emacs even causes data loss in this case when the disk fills up! It needs to either do an fsync/rename or write and fsync a backup file for the duration of the save. Lastly, with ee, there's no backup file and no fsync. Some ktrace snippets are below. 3662 vi CALL open(0x808e260,0x2,0x180) 3662 vi NAMI "/var/tmp/vi.recover/vi.HjDlgO" 3662 vi RET open 4 ... 3662 vi CALL write(0x4,0x809a01c,0x400) 3662 vi GIO fd 4 wrote 1024 bytes "[...]old contents[...]" ... 3662 vi CALL fsync(0x4) 3662 vi RET fsync 0 ... [I edit the file from "old contents" to "new contents"] ... 3662 vi CALL open(0x8095140,0x601,0x1b6) 3662 vi NAMI "foo" 3662 vi RET open 7 ... 3662 vi CALL write(0x7,0x80bb000,0xd) 3662 vi GIO fd 7 wrote 13 bytes "new contents " 3662 vi RET write 13/0xd ... 3662 vi CALL fsync(0x7) 3662 vi RET fsync 0 3662 vi CALL close(0x7) 3662 vi RET close 0 ... 3662 vi CALL lseek(0x4,0,0x400,0,0) 3662 vi RET lseek 1024/0x400 3662 vi CALL write(0x4,0x809a01c,0x400) 3662 vi GIO fd 4 wrote 1024 bytes "[...]new contents[...]" ... 3662 vi CALL fsync(0x4) 3662 vi RET fsync 0 [The following bit only happens if make-backup-files is non-nil] 3799 emacs CALL rename(0x848c328,0x848fba8) 3799 emacs NAMI "/home/test/foo" 3799 emacs NAMI "/home/test/foo~" 3799 emacs RET rename 0 ... [This part happens unconditionally] 3799 emacs CALL open(0x848c328,0x601,0x1b6) 3799 emacs NAMI "/home/test/foo" 3799 emacs RET open 3 3799 emacs CALL write(0x3,0xbfbfae24,0x3) 3799 emacs GIO fd 3 wrote 3 bytes "new" 3799 emacs RET write 3 3799 emacs CALL write(0x3,0xbfbfae24,0x9) 3799 emacs GIO fd 3 wrote 9 bytes " contents" 3799 emacs RET write 9 3799 emacs CALL fsync(0x3) 3799 emacs RET fsync 0 3799 emacs CALL close(0x3) 3799 emacs RET close 0 To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message