problems with fsck_ffs

Simson L. Garfinkel simsong at csail.mit.edu
Thu Aug 26 07:57:05 PDT 2004


Okay. Thanks for your interest!

In fsck_ffs/setup.c, the variable sblock.fs_fsize was 0 because of my 
disk corruption. As a result, dev_bsize was being set to 0, which was 
resulting in a divide-by-zero. Here is the code and my fix:

         /*
          * Compute block size that the file system is based on,
          * according to fsbtodb, and adjust superblock block number
          * so we can tell if this is an alternate later.
          */
         super *= dev_bsize;
         dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);

         /* SLG START */
         if(dev_bsize==0){
           printf("*** dev_bsize==0. This indicates on-disk corruption 
of the superblock.\n");
           return (0);
         }
         /* SLG END */


Attached you'll find a program called find_super.c which scans the 
device for a superblock and fix_super.c which copied the good 
superblock into the expected superblock location. Ironically, even 
though fsck_ffs can take a "-b" option and do a full FSCK from any 
given superblock, mount will not take a superblock argument, so you 
still need to copy the good superblock into the known location.

Both find_super.c and fix_super.c should be integrated into fsck_ffs. 
I'll do so if you think that this is a good way to proceed and if you 
seriously consider taking the changes.

Th
-------------- next part --------------
#include <stdio.h>
#include <err.h>
#include <sys/types.h>
#include <sys/time.h>
#include "/usr/src/sys/ufs/ufs/extattr.h"
#include "/usr/src/sys/ufs/ufs/quota.h"
#include "/usr/src/sys/ufs/ufs/inode.h"
//#include "/usr/src/sys/ufs/ufs/ufsmount.h"
#include "/usr/src/sys/ufs/ffs/fs.h"

main(int argc,char **argv)
{
  FILE *f = fopen(argv[1],"r");
  if(!f) err(1,argv[1]);
  long block=0;
  printf("The FS structure is %d bytes large\n",sizeof(struct fs));
  while(1){
    char buf[8192];
    struct fs *fs = (struct fs *)buf;
    
    if(fs->fs_magic!=0){
      printf("\r%d   ",block);
    }
      if(fread(buf,1,sizeof(buf),f)!=sizeof(buf)){
	err(1,"end of file");
      }
    if(fs->fs_magic==FS_UFS1_MAGIC) printf("UFS1 MAGIC at %d (%d)!\n",block,block*16);
    if(fs->fs_magic==FS_UFS2_MAGIC) printf("UFS2 MAGIC at %d (%d)!\n",block,block*16);
    if(fs->fs_magic==FS_BAD2_MAGIC) printf("UFS2 BAD MAGIC at %d (%d)!\n",block,block*16);
    block++;
  }
}
-------------- next part --------------
#include <stdio.h>
#include <err.h>
#include <sys/types.h>
#include <sys/time.h>
#include <fcntl.h>
#include <unistd.h>
#include "/usr/src/sys/ufs/ufs/extattr.h"
#include "/usr/src/sys/ufs/ufs/quota.h"
#include "/usr/src/sys/ufs/ufs/inode.h"
#include "/usr/src/sys/ufs/ffs/fs.h"

main(int argc,char **argv)
{
  int fd = open("/dev/da0s1e",O_RDWR);
  int fd2 = open("oldblock",O_WRONLY | O_CREAT);
 
  int buf[SBLOCKSIZE];
  struct fs *fs = (struct fs *)buf;
  int from_block = 376224;
  //int to_block = SBLOCK_UFS1;
  int to_block = 128;

  if(fd<0) err(1,"fd");
  if(fd2<0) err(1,"fd2");

  lseek(fd,to_block*512,0);
  read(fd,buf,SBLOCKSIZE);
  write(fd2,buf,SBLOCKSIZE);	/* make a copy */

  /* now get the from_block */
  lseek(fd,from_block*512,0);
  read(fd,buf,SBLOCKSIZE);

  if(fs->fs_magic==FS_UFS1_MAGIC) printf("UFS1 MAGIC at %d\n",from_block);
  if(fs->fs_magic==FS_UFS2_MAGIC) printf("UFS2 MAGIC at %d\n",from_block);
  if(fs->fs_magic==FS_BAD2_MAGIC) printf("UFS2 BAD MAGIC at %d\n",from_block);

  /* Now write it to the to_block */
  lseek(fd,to_block*512,0);
  write(fd,buf,SBLOCKSIZE);
  printf("wrote to block %d\n",to_block);
}
-------------- next part --------------
e good news is that I was able to recover my hard drive with 0 files 
lost! The bad news is that I had to spend about an hour programming in 
order to do so, which was kind of, well, unnevering.


On Aug 26, 2004, at 10:41 AM, Scott Long wrote:

> Simson L. Garfinkel wrote:
>> Greetings. I just had a RAID crash which required some recovery with 
>> fsck_ffs.
>> Two problems with fsck_ffs in 5.2 were discovered:
>> 1. There is a divide-by-0 error that happens under some conditions 
>> when the contents of the superblock and the backup superblock are 
>> partially damaged.
>>     =>Would you like a fix for this?
>
> Of course!
>
>> 2. There is no obvious functionality to scan the whole hard-drive for 
>> backup superblocks.
>>     => I've written such a program. If I integrate it into fsck, will 
>> you take the mods?
>
> I'd definitely like to see it.
>
> Scott
>


More information about the freebsd-fs mailing list