summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Brassow <jbrassow@redhat.com>2009-04-02 22:55:35 +0400
committerAlasdair G Kergon <agk@redhat.com>2009-04-02 22:55:35 +0400
commita32079ce17899192a7b98a42753be467605a8b2f (patch)
tree116fefba16427c16cb792e218889aa971eab755b
parent1e302a929e2da6e8448e2058e4b07b07252b57fe (diff)
downloadlinux-a32079ce17899192a7b98a42753be467605a8b2f.tar.xz
dm snapshot: persistent fix dtr cleanup
The persistent exception store destructor does not properly account for all conditions in which it can be called. If it is called after 'ctr' but before 'read_metadata' (e.g. if something else in 'snapshot_ctr' fails) then it will attempt to free areas of memory that haven't been allocated yet. Signed-off-by: Jonathan Brassow <jbrassow@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
-rw-r--r--drivers/md/dm-snap-persistent.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
index 1799205cd945..e75c6dd76a9a 100644
--- a/drivers/md/dm-snap-persistent.c
+++ b/drivers/md/dm-snap-persistent.c
@@ -162,9 +162,12 @@ static int alloc_area(struct pstore *ps)
static void free_area(struct pstore *ps)
{
- vfree(ps->area);
+ if (ps->area)
+ vfree(ps->area);
ps->area = NULL;
- vfree(ps->zero_area);
+
+ if (ps->zero_area)
+ vfree(ps->zero_area);
ps->zero_area = NULL;
}
@@ -482,9 +485,16 @@ static void persistent_dtr(struct dm_exception_store *store)
struct pstore *ps = get_info(store);
destroy_workqueue(ps->metadata_wq);
- dm_io_client_destroy(ps->io_client);
- vfree(ps->callbacks);
+
+ /* Created in read_header */
+ if (ps->io_client)
+ dm_io_client_destroy(ps->io_client);
free_area(ps);
+
+ /* Allocated in persistent_read_metadata */
+ if (ps->callbacks)
+ vfree(ps->callbacks);
+
kfree(ps);
}
@@ -661,7 +671,7 @@ static int persistent_ctr(struct dm_exception_store *store,
struct pstore *ps;
/* allocate the pstore */
- ps = kmalloc(sizeof(*ps), GFP_KERNEL);
+ ps = kzalloc(sizeof(*ps), GFP_KERNEL);
if (!ps)
return -ENOMEM;