OSDN Git Service

dm table: remove unused buggy code that extends the targets array
[uclinux-h8/linux.git] / drivers / md / dm-table.c
index 8f87835..6a7f2b8 100644 (file)
@@ -155,7 +155,6 @@ static int alloc_targets(struct dm_table *t, unsigned int num)
 {
        sector_t *n_highs;
        struct dm_target *n_targets;
-       int n = t->num_targets;
 
        /*
         * Allocate both the target array and offset array at once.
@@ -169,12 +168,7 @@ static int alloc_targets(struct dm_table *t, unsigned int num)
 
        n_targets = (struct dm_target *) (n_highs + num);
 
-       if (n) {
-               memcpy(n_highs, t->highs, sizeof(*n_highs) * n);
-               memcpy(n_targets, t->targets, sizeof(*n_targets) * n);
-       }
-
-       memset(n_highs + n, -1, sizeof(*n_highs) * (num - n));
+       memset(n_highs, -1, sizeof(*n_highs) * num);
        vfree(t->highs);
 
        t->num_allocated = num;
@@ -200,6 +194,11 @@ int dm_table_create(struct dm_table **result, fmode_t mode,
 
        num_targets = dm_round_up(num_targets, KEYS_PER_NODE);
 
+       if (!num_targets) {
+               kfree(t);
+               return -ENOMEM;
+       }
+
        if (alloc_targets(t, num_targets)) {
                kfree(t);
                return -ENOMEM;
@@ -256,17 +255,6 @@ void dm_table_destroy(struct dm_table *t)
 }
 
 /*
- * Checks to see if we need to extend highs or targets.
- */
-static inline int check_space(struct dm_table *t)
-{
-       if (t->num_targets >= t->num_allocated)
-               return alloc_targets(t, t->num_allocated * 2);
-
-       return 0;
-}
-
-/*
  * See if we've already got a device in the list.
  */
 static struct dm_dev_internal *find_device(struct list_head *l, dev_t dev)
@@ -545,14 +533,28 @@ static int adjoin(struct dm_table *table, struct dm_target *ti)
 
 /*
  * Used to dynamically allocate the arg array.
+ *
+ * We do first allocation with GFP_NOIO because dm-mpath and dm-thin must
+ * process messages even if some device is suspended. These messages have a
+ * small fixed number of arguments.
+ *
+ * On the other hand, dm-switch needs to process bulk data using messages and
+ * excessive use of GFP_NOIO could cause trouble.
  */
 static char **realloc_argv(unsigned *array_size, char **old_argv)
 {
        char **argv;
        unsigned new_size;
+       gfp_t gfp;
 
-       new_size = *array_size ? *array_size * 2 : 64;
-       argv = kmalloc(new_size * sizeof(*argv), GFP_KERNEL);
+       if (*array_size) {
+               new_size = *array_size * 2;
+               gfp = GFP_KERNEL;
+       } else {
+               new_size = 8;
+               gfp = GFP_NOIO;
+       }
+       argv = kmalloc(new_size * sizeof(*argv), gfp);
        if (argv) {
                memcpy(argv, old_argv, *array_size * sizeof(*argv));
                *array_size = new_size;
@@ -712,8 +714,7 @@ int dm_table_add_target(struct dm_table *t, const char *type,
                return -EINVAL;
        }
 
-       if ((r = check_space(t)))
-               return r;
+       BUG_ON(t->num_targets >= t->num_allocated);
 
        tgt = t->targets + t->num_targets;
        memset(tgt, 0, sizeof(*tgt));
@@ -1548,8 +1549,11 @@ int dm_table_resume_targets(struct dm_table *t)
                        continue;
 
                r = ti->type->preresume(ti);
-               if (r)
+               if (r) {
+                       DMERR("%s: %s: preresume failed, error = %d",
+                             dm_device_name(t->md), ti->type->name, r);
                        return r;
+               }
        }
 
        for (i = 0; i < t->num_targets; i++) {