tests: add lock_mtab() performance and reliability test

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>
This commit is contained in:
Karel Zak 2007-03-28 18:43:03 +02:00
parent 61b2affd6e
commit 2cd72ac0e0
6 changed files with 160 additions and 1 deletions

View 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

View 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

View 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

View 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"}

View File

@ -0,0 +1 @@
50

35
tests/ts-mount-mtablock Executable file
View File

@ -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