gpio: mvebu: Don't free chip label memory
[cascardo/linux.git] / drivers / md / dm-snap.c
index a143921..59fc18a 100644 (file)
@@ -79,7 +79,6 @@ struct dm_snapshot {
 
        /* Chunks with outstanding reads */
        spinlock_t tracked_chunk_lock;
-       mempool_t *tracked_chunk_pool;
        struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE];
 
        /* The on disk metadata handler */
@@ -191,35 +190,38 @@ struct dm_snap_tracked_chunk {
        chunk_t chunk;
 };
 
-static struct kmem_cache *tracked_chunk_cache;
+static void init_tracked_chunk(struct bio *bio)
+{
+       struct dm_snap_tracked_chunk *c = dm_per_bio_data(bio, sizeof(struct dm_snap_tracked_chunk));
+       INIT_HLIST_NODE(&c->node);
+}
 
-static struct dm_snap_tracked_chunk *track_chunk(struct dm_snapshot *s,
-                                                chunk_t chunk)
+static bool is_bio_tracked(struct bio *bio)
 {
-       struct dm_snap_tracked_chunk *c = mempool_alloc(s->tracked_chunk_pool,
-                                                       GFP_NOIO);
-       unsigned long flags;
+       struct dm_snap_tracked_chunk *c = dm_per_bio_data(bio, sizeof(struct dm_snap_tracked_chunk));
+       return !hlist_unhashed(&c->node);
+}
+
+static void track_chunk(struct dm_snapshot *s, struct bio *bio, chunk_t chunk)
+{
+       struct dm_snap_tracked_chunk *c = dm_per_bio_data(bio, sizeof(struct dm_snap_tracked_chunk));
 
        c->chunk = chunk;
 
-       spin_lock_irqsave(&s->tracked_chunk_lock, flags);
+       spin_lock_irq(&s->tracked_chunk_lock);
        hlist_add_head(&c->node,
                       &s->tracked_chunk_hash[DM_TRACKED_CHUNK_HASH(chunk)]);
-       spin_unlock_irqrestore(&s->tracked_chunk_lock, flags);
-
-       return c;
+       spin_unlock_irq(&s->tracked_chunk_lock);
 }
 
-static void stop_tracking_chunk(struct dm_snapshot *s,
-                               struct dm_snap_tracked_chunk *c)
+static void stop_tracking_chunk(struct dm_snapshot *s, struct bio *bio)
 {
+       struct dm_snap_tracked_chunk *c = dm_per_bio_data(bio, sizeof(struct dm_snap_tracked_chunk));
        unsigned long flags;
 
        spin_lock_irqsave(&s->tracked_chunk_lock, flags);
        hlist_del(&c->node);
        spin_unlock_irqrestore(&s->tracked_chunk_lock, flags);
-
-       mempool_free(c, s->tracked_chunk_pool);
 }
 
 static int __chunk_is_tracked(struct dm_snapshot *s, chunk_t chunk)
@@ -1120,14 +1122,6 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                goto bad_pending_pool;
        }
 
-       s->tracked_chunk_pool = mempool_create_slab_pool(MIN_IOS,
-                                                        tracked_chunk_cache);
-       if (!s->tracked_chunk_pool) {
-               ti->error = "Could not allocate tracked_chunk mempool for "
-                           "tracking reads";
-               goto bad_tracked_chunk_pool;
-       }
-
        for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++)
                INIT_HLIST_HEAD(&s->tracked_chunk_hash[i]);
 
@@ -1135,6 +1129,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
        ti->private = s;
        ti->num_flush_requests = num_flush_requests;
+       ti->per_bio_data_size = sizeof(struct dm_snap_tracked_chunk);
 
        /* Add snapshot to the list of snapshots for this origin */
        /* Exceptions aren't triggered till snapshot_resume() is called */
@@ -1183,9 +1178,6 @@ bad_read_metadata:
        unregister_snapshot(s);
 
 bad_load_and_register:
-       mempool_destroy(s->tracked_chunk_pool);
-
-bad_tracked_chunk_pool:
        mempool_destroy(s->pending_pool);
 
 bad_pending_pool:
@@ -1290,8 +1282,6 @@ static void snapshot_dtr(struct dm_target *ti)
                BUG_ON(!hlist_empty(&s->tracked_chunk_hash[i]));
 #endif
 
-       mempool_destroy(s->tracked_chunk_pool);
-
        __free_exceptions(s);
 
        mempool_destroy(s->pending_pool);
@@ -1577,8 +1567,7 @@ static void remap_exception(struct dm_snapshot *s, struct dm_exception *e,
                                          s->store->chunk_mask);
 }
 
