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:
parent
61b2affd6e
commit
2cd72ac0e0
|
@ -48,6 +48,9 @@ sbin_PROGRAMS += pivot_root
|
||||||
man_MANS += pivot_root.8
|
man_MANS += pivot_root.8
|
||||||
endif
|
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
|
swapon.c: swapargs.h
|
||||||
|
|
||||||
|
|
117
mount/fstab.c
117
mount/fstab.c
|
@ -662,3 +662,120 @@ update_mtab (const char *dir, struct my_mntent *instead) {
|
||||||
leave:
|
leave:
|
||||||
unlock_mtab();
|
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
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,8 @@ EXTRA_DIST = expected/* \
|
||||||
ts-look-separator \
|
ts-look-separator \
|
||||||
ts-login-checktty \
|
ts-login-checktty \
|
||||||
ts-hwclock-systohc \
|
ts-hwclock-systohc \
|
||||||
ts-mount-special
|
ts-mount-special \
|
||||||
|
ts-mount-mtablock
|
||||||
|
|
||||||
distclean-local:
|
distclean-local:
|
||||||
rm -rf output diff
|
rm -rf output diff
|
||||||
|
|
|
@ -11,6 +11,8 @@ TS_CMD_SWAPON=${TS_CMD_SWAPON:-"$TOPDIR/mount/swapon"}
|
||||||
TS_CMD_SWAPOFF=${TS_CMD_SWAPOFF:-"$TOPDIR/mount/swapoff"}
|
TS_CMD_SWAPOFF=${TS_CMD_SWAPOFF:-"$TOPDIR/mount/swapoff"}
|
||||||
TS_CMD_LOSETUP=${TS_CMD_LOSETUP:-"$TOPDIR/mount/losetup"}
|
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_MKSWAP=${TS_CMD_MKSWAP:-"$TOPDIR/disk-utils/mkswap"}
|
||||||
TS_CMD_MKCRAMFS=${TS_CMD_MKCRAMFS:-"$TOPDIR/disk-utils/mkfs.cramfs"}
|
TS_CMD_MKCRAMFS=${TS_CMD_MKCRAMFS:-"$TOPDIR/disk-utils/mkfs.cramfs"}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
50
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue