If you have a backup from which you can restore or if the data is so trashed that you have to reinstall, then how about running the following against the file system before you put the data back? This will "scrub" the file system with a sequence of patterns and check them. Let it run until the output wraps around, you should see a sequence like 0000111122223333 where the number of each digits varies based on how much data you are scrubbing. You want to scrub the entire file system, and the usage is cd /mnt # or where you have the file system mounted diskscrubber 4900 # about right for a 5GB partition You need to scrub a bit less than the size because the blocks of pointers eat up space as well. If you leave 5-10% that seems to be enough, you can do one run, check disk space, and recorrect it. I use this for a 48 hour burn in on any system where I care about the data. --lm /* * diskscrubber.c - write patterns in datafile[s] and verify them. * Handles 32 bit problems by never writing a single file bigger that 1G, * handles buffering problems by writing all files and then reading them. * * (c) May 2001 Larry McVoy, do whatever you want with this. */ #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #define u32 unsigned int #define BSIZ (4<<20) #define FSIZ (mb<<20) #define CHUNK 1024 void writen(int fd, u32 *buf, int size); void readn(int fd, u32 *buf, int size); void bad(unsigned int off, unsigned int bad, unsigned int want); void doit(char *file, u32 mb, int pass); u32 buf[BSIZ]; /* I do not want to realloc this on each call */ int main(int ac, char **av) { u32 mb, left; int i, pass; char file[200]; char c; if (sizeof(u32) != 4) { fprintf(stderr, "Expected 4 byte ints\n"); exit(1); } if (ac != 2) { printf("Usage: %s amount_in_MB\n", av[0]); exit(0); } mb = atoi(av[1]); if (mb % (BSIZ>>20)) { printf("Usage: %s amount must be a multiple of %d\n", av[0], BSIZ>>20); exit(0); } pass = 0; for ( ;; ) { for (i = 0, left = mb; left > 0; i++) { sprintf(file, "_data%d", i); if (left >= CHUNK) { left -= CHUNK; doit(file, CHUNK, pass); } else { doit(file, left, pass); left = 0; } c = '0' + pass; write(1, &c, 1); } pass = (pass + 1) % 4; /* * Only the first tine through the loop do we need pass 0, * in all other cases pass 4 has done what pass 0 would do. */ if (!pass) pass = 1; } return (0); /* lint */ } void writen(int fd, u32 *buf, int size) { if (write(fd, (char*)buf, size) != size) { perror("write"); exit(1); } } void readn(int fd, u32 *buf, int size) { if (read(fd, (char*)buf, size) != size) { perror("read"); exit(1); } lseek(fd, -size, SEEK_CUR); } void bad(u32 off, u32 bad, u32 want) { printf("\nBAD @ %8u %08x:%08x\n", off, bad, want); exit(1); } /* * Write different bits into the file forcing bit changes. * pass 0 - just write the offset into the file * pass 1 - read data and check for offset, then write 0x55555555 * pass 2 - read data and check for 0x55555555, then write 0xaaaaaaaa * pass 3 - read data and check for 0xaaaaaaaa, then write offset */ void doit(char *file, u32 mb, int pass) { u32 off = 0; int i; int fd = open(file, O_CREAT|O_RDWR, 0666); switch (pass) { case 0: /* pass 0 - just write the offset into the file */ for (off = 0; off < FSIZ; ) { for (i = 0; i < BSIZ/4; buf[i++] = off, off += 4); writen(fd, buf, BSIZ); } break; case 1: /* pass 1 - read and check for offset, then write 0x55555555 */ for (off = 0; off < FSIZ; ) { readn(fd, buf, BSIZ); for (i = 0; i < BSIZ/4; off += 4) { if (buf[i] != off) bad(off, buf[i], off); buf[i++] = 0x55555555; } writen(fd, buf, BSIZ); } break; case 2: /* pass 2 - read and check for 0x55555555, then write 0xaaaaaaaa */ for (off = 0; off < FSIZ; off += BSIZ) { readn(fd, buf, BSIZ); for (i = 0; i < BSIZ/4; ) { if (buf[i] != 0x55555555) { bad(off, buf[i], 0x55555555); } buf[i++] = 0xaaaaaaaa; } writen(fd, buf, BSIZ); } break; case 3: /* pass 4 - read and check for 0xaaaaaaaa, then write offset */ for (off = 0; off < FSIZ; ) { readn(fd, buf, BSIZ); for (i = 0; i < BSIZ/4; off += 4) { if (buf[i] != 0xaaaaaaaa) { bad(off, buf[i], 0xaaaaaaaa); } buf[i++] = off; } writen(fd, buf, BSIZ); } break; } close(fd); }