-static int snapshot_map(struct dm_target *ti, struct bio *bio,
-                       union map_info *map_context)
+static int snapshot_map(struct dm_target *ti, struct bio *bio)
 {
        struct dm_exception *e;
        struct dm_snapshot *s = ti->private;
@@ -1586,6 +1575,8 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
        chunk_t chunk;
        struct dm_snap_pending_exception *pe = NULL;
 
+       init_tracked_chunk(bio);
+
        if (bio->bi_rw & REQ_FLUSH) {
                bio->bi_bdev = s->cow->bdev;
                return DM_MAPIO_REMAPPED;
@@ -1670,7 +1661,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
                }
        } else {
                bio->bi_bdev = s->origin->bdev;
-               map_context->ptr = track_chunk(s, chunk);
+               track_chunk(s, bio, chunk);
        }
 
 out_unlock:
@@ -1691,20 +1682,20 @@ out:
  * If merging is currently taking place on the chunk in question, the
  * I/O is deferred by adding it to s->bios_queued_during_merge.
  */
-static int snapshot_merge_map(struct dm_target *ti, struct bio *bio,
-                             union map_info *map_context)
+static int snapshot_merge_map(struct dm_target *ti, struct bio *bio)
 {
        struct dm_exception *e;
        struct dm_snapshot *s = ti->private;
        int r = DM_MAPIO_REMAPPED;
        chunk_t chunk;
 
+       init_tracked_chunk(bio);
+
        if (bio->bi_rw & REQ_FLUSH) {
-               if (!map_context->target_request_nr)
+               if (!dm_bio_get_target_request_nr(bio))
                        bio->bi_bdev = s->origin->bdev;
                else
                        bio->bi_bdev = s->cow->bdev;
-               map_context->ptr = NULL;
                return DM_MAPIO_REMAPPED;
        }
 
@@ -1733,7 +1724,7 @@ static int snapshot_merge_map(struct dm_target *ti, struct bio *bio,
                remap_exception(s, e, bio, chunk);
 
                if (bio_rw(bio) == WRITE)
-                       map_context->ptr = track_chunk(s, chunk);
+                       track_chunk(s, bio, chunk);
                goto out_unlock;
        }
 
@@ -1751,14 +1742,12 @@ out_unlock:
        return r;
 }
 
-static int snapshot_end_io(struct dm_target *ti, struct bio *bio,
-                          int error, union map_info *map_context)
+static int snapshot_end_io(struct dm_target *ti, struct bio *bio, int error)
 {
        struct dm_snapshot *s = ti->private;
-       struct dm_snap_tracked_chunk *c = map_context->ptr;
 
-       if (c)
-               stop_tracking_chunk(s, c);
+       if (is_bio_tracked(bio))
+               stop_tracking_chunk(s, bio);
 
        return 0;
 }
@@ -2127,8 +2116,7 @@ static void origin_dtr(struct dm_target *ti)
        dm_put_device(ti, dev);
 }
 
-static int origin_map(struct dm_target *ti, struct bio *bio,
-                     union map_info *map_context)
+static int origin_map(struct dm_target *ti, struct bio *bio)
 {
        struct dm_dev *dev = ti->private;
        bio->bi_bdev = dev->bdev;
@@ -2193,7 +2181,7 @@ static int origin_iterate_devices(struct dm_target *ti,
 
 static struct target_type origin_target = {
        .name    = "snapshot-origin",
-       .version = {1, 7, 1},
+       .version = {1, 8, 0},
        .module  = THIS_MODULE,
        .ctr     = origin_ctr,
        .dtr     = origin_dtr,
@@ -2206,7 +2194,7 @@ static struct target_type origin_target = {
 
 static struct target_type snapshot_target = {
        .name    = "snapshot",
-       .version = {1, 10, 0},
+       .version = {1, 11, 0},
        .module  = THIS_MODULE,
        .ctr     = snapshot_ctr,
        .dtr     = snapshot_dtr,
@@ -2220,7 +2208,7 @@ static struct target_type snapshot_target = {
 
 static struct target_type merge_target = {
        .name    = dm_snapshot_merge_target_name,
-       .version = {1, 1, 0},
+       .version = {1, 2, 0},
        .module  = THIS_MODULE,
        .ctr     = snapshot_ctr,
        .dtr     = snapshot_dtr,
@@ -2281,17 +2269,8 @@ static int __init dm_snapshot_init(void)
                goto bad_pending_cache;
        }
 
-       tracked_chunk_cache = KMEM_CACHE(dm_snap_tracked_chunk, 0);
-       if (!tracked_chunk_cache) {
-               DMERR("Couldn't create cache to track chunks in use.");
-               r = -ENOMEM;
-               goto bad_tracked_chunk_cache;
-       }
-
        return 0;
 
-bad_tracked_chunk_cache:
-       kmem_cache_destroy(pending_cache);
 bad_pending_cache:
        kmem_cache_destroy(exception_cache);
 bad_exception_cache:
@@ -2317,7 +2296,6 @@ static void __exit dm_snapshot_exit(void)
        exit_origin_hash();
        kmem_cache_destroy(pending_cache);
        kmem_cache_destroy(exception_cache);
-       kmem_cache_destroy(tracked_chunk_cache);
 
        dm_exception_store_exit();
 }