[PATCH] dm table: store md
authorMike Anderson <andmike@us.ibm.com>
Mon, 27 Mar 2006 09:17:54 +0000 (01:17 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Mon, 27 Mar 2006 16:44:59 +0000 (08:44 -0800)
Store an up-pointer to the owning struct mapped_device in every table when it
is created.

Access it with:
  struct mapped_device *dm_table_get_md(struct dm_table *t)

Tables linked to md must be destroyed before the md itself.

Signed-off-by: Mike Anderson <andmike@us.ibm.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
drivers/md/dm-ioctl.c
drivers/md/dm-table.c
drivers/md/dm.c
drivers/md/dm.h

index 0693b6f54b7dd6939488e4c7a44409015735d348..65826bdac00c7b3649c4815690cf64fc0d2faac2 100644 (file)
@@ -244,9 +244,9 @@ static void __hash_remove(struct hash_cell *hc)
                dm_table_put(table);
        }
 
-       dm_put(hc->md);
        if (hc->new_map)
                dm_table_put(hc->new_map);
+       dm_put(hc->md);
        free_cell(hc);
 }
 
@@ -985,33 +985,43 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
        int r;
        struct hash_cell *hc;
        struct dm_table *t;
+       struct mapped_device *md;
+
+       md = find_device(param);
+       if (!md)
+               return -ENXIO;
 
-       r = dm_table_create(&t, get_mode(param), param->target_count);
+       r = dm_table_create(&t, get_mode(param), param->target_count, md);
        if (r)
-               return r;
+               goto out;
 
        r = populate_table(t, param, param_size);
        if (r) {
                dm_table_put(t);
-               return r;
+               goto out;
        }
 
        down_write(&_hash_lock);
-       hc = __find_device_hash_cell(param);
-       if (!hc) {
-               DMWARN("device doesn't appear to be in the dev hash table.");
-               up_write(&_hash_lock);
+       hc = dm_get_mdptr(md);
+       if (!hc || hc->md != md) {
+               DMWARN("device has been removed from the dev hash table.");
                dm_table_put(t);
-               return -ENXIO;
+               up_write(&_hash_lock);
+               r = -ENXIO;
+               goto out;
        }
 
        if (hc->new_map)
                dm_table_put(hc->new_map);
        hc->new_map = t;
+       up_write(&_hash_lock);
+
        param->flags |= DM_INACTIVE_PRESENT_FLAG;
+       r = __dev_status(md, param);
+
+out:
+       dm_put(md);
 
-       r = __dev_status(hc->md, param);
-       up_write(&_hash_lock);
        return r;
 }
 
index 9558a4acec129d4f4484a2eea3adbeb6b7f14333..84f4594afd3ccffcd5f2f72cb96785291b28b0cc 100644 (file)
@@ -22,6 +22,7 @@
 #define CHILDREN_PER_NODE (KEYS_PER_NODE + 1)
 
 struct dm_table {
+       struct mapped_device *md;
        atomic_t holders;
 
        /* btree table */
@@ -206,7 +207,8 @@ static int alloc_targets(struct dm_table *t, unsigned int num)
        return 0;
 }
 
-int dm_table_create(struct dm_table **result, int mode, unsigned num_targets)
+int dm_table_create(struct dm_table **result, int mode,
+                   unsigned num_targets, struct mapped_device *md)
 {
        struct dm_table *t = kmalloc(sizeof(*t), GFP_KERNEL);
 
@@ -229,6 +231,7 @@ int dm_table_create(struct dm_table **result, int mode, unsigned num_targets)
        }
 
        t->mode = mode;
+       t->md = md;
        *result = t;
        return 0;
 }
@@ -952,12 +955,20 @@ int dm_table_flush_all(struct dm_table *t)
        return ret;
 }
 
+struct mapped_device *dm_table_get_md(struct dm_table *t)
+{
+       dm_get(t->md);
+
+       return t->md;
+}
+
 EXPORT_SYMBOL(dm_vcalloc);
 EXPORT_SYMBOL(dm_get_device);
 EXPORT_SYMBOL(dm_put_device);
 EXPORT_SYMBOL(dm_table_event);
 EXPORT_SYMBOL(dm_table_get_size);
 EXPORT_SYMBOL(dm_table_get_mode);
+EXPORT_SYMBOL(dm_table_get_md);
 EXPORT_SYMBOL(dm_table_put);
 EXPORT_SYMBOL(dm_table_get);
 EXPORT_SYMBOL(dm_table_unplug_all);
index 3d121cbc2fde8f7740e673cc2527abc37030db51..b99df48cffed554773f5c6e63c047c05decd44be 100644 (file)
@@ -1007,18 +1007,18 @@ void dm_get(struct mapped_device *md)
 
 void dm_put(struct mapped_device *md)
 {
-       struct dm_table *map = dm_get_table(md);
+       struct dm_table *map;
 
        if (atomic_dec_and_test(&md->holders)) {
+               map = dm_get_table(md);
                if (!dm_suspended(md)) {
                        dm_table_presuspend_targets(map);
                        dm_table_postsuspend_targets(map);
                }
                __unbind(md);
+               dm_table_put(map);
                free_dev(md);
        }
-
-       dm_table_put(map);
 }
 
 /*
index 17ffa8d671a70950c42e85c3a20b345bfe210d48..79e800051a10b1f39f35eb0768a9bb84ffdae3a0 100644 (file)
@@ -89,7 +89,8 @@ int dm_suspended(struct mapped_device *md);
  * Functions for manipulating a table.  Tables are also reference
  * counted.
  *---------------------------------------------------------------*/
-int dm_table_create(struct dm_table **result, int mode, unsigned num_targets);
+int dm_table_create(struct dm_table **result, int mode,
+                   unsigned num_targets, struct mapped_device *md);
 
 void dm_table_get(struct dm_table *t);
 void dm_table_put(struct dm_table *t);
@@ -107,6 +108,7 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q);
 unsigned int dm_table_get_num_targets(struct dm_table *t);
 struct list_head *dm_table_get_devices(struct dm_table *t);
 int dm_table_get_mode(struct dm_table *t);
+struct mapped_device *dm_table_get_md(struct dm_table *t);
 void dm_table_presuspend_targets(struct dm_table *t);
 void dm_table_postsuspend_targets(struct dm_table *t);
 void dm_table_resume_targets(struct dm_table *t);