/* * Concurrent directory operations test. * * Your system should survive this (without leaving a corrupted file * system behind) once the file system assignment is complete. */ #include #include #include #include #include #include #include #include #include #define NTRIES 10000 /* loop count */ #define NPROCS 50 /* actually totals 4x this +1 processes */ #define TESTDIR "dirconc" #define NNAMES 4 #define NAMESIZE 32 //////////////////////////////////////////////////////////// static const char *const names[NNAMES] = { "aaaa", "bbbb", "cccc", "dddd", }; static void choose_name(char *buf, size_t len) { const char *a, *b, *c; a = names[random()%NNAMES]; if (random()%2==0) { snprintf(buf, len, "%s", a); return; } b = names[random()%NNAMES]; if (random()%2==0) { snprintf(buf, len, "%s/%s", a, b); return; } c = names[random()%NNAMES]; snprintf(buf, len, "%s/%s/%s", a, b, c); } //////////////////////////////////////////////////////////// /* * The purpose of this is to be atomic. In our world, straight * printf tends not to be. */ static void #ifdef __GNUC__ __attribute__((__format__(__printf__, 1, 2))) #endif say(const char *fmt, ...) { char buf[512]; va_list ap; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); write(STDOUT_FILENO, buf, strlen(buf)); } //////////////////////////////////////////////////////////// static void dorename(const char *name1, const char *name2) { if (rename(name1, name2) < 0) { switch (errno) { case ENOENT: case ENOTEMPTY: case EINVAL: break; default: say("pid %d: rename %s -> %s: %s\n", getpid(), name1, name2, strerror(errno)); break; } } } static void domkdir(const char *name) { if (mkdir(name, 0775)<0) { switch (errno) { case ENOENT: case EEXIST: break; default: say("pid %d: mkdir %s: %s\n", getpid(), name, strerror(errno)); break; } } } static void dormdir(const char *name) { if (rmdir(name)<0) { switch (errno) { case ENOENT: case ENOTEMPTY: case EINVAL: break; default: say("pid %d: rmdir %s: %s\n", getpid(), name, strerror(errno)); break; } } } static void cleanup_rmdir(const char *name) { if (rmdir(name)<0) { switch (errno) { case ENOENT: break; default: say("cleanup (pid %d): rmdir %s: %s\n", getpid(), name, strerror(errno)); break; } } } //////////////////////////////////////////////////////////// static void rename_proc(void) { char name1[NAMESIZE], name2[NAMESIZE]; int ct; for (ct=0; ct %s\n", (int)getpid(), name1, name2); dorename(name1, name2); } } static void mkdir_proc(void) { char name[NAMESIZE]; int ct; for (ct=0; ct