Re: [PATCH] fix htree dir corrupt after fsck -fD

Ryan Cumming
2002-09-29T08:31:45Z

[-- Attachment #1: clearsigned data --]
[-- Type: Text/Plain, Size: 1035 bytes --]

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On September 29, 2002 01:16, Ryan Cumming wrote:
> This is a completely fresh loopback EXT3 filesystem, untouched by fsck -D,
> and normally unmounted.

Oh, and I've attached the current version of my test program if anyone is
interested.

It spawns 8 child processes which repeatedly create up to 1,000,000 files
each, stat up to 1,000,000 (probably) non-existant files, and then unlink the
files they created.

It also spawns another 4 processes which iterate over all of the directory
entries using readdir(). For each file it encounters, it has an equal
probability of renaming it, unlinking it, or truncating it to a random
length.

It can corrupt my loopback test filesystems in under 5 minutes. Note that it
will completely destroy any data in its working directory, however.

- -Ryan
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.0 (GNU/Linux)

iD8DBQE9lrulLGMzRzbJfbQRAgxMAJ46Y/L4FA8nuwe76MyGCyhG+mSE3QCgjb5a
TBJbqp55p5yOU2BY0AnW/TA=
=cKn9
-----END PGP SIGNATURE-----

[-- Attachment #2: fs-ream.c --]
[-- Type: text/x-csrc, Size: 1982 bytes --]

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <time.h>

#define BLIND_THREADS 8
#define READDIR_THREADS 4
#define MAX_FILE_COUNT_PER_THREAD 200000
#define SYNC_INTERVAL 1
#define MAX_FILE_SIZE (8 * 1024 * 1024)

void blind_thread();
void readdir_thread();

int main(int argc, char *argv[])
{
int i = 0;

for(i = 0;i < BLIND_THREADS;i++)
{
if (!fork())
{
blind_thread();
}
}
for(i = 0;i < READDIR_THREADS;i++)
{
if (!fork())
{
readdir_thread();
}
}

while(1)
{
sleep(SYNC_INTERVAL);
sync();
}

return 0;
}

void blind_thread()
{
while(1)
{
unsigned int seed;
struct timeval tv;
int i;
int count;

gettimeofday(&tv, NULL);
seed = tv.tv_usec;
count = seed % MAX_FILE_COUNT_PER_THREAD;

srand(seed);
printf("Creating %i files\n" , count);
for(i = 0; i < count;i++)
{
char filename[32];
snprintf(filename, 32, "%x", rand());
close(open(filename, O_CREAT | O_RDONLY));
}

printf("Performing %i random lookups\n" , count);
for(i = 0; i < count;i++)
{
char filename[32];
struct stat useless;

snprintf(filename, 32, "%x", rand());
stat(filename, &useless);
}

srand(seed);
printf("Unlinking %i files\n" , count);
for(i = 0; i < count;i++)
{
char filename[32];
snprintf(filename, 32, "%x", rand());
unlink(filename);
}
}
}

void readdir_thread()
{
while(1)
{
DIR *dir;
struct dirent *entry;
dir = opendir(".");

while((entry = readdir(dir)))
{
struct stat st;
stat(entry->d_name, &st);

if (S_ISREG(st.st_mode))
{
switch(rand() % 3)
{
case 0:
unlink(entry->d_name);
case 1:
truncate(entry->d_name, rand() % MAX_FILE_SIZE);
case 2:
{
char filename[32];
snprintf(filename, 32, "%x", rand());
rename(entry->d_name, filename);
}
}
}
}

closedir(dir);
}
}