For the most part, reference counting in the dm code is ok, but it must be
taken under the _minor_lock. There are paths where a mapped_device pointer
is returned and then a reference is taken - and taking the reference may be
too late.
This patch fixes a number of paths so that the reference is always taken
under the lock.
Signed-off-by: Jeff Mahoney <[email protected]>
--
drivers/md/dm-ioctl.c | 20 ++++++++++++++++----
drivers/md/dm.c | 16 ++++------------
2 files changed, 20 insertions(+), 16 deletions(-)
diff -ruNpX ../dontdiff linux-2.6.16-staging1/drivers/md/dm.c linux-2.6.16-staging2/drivers/md/dm.c
--- linux-2.6.16-staging1/drivers/md/dm.c 2006-04-13 16:18:22.000000000 -0400
+++ linux-2.6.16-staging2/drivers/md/dm.c 2006-04-13 16:18:22.000000000 -0400
@@ -969,7 +969,7 @@ int dm_create_with_minor(unsigned int mi
return create_aux(minor, 1, result);
}
-static struct mapped_device *dm_find_md(dev_t dev)
+struct mapped_device *dm_get_md(dev_t dev)
{
struct mapped_device *md;
unsigned minor = MINOR(dev);
@@ -986,6 +986,8 @@ static struct mapped_device *dm_find_md(
if (md) {
if (test_bit(DMF_FREEING, &md->flags))
md = NULL;
+ else
+ dm_get(md);
}
spin_unlock(&_minor_lock);
@@ -993,22 +995,12 @@ static struct mapped_device *dm_find_md(
return md;
}
-struct mapped_device *dm_get_md(dev_t dev)
-{
- struct mapped_device *md = dm_find_md(dev);
-
- if (md)
- dm_get(md);
-
- return md;
-}
-
void *dm_get_mdptr(dev_t dev)
{
struct mapped_device *md;
void *mdptr = NULL;
- md = dm_find_md(dev);
+ md = dm_get_md(dev);
if (md)
mdptr = md->interface_ptr;
return mdptr;
diff -ruNpX ../dontdiff linux-2.6.16-staging1/drivers/md/dm-ioctl.c linux-2.6.16-staging2/drivers/md/dm-ioctl.c
--- linux-2.6.16-staging1/drivers/md/dm-ioctl.c 2006-04-05 14:02:34.000000000 -0400
+++ linux-2.6.16-staging2/drivers/md/dm-ioctl.c 2006-04-13 16:18:22.000000000 -0400
@@ -600,12 +600,16 @@ static int dev_create(struct dm_ioctl *p
*/
static struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param)
{
+ struct hash_cell *hc;
if (*param->uuid)
- return __get_uuid_cell(param->uuid);
+ hc = __get_uuid_cell(param->uuid);
else if (*param->name)
- return __get_name_cell(param->name);
+ hc = __get_name_cell(param->name);
else
return dm_get_mdptr(huge_decode_dev(param->dev));
+ if (hc)
+ dm_get(hc->md);
+ return hc;
}
static struct mapped_device *find_device(struct dm_ioctl *param)
@@ -617,7 +621,6 @@ static struct mapped_device *find_device
hc = __find_device_hash_cell(param);
if (hc) {
md = hc->md;
- dm_get(md);
/*
* Sneakily write in both the name and the uuid
@@ -642,6 +645,7 @@ static struct mapped_device *find_device
static int dev_remove(struct dm_ioctl *param, size_t param_size)
{
struct hash_cell *hc;
+ struct mapped_device *md;
down_write(&_hash_lock);
hc = __find_device_hash_cell(param);
@@ -652,8 +656,11 @@ static int dev_remove(struct dm_ioctl *p
return -ENXIO;
}
+ md = hc->md;
+
__hash_remove(hc);
up_write(&_hash_lock);
+ dm_put(md);
param->data_size = 0;
return 0;
}
@@ -731,7 +738,6 @@ static int do_resume(struct dm_ioctl *pa
}
md = hc->md;
- dm_get(md);
new_map = hc->new_map;
hc->new_map = NULL;
@@ -975,6 +981,7 @@ static int table_load(struct dm_ioctl *p
int r;
struct hash_cell *hc;
struct dm_table *t;
+ struct mapped_device *md;
r = dm_table_create(&t, get_mode(param), param->target_count);
if (r)
@@ -1001,7 +1008,9 @@ static int table_load(struct dm_ioctl *p
param->flags |= DM_INACTIVE_PRESENT_FLAG;
r = __dev_status(hc->md, param);
+ md = hc->md;
up_write(&_hash_lock);
+ dm_put(md);
return r;
}
@@ -1009,6 +1018,7 @@ static int table_clear(struct dm_ioctl *
{
int r;
struct hash_cell *hc;
+ struct mapped_device *md;
down_write(&_hash_lock);
@@ -1027,7 +1037,9 @@ static int table_clear(struct dm_ioctl *
param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
r = __dev_status(hc->md, param);
+ md = hc->md;
up_write(&_hash_lock);
+ dm_put(md);
return r;
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]