]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/md/dm-cache-target.c
Merge branch 'late/clksrc' into late/cleanup
[karo-tx-linux.git] / drivers / md / dm-cache-target.c
index 66120bd46d15639613cdeaf09b4474db48550845..10744091e6cabb5f6bb55e59709eb4ba0350a98b 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "dm.h"
 #include "dm-bio-prison.h"
+#include "dm-bio-record.h"
 #include "dm-cache-metadata.h"
 
 #include <linux/dm-io.h>
@@ -201,10 +202,15 @@ struct per_bio_data {
        unsigned req_nr:2;
        struct dm_deferred_entry *all_io_entry;
 
-       /* writethrough fields */
+       /*
+        * writethrough fields.  These MUST remain at the end of this
+        * structure and the 'cache' member must be the first as it
+        * is used to determine the offsetof the writethrough fields.
+        */
        struct cache *cache;
        dm_cblock_t cblock;
        bio_end_io_t *saved_bi_end_io;
+       struct dm_bio_details bio_details;
 };
 
 struct dm_cache_migration {
@@ -513,16 +519,28 @@ static void save_stats(struct cache *cache)
 /*----------------------------------------------------------------
  * Per bio data
  *--------------------------------------------------------------*/
-static struct per_bio_data *get_per_bio_data(struct bio *bio)
+
+/*
+ * If using writeback, leave out struct per_bio_data's writethrough fields.
+ */
+#define PB_DATA_SIZE_WB (offsetof(struct per_bio_data, cache))
+#define PB_DATA_SIZE_WT (sizeof(struct per_bio_data))
+
+static size_t get_per_bio_data_size(struct cache *cache)
+{
+       return cache->features.write_through ? PB_DATA_SIZE_WT : PB_DATA_SIZE_WB;
+}
+
+static struct per_bio_data *get_per_bio_data(struct bio *bio, size_t data_size)
 {
-       struct per_bio_data *pb = dm_per_bio_data(bio, sizeof(struct per_bio_data));
+       struct per_bio_data *pb = dm_per_bio_data(bio, data_size);
        BUG_ON(!pb);
        return pb;
 }
 
-static struct per_bio_data *init_per_bio_data(struct bio *bio)
+static struct per_bio_data *init_per_bio_data(struct bio *bio, size_t data_size)
 {
-       struct per_bio_data *pb = get_per_bio_data(bio);
+       struct per_bio_data *pb = get_per_bio_data(bio, data_size);
 
        pb->tick = false;
        pb->req_nr = dm_bio_get_target_bio_nr(bio);
@@ -556,7 +574,8 @@ static void remap_to_cache(struct cache *cache, struct bio *bio,
 static void check_if_tick_bio_needed(struct cache *cache, struct bio *bio)
 {
        unsigned long flags;
-       struct per_bio_data *pb = get_per_bio_data(bio);
+       size_t pb_data_size = get_per_bio_data_size(cache);
+       struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
 
        spin_lock_irqsave(&cache->lock, flags);
        if (cache->need_tick_bio &&
@@ -635,7 +654,7 @@ static void defer_writethrough_bio(struct cache *cache, struct bio *bio)
 
 static void writethrough_endio(struct bio *bio, int err)
 {
-       struct per_bio_data *pb = get_per_bio_data(bio);
+       struct per_bio_data *pb = get_per_bio_data(bio, PB_DATA_SIZE_WT);
        bio->bi_end_io = pb->saved_bi_end_io;
 
        if (err) {
@@ -643,6 +662,7 @@ static void writethrough_endio(struct bio *bio, int err)
                return;
        }
 
+       dm_bio_restore(&pb->bio_details, bio);
        remap_to_cache(pb->cache, bio, pb->cblock);
 
        /*
@@ -662,11 +682,12 @@ static void writethrough_endio(struct bio *bio, int err)
 static void remap_to_origin_then_cache(struct cache *cache, struct bio *bio,
                                       dm_oblock_t oblock, dm_cblock_t cblock)
 {
-       struct per_bio_data *pb = get_per_bio_data(bio);
+       struct per_bio_data *pb = get_per_bio_data(bio, PB_DATA_SIZE_WT);
 
        pb->cache = cache;
        pb->cblock = cblock;
        pb->saved_bi_end_io = bio->bi_end_io;
+       dm_bio_record(&pb->bio_details, bio);
        bio->bi_end_io = writethrough_endio;
 
        remap_to_origin_clear_discard(pb->cache, bio, oblock);
@@ -1035,7 +1056,8 @@ static void defer_bio(struct cache *cache, struct bio *bio)
 
 static void process_flush_bio(struct cache *cache, struct bio *bio)
 {
-       struct per_bio_data *pb = get_per_bio_data(bio);
+       size_t pb_data_size = get_per_bio_data_size(cache);
+       struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
 
        BUG_ON(bio->bi_size);
        if (!pb->req_nr)
@@ -1107,7 +1129,8 @@ static void process_bio(struct cache *cache, struct prealloc *structs,
        dm_oblock_t block = get_bio_block(cache, bio);
        struct dm_bio_prison_cell *cell_prealloc, *old_ocell, *new_ocell;
        struct policy_result lookup_result;
-       struct per_bio_data *pb = get_per_bio_data(bio);
+       size_t pb_data_size = get_per_bio_data_size(cache);
+       struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
        bool discarded_block = is_discarded_oblock(cache, block);
        bool can_migrate = discarded_block || spare_migration_bandwidth(cache);
 
@@ -1881,7 +1904,6 @@ static int cache_create(struct cache_args *ca, struct cache **result)
 
        cache->ti = ca->ti;
        ti->private = cache;
-       ti->per_bio_data_size = sizeof(struct per_bio_data);
        ti->num_flush_bios = 2;
        ti->flush_supported = true;
 
@@ -1890,6 +1912,7 @@ static int cache_create(struct cache_args *ca, struct cache **result)
        ti->discard_zeroes_data_unsupported = true;
 
        memcpy(&cache->features, &ca->features, sizeof(cache->features));
+       ti->per_bio_data_size = get_per_bio_data_size(cache);
 
        cache->callbacks.congested_fn = cache_is_congested;
        dm_table_add_target_callbacks(ti->table, &cache->callbacks);
@@ -2092,6 +2115,7 @@ static int cache_map(struct dm_target *ti, struct bio *bio)
 
        int r;
        dm_oblock_t block = get_bio_block(cache, bio);
+       size_t pb_data_size = get_per_bio_data_size(cache);
        bool can_migrate = false;
        bool discarded_block;
        struct dm_bio_prison_cell *cell;
@@ -2108,7 +2132,7 @@ static int cache_map(struct dm_target *ti, struct bio *bio)
                return DM_MAPIO_REMAPPED;
        }
 
-       pb = init_per_bio_data(bio);
+       pb = init_per_bio_data(bio, pb_data_size);
 
        if (bio->bi_rw & (REQ_FLUSH | REQ_FUA | REQ_DISCARD)) {
                defer_bio(cache, bio);
@@ -2193,7 +2217,8 @@ static int cache_end_io(struct dm_target *ti, struct bio *bio, int error)
 {
        struct cache *cache = ti->private;
        unsigned long flags;
-       struct per_bio_data *pb = get_per_bio_data(bio);
+       size_t pb_data_size = get_per_bio_data_size(cache);
+       struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
 
        if (pb->tick) {
                policy_tick(cache->policy);