]> err.no Git - util-linux/commitdiff
tests: add lock_mtab() performance and reliability test
authorKarel Zak <kzak@redhat.com>
Wed, 28 Mar 2007 16:43:03 +0000 (18:43 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 28 Mar 2007 16:43:03 +0000 (18:43 +0200)
The test starts concurrently many processes that use lock_mtab() as
lock for access to same file.

Signed-off-by: Karel Zak <kzak@redhat.com>
mount/Makefile.am
mount/fstab.c
tests/Makefile.am
tests/commands.sh.in
tests/expected/ts-mount-mtablock [new file with mode: 0644]
tests/ts-mount-mtablock [new file with mode: 0755]

index 605c4520c8997754f12ef33ed8216e358343aa52..f34fc83b96c6160ed14961e45dba76937191a29a 100644 (file)
@@ -48,6 +48,9 @@ sbin_PROGRAMS += pivot_root
 man_MANS += pivot_root.8
 endif
 
+noinst_PROGRAMS = mtab_lock_test
+mtab_lock_test_SOURCES = fstab.c sundries.c xmalloc.c $(MNTHDRS)
+mtab_lock_test_CFLAGS = -DMAIN_TEST_MTABLOCK
 
 swapon.c: swapargs.h
 
index 2de44e68fa5bea5b9b9a3d66b2be93befad92645..2c00dea5f8116826c4ed15eeb1347b14191d0b69 100644 (file)
@@ -662,3 +662,120 @@ update_mtab (const char *dir, struct my_mntent *instead) {
  leave:
        unlock_mtab();
 }
+
+
+#ifdef MAIN_TEST_MTABLOCK
+
+/*
+ * This is mtab locking code test for:
+ *
+ *     - performance (how many concurrent processes)
+ *
+ *     - lock reliability (is possible to see corrupted data  if more
+ *                         concurrent processes modify a same file)
+ *
+ *  The test is very simple -- it reads a number from locked file, increments the
+ *  number and writes the number back to the file.
+ */
+
+/* dummy */
+int verbose;
+int mount_quiet;
+char *progname;
+
+const char *mount_get_volume_label_by_spec(const char *spec) { return NULL; }
+const char *mount_get_devname_by_uuid(const char *uuid) { return NULL; }
+struct my_mntent *my_getmntent (mntFILE *mfp) { return NULL; }
+mntFILE *my_setmntent (const char *file, char *mode) { return NULL; }
+void my_endmntent (mntFILE *mfp) { }
+int my_addmntent (mntFILE *mfp, struct my_mntent *mnt) { return 0; }
+char *myrealpath(const char *path, char *resolved_path, int m) { return NULL; }
+
+int
+main(int argc, char **argv)
+{
+       time_t synctime;
+       char *filename;
+       int nloops, id, i;
+       pid_t pid = getpid();
+       unsigned int usecs;
+       struct timeval tv;
+       struct stat st;
+       long last = 0;
+
+       progname = argv[0];
+
+       if (argc < 3)
+               die(EXIT_FAILURE,
+                       "usage: %s <id> <synctime> <file> <nloops>\n",
+                       progname);
+
+       id = atoi(argv[1]);
+       synctime = (time_t) atol(argv[2]);
+       filename = argv[3];
+       nloops = atoi(argv[4]);
+
+       if (stat(filename, &st) < -1)
+               die(EXIT_FAILURE, "%s: %s\n", filename, strerror(errno));
+
+       fprintf(stderr, "%05d (pid=%05d): START\n", id, pid);
+
+       gettimeofday(&tv, NULL);
+       if (synctime && synctime - tv.tv_sec > 1) {
+               usecs = ((synctime - tv.tv_sec) * 1000000UL) -
+                                       (1000000UL - tv.tv_usec);
+               usleep(usecs);
+       }
+
+       for (i = 0; i < nloops; i++) {
+               FILE *f;
+               long num;
+               char buf[256];
+
+               lock_mtab();
+
+               if (!(f = fopen(filename, "r"))) {
+                       unlock_mtab();
+                       die(EXIT_FAILURE, "ERROR: %d (pid=%d, loop=%d): "
+                                       "open for read failed\n", id, pid, i);
+               }
+               if (!fgets(buf, sizeof(buf), f)) {
+                       unlock_mtab();
+                       die(EXIT_FAILURE, "ERROR: %d (pid=%d, loop=%d): "
+                                       "read failed\n", id, pid, i);
+               }
+               fclose(f);
+
+               num = atol(buf) + 1;
+
+               if (!(f = fopen(filename, "w"))) {
+                       unlock_mtab();
+                       die(EXIT_FAILURE, "ERROR: %d (pid=%d, loop=%d): "
+                                       "open for write failed\n", id, pid, i);
+               }
+               fprintf(f, "%ld", num);
+               fclose(f);
+
+               unlock_mtab();
+
+               gettimeofday(&tv, NULL);
+
+               fprintf(stderr, "%010ld.%06ld %04d (pid=%05d, loop=%05d): "
+                               "num=%09ld last=%09ld\n",
+                               tv.tv_sec, tv.tv_usec, id,
+                               pid, i, num, last);
+               last = num;
+
+               /* The mount command usually finish after mtab update. We
+                * simulate this via short sleep -- it's also enough to make
+                * concurrent processes happy.
+                */
+               usleep(50000);
+       }
+
+       fprintf(stderr, "%05d (pid=%05d): DONE\n", id, pid);
+
+       exit(EXIT_SUCCESS);
+}
+#endif
+
index 1cf3101cfb37b97f3c044eff27b1c1d9bf7c1d17..79b43d36ee52a331d0c6a1a2331ca7e5a70349d3 100644 (file)
@@ -19,7 +19,8 @@ EXTRA_DIST =  expected/* \
                ts-look-separator \
                ts-login-checktty \
                ts-hwclock-systohc \
-               ts-mount-special
+               ts-mount-special \
+               ts-mount-mtablock
 
 distclean-local:
        rm -rf output diff
index 44eca14ad4157fca1a0ad440680aee6227682202..9ed88a9c222340035394b1d92885c6ef93452096 100644 (file)
@@ -11,6 +11,8 @@ TS_CMD_SWAPON=${TS_CMD_SWAPON:-"$TOPDIR/mount/swapon"}
 TS_CMD_SWAPOFF=${TS_CMD_SWAPOFF:-"$TOPDIR/mount/swapoff"}
 TS_CMD_LOSETUP=${TS_CMD_LOSETUP:-"$TOPDIR/mount/losetup"}
 
+TS_CMD_MTABLOCK=${TS_CMD_MTABLOCK:-"$TOPDIR/mount/mtab_lock_test"}
+
 TS_CMD_MKSWAP=${TS_CMD_MKSWAP:-"$TOPDIR/disk-utils/mkswap"}
 TS_CMD_MKCRAMFS=${TS_CMD_MKCRAMFS:-"$TOPDIR/disk-utils/mkfs.cramfs"}
 
diff --git a/tests/expected/ts-mount-mtablock b/tests/expected/ts-mount-mtablock
new file mode 100644 (file)
index 0000000..c5b431b
--- /dev/null
@@ -0,0 +1 @@
+50
\ No newline at end of file
diff --git a/tests/ts-mount-mtablock b/tests/ts-mount-mtablock
new file mode 100755 (executable)
index 0000000..44834dc
--- /dev/null
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+. commands.sh
+. functions.sh
+
+TS_COMPONENT="mount"
+TS_DESC="mtablock"
+
+#
+# Be careful with number of processes. Don't forget that there is time limit
+# when the mount waits on the mtab lock. If you define too much processes some
+# of them will fail with timeout.
+#
+# Note: the original version (< 2.13) of util-linux is completely useless for
+# this test (maximum for this old version is NLOOPS=10 and NPROCESSES=5 (2-way
+# 2GHz machine)). It has terrible performance due a bad timeouts implemntation
+# in lock_mtab().
+#
+NLOOPS=10
+NPROCESSES=5
+
+ts_init
+
+> $TS_OUTPUT.debug
+echo 0 > $TS_OUTPUT
+SYNCTIME=$(( $(date +%s) + 10 ))
+
+for id in $(seq 0 $(( $NPROCESSES - 1 ))); do
+       $TS_CMD_MTABLOCK $id $SYNCTIME $TS_OUTPUT $NLOOPS >> $TS_OUTPUT.debug 2>&1 &
+done
+
+wait
+
+ts_finalize
+