From owner-freebsd-hackers Tue Oct 28 09:37:52 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.7/8.8.7) id JAA06295 for hackers-outgoing; Tue, 28 Oct 1997 09:37:52 -0800 (PST) (envelope-from owner-freebsd-hackers) Received: from smtp04.primenet.com (smtp04.primenet.com [206.165.5.85]) by hub.freebsd.org (8.8.7/8.8.7) with ESMTP id JAA06279 for ; Tue, 28 Oct 1997 09:37:42 -0800 (PST) (envelope-from tlambert@usr06.primenet.com) Received: (from daemon@localhost) by smtp04.primenet.com (8.8.7/8.8.7) id KAA20210; Tue, 28 Oct 1997 10:37:33 -0700 (MST) Received: from usr06.primenet.com(206.165.6.206) via SMTP by smtp04.primenet.com, id smtpd020195; Tue Oct 28 10:37:26 1997 Received: (from tlambert@localhost) by usr06.primenet.com (8.8.5/8.8.5) id KAA27459; Tue, 28 Oct 1997 10:37:15 -0700 (MST) From: Terry Lambert Message-Id: <199710281737.KAA27459@usr06.primenet.com> Subject: Re: Recovering Lost Inode? To: grog@lemis.com (Greg Lehey) Date: Tue, 28 Oct 1997 17:37:15 +0000 (GMT) Cc: james@reef.com, freebsd-hackers@FreeBSD.ORG In-Reply-To: <19971028153059.20678@lemis.com> from "Greg Lehey" at Oct 28, 97 03:30:59 pm X-Mailer: ELM [version 2.4 PL23] Content-Type: text Sender: owner-freebsd-hackers@FreeBSD.ORG X-Loop: FreeBSD.org Precedence: bulk > > Thanks for the response. I'm sure it's too late now, with inode > > recycling, etc. However, if I had been unable to umount the > > filesystem... (we now enter the theoretical zone) > > *could* I have been able to use somekindof Norton's Utilities-esque > > package for UNIX which could check inodes and look for ones that > > were 'file starters', and maybe check the that if all of the inodes > > pointed to by that starter inode (it was big file so I excect > > a level or two of inode redirection) were still intact it could > > pull it back? Kinda like an 'un-delete' fsck? Ever hear of > > such a thing? > > Good question. I don't have a good answer. The first big problem is > identifying the inode. You could have literally millions to check. After deleting some important code, I immediately hit the power switch. With a daemon holding the reference, you could have sync'ed your system and flipped the switch, and the inode would be unreferenced by a directory, but present. A boot to single user mode (assuming the inode wasn't on / -- you'd need a floppy boot for that) and an fsck without "-y" (the default if you don't run it manually), and you could force the inode to come back in lost+found by saying "no" to a "clear?" prompt. If you delete the reference, hitting the power without a sync is the best bet to prevent the file's blocks being reused. The following assumes that you are not mounted "async", and you are using FFS (if you are mounting "async", you should probably change every occurance of "async" to "I_dont_care_if_you_eat_my_files" in the code to be more accurate about its function). Now it is time to grovel the disk. If you knew the previous location of the file, and it was not the first entry in a directory block, then the space used by the dirent was recovered by concatenating the space to the entry immediately previous to it. This will have the inode number in it (check here first). If the entry was compacted by a subsequent create (create/rename/link) operation, then it was destroyed. If the entry was the first entry in the directory block, it could not be compacted. Because FFS does not use a "deleted" flag bit, it indicated the deleted entry by zeroing the inode number (this is bogus, but I can't commit a fix). In either case, the inode number information is lost. If the inode number information is lost, you can look for the inode by inverse masking. You do this by finding all the inodes with a non-zero reference count. When you find these... these aren't the onces you're looking for. If you have lost either the inode or direct or indirect block mappings, the problem gets harder. Again you can use inverse masking: blocks which are allocated in the allocation bitmap.... aren't the ones you're looking for. At this point, you have only reduced the search space. Now you have to go through the block contents looking for something you recognize as the correct file contents. Clearly, this is pretty useless with executables. However, if you find file contents, you can find the inode or indirect block that refers to the identified content block. If you can do this, you can traverse the chain and find some or all of the rest of the file. It is useful to build an "unallocated block contents grepper" and supply it with a string you know is in the file, but unlikely to be found in other files. Generally, if the disk is not overfull already, you will find the file data in write clusters (most blocks will be physically contiguous to previous blocks). This won't work for frags, but frags will either start at the start of the block, or they will be a member of a frag block. Finally, it is useful to build a "block list assembly editor"; it's purpose is to make it easier to recognize candidate blocks. Say you have a block ending with "We hold these truths to be self evi". The next block in sequence will have a high probability of starting with "dent". This relies on you, the human syntactic pattern recognizer. With a couple of home-grown tools (FS's are generally different enough in layout that the tools must be home grown, since you must have order of operation clues to make some of the above assumptions) and a little patience, you can usually recover most if not all of your data. On the other hand, you could just keep reasonable backups. 8-) 8-). Terry Lambert terry@lambert.org --- Any opinions in this posting are my own and not those of my present or previous employers.