From 58ea7af08c300e9d5745084a3a2cc68ca0dd171a Mon Sep 17 00:00:00 2001 From: Petr Rockai Date: Mon, 21 Nov 2011 12:31:18 +0000 Subject: [PATCH] Fix a bug in dmeventd snapshot monitoring code where the monitoring threshold would grow with subsequent snapshot extensions (RHBZ 754198). --- .../plugins/snapshot/dmeventd_snapshot.c | 37 +++++++++++++++---- test/shell/lvextend-snapshot-dmeventd.sh | 13 ++++++- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c b/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c index fcf21e2b8..b21f6a1a0 100644 --- a/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c +++ b/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c @@ -40,6 +40,11 @@ struct snap_status { int max; }; +struct dso_state { + int percent_check; + int known_size; +}; + /* FIXME possibly reconcile this with target_percent when we gain access to regular LVM library here. */ static void _parse_snapshot_params(char *params, struct snap_status *status) @@ -181,10 +186,11 @@ void process_event(struct dm_task *dmt, char *params; struct snap_status status = { 0 }; const char *device = dm_task_get_name(dmt); - int percent, *percent_check = (int*)private; + int percent; + struct dso_state *state = *private; /* No longer monitoring, waiting for remove */ - if (!*percent_check) + if (!state->percent_check) return; dmeventd_lvm2_lock(); @@ -204,27 +210,35 @@ void process_event(struct dm_task *dmt, } /* else; too bad, but this is best-effort thing... */ } + /* Snapshot size had changed. Clear the threshold. */ + if (state->known_size != status.max) { + state->percent_check = CHECK_MINIMUM; + state->known_size = status.max; + } + /* * If the snapshot has been invalidated or we failed to parse * the status string. Report the full status string to syslog. */ if (status.invalid || !status.max) { syslog(LOG_ERR, "Snapshot %s changed state to: %s\n", device, params); - *percent_check = 0; + state->percent_check = 0; goto out; } percent = 100 * status.used / status.max; - if (percent >= *percent_check) { + if (percent >= state->percent_check) { /* Usage has raised more than CHECK_STEP since the last time. Run actions. */ - *percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP; + state->percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP; + if (percent >= WARNING_THRESH) /* Print a warning to syslog. */ syslog(LOG_WARNING, "Snapshot %s is now %i%% full.\n", device, percent); /* Try to extend the snapshot, in accord with user-set policies */ if (!_extend(device)) syslog(LOG_ERR, "Failed to extend snapshot %s.", device); } + out: dmeventd_lvm2_unlock(); } @@ -235,10 +249,14 @@ int register_device(const char *device, int minor __attribute__((unused)), void **private) { - int *percent_check = (int*)private; + struct dso_state **state = (struct dso_state **) private; int r = dmeventd_lvm2_init(); - *percent_check = CHECK_MINIMUM; + if (!(*state = dm_malloc(sizeof (struct dso_state)))) + return 0; + + (*state)->percent_check = CHECK_MINIMUM; + (*state)->known_size = 0; syslog(LOG_INFO, "Monitoring snapshot %s\n", device); return r; @@ -248,10 +266,13 @@ int unregister_device(const char *device, const char *uuid __attribute__((unused)), int major __attribute__((unused)), int minor __attribute__((unused)), - void **unused __attribute__((unused))) + void **private) { + struct dso_state *state = *private; syslog(LOG_INFO, "No longer monitoring snapshot %s\n", device); + + dm_free(state); dmeventd_lvm2_exit(); return 1; } diff --git a/test/shell/lvextend-snapshot-dmeventd.sh b/test/shell/lvextend-snapshot-dmeventd.sh index 44b5a291f..e76aeccb6 100644 --- a/test/shell/lvextend-snapshot-dmeventd.sh +++ b/test/shell/lvextend-snapshot-dmeventd.sh @@ -27,7 +27,7 @@ percent() { which mkfs.ext2 || exit 200 -aux prepare_vg 2 +aux prepare_vg 3 aux prepare_dmeventd lvcreate -l 8 -n base $vg @@ -44,8 +44,19 @@ sleep 10 # dmeventd only checks every 10 seconds :( post=`percent` test $pre = $post + write 2 5000 pre=`percent` sleep 10 # dmeventd only checks every 10 seconds :( post=`percent` test $pre -gt $post + +# check that a second extension happens; we used to fail to extend when the +# utilisation ended up between THRESH and (THRESH + 10)... see RHBZ 754198 +# (the utilisation after the write should be 57 %) + +write 3 5000 +pre=`percent` +sleep 10 # dmeventd only checks every 10 seconds :( +post=`percent` +test $pre -gt $post