wc_entry.index removed: This can be computed by pointer arithmetic without 
storage.
wc_entry.age reduced to 32 bits: It only needs to be big enough to hold 
max_age, which is limited to well below 32-bit range.

Reduces wc_entry size from 56 bytes to 48 bytes (from 72 to 64 bytes if 
DM_WRITECACHE_HANDLE_HARDWARE_ERRORS enabled).

Signed-off-by: Henry Wong <[email protected]>
---
 drivers/md/dm-writecache.c | 39 ++++++++++++++++++--------------------
 1 file changed, 18 insertions(+), 21 deletions(-)

diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c
index 978646f71f99..68e3fb300fc1 100644
--- a/drivers/md/dm-writecache.c
+++ b/drivers/md/dm-writecache.c
@@ -81,15 +81,9 @@ struct wc_memory_superblock {
 struct wc_entry {
        struct rb_node rb_node;
        struct list_head lru;
+       u32 age; // jiffies
        unsigned short wc_list_contiguous;
-#if BITS_PER_LONG == 64
-       bool write_in_progress : 1;
-       unsigned long index : 47;
-#else
        bool write_in_progress;
-       unsigned long index;
-#endif
-       unsigned long age;
 #ifdef DM_WRITECACHE_HANDLE_HARDWARE_ERRORS
        uint64_t original_sector;
        uint64_t seq_count;
@@ -389,20 +383,28 @@ static struct wc_memory_superblock *sb(struct 
dm_writecache *wc)
        return wc->memory_map;
 }
 
+static inline unsigned long wc_entry_index(const struct wc_entry *base, const 
struct wc_entry *entry)
+{
+       return entry - base;
+}
+
 static struct wc_memory_entry *memory_entry(struct dm_writecache *wc, struct 
wc_entry *e)
 {
-       return &sb(wc)->entries[e->index];
+       const unsigned long index = wc_entry_index(wc->entries, e);
+       return &sb(wc)->entries[index];
 }
 
 static void *memory_data(struct dm_writecache *wc, struct wc_entry *e)
 {
-       return (char *)wc->block_start + (e->index << wc->block_size_bits);
+       const unsigned long index = wc_entry_index(wc->entries, e);
+       return (char *)wc->block_start + (index << wc->block_size_bits);
 }
 
 static sector_t cache_sector(struct dm_writecache *wc, struct wc_entry *e)
 {
+       const unsigned long index = wc_entry_index(wc->entries, e);
        return wc->start_sector + wc->metadata_sectors +
-               ((sector_t)e->index << (wc->block_size_bits - SECTOR_SHIFT));
+               ((sector_t)index << (wc->block_size_bits - SECTOR_SHIFT));
 }
 
 static uint64_t read_original_sector(struct dm_writecache *wc, struct wc_entry 
*e)
@@ -668,7 +670,7 @@ static void writecache_insert_entry(struct dm_writecache 
*wc, struct wc_entry *i
        rb_link_node(&ins->rb_node, parent, node);
        rb_insert_color(&ins->rb_node, &wc->tree);
        list_add(&ins->lru, &wc->lru);
-       ins->age = jiffies;
+       ins->age = (u32)jiffies;
 }
 
 static void writecache_unlink(struct dm_writecache *wc, struct wc_entry *e)
@@ -969,7 +971,6 @@ static int writecache_alloc_entries(struct dm_writecache 
*wc)
        for (b = 0; b < wc->n_blocks; b++) {
                struct wc_entry *e = &wc->entries[b];
 
-               e->index = b;
                e->write_in_progress = false;
                cond_resched();
        }
@@ -1986,7 +1987,7 @@ static void writecache_writeback(struct work_struct *work)
        while (!list_empty(&wc->lru) &&
               (wc->writeback_all ||
                wc->freelist_size + wc->writeback_size <= 
wc->freelist_low_watermark ||
-               (jiffies - container_of(wc->lru.prev, struct wc_entry, 
lru)->age >=
+               ((u32)(jiffies - container_of(wc->lru.prev, struct wc_entry, 
lru)->age) >=
                 wc->max_age - wc->max_age / MAX_AGE_DIV))) {
 
                n_walked++;
@@ -2107,7 +2108,6 @@ static int calculate_memory_size(uint64_t device_size, 
unsigned int block_size,
                                 size_t *n_blocks_p, size_t 
*n_metadata_blocks_p)
 {
        uint64_t n_blocks, offset;
-       struct wc_entry e;
 
        n_blocks = device_size;
        do_div(n_blocks, block_size + sizeof(struct wc_memory_entry));
@@ -2126,11 +2126,6 @@ static int calculate_memory_size(uint64_t device_size, 
unsigned int block_size,
                n_blocks--;
        }
 
-       /* check if the bit field overflows */
-       e.index = n_blocks;
-       if (e.index != n_blocks)
-               return -EFBIG;
-
        if (n_blocks_p)
                *n_blocks_p = n_blocks;
        if (n_metadata_blocks_p)
@@ -2444,13 +2439,15 @@ static int writecache_ctr(struct dm_target *ti, 
unsigned int argc, char **argv)
                        wc->autocommit_time_set = true;
                } else if (!strcasecmp(string, "max_age") && opt_params >= 1) {
                        unsigned int max_age_msecs;
+                       unsigned long max_age_jiffies;
 
                        string = dm_shift_arg(&as), opt_params--;
                        if (sscanf(string, "%u%c", &max_age_msecs, &dummy) != 1)
                                goto invalid_optional;
-                       if (max_age_msecs > 86400000)
+                       max_age_jiffies = msecs_to_jiffies(max_age_msecs);
+                       if (max_age_jiffies >= min(MAX_JIFFY_OFFSET, (7 << 
28))) // 7/8ths of 1 << 31
                                goto invalid_optional;
-                       wc->max_age = msecs_to_jiffies(max_age_msecs);
+                       wc->max_age = max_age_jiffies;
                        wc->max_age_set = true;
                        wc->max_age_value = max_age_msecs;
                } else if (!strcasecmp(string, "cleaner")) {
-- 
2.52.0


Reply via email to