]> sourceware.org Git - dm.git/commitdiff
Sync with ejt 2.4.23-pre7-umd1
authorAlasdair Kergon <agk@redhat.com>
Thu, 20 Nov 2003 19:02:15 +0000 (19:02 +0000)
committerAlasdair Kergon <agk@redhat.com>
Thu, 20 Nov 2003 19:02:15 +0000 (19:02 +0000)
(excl. vfs lock move (7); with incl bitops & GFP_KERNEL repl NOIO)

kernel/common/dm-io.c
kernel/common/dm-log.c
kernel/common/dm-table.c
kernel/common/kcopyd.c
kernel/ioctl/dm-ioctl.c
kernel/ioctl/dm-ioctl.h

index 43d3482c2cd7c584a87a09acb6faf6eb9bbafa51..cd766f5ac0d6aaecbd8e432d58bd5ce067d9c7a3 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/bitops.h>
 
 /* FIXME: can we shrink this ? */
 struct io_context {
index f3f8c9b263e210286572377b5b77b540c260fadf..a58777b3a8ad28896f339b9a6b072e6962240de5 100644 (file)
@@ -124,6 +124,8 @@ struct core_log {
        int sync_search;
 };
 
+#define BYTE_SHIFT 3
+
 static int core_ctr(struct dirty_log *log, sector_t dev_size,
                    unsigned int argc, char **argv)
 {
@@ -153,8 +155,13 @@ static int core_ctr(struct dirty_log *log, sector_t dev_size,
        clog->region_size = region_size;
        clog->region_count = region_count;
 
-       bitset_size = dm_round_up((region_count + 7) >> 3,
-                                 sizeof(*clog->clean_bits));
+       /*
+        * Work out how many words we need to hold the bitset.
+        */
+       bitset_size = dm_round_up(region_count,
+                                 sizeof(*clog->clean_bits) << BYTE_SHIFT);
+       bitset_size >>= BYTE_SHIFT;
+
        clog->clean_bits = vmalloc(bitset_size);
        if (!clog->clean_bits) {
                DMWARN("couldn't allocate clean bitset");
index bbf7d3ca9bc1d27acf26d9bf3cbc3b9dcefcda08..a3d864249b92b1dcf233626720212dccdce97917 100644 (file)
@@ -17,7 +17,6 @@
 #define NODE_SIZE L1_CACHE_BYTES
 #define KEYS_PER_NODE (NODE_SIZE / sizeof(sector_t))
 #define CHILDREN_PER_NODE (KEYS_PER_NODE + 1)
-#define MAX_TARGET_ARGS 64
 
 struct dm_table {
        atomic_t holders;
@@ -113,40 +112,7 @@ static int setup_btree_index(unsigned int l, struct dm_table *t)
        return 0;
 }
 
-/*
- * highs, and targets are managed as dynamic arrays during a
- * table load.
- */
-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.
-        */
-       n_highs = (sector_t *) vcalloc(sizeof(struct dm_target) +
-                                      sizeof(sector_t), num);
-       if (!n_highs)
-               return -ENOMEM;
 
-       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));
-       vfree(t->highs);
-
-       t->num_allocated = num;
-       t->highs = n_highs;
-       t->targets = n_targets;
-
-       return 0;
-}
 
 int dm_table_create(struct dm_table **result, int mode, unsigned num_targets)
 {
@@ -159,15 +125,20 @@ int dm_table_create(struct dm_table **result, int mode, unsigned num_targets)
        INIT_LIST_HEAD(&t->devices);
        atomic_set(&t->holders, 1);
 
-       if (!num_targets)
-               num_targets = KEYS_PER_NODE;
+       num_targets = dm_round_up(num_targets, KEYS_PER_NODE);
 
-       if (alloc_targets(t, num_targets)) {
+       /* Allocate both the target array and offset array at once. */
+       t->highs = (sector_t *) vcalloc(sizeof(struct dm_target) +
+                                       sizeof(sector_t), num_targets);
+       if (!t->highs) {
                kfree(t);
-               t = NULL;
                return -ENOMEM;
        }
 
+       memset(t->highs, -1, sizeof(*t->highs) * num_targets);
+
+       t->targets = (struct dm_target *) (t->highs + num_targets);
+       t->num_allocated = num_targets;
        t->mode = mode;
        *result = t;
        return 0;
@@ -226,17 +197,6 @@ void dm_table_put(struct dm_table *t)
                table_destroy(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;
-}
-
 /*
  * Convert a device path to a dev_t.
  */
@@ -443,17 +403,35 @@ static int adjoin(struct dm_table *table, struct dm_target *ti)
        return (ti->begin == (prev->begin + prev->len));
 }
 
+/*
+ * Used to dynamically allocate the arg array.
+ */
+static char **realloc_argv(unsigned *array_size, char **old_argv)
+{
+       char **argv;
+       unsigned new_size;
+
+       new_size = *array_size ? *array_size * 2 : 64;
+       argv = kmalloc(new_size * sizeof(*argv), GFP_NOIO);
+       if (argv) {
+               memcpy(argv, old_argv, *array_size * sizeof(*argv));
+               *array_size = new_size;
+       }
+
+       kfree(old_argv);
+       return argv;
+}
+
 /*
  * Destructively splits up the argument list to pass to ctr.
  */
 static int split_args(int *argc, char ***argvp, char *input)
 {
-       char *start, *end = input, *out;
-       char **argv;
-       int max_args = MAX_TARGET_ARGS;
+       char *start, *end = input, *out, **argv = NULL;
+       unsigned array_size = 0;
 
        *argc = 0;
-       argv = kmalloc(sizeof(*argv) * max_args, GFP_NOIO);
+       argv = realloc_argv(&array_size, argv);
        if (!argv)
                return -ENOMEM;
 
@@ -484,19 +462,10 @@ static int split_args(int *argc, char ***argvp, char *input)
                }
 
                /* have we already filled the array ? */
-               if ((*argc + 1) > max_args) {
-                       char **argv2;
-                       
-                       max_args *= 2;
-                       argv2 = kmalloc(sizeof(*argv2) * max_args, GFP_NOIO);
-                       if (!argv2) {
-                               kfree(argv);
+               if ((*argc + 1) > array_size) {
+                       argv = realloc_argv(&array_size, argv);
+                       if (!argv)
                                return -ENOMEM;
-                       }
-
-                       memcpy(argv2, argv, sizeof(*argv) * *argc);
-                       kfree(argv);
-                       argv = argv2;
                }
 
                /* we know this is whitespace */
@@ -520,8 +489,8 @@ int dm_table_add_target(struct dm_table *t, const char *type,
        char **argv;
        struct dm_target *tgt;
 
-       if ((r = check_space(t)))
-               return r;
+       if (t->num_targets >= t->num_allocated)
+               return -ENOMEM;
 
        tgt = t->targets + t->num_targets;
        memset(tgt, 0, sizeof(*tgt));
index bcbfb8e1dea4bcbd8928e26b09439a771848e6a9..5b7653f6b1adcbcffbffe84291d978f21d6af240 100644 (file)
 
 static struct dm_daemon _kcopyd;
 
+#define SECTORS_PER_PAGE (PAGE_SIZE / SECTOR_SIZE)
+#define SUB_JOB_SIZE 128
+#define PAGES_PER_SUB_JOB (SUB_JOB_SIZE / SECTORS_PER_PAGE)
+#define SUB_JOB_COUNT 8
+
 /*-----------------------------------------------------------------
  * Each kcopyd client has its own little pool of preallocated
  * pages for kcopyd io.
@@ -38,6 +43,7 @@ struct kcopyd_client {
        struct list_head pages;
        unsigned int nr_pages;
        unsigned int nr_free_pages;
+       unsigned int max_split;
 };
 
 static inline void __push_page(struct kcopyd_client *kc, struct page *p)
@@ -122,6 +128,10 @@ static int client_alloc_pages(struct kcopyd_client *kc, unsigned int nr)
 
        kcopyd_put_pages(kc, &new);
        kc->nr_pages += nr;
+       kc->max_split = kc->nr_pages / PAGES_PER_SUB_JOB;
+       if (kc->max_split > SUB_JOB_COUNT)
+               kc->max_split = SUB_JOB_COUNT;
+
        return 0;
 }
 
@@ -334,7 +344,6 @@ static int run_io_job(struct kcopyd_job *job)
        return r;
 }
 
-#define SECTORS_PER_PAGE (PAGE_SIZE / SECTOR_SIZE)
 static int run_pages_job(struct kcopyd_job *job)
 {
        int r;
@@ -422,7 +431,6 @@ static void dispatch_job(struct kcopyd_job *job)
        dm_daemon_wake(&_kcopyd);
 }
 
-#define SUB_JOB_SIZE 128
 static void segment_complete(int read_err,
                             unsigned int write_err, void *context)
 {
@@ -491,17 +499,19 @@ static void segment_complete(int read_err,
  * Create some little jobs that will do the move between
  * them.
  */
-#define SPLIT_COUNT 8
 static void split_job(struct kcopyd_job *job)
 {
-       int i;
+       int nr;
+
+       nr = dm_div_up(job->source.count, SUB_JOB_SIZE);
+       if (nr > job->kc->max_split)
+               nr = job->kc->max_split;
 
-       atomic_set(&job->sub_jobs, SPLIT_COUNT);
-       for (i = 0; i < SPLIT_COUNT; i++)
+       atomic_set(&job->sub_jobs, nr);
+       while (nr--)
                segment_complete(0, 0u, job);
 }
 
-#define SUB_JOB_THRESHOLD (SPLIT_COUNT * SUB_JOB_SIZE)
 int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
                unsigned int num_dests, struct io_region *dests,
                unsigned int flags, kcopyd_notify_fn fn, void *context)
@@ -534,7 +544,7 @@ int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
        job->fn = fn;
        job->context = context;
 
-       if (job->source.count < SUB_JOB_THRESHOLD)
+       if (job->source.count < SUB_JOB_SIZE)
                dispatch_job(job);
 
        else {
@@ -582,9 +592,9 @@ int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result)
        int r = 0;
        struct kcopyd_client *kc;
 
-       if (nr_pages * SECTORS_PER_PAGE < SUB_JOB_SIZE * SPLIT_COUNT) {
+       if (nr_pages * SECTORS_PER_PAGE < SUB_JOB_SIZE) {
                DMERR("kcopyd client requested %u pages: minimum is %lu",
-                     nr_pages, SUB_JOB_SIZE * SPLIT_COUNT / SECTORS_PER_PAGE);
+                     nr_pages, SUB_JOB_SIZE / SECTORS_PER_PAGE);
                return -ENOMEM;
        }
 
index 42d26df71bd1c9a8a2ccab6957159c2d8db09b5c..9f1ea41968b4d941a605a3a5786d74707855810e 100644 (file)
@@ -698,6 +698,113 @@ static int dev_status(struct dm_ioctl *param, size_t param_size)
        return r;
 }
 
+/*
+ * Build up the status struct for each target
+ */
+static void retrieve_status(struct dm_table *table, struct dm_ioctl *param,
+                           size_t param_size)
+{
+       unsigned int i, num_targets;
+       struct dm_target_spec *spec;
+       char *outbuf, *outptr;
+       status_type_t type;
+       size_t remaining, len, used = 0;
+
+       outptr = outbuf = get_result_buffer(param, param_size, &len);
+
+       if (param->flags & DM_STATUS_TABLE_FLAG)
+               type = STATUSTYPE_TABLE;
+       else
+               type = STATUSTYPE_INFO;
+
+       /* Get all the target info */
+       num_targets = dm_table_get_num_targets(table);
+       for (i = 0; i < num_targets; i++) {
+               struct dm_target *ti = dm_table_get_target(table, i);
+
+               remaining = len - (outptr - outbuf);
+               if (remaining < sizeof(struct dm_target_spec)) {
+                       param->flags |= DM_BUFFER_FULL_FLAG;
+                       break;
+               }
+
+               spec = (struct dm_target_spec *) outptr;
+
+               spec->status = 0;
+               spec->sector_start = ti->begin;
+               spec->length = ti->len;
+               strncpy(spec->target_type, ti->type->name,
+                       sizeof(spec->target_type));
+
+               outptr += sizeof(struct dm_target_spec);
+               remaining = len - (outptr - outbuf);
+
+               /* Get the status/table string from the target driver */
+               if (ti->type->status) {
+                       if (ti->type->status(ti, type, outptr, remaining)) {
+                               param->flags |= DM_BUFFER_FULL_FLAG;
+                               break;
+                       }
+               } else
+                       outptr[0] = '\0';
+
+               outptr += strlen(outptr) + 1;
+               used = param->data_start + (outptr - outbuf);
+
+               align_ptr(outptr);
+               spec->next = outptr - outbuf;
+       }
+
+       if (used)
+               param->data_size = used;
+
+       param->target_count = num_targets;
+}
+
+/*
+ * Wait for a device to report an event
+ */
+static int dev_wait(struct dm_ioctl *param, size_t param_size)
+{
+       int r;
+       struct mapped_device *md;
+       struct dm_table *table;
+       DECLARE_WAITQUEUE(wq, current);
+
+       md = find_device(param);
+       if (!md)
+               return -ENXIO;
+
+       /*
+        * Wait for a notification event
+        */
+       set_current_state(TASK_INTERRUPTIBLE);
+       if (!dm_add_wait_queue(md, &wq, param->event_nr)) {
+               schedule();
+               dm_remove_wait_queue(md, &wq);
+       }
+       set_current_state(TASK_RUNNING);
+
+       /*
+        * The userland program is going to want to know what
+        * changed to trigger the event, so we may as well tell
+        * him and save an ioctl.
+        */
+       r = __dev_status(md, param);
+       if (r)
+               goto out;
+
+       table = dm_get_table(md);
+       if (table) {
+               retrieve_status(table, param, param_size);
+               dm_table_put(table);
+       }
+
+ out:
+       dm_put(md);
+       return r;
+}
+
 static inline int get_mode(struct dm_ioctl *param)
 {
        int mode = FMODE_READ | FMODE_WRITE;
@@ -884,69 +991,6 @@ static int table_deps(struct dm_ioctl *param, size_t param_size)
        return r;
 }
 
-/*
- * Build up the status struct for each target
- */
-static void retrieve_status(struct dm_table *table, struct dm_ioctl *param,
-                           size_t param_size)
-{
-       unsigned int i, num_targets;
-       struct dm_target_spec *spec;
-       char *outbuf, *outptr;
-       status_type_t type;
-       size_t remaining, len, used = 0;
-
-       outptr = outbuf = get_result_buffer(param, param_size, &len);
-
-       if (param->flags & DM_STATUS_TABLE_FLAG)
-               type = STATUSTYPE_TABLE;
-       else
-               type = STATUSTYPE_INFO;
-
-       /* Get all the target info */
-       num_targets = dm_table_get_num_targets(table);
-       for (i = 0; i < num_targets; i++) {
-               struct dm_target *ti = dm_table_get_target(table, i);
-
-               remaining = len - (outptr - outbuf);
-               if (remaining < sizeof(struct dm_target_spec)) {
-                       param->flags |= DM_BUFFER_FULL_FLAG;
-                       break;
-               }
-
-               spec = (struct dm_target_spec *) outptr;
-
-               spec->status = 0;
-               spec->sector_start = ti->begin;
-               spec->length = ti->len;
-               strncpy(spec->target_type, ti->type->name,
-                       sizeof(spec->target_type));
-
-               outptr += sizeof(struct dm_target_spec);
-               remaining = len - (outptr - outbuf);
-
-               /* Get the status/table string from the target driver */
-               if (ti->type->status) {
-                       if (ti->type->status(ti, type, outptr, remaining)) {
-                               param->flags |= DM_BUFFER_FULL_FLAG;
-                               break;
-                       }
-               } else
-                       outptr[0] = '\0';
-
-               outptr += strlen(outptr) + 1;
-               used = param->data_start + (outptr - outbuf);
-
-               align_ptr(outptr);
-               spec->next = outptr - outbuf;
-       }
-
-       if (used)
-               param->data_size = used;
-
-       param->target_count = num_targets;
-}
-
 /*
  * Return the status of a device as a text string for each
  * target.
@@ -976,50 +1020,6 @@ static int table_status(struct dm_ioctl *param, size_t param_size)
        return r;
 }
 
-/*
- * Wait for a device to report an event
- */
-static int dev_wait(struct dm_ioctl *param, size_t param_size)
-{
-       int r;
-       struct mapped_device *md;
-       struct dm_table *table;
-       DECLARE_WAITQUEUE(wq, current);
-
-       md = find_device(param);
-       if (!md)
-               return -ENXIO;
-
-       /*
-        * Wait for a notification event
-        */
-       set_current_state(TASK_INTERRUPTIBLE);
-       if (!dm_add_wait_queue(md, &wq, param->event_nr)) {
-               schedule();
-               dm_remove_wait_queue(md, &wq);
-       }
-       set_current_state(TASK_RUNNING);
-
-       /*
-        * The userland program is going to want to know what
-        * changed to trigger the event, so we may as well tell
-        * him and save an ioctl.
-        */
-       r = __dev_status(md, param);
-       if (r)
-               goto out;
-
-       table = dm_get_table(md);
-       if (table) {
-               retrieve_status(table, param, param_size);
-               dm_table_put(table);
-       }
-
- out:
-       dm_put(md);
-       return r;
-}
-
 /*-----------------------------------------------------------------
  * Implementation of open/close/ioctl on the special char
  * device.
index 552c554c07ceea85742a6687065029aa6d8e94ca..7487d36ae5d770a5a4981eef98a786666aae1501 100644 (file)
@@ -207,8 +207,8 @@ enum {
 
 #define DM_VERSION_MAJOR       4
 #define DM_VERSION_MINOR       0
-#define DM_VERSION_PATCHLEVEL  4
-#define DM_VERSION_EXTRA       "-ioctl-cvs (2003-08-30)"
+#define DM_VERSION_PATCHLEVEL  5
+#define DM_VERSION_EXTRA       "-ioctl-cvs (2003-11-18)"
 
 /* Status bits */
 #define DM_READONLY_FLAG       (1 << 0) /* In/Out */
This page took 0.041895 seconds and 5 git commands to generate.