Add a test program to exercise a specific bug - racing unlink/write on a full filesystem
authorfsgqa <fsgqa>
Wed, 12 Nov 2003 06:58:32 +0000 (06:58 +0000)
committerfsgqa <fsgqa>
Wed, 12 Nov 2003 06:58:32 +0000 (06:58 +0000)
src/Makefile
src/enospc_unlink.c [new file with mode: 0644]

index 5bbb6c1e516f716f081855625cb3348be72c5679..36cc7e343e58cfe586a1e06c07d58171a5c8bf96 100644 (file)
@@ -37,7 +37,7 @@ TARGETS = alloc acl_get bstat devzero dirstress fault feature \
          fill fill2 getpagesize holes xfsctl loggen lstat64 \
          nametest permname randholes runas truncfile usemem \
          fstest mmapcat append_reader append_writer \
-         dirperf metaperf
+         dirperf metaperf enospc_unlink
 ifeq ($(ENABLE_DBM), yes)
 TARGETS += dbtest
 endif
diff --git a/src/enospc_unlink.c b/src/enospc_unlink.c
new file mode 100644 (file)
index 0000000..0cfe53e
--- /dev/null
@@ -0,0 +1,78 @@
+/* 
+ * Write a file until filesystem full is reached and then unlink it.
+ * Demonstrates a particular deadlock that Kaz hit in testing.  Run
+ * several iterations of this in parallel on a near-full filesystem.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+int main(int argc, char **argv)
+{
+       int                     fd, sz, done;
+       void                    *ptr;
+       size_t                  written;
+       unsigned int            i, count = 0;
+       unsigned long long      bytes = 0;
+
+       if (argc < 2) {
+               fprintf(stderr, "Insufficient arguments\n");
+               exit(1);
+       }
+       if (argc < 3) {
+               count = (unsigned int)atoi(argv[2]);
+       }
+
+       sz = 1024 * 1024;
+
+       ptr = memalign(sz, sz);
+       if (!ptr) {
+               perror("memalign");
+               exit(1);
+       }
+       memset(ptr, 0xffffffff, sz);
+
+       for (i = 0; i < count; i++) {
+               fd = open(argv[1], O_CREAT|O_WRONLY);
+               if (fd < 0) {
+                       perror(argv[1]);
+                       exit(1);
+               }
+
+               done = 0;
+               while (!done) {
+                       written = write(fd, ptr, sz);
+                       if (written == -1) {
+                               if (errno == ENOSPC) {
+                                       close(fd);
+                                       unlink(argv[1]);
+                                       printf("Unlinked %s\n", argv[1]);
+                                       done = 1;
+                               }
+                               else {
+                                       printf("Skipped unlink %s (%s)\n",
+                                               argv[1], strerror(errno));
+                                       done = -1;
+                               }
+                       }
+                       if (written == 0) {
+                               printf("Wrote zero bytes?\n");
+                               done = -1;
+                       }
+                       bytes += written;
+               }
+               if (done > 0)
+                       printf("Wrote %llu bytes total.\n", bytes);
+               else
+                       exit(1);
+       }
+       printf("Completed %u iterations of unlink/out-of-space test.\n", i);
+       exit(0);
+}