On Thu, Aug 21, 2003 at 08:18:03PM +0100, Alasdair Kergon wrote: > Well, many thanks for producing all the diagnostics: > I don't know what's wrong yet, but I have managed to > reproduce your setup on a test machine here and > I reproduced the problem 5 minutes ago. I attach a patch which should workaround the problem. Memory that is still referenced gets freed if pvmove tries to move more than 8 LV segments at once, so all pvmove (dm_mirror target) users should apply this patch. It's in CVS now, and I'll update the tarball on the ftp site to 1.00.04. Alasdair -- agk@uk.sistina.com
Supply #targets when creating a table to avoid needing to extend it later. --- linux-2.4.21/drivers/md/dm-ioctl.c Mon Aug 18 21:24:26 2003 +++ linux/drivers/md/dm-ioctl.c Fri Aug 22 13:49:01 2003 @@ -764,7 +764,7 @@ struct hash_cell *hc; struct dm_table *t; - r = dm_table_create(&t, get_mode(param)); + r = dm_table_create(&t, get_mode(param), param->target_count); if (r) return r; --- linux-2.4.21/drivers/md/dm-table.c Tue Aug 19 15:43:50 2003 +++ linux/drivers/md/dm-table.c Fri Aug 22 14:48:50 2003 @@ -148,7 +148,7 @@ return 0; } -int dm_table_create(struct dm_table **result, int mode) +int dm_table_create(struct dm_table **result, int mode, unsigned num_targets) { struct dm_table *t = kmalloc(sizeof(*t), GFP_NOIO); @@ -159,8 +159,10 @@ INIT_LIST_HEAD(&t->devices); atomic_set(&t->holders, 1); - /* allocate a single nodes worth of targets to begin with */ - if (alloc_targets(t, KEYS_PER_NODE)) { + if (!num_targets) + num_targets = KEYS_PER_NODE; + + if (alloc_targets(t, num_targets)) { kfree(t); t = NULL; return -ENOMEM; --- linux-2.4.21/drivers/md/dm.h Sat Jul 12 17:06:52 2003 +++ linux/drivers/md/dm.h Fri Aug 22 13:50:19 2003 @@ -96,7 +96,7 @@ * Functions for manipulating a table. Tables are also reference * counted. *---------------------------------------------------------------*/ -int dm_table_create(struct dm_table **result, int mode); +int dm_table_create(struct dm_table **result, int mode, unsigned num_targets); void dm_table_get(struct dm_table *t); void dm_table_put(struct dm_table *t);