summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlasdair Kergon <agk@redhat.com>2011-06-29 21:56:46 +0000
committerAlasdair Kergon <agk@redhat.com>2011-06-29 21:56:46 +0000
commitf96cf55d3689725394e1a4fe7385c0b859be420f (patch)
tree38029b1422b76941fbc536a54db02f6635937d91
parent5ffa914c5983afc7ed95eff44fa371496be7801a (diff)
downloadlvm2-f96cf55d3689725394e1a4fe7385c0b859be420f.tar.gz
lvm2-f96cf55d3689725394e1a4fe7385c0b859be420f.tar.xz
lvm2-f96cf55d3689725394e1a4fe7385c0b859be420f.zip
Add age filter to dmsetup udevcomplete_all to minimise concurrency problems.
-rw-r--r--WHATS_NEW_DM1
-rw-r--r--man/dmsetup.8.in7
-rw-r--r--test/lib/utils.sh4
-rw-r--r--tools/dmsetup.c41
4 files changed, 40 insertions, 13 deletions
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index e86c69b9..a28ed9b1 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,5 +1,6 @@
Version 1.02.65 -
==================================
+ Add age_in_minutes parameter to dmsetup udevcomplete_all.
Return immediately from dm_lib_exit() if called more than once.
Disable udev fallback by default and add --verifyudev option to dmsetup.
Warn if a table is loaded while a device is known to be in suspended state.
diff --git a/man/dmsetup.8.in b/man/dmsetup.8.in
index ce063bd5..3b82b64e 100644
--- a/man/dmsetup.8.in
+++ b/man/dmsetup.8.in
@@ -80,6 +80,7 @@ dmsetup \- low level logical volume management
.I cookie
.br
.B dmsetup udevcomplete_all
+.I [age_in_minutes]
.br
.B dmsetup udevcookies
.br
@@ -389,8 +390,10 @@ always reported as DM_SUBSYSTEM_UDEV_FLAG<flag_position>='1'. There are
.br
Wake any processes that are waiting for udev to complete processing the specified cookie.
.br
-.IP \fBudevcomplete_all
-Remove all cookies. Any process waiting on a cookie will be resumed immediately.
+.IP \fBudevcomplete_all
+.I[age_in_minutes]
+Remove all cookies older than the specified number of minutes.
+Any process waiting on a cookie will be resumed immediately.
.br
.IP \fBudevcookies
List all existing cookies. Cookies are system-wide semaphores with keys
diff --git a/test/lib/utils.sh b/test/lib/utils.sh
index b2a7af6e..4c3cd938 100644
--- a/test/lib/utils.sh
+++ b/test/lib/utils.sh
@@ -149,7 +149,9 @@ finish_udev_transaction() {
teardown_udev_cookies() {
if test "$DM_UDEV_SYNCHRONISATION" = 1; then
- dmsetup udevcomplete_all -y
+ # Delete any cookies created more than 10 minutes ago
+ # and not used in the last 10 minutes.
+ dmsetup udevcomplete_all -y 10
fi
}
diff --git a/tools/dmsetup.c b/tools/dmsetup.c
index bf185ba9..3cf18a02 100644
--- a/tools/dmsetup.c
+++ b/tools/dmsetup.c
@@ -1085,10 +1085,19 @@ static int _udevcomplete_all(CMD_ARGS)
struct seminfo sinfo;
struct semid_ds sdata;
int counter = 0;
+ int skipped = 0;
+ unsigned age = 0;
+ time_t t;
+
+ if (argc == 2 && (sscanf(argv[1], "%i", &age) != 1)) {
+ log_error("Failed to read age_in_minutes parameter.");
+ return 0;
+ }
if (!_switches[YES_ARG]) {
- log_warn("This operation will destroy all semaphores with keys "
+ log_warn("This operation will destroy all semaphores %s%.0d%swith keys "
"that have a prefix %" PRIu16 " (0x%" PRIx16 ").",
+ age ? "older than " : "", age, age ? " minutes " : "",
DM_COOKIE_MAGIC, DM_COOKIE_MAGIC);
if (_yes_no_prompt("Do you really want to continue? [y/n]: ") == 'n') {
@@ -1109,6 +1118,13 @@ static int _udevcomplete_all(CMD_ARGS)
continue;
if (sdata.sem_perm.__key >> 16 == DM_COOKIE_MAGIC) {
+ t = time(NULL);
+
+ if (sdata.sem_ctime + age * 60 > t ||
+ sdata.sem_otime + age * 60 > t) {
+ skipped++;
+ continue;
+ }
if (semctl(sid, 0, IPC_RMID, 0) < 0) {
log_error("Could not cleanup notification semaphore "
"with semid %d and cookie value "
@@ -1122,8 +1138,8 @@ static int _udevcomplete_all(CMD_ARGS)
}
log_print("%d semaphores with keys prefixed by "
- "%" PRIu16 " (0x%" PRIx16 ") destroyed.",
- counter, DM_COOKIE_MAGIC, DM_COOKIE_MAGIC);
+ "%" PRIu16 " (0x%" PRIx16 ") destroyed. %d skipped.",
+ counter, DM_COOKIE_MAGIC, DM_COOKIE_MAGIC, skipped);
return 1;
}
@@ -1134,14 +1150,15 @@ static int _udevcookies(CMD_ARGS)
struct seminfo sinfo;
struct semid_ds sdata;
int val;
- char *time_str;
+ char otime_str[26], ctime_str[26];
+ char *otimes, *ctimes;
if ((max_id = semctl(0, 0, SEM_INFO, &sinfo)) < 0) {
log_sys_error("sem_ctl", "SEM_INFO");
return 0;
}
- printf("cookie semid value last_semop_time\n");
+ printf("Cookie Semid Value Last semop time Last change time\n");
for (id = 0; id <= max_id; id++) {
if ((sid = semctl(id, 0, SEM_STAT, &sdata)) < 0)
@@ -1156,10 +1173,14 @@ static int _udevcookies(CMD_ARGS)
continue;
}
- time_str = ctime((const time_t *) &sdata.sem_otime);
+ if ((otimes = ctime_r((const time_t *) &sdata.sem_otime, (char *)&otime_str)))
+ otime_str[strlen(otimes)-1] = '\0';
+ if ((ctimes = ctime_r((const time_t *) &sdata.sem_ctime, (char *)&ctime_str)))
+ ctime_str[strlen(ctimes)-1] = '\0';
- printf("0x%-10x %-10d %-10d %s", sdata.sem_perm.__key,
- sid, val, time_str ? time_str : "unknown\n");
+ printf("0x%-10x %-10d %-10d %s %s\n", sdata.sem_perm.__key,
+ sid, val, otimes ? : "unknown",
+ ctimes? : "unknown");
}
}
@@ -2728,7 +2749,7 @@ static struct command _commands[] = {
{"udevreleasecookie", "[<cookie>]", 0, 1, 0, _udevreleasecookie},
{"udevflags", "<cookie>", 1, 1, 0, _udevflags},
{"udevcomplete", "<cookie>", 1, 1, 0, _udevcomplete},
- {"udevcomplete_all", "", 0, 0, 0, _udevcomplete_all},
+ {"udevcomplete_all", "<age_in_minutes>", 0, 1, 0, _udevcomplete_all},
{"udevcookies", "", 0, 0, 0, _udevcookies},
{"targets", "", 0, 0, 0, _targets},
{"version", "", 0, 0, 0, _version},
@@ -2745,7 +2766,7 @@ static void _usage(FILE *out)
fprintf(out, "dmsetup [--version] [-h|--help [-c|-C|--columns]]\n"
" [-v|--verbose [-v|--verbose ...]]\n"
" [-r|--readonly] [--noopencount] [--nolockfs] [--inactive]\n"
- " [--udevcookie] [--noudevrules] [--noudevsync] [--verifyudev]\n"
+ " [--udevcookie [cookie]] [--noudevrules] [--noudevsync] [--verifyudev]\n"
" [-y|--yes] [--readahead [+]<sectors>|auto|none]\n"
" [-c|-C|--columns] [-o <fields>] [-O|--sort <sort_fields>]\n"
" [--nameprefixes] [--noheadings] [--separator <separator>]\n\n");