148debafeSMikulas Patocka // SPDX-License-Identifier: GPL-2.0 248debafeSMikulas Patocka /* 348debafeSMikulas Patocka * Copyright (C) 2018 Red Hat. All rights reserved. 448debafeSMikulas Patocka * 548debafeSMikulas Patocka * This file is released under the GPL. 648debafeSMikulas Patocka */ 748debafeSMikulas Patocka 848debafeSMikulas Patocka #include <linux/device-mapper.h> 948debafeSMikulas Patocka #include <linux/module.h> 1048debafeSMikulas Patocka #include <linux/init.h> 1148debafeSMikulas Patocka #include <linux/vmalloc.h> 1248debafeSMikulas Patocka #include <linux/kthread.h> 1348debafeSMikulas Patocka #include <linux/dm-io.h> 1448debafeSMikulas Patocka #include <linux/dm-kcopyd.h> 1548debafeSMikulas Patocka #include <linux/dax.h> 1648debafeSMikulas Patocka #include <linux/pfn_t.h> 1748debafeSMikulas Patocka #include <linux/libnvdimm.h> 1848debafeSMikulas Patocka 1948debafeSMikulas Patocka #define DM_MSG_PREFIX "writecache" 2048debafeSMikulas Patocka 2148debafeSMikulas Patocka #define HIGH_WATERMARK 50 2248debafeSMikulas Patocka #define LOW_WATERMARK 45 2348debafeSMikulas Patocka #define MAX_WRITEBACK_JOBS 0 2448debafeSMikulas Patocka #define ENDIO_LATENCY 16 2548debafeSMikulas Patocka #define WRITEBACK_LATENCY 64 2648debafeSMikulas Patocka #define AUTOCOMMIT_BLOCKS_SSD 65536 2748debafeSMikulas Patocka #define AUTOCOMMIT_BLOCKS_PMEM 64 2848debafeSMikulas Patocka #define AUTOCOMMIT_MSEC 1000 2948debafeSMikulas Patocka 3048debafeSMikulas Patocka #define BITMAP_GRANULARITY 65536 3148debafeSMikulas Patocka #if BITMAP_GRANULARITY < PAGE_SIZE 3248debafeSMikulas Patocka #undef BITMAP_GRANULARITY 3348debafeSMikulas Patocka #define BITMAP_GRANULARITY PAGE_SIZE 3448debafeSMikulas Patocka #endif 3548debafeSMikulas Patocka 3648debafeSMikulas Patocka #if IS_ENABLED(CONFIG_ARCH_HAS_PMEM_API) && IS_ENABLED(CONFIG_DAX_DRIVER) 3748debafeSMikulas Patocka #define DM_WRITECACHE_HAS_PMEM 3848debafeSMikulas Patocka #endif 3948debafeSMikulas Patocka 4048debafeSMikulas Patocka #ifdef DM_WRITECACHE_HAS_PMEM 4148debafeSMikulas Patocka #define pmem_assign(dest, src) \ 4248debafeSMikulas Patocka do { \ 4348debafeSMikulas Patocka typeof(dest) uniq = (src); \ 4448debafeSMikulas Patocka memcpy_flushcache(&(dest), &uniq, sizeof(dest)); \ 4548debafeSMikulas Patocka } while (0) 4648debafeSMikulas Patocka #else 4748debafeSMikulas Patocka #define pmem_assign(dest, src) ((dest) = (src)) 4848debafeSMikulas Patocka #endif 4948debafeSMikulas Patocka 5048debafeSMikulas Patocka #if defined(__HAVE_ARCH_MEMCPY_MCSAFE) && defined(DM_WRITECACHE_HAS_PMEM) 5148debafeSMikulas Patocka #define DM_WRITECACHE_HANDLE_HARDWARE_ERRORS 5248debafeSMikulas Patocka #endif 5348debafeSMikulas Patocka 5448debafeSMikulas Patocka #define MEMORY_SUPERBLOCK_MAGIC 0x23489321 5548debafeSMikulas Patocka #define MEMORY_SUPERBLOCK_VERSION 1 5648debafeSMikulas Patocka 5748debafeSMikulas Patocka struct wc_memory_entry { 5848debafeSMikulas Patocka __le64 original_sector; 5948debafeSMikulas Patocka __le64 seq_count; 6048debafeSMikulas Patocka }; 6148debafeSMikulas Patocka 6248debafeSMikulas Patocka struct wc_memory_superblock { 6348debafeSMikulas Patocka union { 6448debafeSMikulas Patocka struct { 6548debafeSMikulas Patocka __le32 magic; 6648debafeSMikulas Patocka __le32 version; 6748debafeSMikulas Patocka __le32 block_size; 6848debafeSMikulas Patocka __le32 pad; 6948debafeSMikulas Patocka __le64 n_blocks; 7048debafeSMikulas Patocka __le64 seq_count; 7148debafeSMikulas Patocka }; 7248debafeSMikulas Patocka __le64 padding[8]; 7348debafeSMikulas Patocka }; 7448debafeSMikulas Patocka struct wc_memory_entry entries[0]; 7548debafeSMikulas Patocka }; 7648debafeSMikulas Patocka 7748debafeSMikulas Patocka struct wc_entry { 7848debafeSMikulas Patocka struct rb_node rb_node; 7948debafeSMikulas Patocka struct list_head lru; 8048debafeSMikulas Patocka unsigned short wc_list_contiguous; 8148debafeSMikulas Patocka bool write_in_progress 8248debafeSMikulas Patocka #if BITS_PER_LONG == 64 8348debafeSMikulas Patocka :1 8448debafeSMikulas Patocka #endif 8548debafeSMikulas Patocka ; 8648debafeSMikulas Patocka unsigned long index 8748debafeSMikulas Patocka #if BITS_PER_LONG == 64 8848debafeSMikulas Patocka :47 8948debafeSMikulas Patocka #endif 9048debafeSMikulas Patocka ; 9148debafeSMikulas Patocka #ifdef DM_WRITECACHE_HANDLE_HARDWARE_ERRORS 9248debafeSMikulas Patocka uint64_t original_sector; 9348debafeSMikulas Patocka uint64_t seq_count; 9448debafeSMikulas Patocka #endif 9548debafeSMikulas Patocka }; 9648debafeSMikulas Patocka 9748debafeSMikulas Patocka #ifdef DM_WRITECACHE_HAS_PMEM 9848debafeSMikulas Patocka #define WC_MODE_PMEM(wc) ((wc)->pmem_mode) 9948debafeSMikulas Patocka #define WC_MODE_FUA(wc) ((wc)->writeback_fua) 10048debafeSMikulas Patocka #else 10148debafeSMikulas Patocka #define WC_MODE_PMEM(wc) false 10248debafeSMikulas Patocka #define WC_MODE_FUA(wc) false 10348debafeSMikulas Patocka #endif 10448debafeSMikulas Patocka #define WC_MODE_SORT_FREELIST(wc) (!WC_MODE_PMEM(wc)) 10548debafeSMikulas Patocka 10648debafeSMikulas Patocka struct dm_writecache { 10748debafeSMikulas Patocka struct mutex lock; 10848debafeSMikulas Patocka struct list_head lru; 10948debafeSMikulas Patocka union { 11048debafeSMikulas Patocka struct list_head freelist; 11148debafeSMikulas Patocka struct { 11248debafeSMikulas Patocka struct rb_root freetree; 11348debafeSMikulas Patocka struct wc_entry *current_free; 11448debafeSMikulas Patocka }; 11548debafeSMikulas Patocka }; 11648debafeSMikulas Patocka struct rb_root tree; 11748debafeSMikulas Patocka 11848debafeSMikulas Patocka size_t freelist_size; 11948debafeSMikulas Patocka size_t writeback_size; 12048debafeSMikulas Patocka size_t freelist_high_watermark; 12148debafeSMikulas Patocka size_t freelist_low_watermark; 12248debafeSMikulas Patocka 12348debafeSMikulas Patocka unsigned uncommitted_blocks; 12448debafeSMikulas Patocka unsigned autocommit_blocks; 12548debafeSMikulas Patocka unsigned max_writeback_jobs; 12648debafeSMikulas Patocka 12748debafeSMikulas Patocka int error; 12848debafeSMikulas Patocka 12948debafeSMikulas Patocka unsigned long autocommit_jiffies; 13048debafeSMikulas Patocka struct timer_list autocommit_timer; 13148debafeSMikulas Patocka struct wait_queue_head freelist_wait; 13248debafeSMikulas Patocka 13348debafeSMikulas Patocka atomic_t bio_in_progress[2]; 13448debafeSMikulas Patocka struct wait_queue_head bio_in_progress_wait[2]; 13548debafeSMikulas Patocka 13648debafeSMikulas Patocka struct dm_target *ti; 13748debafeSMikulas Patocka struct dm_dev *dev; 13848debafeSMikulas Patocka struct dm_dev *ssd_dev; 139d284f824SMikulas Patocka sector_t start_sector; 14048debafeSMikulas Patocka void *memory_map; 14148debafeSMikulas Patocka uint64_t memory_map_size; 14248debafeSMikulas Patocka size_t metadata_sectors; 14348debafeSMikulas Patocka size_t n_blocks; 14448debafeSMikulas Patocka uint64_t seq_count; 14548debafeSMikulas Patocka void *block_start; 14648debafeSMikulas Patocka struct wc_entry *entries; 14748debafeSMikulas Patocka unsigned block_size; 14848debafeSMikulas Patocka unsigned char block_size_bits; 14948debafeSMikulas Patocka 15048debafeSMikulas Patocka bool pmem_mode:1; 15148debafeSMikulas Patocka bool writeback_fua:1; 15248debafeSMikulas Patocka 15348debafeSMikulas Patocka bool overwrote_committed:1; 15448debafeSMikulas Patocka bool memory_vmapped:1; 15548debafeSMikulas Patocka 15648debafeSMikulas Patocka bool high_wm_percent_set:1; 15748debafeSMikulas Patocka bool low_wm_percent_set:1; 15848debafeSMikulas Patocka bool max_writeback_jobs_set:1; 15948debafeSMikulas Patocka bool autocommit_blocks_set:1; 16048debafeSMikulas Patocka bool autocommit_time_set:1; 16148debafeSMikulas Patocka bool writeback_fua_set:1; 16248debafeSMikulas Patocka bool flush_on_suspend:1; 16348debafeSMikulas Patocka 16448debafeSMikulas Patocka unsigned writeback_all; 16548debafeSMikulas Patocka struct workqueue_struct *writeback_wq; 16648debafeSMikulas Patocka struct work_struct writeback_work; 16748debafeSMikulas Patocka struct work_struct flush_work; 16848debafeSMikulas Patocka 16948debafeSMikulas Patocka struct dm_io_client *dm_io; 17048debafeSMikulas Patocka 17148debafeSMikulas Patocka raw_spinlock_t endio_list_lock; 17248debafeSMikulas Patocka struct list_head endio_list; 17348debafeSMikulas Patocka struct task_struct *endio_thread; 17448debafeSMikulas Patocka 17548debafeSMikulas Patocka struct task_struct *flush_thread; 17648debafeSMikulas Patocka struct bio_list flush_list; 17748debafeSMikulas Patocka 17848debafeSMikulas Patocka struct dm_kcopyd_client *dm_kcopyd; 17948debafeSMikulas Patocka unsigned long *dirty_bitmap; 18048debafeSMikulas Patocka unsigned dirty_bitmap_size; 18148debafeSMikulas Patocka 18248debafeSMikulas Patocka struct bio_set bio_set; 18348debafeSMikulas Patocka mempool_t copy_pool; 18448debafeSMikulas Patocka }; 18548debafeSMikulas Patocka 18648debafeSMikulas Patocka #define WB_LIST_INLINE 16 18748debafeSMikulas Patocka 18848debafeSMikulas Patocka struct writeback_struct { 18948debafeSMikulas Patocka struct list_head endio_entry; 19048debafeSMikulas Patocka struct dm_writecache *wc; 19148debafeSMikulas Patocka struct wc_entry **wc_list; 19248debafeSMikulas Patocka unsigned wc_list_n; 19348debafeSMikulas Patocka struct wc_entry *wc_list_inline[WB_LIST_INLINE]; 19448debafeSMikulas Patocka struct bio bio; 19548debafeSMikulas Patocka }; 19648debafeSMikulas Patocka 19748debafeSMikulas Patocka struct copy_struct { 19848debafeSMikulas Patocka struct list_head endio_entry; 19948debafeSMikulas Patocka struct dm_writecache *wc; 20048debafeSMikulas Patocka struct wc_entry *e; 20148debafeSMikulas Patocka unsigned n_entries; 20248debafeSMikulas Patocka int error; 20348debafeSMikulas Patocka }; 20448debafeSMikulas Patocka 20548debafeSMikulas Patocka DECLARE_DM_KCOPYD_THROTTLE_WITH_MODULE_PARM(dm_writecache_throttle, 20648debafeSMikulas Patocka "A percentage of time allocated for data copying"); 20748debafeSMikulas Patocka 20848debafeSMikulas Patocka static void wc_lock(struct dm_writecache *wc) 20948debafeSMikulas Patocka { 21048debafeSMikulas Patocka mutex_lock(&wc->lock); 21148debafeSMikulas Patocka } 21248debafeSMikulas Patocka 21348debafeSMikulas Patocka static void wc_unlock(struct dm_writecache *wc) 21448debafeSMikulas Patocka { 21548debafeSMikulas Patocka mutex_unlock(&wc->lock); 21648debafeSMikulas Patocka } 21748debafeSMikulas Patocka 21848debafeSMikulas Patocka #ifdef DM_WRITECACHE_HAS_PMEM 21948debafeSMikulas Patocka static int persistent_memory_claim(struct dm_writecache *wc) 22048debafeSMikulas Patocka { 22148debafeSMikulas Patocka int r; 22248debafeSMikulas Patocka loff_t s; 22348debafeSMikulas Patocka long p, da; 22448debafeSMikulas Patocka pfn_t pfn; 22548debafeSMikulas Patocka int id; 22648debafeSMikulas Patocka struct page **pages; 22748debafeSMikulas Patocka 22848debafeSMikulas Patocka wc->memory_vmapped = false; 22948debafeSMikulas Patocka 23048debafeSMikulas Patocka if (!wc->ssd_dev->dax_dev) { 23148debafeSMikulas Patocka r = -EOPNOTSUPP; 23248debafeSMikulas Patocka goto err1; 23348debafeSMikulas Patocka } 23448debafeSMikulas Patocka s = wc->memory_map_size; 23548debafeSMikulas Patocka p = s >> PAGE_SHIFT; 23648debafeSMikulas Patocka if (!p) { 23748debafeSMikulas Patocka r = -EINVAL; 23848debafeSMikulas Patocka goto err1; 23948debafeSMikulas Patocka } 24048debafeSMikulas Patocka if (p != s >> PAGE_SHIFT) { 24148debafeSMikulas Patocka r = -EOVERFLOW; 24248debafeSMikulas Patocka goto err1; 24348debafeSMikulas Patocka } 24448debafeSMikulas Patocka 24548debafeSMikulas Patocka id = dax_read_lock(); 24648debafeSMikulas Patocka 24748debafeSMikulas Patocka da = dax_direct_access(wc->ssd_dev->dax_dev, 0, p, &wc->memory_map, &pfn); 24848debafeSMikulas Patocka if (da < 0) { 24948debafeSMikulas Patocka wc->memory_map = NULL; 25048debafeSMikulas Patocka r = da; 25148debafeSMikulas Patocka goto err2; 25248debafeSMikulas Patocka } 25348debafeSMikulas Patocka if (!pfn_t_has_page(pfn)) { 25448debafeSMikulas Patocka wc->memory_map = NULL; 25548debafeSMikulas Patocka r = -EOPNOTSUPP; 25648debafeSMikulas Patocka goto err2; 25748debafeSMikulas Patocka } 25848debafeSMikulas Patocka if (da != p) { 25948debafeSMikulas Patocka long i; 26048debafeSMikulas Patocka wc->memory_map = NULL; 26150a7d3baSKees Cook pages = kvmalloc_array(p, sizeof(struct page *), GFP_KERNEL); 26248debafeSMikulas Patocka if (!pages) { 26348debafeSMikulas Patocka r = -ENOMEM; 26448debafeSMikulas Patocka goto err2; 26548debafeSMikulas Patocka } 26648debafeSMikulas Patocka i = 0; 26748debafeSMikulas Patocka do { 26848debafeSMikulas Patocka long daa; 26948debafeSMikulas Patocka daa = dax_direct_access(wc->ssd_dev->dax_dev, i, p - i, 270f742267aSHuaisheng Ye NULL, &pfn); 27148debafeSMikulas Patocka if (daa <= 0) { 27248debafeSMikulas Patocka r = daa ? daa : -EINVAL; 27348debafeSMikulas Patocka goto err3; 27448debafeSMikulas Patocka } 27548debafeSMikulas Patocka if (!pfn_t_has_page(pfn)) { 27648debafeSMikulas Patocka r = -EOPNOTSUPP; 27748debafeSMikulas Patocka goto err3; 27848debafeSMikulas Patocka } 27948debafeSMikulas Patocka while (daa-- && i < p) { 28048debafeSMikulas Patocka pages[i++] = pfn_t_to_page(pfn); 28148debafeSMikulas Patocka pfn.val++; 28248debafeSMikulas Patocka } 28348debafeSMikulas Patocka } while (i < p); 28448debafeSMikulas Patocka wc->memory_map = vmap(pages, p, VM_MAP, PAGE_KERNEL); 28548debafeSMikulas Patocka if (!wc->memory_map) { 28648debafeSMikulas Patocka r = -ENOMEM; 28748debafeSMikulas Patocka goto err3; 28848debafeSMikulas Patocka } 28948debafeSMikulas Patocka kvfree(pages); 29048debafeSMikulas Patocka wc->memory_vmapped = true; 29148debafeSMikulas Patocka } 29248debafeSMikulas Patocka 29348debafeSMikulas Patocka dax_read_unlock(id); 294d284f824SMikulas Patocka 295d284f824SMikulas Patocka wc->memory_map += (size_t)wc->start_sector << SECTOR_SHIFT; 296d284f824SMikulas Patocka wc->memory_map_size -= (size_t)wc->start_sector << SECTOR_SHIFT; 297d284f824SMikulas Patocka 29848debafeSMikulas Patocka return 0; 29948debafeSMikulas Patocka err3: 30048debafeSMikulas Patocka kvfree(pages); 30148debafeSMikulas Patocka err2: 30248debafeSMikulas Patocka dax_read_unlock(id); 30348debafeSMikulas Patocka err1: 30448debafeSMikulas Patocka return r; 30548debafeSMikulas Patocka } 30648debafeSMikulas Patocka #else 30748debafeSMikulas Patocka static int persistent_memory_claim(struct dm_writecache *wc) 30848debafeSMikulas Patocka { 30948debafeSMikulas Patocka BUG(); 31048debafeSMikulas Patocka } 31148debafeSMikulas Patocka #endif 31248debafeSMikulas Patocka 31348debafeSMikulas Patocka static void persistent_memory_release(struct dm_writecache *wc) 31448debafeSMikulas Patocka { 31548debafeSMikulas Patocka if (wc->memory_vmapped) 316d284f824SMikulas Patocka vunmap(wc->memory_map - ((size_t)wc->start_sector << SECTOR_SHIFT)); 31748debafeSMikulas Patocka } 31848debafeSMikulas Patocka 31948debafeSMikulas Patocka static struct page *persistent_memory_page(void *addr) 32048debafeSMikulas Patocka { 32148debafeSMikulas Patocka if (is_vmalloc_addr(addr)) 32248debafeSMikulas Patocka return vmalloc_to_page(addr); 32348debafeSMikulas Patocka else 32448debafeSMikulas Patocka return virt_to_page(addr); 32548debafeSMikulas Patocka } 32648debafeSMikulas Patocka 32748debafeSMikulas Patocka static unsigned persistent_memory_page_offset(void *addr) 32848debafeSMikulas Patocka { 32948debafeSMikulas Patocka return (unsigned long)addr & (PAGE_SIZE - 1); 33048debafeSMikulas Patocka } 33148debafeSMikulas Patocka 33248debafeSMikulas Patocka static void persistent_memory_flush_cache(void *ptr, size_t size) 33348debafeSMikulas Patocka { 33448debafeSMikulas Patocka if (is_vmalloc_addr(ptr)) 33548debafeSMikulas Patocka flush_kernel_vmap_range(ptr, size); 33648debafeSMikulas Patocka } 33748debafeSMikulas Patocka 33848debafeSMikulas Patocka static void persistent_memory_invalidate_cache(void *ptr, size_t size) 33948debafeSMikulas Patocka { 34048debafeSMikulas Patocka if (is_vmalloc_addr(ptr)) 34148debafeSMikulas Patocka invalidate_kernel_vmap_range(ptr, size); 34248debafeSMikulas Patocka } 34348debafeSMikulas Patocka 34448debafeSMikulas Patocka static struct wc_memory_superblock *sb(struct dm_writecache *wc) 34548debafeSMikulas Patocka { 34648debafeSMikulas Patocka return wc->memory_map; 34748debafeSMikulas Patocka } 34848debafeSMikulas Patocka 34948debafeSMikulas Patocka static struct wc_memory_entry *memory_entry(struct dm_writecache *wc, struct wc_entry *e) 35048debafeSMikulas Patocka { 35148debafeSMikulas Patocka return &sb(wc)->entries[e->index]; 35248debafeSMikulas Patocka } 35348debafeSMikulas Patocka 35448debafeSMikulas Patocka static void *memory_data(struct dm_writecache *wc, struct wc_entry *e) 35548debafeSMikulas Patocka { 35648debafeSMikulas Patocka return (char *)wc->block_start + (e->index << wc->block_size_bits); 35748debafeSMikulas Patocka } 35848debafeSMikulas Patocka 35948debafeSMikulas Patocka static sector_t cache_sector(struct dm_writecache *wc, struct wc_entry *e) 36048debafeSMikulas Patocka { 361d284f824SMikulas Patocka return wc->start_sector + wc->metadata_sectors + 36248debafeSMikulas Patocka ((sector_t)e->index << (wc->block_size_bits - SECTOR_SHIFT)); 36348debafeSMikulas Patocka } 36448debafeSMikulas Patocka 36548debafeSMikulas Patocka static uint64_t read_original_sector(struct dm_writecache *wc, struct wc_entry *e) 36648debafeSMikulas Patocka { 36748debafeSMikulas Patocka #ifdef DM_WRITECACHE_HANDLE_HARDWARE_ERRORS 36848debafeSMikulas Patocka return e->original_sector; 36948debafeSMikulas Patocka #else 37048debafeSMikulas Patocka return le64_to_cpu(memory_entry(wc, e)->original_sector); 37148debafeSMikulas Patocka #endif 37248debafeSMikulas Patocka } 37348debafeSMikulas Patocka 37448debafeSMikulas Patocka static uint64_t read_seq_count(struct dm_writecache *wc, struct wc_entry *e) 37548debafeSMikulas Patocka { 37648debafeSMikulas Patocka #ifdef DM_WRITECACHE_HANDLE_HARDWARE_ERRORS 37748debafeSMikulas Patocka return e->seq_count; 37848debafeSMikulas Patocka #else 37948debafeSMikulas Patocka return le64_to_cpu(memory_entry(wc, e)->seq_count); 38048debafeSMikulas Patocka #endif 38148debafeSMikulas Patocka } 38248debafeSMikulas Patocka 38348debafeSMikulas Patocka static void clear_seq_count(struct dm_writecache *wc, struct wc_entry *e) 38448debafeSMikulas Patocka { 38548debafeSMikulas Patocka #ifdef DM_WRITECACHE_HANDLE_HARDWARE_ERRORS 38648debafeSMikulas Patocka e->seq_count = -1; 38748debafeSMikulas Patocka #endif 38848debafeSMikulas Patocka pmem_assign(memory_entry(wc, e)->seq_count, cpu_to_le64(-1)); 38948debafeSMikulas Patocka } 39048debafeSMikulas Patocka 39148debafeSMikulas Patocka static void write_original_sector_seq_count(struct dm_writecache *wc, struct wc_entry *e, 39248debafeSMikulas Patocka uint64_t original_sector, uint64_t seq_count) 39348debafeSMikulas Patocka { 39448debafeSMikulas Patocka struct wc_memory_entry me; 39548debafeSMikulas Patocka #ifdef DM_WRITECACHE_HANDLE_HARDWARE_ERRORS 39648debafeSMikulas Patocka e->original_sector = original_sector; 39748debafeSMikulas Patocka e->seq_count = seq_count; 39848debafeSMikulas Patocka #endif 39948debafeSMikulas Patocka me.original_sector = cpu_to_le64(original_sector); 40048debafeSMikulas Patocka me.seq_count = cpu_to_le64(seq_count); 40148debafeSMikulas Patocka pmem_assign(*memory_entry(wc, e), me); 40248debafeSMikulas Patocka } 40348debafeSMikulas Patocka 40448debafeSMikulas Patocka #define writecache_error(wc, err, msg, arg...) \ 40548debafeSMikulas Patocka do { \ 40648debafeSMikulas Patocka if (!cmpxchg(&(wc)->error, 0, err)) \ 40748debafeSMikulas Patocka DMERR(msg, ##arg); \ 40848debafeSMikulas Patocka wake_up(&(wc)->freelist_wait); \ 40948debafeSMikulas Patocka } while (0) 41048debafeSMikulas Patocka 41148debafeSMikulas Patocka #define writecache_has_error(wc) (unlikely(READ_ONCE((wc)->error))) 41248debafeSMikulas Patocka 41348debafeSMikulas Patocka static void writecache_flush_all_metadata(struct dm_writecache *wc) 41448debafeSMikulas Patocka { 41548debafeSMikulas Patocka if (!WC_MODE_PMEM(wc)) 41648debafeSMikulas Patocka memset(wc->dirty_bitmap, -1, wc->dirty_bitmap_size); 41748debafeSMikulas Patocka } 41848debafeSMikulas Patocka 41948debafeSMikulas Patocka static void writecache_flush_region(struct dm_writecache *wc, void *ptr, size_t size) 42048debafeSMikulas Patocka { 42148debafeSMikulas Patocka if (!WC_MODE_PMEM(wc)) 42248debafeSMikulas Patocka __set_bit(((char *)ptr - (char *)wc->memory_map) / BITMAP_GRANULARITY, 42348debafeSMikulas Patocka wc->dirty_bitmap); 42448debafeSMikulas Patocka } 42548debafeSMikulas Patocka 42648debafeSMikulas Patocka static void writecache_disk_flush(struct dm_writecache *wc, struct dm_dev *dev); 42748debafeSMikulas Patocka 42848debafeSMikulas Patocka struct io_notify { 42948debafeSMikulas Patocka struct dm_writecache *wc; 43048debafeSMikulas Patocka struct completion c; 43148debafeSMikulas Patocka atomic_t count; 43248debafeSMikulas Patocka }; 43348debafeSMikulas Patocka 43448debafeSMikulas Patocka static void writecache_notify_io(unsigned long error, void *context) 43548debafeSMikulas Patocka { 43648debafeSMikulas Patocka struct io_notify *endio = context; 43748debafeSMikulas Patocka 43848debafeSMikulas Patocka if (unlikely(error != 0)) 43948debafeSMikulas Patocka writecache_error(endio->wc, -EIO, "error writing metadata"); 44048debafeSMikulas Patocka BUG_ON(atomic_read(&endio->count) <= 0); 44148debafeSMikulas Patocka if (atomic_dec_and_test(&endio->count)) 44248debafeSMikulas Patocka complete(&endio->c); 44348debafeSMikulas Patocka } 44448debafeSMikulas Patocka 44548debafeSMikulas Patocka static void ssd_commit_flushed(struct dm_writecache *wc) 44648debafeSMikulas Patocka { 44748debafeSMikulas Patocka struct dm_io_region region; 44848debafeSMikulas Patocka struct dm_io_request req; 44948debafeSMikulas Patocka struct io_notify endio = { 45048debafeSMikulas Patocka wc, 45148debafeSMikulas Patocka COMPLETION_INITIALIZER_ONSTACK(endio.c), 45248debafeSMikulas Patocka ATOMIC_INIT(1), 45348debafeSMikulas Patocka }; 4541e1132eaSMikulas Patocka unsigned bitmap_bits = wc->dirty_bitmap_size * 8; 45548debafeSMikulas Patocka unsigned i = 0; 45648debafeSMikulas Patocka 45748debafeSMikulas Patocka while (1) { 45848debafeSMikulas Patocka unsigned j; 45948debafeSMikulas Patocka i = find_next_bit(wc->dirty_bitmap, bitmap_bits, i); 46048debafeSMikulas Patocka if (unlikely(i == bitmap_bits)) 46148debafeSMikulas Patocka break; 46248debafeSMikulas Patocka j = find_next_zero_bit(wc->dirty_bitmap, bitmap_bits, i); 46348debafeSMikulas Patocka 46448debafeSMikulas Patocka region.bdev = wc->ssd_dev->bdev; 46548debafeSMikulas Patocka region.sector = (sector_t)i * (BITMAP_GRANULARITY >> SECTOR_SHIFT); 46648debafeSMikulas Patocka region.count = (sector_t)(j - i) * (BITMAP_GRANULARITY >> SECTOR_SHIFT); 46748debafeSMikulas Patocka 46848debafeSMikulas Patocka if (unlikely(region.sector >= wc->metadata_sectors)) 46948debafeSMikulas Patocka break; 47048debafeSMikulas Patocka if (unlikely(region.sector + region.count > wc->metadata_sectors)) 47148debafeSMikulas Patocka region.count = wc->metadata_sectors - region.sector; 47248debafeSMikulas Patocka 473d284f824SMikulas Patocka region.sector += wc->start_sector; 47448debafeSMikulas Patocka atomic_inc(&endio.count); 47548debafeSMikulas Patocka req.bi_op = REQ_OP_WRITE; 47648debafeSMikulas Patocka req.bi_op_flags = REQ_SYNC; 47748debafeSMikulas Patocka req.mem.type = DM_IO_VMA; 47848debafeSMikulas Patocka req.mem.ptr.vma = (char *)wc->memory_map + (size_t)i * BITMAP_GRANULARITY; 47948debafeSMikulas Patocka req.client = wc->dm_io; 48048debafeSMikulas Patocka req.notify.fn = writecache_notify_io; 48148debafeSMikulas Patocka req.notify.context = &endio; 48248debafeSMikulas Patocka 48348debafeSMikulas Patocka /* writing via async dm-io (implied by notify.fn above) won't return an error */ 48448debafeSMikulas Patocka (void) dm_io(&req, 1, ®ion, NULL); 48548debafeSMikulas Patocka i = j; 48648debafeSMikulas Patocka } 48748debafeSMikulas Patocka 48848debafeSMikulas Patocka writecache_notify_io(0, &endio); 48948debafeSMikulas Patocka wait_for_completion_io(&endio.c); 49048debafeSMikulas Patocka 49148debafeSMikulas Patocka writecache_disk_flush(wc, wc->ssd_dev); 49248debafeSMikulas Patocka 49348debafeSMikulas Patocka memset(wc->dirty_bitmap, 0, wc->dirty_bitmap_size); 49448debafeSMikulas Patocka } 49548debafeSMikulas Patocka 49648debafeSMikulas Patocka static void writecache_commit_flushed(struct dm_writecache *wc) 49748debafeSMikulas Patocka { 49848debafeSMikulas Patocka if (WC_MODE_PMEM(wc)) 49948debafeSMikulas Patocka wmb(); 50048debafeSMikulas Patocka else 50148debafeSMikulas Patocka ssd_commit_flushed(wc); 50248debafeSMikulas Patocka } 50348debafeSMikulas Patocka 50448debafeSMikulas Patocka static void writecache_disk_flush(struct dm_writecache *wc, struct dm_dev *dev) 50548debafeSMikulas Patocka { 50648debafeSMikulas Patocka int r; 50748debafeSMikulas Patocka struct dm_io_region region; 50848debafeSMikulas Patocka struct dm_io_request req; 50948debafeSMikulas Patocka 51048debafeSMikulas Patocka region.bdev = dev->bdev; 51148debafeSMikulas Patocka region.sector = 0; 51248debafeSMikulas Patocka region.count = 0; 51348debafeSMikulas Patocka req.bi_op = REQ_OP_WRITE; 51448debafeSMikulas Patocka req.bi_op_flags = REQ_PREFLUSH; 51548debafeSMikulas Patocka req.mem.type = DM_IO_KMEM; 51648debafeSMikulas Patocka req.mem.ptr.addr = NULL; 51748debafeSMikulas Patocka req.client = wc->dm_io; 51848debafeSMikulas Patocka req.notify.fn = NULL; 51948debafeSMikulas Patocka 52048debafeSMikulas Patocka r = dm_io(&req, 1, ®ion, NULL); 52148debafeSMikulas Patocka if (unlikely(r)) 52248debafeSMikulas Patocka writecache_error(wc, r, "error flushing metadata: %d", r); 52348debafeSMikulas Patocka } 52448debafeSMikulas Patocka 52548debafeSMikulas Patocka static void writecache_wait_for_ios(struct dm_writecache *wc, int direction) 52648debafeSMikulas Patocka { 52748debafeSMikulas Patocka wait_event(wc->bio_in_progress_wait[direction], 52848debafeSMikulas Patocka !atomic_read(&wc->bio_in_progress[direction])); 52948debafeSMikulas Patocka } 53048debafeSMikulas Patocka 53148debafeSMikulas Patocka #define WFE_RETURN_FOLLOWING 1 53248debafeSMikulas Patocka #define WFE_LOWEST_SEQ 2 53348debafeSMikulas Patocka 53448debafeSMikulas Patocka static struct wc_entry *writecache_find_entry(struct dm_writecache *wc, 53548debafeSMikulas Patocka uint64_t block, int flags) 53648debafeSMikulas Patocka { 53748debafeSMikulas Patocka struct wc_entry *e; 53848debafeSMikulas Patocka struct rb_node *node = wc->tree.rb_node; 53948debafeSMikulas Patocka 54048debafeSMikulas Patocka if (unlikely(!node)) 54148debafeSMikulas Patocka return NULL; 54248debafeSMikulas Patocka 54348debafeSMikulas Patocka while (1) { 54448debafeSMikulas Patocka e = container_of(node, struct wc_entry, rb_node); 54548debafeSMikulas Patocka if (read_original_sector(wc, e) == block) 54648debafeSMikulas Patocka break; 547f8011d33SMikulas Patocka 54848debafeSMikulas Patocka node = (read_original_sector(wc, e) >= block ? 54948debafeSMikulas Patocka e->rb_node.rb_left : e->rb_node.rb_right); 55048debafeSMikulas Patocka if (unlikely(!node)) { 551f8011d33SMikulas Patocka if (!(flags & WFE_RETURN_FOLLOWING)) 55248debafeSMikulas Patocka return NULL; 55348debafeSMikulas Patocka if (read_original_sector(wc, e) >= block) { 554f8011d33SMikulas Patocka return e; 55548debafeSMikulas Patocka } else { 55648debafeSMikulas Patocka node = rb_next(&e->rb_node); 557f8011d33SMikulas Patocka if (unlikely(!node)) 55848debafeSMikulas Patocka return NULL; 55948debafeSMikulas Patocka e = container_of(node, struct wc_entry, rb_node); 560f8011d33SMikulas Patocka return e; 56148debafeSMikulas Patocka } 56248debafeSMikulas Patocka } 56348debafeSMikulas Patocka } 56448debafeSMikulas Patocka 56548debafeSMikulas Patocka while (1) { 56648debafeSMikulas Patocka struct wc_entry *e2; 56748debafeSMikulas Patocka if (flags & WFE_LOWEST_SEQ) 56848debafeSMikulas Patocka node = rb_prev(&e->rb_node); 56948debafeSMikulas Patocka else 57048debafeSMikulas Patocka node = rb_next(&e->rb_node); 57184420b1eSHuaisheng Ye if (unlikely(!node)) 57248debafeSMikulas Patocka return e; 57348debafeSMikulas Patocka e2 = container_of(node, struct wc_entry, rb_node); 57448debafeSMikulas Patocka if (read_original_sector(wc, e2) != block) 57548debafeSMikulas Patocka return e; 57648debafeSMikulas Patocka e = e2; 57748debafeSMikulas Patocka } 57848debafeSMikulas Patocka } 57948debafeSMikulas Patocka 58048debafeSMikulas Patocka static void writecache_insert_entry(struct dm_writecache *wc, struct wc_entry *ins) 58148debafeSMikulas Patocka { 58248debafeSMikulas Patocka struct wc_entry *e; 58348debafeSMikulas Patocka struct rb_node **node = &wc->tree.rb_node, *parent = NULL; 58448debafeSMikulas Patocka 58548debafeSMikulas Patocka while (*node) { 58648debafeSMikulas Patocka e = container_of(*node, struct wc_entry, rb_node); 58748debafeSMikulas Patocka parent = &e->rb_node; 58848debafeSMikulas Patocka if (read_original_sector(wc, e) > read_original_sector(wc, ins)) 58948debafeSMikulas Patocka node = &parent->rb_left; 59048debafeSMikulas Patocka else 59148debafeSMikulas Patocka node = &parent->rb_right; 59248debafeSMikulas Patocka } 59348debafeSMikulas Patocka rb_link_node(&ins->rb_node, parent, node); 59448debafeSMikulas Patocka rb_insert_color(&ins->rb_node, &wc->tree); 59548debafeSMikulas Patocka list_add(&ins->lru, &wc->lru); 59648debafeSMikulas Patocka } 59748debafeSMikulas Patocka 59848debafeSMikulas Patocka static void writecache_unlink(struct dm_writecache *wc, struct wc_entry *e) 59948debafeSMikulas Patocka { 60048debafeSMikulas Patocka list_del(&e->lru); 60148debafeSMikulas Patocka rb_erase(&e->rb_node, &wc->tree); 60248debafeSMikulas Patocka } 60348debafeSMikulas Patocka 60448debafeSMikulas Patocka static void writecache_add_to_freelist(struct dm_writecache *wc, struct wc_entry *e) 60548debafeSMikulas Patocka { 60648debafeSMikulas Patocka if (WC_MODE_SORT_FREELIST(wc)) { 60748debafeSMikulas Patocka struct rb_node **node = &wc->freetree.rb_node, *parent = NULL; 60848debafeSMikulas Patocka if (unlikely(!*node)) 60948debafeSMikulas Patocka wc->current_free = e; 61048debafeSMikulas Patocka while (*node) { 61148debafeSMikulas Patocka parent = *node; 61248debafeSMikulas Patocka if (&e->rb_node < *node) 61348debafeSMikulas Patocka node = &parent->rb_left; 61448debafeSMikulas Patocka else 61548debafeSMikulas Patocka node = &parent->rb_right; 61648debafeSMikulas Patocka } 61748debafeSMikulas Patocka rb_link_node(&e->rb_node, parent, node); 61848debafeSMikulas Patocka rb_insert_color(&e->rb_node, &wc->freetree); 61948debafeSMikulas Patocka } else { 62048debafeSMikulas Patocka list_add_tail(&e->lru, &wc->freelist); 62148debafeSMikulas Patocka } 62248debafeSMikulas Patocka wc->freelist_size++; 62348debafeSMikulas Patocka } 62448debafeSMikulas Patocka 62548debafeSMikulas Patocka static struct wc_entry *writecache_pop_from_freelist(struct dm_writecache *wc) 62648debafeSMikulas Patocka { 62748debafeSMikulas Patocka struct wc_entry *e; 62848debafeSMikulas Patocka 62948debafeSMikulas Patocka if (WC_MODE_SORT_FREELIST(wc)) { 63048debafeSMikulas Patocka struct rb_node *next; 63148debafeSMikulas Patocka if (unlikely(!wc->current_free)) 63248debafeSMikulas Patocka return NULL; 63348debafeSMikulas Patocka e = wc->current_free; 63448debafeSMikulas Patocka next = rb_next(&e->rb_node); 63548debafeSMikulas Patocka rb_erase(&e->rb_node, &wc->freetree); 63648debafeSMikulas Patocka if (unlikely(!next)) 63748debafeSMikulas Patocka next = rb_first(&wc->freetree); 63848debafeSMikulas Patocka wc->current_free = next ? container_of(next, struct wc_entry, rb_node) : NULL; 63948debafeSMikulas Patocka } else { 64048debafeSMikulas Patocka if (unlikely(list_empty(&wc->freelist))) 64148debafeSMikulas Patocka return NULL; 64248debafeSMikulas Patocka e = container_of(wc->freelist.next, struct wc_entry, lru); 64348debafeSMikulas Patocka list_del(&e->lru); 64448debafeSMikulas Patocka } 64548debafeSMikulas Patocka wc->freelist_size--; 64648debafeSMikulas Patocka if (unlikely(wc->freelist_size + wc->writeback_size <= wc->freelist_high_watermark)) 64748debafeSMikulas Patocka queue_work(wc->writeback_wq, &wc->writeback_work); 64848debafeSMikulas Patocka 64948debafeSMikulas Patocka return e; 65048debafeSMikulas Patocka } 65148debafeSMikulas Patocka 65248debafeSMikulas Patocka static void writecache_free_entry(struct dm_writecache *wc, struct wc_entry *e) 65348debafeSMikulas Patocka { 65448debafeSMikulas Patocka writecache_unlink(wc, e); 65548debafeSMikulas Patocka writecache_add_to_freelist(wc, e); 65648debafeSMikulas Patocka clear_seq_count(wc, e); 65748debafeSMikulas Patocka writecache_flush_region(wc, memory_entry(wc, e), sizeof(struct wc_memory_entry)); 65848debafeSMikulas Patocka if (unlikely(waitqueue_active(&wc->freelist_wait))) 65948debafeSMikulas Patocka wake_up(&wc->freelist_wait); 66048debafeSMikulas Patocka } 66148debafeSMikulas Patocka 66248debafeSMikulas Patocka static void writecache_wait_on_freelist(struct dm_writecache *wc) 66348debafeSMikulas Patocka { 66448debafeSMikulas Patocka DEFINE_WAIT(wait); 66548debafeSMikulas Patocka 66648debafeSMikulas Patocka prepare_to_wait(&wc->freelist_wait, &wait, TASK_UNINTERRUPTIBLE); 66748debafeSMikulas Patocka wc_unlock(wc); 66848debafeSMikulas Patocka io_schedule(); 66948debafeSMikulas Patocka finish_wait(&wc->freelist_wait, &wait); 67048debafeSMikulas Patocka wc_lock(wc); 67148debafeSMikulas Patocka } 67248debafeSMikulas Patocka 67348debafeSMikulas Patocka static void writecache_poison_lists(struct dm_writecache *wc) 67448debafeSMikulas Patocka { 67548debafeSMikulas Patocka /* 67648debafeSMikulas Patocka * Catch incorrect access to these values while the device is suspended. 67748debafeSMikulas Patocka */ 67848debafeSMikulas Patocka memset(&wc->tree, -1, sizeof wc->tree); 67948debafeSMikulas Patocka wc->lru.next = LIST_POISON1; 68048debafeSMikulas Patocka wc->lru.prev = LIST_POISON2; 68148debafeSMikulas Patocka wc->freelist.next = LIST_POISON1; 68248debafeSMikulas Patocka wc->freelist.prev = LIST_POISON2; 68348debafeSMikulas Patocka } 68448debafeSMikulas Patocka 68548debafeSMikulas Patocka static void writecache_flush_entry(struct dm_writecache *wc, struct wc_entry *e) 68648debafeSMikulas Patocka { 68748debafeSMikulas Patocka writecache_flush_region(wc, memory_entry(wc, e), sizeof(struct wc_memory_entry)); 68848debafeSMikulas Patocka if (WC_MODE_PMEM(wc)) 68948debafeSMikulas Patocka writecache_flush_region(wc, memory_data(wc, e), wc->block_size); 69048debafeSMikulas Patocka } 69148debafeSMikulas Patocka 69248debafeSMikulas Patocka static bool writecache_entry_is_committed(struct dm_writecache *wc, struct wc_entry *e) 69348debafeSMikulas Patocka { 69448debafeSMikulas Patocka return read_seq_count(wc, e) < wc->seq_count; 69548debafeSMikulas Patocka } 69648debafeSMikulas Patocka 69748debafeSMikulas Patocka static void writecache_flush(struct dm_writecache *wc) 69848debafeSMikulas Patocka { 69948debafeSMikulas Patocka struct wc_entry *e, *e2; 70048debafeSMikulas Patocka bool need_flush_after_free; 70148debafeSMikulas Patocka 70248debafeSMikulas Patocka wc->uncommitted_blocks = 0; 70348debafeSMikulas Patocka del_timer(&wc->autocommit_timer); 70448debafeSMikulas Patocka 70548debafeSMikulas Patocka if (list_empty(&wc->lru)) 70648debafeSMikulas Patocka return; 70748debafeSMikulas Patocka 70848debafeSMikulas Patocka e = container_of(wc->lru.next, struct wc_entry, lru); 70948debafeSMikulas Patocka if (writecache_entry_is_committed(wc, e)) { 71048debafeSMikulas Patocka if (wc->overwrote_committed) { 71148debafeSMikulas Patocka writecache_wait_for_ios(wc, WRITE); 71248debafeSMikulas Patocka writecache_disk_flush(wc, wc->ssd_dev); 71348debafeSMikulas Patocka wc->overwrote_committed = false; 71448debafeSMikulas Patocka } 71548debafeSMikulas Patocka return; 71648debafeSMikulas Patocka } 71748debafeSMikulas Patocka while (1) { 71848debafeSMikulas Patocka writecache_flush_entry(wc, e); 71948debafeSMikulas Patocka if (unlikely(e->lru.next == &wc->lru)) 72048debafeSMikulas Patocka break; 72148debafeSMikulas Patocka e2 = container_of(e->lru.next, struct wc_entry, lru); 72248debafeSMikulas Patocka if (writecache_entry_is_committed(wc, e2)) 72348debafeSMikulas Patocka break; 72448debafeSMikulas Patocka e = e2; 72548debafeSMikulas Patocka cond_resched(); 72648debafeSMikulas Patocka } 72748debafeSMikulas Patocka writecache_commit_flushed(wc); 72848debafeSMikulas Patocka 72948debafeSMikulas Patocka writecache_wait_for_ios(wc, WRITE); 73048debafeSMikulas Patocka 73148debafeSMikulas Patocka wc->seq_count++; 73248debafeSMikulas Patocka pmem_assign(sb(wc)->seq_count, cpu_to_le64(wc->seq_count)); 73348debafeSMikulas Patocka writecache_flush_region(wc, &sb(wc)->seq_count, sizeof sb(wc)->seq_count); 73448debafeSMikulas Patocka writecache_commit_flushed(wc); 73548debafeSMikulas Patocka 73648debafeSMikulas Patocka wc->overwrote_committed = false; 73748debafeSMikulas Patocka 73848debafeSMikulas Patocka need_flush_after_free = false; 73948debafeSMikulas Patocka while (1) { 74048debafeSMikulas Patocka /* Free another committed entry with lower seq-count */ 74148debafeSMikulas Patocka struct rb_node *rb_node = rb_prev(&e->rb_node); 74248debafeSMikulas Patocka 74348debafeSMikulas Patocka if (rb_node) { 74448debafeSMikulas Patocka e2 = container_of(rb_node, struct wc_entry, rb_node); 74548debafeSMikulas Patocka if (read_original_sector(wc, e2) == read_original_sector(wc, e) && 74648debafeSMikulas Patocka likely(!e2->write_in_progress)) { 74748debafeSMikulas Patocka writecache_free_entry(wc, e2); 74848debafeSMikulas Patocka need_flush_after_free = true; 74948debafeSMikulas Patocka } 75048debafeSMikulas Patocka } 75148debafeSMikulas Patocka if (unlikely(e->lru.prev == &wc->lru)) 75248debafeSMikulas Patocka break; 75348debafeSMikulas Patocka e = container_of(e->lru.prev, struct wc_entry, lru); 75448debafeSMikulas Patocka cond_resched(); 75548debafeSMikulas Patocka } 75648debafeSMikulas Patocka 75748debafeSMikulas Patocka if (need_flush_after_free) 75848debafeSMikulas Patocka writecache_commit_flushed(wc); 75948debafeSMikulas Patocka } 76048debafeSMikulas Patocka 76148debafeSMikulas Patocka static void writecache_flush_work(struct work_struct *work) 76248debafeSMikulas Patocka { 76348debafeSMikulas Patocka struct dm_writecache *wc = container_of(work, struct dm_writecache, flush_work); 76448debafeSMikulas Patocka 76548debafeSMikulas Patocka wc_lock(wc); 76648debafeSMikulas Patocka writecache_flush(wc); 76748debafeSMikulas Patocka wc_unlock(wc); 76848debafeSMikulas Patocka } 76948debafeSMikulas Patocka 77048debafeSMikulas Patocka static void writecache_autocommit_timer(struct timer_list *t) 77148debafeSMikulas Patocka { 77248debafeSMikulas Patocka struct dm_writecache *wc = from_timer(wc, t, autocommit_timer); 77348debafeSMikulas Patocka if (!writecache_has_error(wc)) 77448debafeSMikulas Patocka queue_work(wc->writeback_wq, &wc->flush_work); 77548debafeSMikulas Patocka } 77648debafeSMikulas Patocka 77748debafeSMikulas Patocka static void writecache_schedule_autocommit(struct dm_writecache *wc) 77848debafeSMikulas Patocka { 77948debafeSMikulas Patocka if (!timer_pending(&wc->autocommit_timer)) 78048debafeSMikulas Patocka mod_timer(&wc->autocommit_timer, jiffies + wc->autocommit_jiffies); 78148debafeSMikulas Patocka } 78248debafeSMikulas Patocka 78348debafeSMikulas Patocka static void writecache_discard(struct dm_writecache *wc, sector_t start, sector_t end) 78448debafeSMikulas Patocka { 78548debafeSMikulas Patocka struct wc_entry *e; 78648debafeSMikulas Patocka bool discarded_something = false; 78748debafeSMikulas Patocka 78848debafeSMikulas Patocka e = writecache_find_entry(wc, start, WFE_RETURN_FOLLOWING | WFE_LOWEST_SEQ); 78948debafeSMikulas Patocka if (unlikely(!e)) 79048debafeSMikulas Patocka return; 79148debafeSMikulas Patocka 79248debafeSMikulas Patocka while (read_original_sector(wc, e) < end) { 79348debafeSMikulas Patocka struct rb_node *node = rb_next(&e->rb_node); 79448debafeSMikulas Patocka 79548debafeSMikulas Patocka if (likely(!e->write_in_progress)) { 79648debafeSMikulas Patocka if (!discarded_something) { 79748debafeSMikulas Patocka writecache_wait_for_ios(wc, READ); 79848debafeSMikulas Patocka writecache_wait_for_ios(wc, WRITE); 79948debafeSMikulas Patocka discarded_something = true; 80048debafeSMikulas Patocka } 80148debafeSMikulas Patocka writecache_free_entry(wc, e); 80248debafeSMikulas Patocka } 80348debafeSMikulas Patocka 80484420b1eSHuaisheng Ye if (unlikely(!node)) 80548debafeSMikulas Patocka break; 80648debafeSMikulas Patocka 80748debafeSMikulas Patocka e = container_of(node, struct wc_entry, rb_node); 80848debafeSMikulas Patocka } 80948debafeSMikulas Patocka 81048debafeSMikulas Patocka if (discarded_something) 81148debafeSMikulas Patocka writecache_commit_flushed(wc); 81248debafeSMikulas Patocka } 81348debafeSMikulas Patocka 81448debafeSMikulas Patocka static bool writecache_wait_for_writeback(struct dm_writecache *wc) 81548debafeSMikulas Patocka { 81648debafeSMikulas Patocka if (wc->writeback_size) { 81748debafeSMikulas Patocka writecache_wait_on_freelist(wc); 81848debafeSMikulas Patocka return true; 81948debafeSMikulas Patocka } 82048debafeSMikulas Patocka return false; 82148debafeSMikulas Patocka } 82248debafeSMikulas Patocka 82348debafeSMikulas Patocka static void writecache_suspend(struct dm_target *ti) 82448debafeSMikulas Patocka { 82548debafeSMikulas Patocka struct dm_writecache *wc = ti->private; 82648debafeSMikulas Patocka bool flush_on_suspend; 82748debafeSMikulas Patocka 82848debafeSMikulas Patocka del_timer_sync(&wc->autocommit_timer); 82948debafeSMikulas Patocka 83048debafeSMikulas Patocka wc_lock(wc); 83148debafeSMikulas Patocka writecache_flush(wc); 83248debafeSMikulas Patocka flush_on_suspend = wc->flush_on_suspend; 83348debafeSMikulas Patocka if (flush_on_suspend) { 83448debafeSMikulas Patocka wc->flush_on_suspend = false; 83548debafeSMikulas Patocka wc->writeback_all++; 83648debafeSMikulas Patocka queue_work(wc->writeback_wq, &wc->writeback_work); 83748debafeSMikulas Patocka } 83848debafeSMikulas Patocka wc_unlock(wc); 83948debafeSMikulas Patocka 84048debafeSMikulas Patocka flush_workqueue(wc->writeback_wq); 84148debafeSMikulas Patocka 84248debafeSMikulas Patocka wc_lock(wc); 84348debafeSMikulas Patocka if (flush_on_suspend) 84448debafeSMikulas Patocka wc->writeback_all--; 84548debafeSMikulas Patocka while (writecache_wait_for_writeback(wc)); 84648debafeSMikulas Patocka 84748debafeSMikulas Patocka if (WC_MODE_PMEM(wc)) 84848debafeSMikulas Patocka persistent_memory_flush_cache(wc->memory_map, wc->memory_map_size); 84948debafeSMikulas Patocka 85048debafeSMikulas Patocka writecache_poison_lists(wc); 85148debafeSMikulas Patocka 85248debafeSMikulas Patocka wc_unlock(wc); 85348debafeSMikulas Patocka } 85448debafeSMikulas Patocka 85548debafeSMikulas Patocka static int writecache_alloc_entries(struct dm_writecache *wc) 85648debafeSMikulas Patocka { 85748debafeSMikulas Patocka size_t b; 85848debafeSMikulas Patocka 85948debafeSMikulas Patocka if (wc->entries) 86048debafeSMikulas Patocka return 0; 86150a7d3baSKees Cook wc->entries = vmalloc(array_size(sizeof(struct wc_entry), wc->n_blocks)); 86248debafeSMikulas Patocka if (!wc->entries) 86348debafeSMikulas Patocka return -ENOMEM; 86448debafeSMikulas Patocka for (b = 0; b < wc->n_blocks; b++) { 86548debafeSMikulas Patocka struct wc_entry *e = &wc->entries[b]; 86648debafeSMikulas Patocka e->index = b; 86748debafeSMikulas Patocka e->write_in_progress = false; 86848debafeSMikulas Patocka } 86948debafeSMikulas Patocka 87048debafeSMikulas Patocka return 0; 87148debafeSMikulas Patocka } 87248debafeSMikulas Patocka 87348debafeSMikulas Patocka static void writecache_resume(struct dm_target *ti) 87448debafeSMikulas Patocka { 87548debafeSMikulas Patocka struct dm_writecache *wc = ti->private; 87648debafeSMikulas Patocka size_t b; 87748debafeSMikulas Patocka bool need_flush = false; 87848debafeSMikulas Patocka __le64 sb_seq_count; 87948debafeSMikulas Patocka int r; 88048debafeSMikulas Patocka 88148debafeSMikulas Patocka wc_lock(wc); 88248debafeSMikulas Patocka 88348debafeSMikulas Patocka if (WC_MODE_PMEM(wc)) 88448debafeSMikulas Patocka persistent_memory_invalidate_cache(wc->memory_map, wc->memory_map_size); 88548debafeSMikulas Patocka 88648debafeSMikulas Patocka wc->tree = RB_ROOT; 88748debafeSMikulas Patocka INIT_LIST_HEAD(&wc->lru); 88848debafeSMikulas Patocka if (WC_MODE_SORT_FREELIST(wc)) { 88948debafeSMikulas Patocka wc->freetree = RB_ROOT; 89048debafeSMikulas Patocka wc->current_free = NULL; 89148debafeSMikulas Patocka } else { 89248debafeSMikulas Patocka INIT_LIST_HEAD(&wc->freelist); 89348debafeSMikulas Patocka } 89448debafeSMikulas Patocka wc->freelist_size = 0; 89548debafeSMikulas Patocka 89648debafeSMikulas Patocka r = memcpy_mcsafe(&sb_seq_count, &sb(wc)->seq_count, sizeof(uint64_t)); 89748debafeSMikulas Patocka if (r) { 89848debafeSMikulas Patocka writecache_error(wc, r, "hardware memory error when reading superblock: %d", r); 89948debafeSMikulas Patocka sb_seq_count = cpu_to_le64(0); 90048debafeSMikulas Patocka } 90148debafeSMikulas Patocka wc->seq_count = le64_to_cpu(sb_seq_count); 90248debafeSMikulas Patocka 90348debafeSMikulas Patocka #ifdef DM_WRITECACHE_HANDLE_HARDWARE_ERRORS 90448debafeSMikulas Patocka for (b = 0; b < wc->n_blocks; b++) { 90548debafeSMikulas Patocka struct wc_entry *e = &wc->entries[b]; 90648debafeSMikulas Patocka struct wc_memory_entry wme; 90748debafeSMikulas Patocka if (writecache_has_error(wc)) { 90848debafeSMikulas Patocka e->original_sector = -1; 90948debafeSMikulas Patocka e->seq_count = -1; 91048debafeSMikulas Patocka continue; 91148debafeSMikulas Patocka } 91248debafeSMikulas Patocka r = memcpy_mcsafe(&wme, memory_entry(wc, e), sizeof(struct wc_memory_entry)); 91348debafeSMikulas Patocka if (r) { 91448debafeSMikulas Patocka writecache_error(wc, r, "hardware memory error when reading metadata entry %lu: %d", 91548debafeSMikulas Patocka (unsigned long)b, r); 91648debafeSMikulas Patocka e->original_sector = -1; 91748debafeSMikulas Patocka e->seq_count = -1; 91848debafeSMikulas Patocka } else { 91948debafeSMikulas Patocka e->original_sector = le64_to_cpu(wme.original_sector); 92048debafeSMikulas Patocka e->seq_count = le64_to_cpu(wme.seq_count); 92148debafeSMikulas Patocka } 92248debafeSMikulas Patocka } 92348debafeSMikulas Patocka #endif 92448debafeSMikulas Patocka for (b = 0; b < wc->n_blocks; b++) { 92548debafeSMikulas Patocka struct wc_entry *e = &wc->entries[b]; 92648debafeSMikulas Patocka if (!writecache_entry_is_committed(wc, e)) { 92748debafeSMikulas Patocka if (read_seq_count(wc, e) != -1) { 92848debafeSMikulas Patocka erase_this: 92948debafeSMikulas Patocka clear_seq_count(wc, e); 93048debafeSMikulas Patocka need_flush = true; 93148debafeSMikulas Patocka } 93248debafeSMikulas Patocka writecache_add_to_freelist(wc, e); 93348debafeSMikulas Patocka } else { 93448debafeSMikulas Patocka struct wc_entry *old; 93548debafeSMikulas Patocka 93648debafeSMikulas Patocka old = writecache_find_entry(wc, read_original_sector(wc, e), 0); 93748debafeSMikulas Patocka if (!old) { 93848debafeSMikulas Patocka writecache_insert_entry(wc, e); 93948debafeSMikulas Patocka } else { 94048debafeSMikulas Patocka if (read_seq_count(wc, old) == read_seq_count(wc, e)) { 94148debafeSMikulas Patocka writecache_error(wc, -EINVAL, 94248debafeSMikulas Patocka "two identical entries, position %llu, sector %llu, sequence %llu", 94348debafeSMikulas Patocka (unsigned long long)b, (unsigned long long)read_original_sector(wc, e), 94448debafeSMikulas Patocka (unsigned long long)read_seq_count(wc, e)); 94548debafeSMikulas Patocka } 94648debafeSMikulas Patocka if (read_seq_count(wc, old) > read_seq_count(wc, e)) { 94748debafeSMikulas Patocka goto erase_this; 94848debafeSMikulas Patocka } else { 94948debafeSMikulas Patocka writecache_free_entry(wc, old); 95048debafeSMikulas Patocka writecache_insert_entry(wc, e); 95148debafeSMikulas Patocka need_flush = true; 95248debafeSMikulas Patocka } 95348debafeSMikulas Patocka } 95448debafeSMikulas Patocka } 95548debafeSMikulas Patocka cond_resched(); 95648debafeSMikulas Patocka } 95748debafeSMikulas Patocka 95848debafeSMikulas Patocka if (need_flush) { 95948debafeSMikulas Patocka writecache_flush_all_metadata(wc); 96048debafeSMikulas Patocka writecache_commit_flushed(wc); 96148debafeSMikulas Patocka } 96248debafeSMikulas Patocka 96348debafeSMikulas Patocka wc_unlock(wc); 96448debafeSMikulas Patocka } 96548debafeSMikulas Patocka 96648debafeSMikulas Patocka static int process_flush_mesg(unsigned argc, char **argv, struct dm_writecache *wc) 96748debafeSMikulas Patocka { 96848debafeSMikulas Patocka if (argc != 1) 96948debafeSMikulas Patocka return -EINVAL; 97048debafeSMikulas Patocka 97148debafeSMikulas Patocka wc_lock(wc); 97248debafeSMikulas Patocka if (dm_suspended(wc->ti)) { 97348debafeSMikulas Patocka wc_unlock(wc); 97448debafeSMikulas Patocka return -EBUSY; 97548debafeSMikulas Patocka } 97648debafeSMikulas Patocka if (writecache_has_error(wc)) { 97748debafeSMikulas Patocka wc_unlock(wc); 97848debafeSMikulas Patocka return -EIO; 97948debafeSMikulas Patocka } 98048debafeSMikulas Patocka 98148debafeSMikulas Patocka writecache_flush(wc); 98248debafeSMikulas Patocka wc->writeback_all++; 98348debafeSMikulas Patocka queue_work(wc->writeback_wq, &wc->writeback_work); 98448debafeSMikulas Patocka wc_unlock(wc); 98548debafeSMikulas Patocka 98648debafeSMikulas Patocka flush_workqueue(wc->writeback_wq); 98748debafeSMikulas Patocka 98848debafeSMikulas Patocka wc_lock(wc); 98948debafeSMikulas Patocka wc->writeback_all--; 99048debafeSMikulas Patocka if (writecache_has_error(wc)) { 99148debafeSMikulas Patocka wc_unlock(wc); 99248debafeSMikulas Patocka return -EIO; 99348debafeSMikulas Patocka } 99448debafeSMikulas Patocka wc_unlock(wc); 99548debafeSMikulas Patocka 99648debafeSMikulas Patocka return 0; 99748debafeSMikulas Patocka } 99848debafeSMikulas Patocka 99948debafeSMikulas Patocka static int process_flush_on_suspend_mesg(unsigned argc, char **argv, struct dm_writecache *wc) 100048debafeSMikulas Patocka { 100148debafeSMikulas Patocka if (argc != 1) 100248debafeSMikulas Patocka return -EINVAL; 100348debafeSMikulas Patocka 100448debafeSMikulas Patocka wc_lock(wc); 100548debafeSMikulas Patocka wc->flush_on_suspend = true; 100648debafeSMikulas Patocka wc_unlock(wc); 100748debafeSMikulas Patocka 100848debafeSMikulas Patocka return 0; 100948debafeSMikulas Patocka } 101048debafeSMikulas Patocka 101148debafeSMikulas Patocka static int writecache_message(struct dm_target *ti, unsigned argc, char **argv, 101248debafeSMikulas Patocka char *result, unsigned maxlen) 101348debafeSMikulas Patocka { 101448debafeSMikulas Patocka int r = -EINVAL; 101548debafeSMikulas Patocka struct dm_writecache *wc = ti->private; 101648debafeSMikulas Patocka 101748debafeSMikulas Patocka if (!strcasecmp(argv[0], "flush")) 101848debafeSMikulas Patocka r = process_flush_mesg(argc, argv, wc); 101948debafeSMikulas Patocka else if (!strcasecmp(argv[0], "flush_on_suspend")) 102048debafeSMikulas Patocka r = process_flush_on_suspend_mesg(argc, argv, wc); 102148debafeSMikulas Patocka else 102248debafeSMikulas Patocka DMERR("unrecognised message received: %s", argv[0]); 102348debafeSMikulas Patocka 102448debafeSMikulas Patocka return r; 102548debafeSMikulas Patocka } 102648debafeSMikulas Patocka 102748debafeSMikulas Patocka static void bio_copy_block(struct dm_writecache *wc, struct bio *bio, void *data) 102848debafeSMikulas Patocka { 102948debafeSMikulas Patocka void *buf; 103048debafeSMikulas Patocka unsigned long flags; 103148debafeSMikulas Patocka unsigned size; 103248debafeSMikulas Patocka int rw = bio_data_dir(bio); 103348debafeSMikulas Patocka unsigned remaining_size = wc->block_size; 103448debafeSMikulas Patocka 103548debafeSMikulas Patocka do { 103648debafeSMikulas Patocka struct bio_vec bv = bio_iter_iovec(bio, bio->bi_iter); 103748debafeSMikulas Patocka buf = bvec_kmap_irq(&bv, &flags); 103848debafeSMikulas Patocka size = bv.bv_len; 103948debafeSMikulas Patocka if (unlikely(size > remaining_size)) 104048debafeSMikulas Patocka size = remaining_size; 104148debafeSMikulas Patocka 104248debafeSMikulas Patocka if (rw == READ) { 104348debafeSMikulas Patocka int r; 104448debafeSMikulas Patocka r = memcpy_mcsafe(buf, data, size); 104548debafeSMikulas Patocka flush_dcache_page(bio_page(bio)); 104648debafeSMikulas Patocka if (unlikely(r)) { 104748debafeSMikulas Patocka writecache_error(wc, r, "hardware memory error when reading data: %d", r); 104848debafeSMikulas Patocka bio->bi_status = BLK_STS_IOERR; 104948debafeSMikulas Patocka } 105048debafeSMikulas Patocka } else { 105148debafeSMikulas Patocka flush_dcache_page(bio_page(bio)); 105248debafeSMikulas Patocka memcpy_flushcache(data, buf, size); 105348debafeSMikulas Patocka } 105448debafeSMikulas Patocka 105548debafeSMikulas Patocka bvec_kunmap_irq(buf, &flags); 105648debafeSMikulas Patocka 105748debafeSMikulas Patocka data = (char *)data + size; 105848debafeSMikulas Patocka remaining_size -= size; 105948debafeSMikulas Patocka bio_advance(bio, size); 106048debafeSMikulas Patocka } while (unlikely(remaining_size)); 106148debafeSMikulas Patocka } 106248debafeSMikulas Patocka 106348debafeSMikulas Patocka static int writecache_flush_thread(void *data) 106448debafeSMikulas Patocka { 106548debafeSMikulas Patocka struct dm_writecache *wc = data; 106648debafeSMikulas Patocka 106748debafeSMikulas Patocka while (1) { 106848debafeSMikulas Patocka struct bio *bio; 106948debafeSMikulas Patocka 107048debafeSMikulas Patocka wc_lock(wc); 107148debafeSMikulas Patocka bio = bio_list_pop(&wc->flush_list); 107248debafeSMikulas Patocka if (!bio) { 107348debafeSMikulas Patocka set_current_state(TASK_INTERRUPTIBLE); 107448debafeSMikulas Patocka wc_unlock(wc); 107548debafeSMikulas Patocka 107648debafeSMikulas Patocka if (unlikely(kthread_should_stop())) { 107748debafeSMikulas Patocka set_current_state(TASK_RUNNING); 107848debafeSMikulas Patocka break; 107948debafeSMikulas Patocka } 108048debafeSMikulas Patocka 108148debafeSMikulas Patocka schedule(); 108248debafeSMikulas Patocka continue; 108348debafeSMikulas Patocka } 108448debafeSMikulas Patocka 108548debafeSMikulas Patocka if (bio_op(bio) == REQ_OP_DISCARD) { 108648debafeSMikulas Patocka writecache_discard(wc, bio->bi_iter.bi_sector, 108748debafeSMikulas Patocka bio_end_sector(bio)); 108848debafeSMikulas Patocka wc_unlock(wc); 108948debafeSMikulas Patocka bio_set_dev(bio, wc->dev->bdev); 109048debafeSMikulas Patocka generic_make_request(bio); 109148debafeSMikulas Patocka } else { 109248debafeSMikulas Patocka writecache_flush(wc); 109348debafeSMikulas Patocka wc_unlock(wc); 109448debafeSMikulas Patocka if (writecache_has_error(wc)) 109548debafeSMikulas Patocka bio->bi_status = BLK_STS_IOERR; 109648debafeSMikulas Patocka bio_endio(bio); 109748debafeSMikulas Patocka } 109848debafeSMikulas Patocka } 109948debafeSMikulas Patocka 110048debafeSMikulas Patocka return 0; 110148debafeSMikulas Patocka } 110248debafeSMikulas Patocka 110348debafeSMikulas Patocka static void writecache_offload_bio(struct dm_writecache *wc, struct bio *bio) 110448debafeSMikulas Patocka { 110548debafeSMikulas Patocka if (bio_list_empty(&wc->flush_list)) 110648debafeSMikulas Patocka wake_up_process(wc->flush_thread); 110748debafeSMikulas Patocka bio_list_add(&wc->flush_list, bio); 110848debafeSMikulas Patocka } 110948debafeSMikulas Patocka 111048debafeSMikulas Patocka static int writecache_map(struct dm_target *ti, struct bio *bio) 111148debafeSMikulas Patocka { 111248debafeSMikulas Patocka struct wc_entry *e; 111348debafeSMikulas Patocka struct dm_writecache *wc = ti->private; 111448debafeSMikulas Patocka 111548debafeSMikulas Patocka bio->bi_private = NULL; 111648debafeSMikulas Patocka 111748debafeSMikulas Patocka wc_lock(wc); 111848debafeSMikulas Patocka 111948debafeSMikulas Patocka if (unlikely(bio->bi_opf & REQ_PREFLUSH)) { 112048debafeSMikulas Patocka if (writecache_has_error(wc)) 112148debafeSMikulas Patocka goto unlock_error; 112248debafeSMikulas Patocka if (WC_MODE_PMEM(wc)) { 112348debafeSMikulas Patocka writecache_flush(wc); 112448debafeSMikulas Patocka if (writecache_has_error(wc)) 112548debafeSMikulas Patocka goto unlock_error; 112648debafeSMikulas Patocka goto unlock_submit; 112748debafeSMikulas Patocka } else { 112848debafeSMikulas Patocka writecache_offload_bio(wc, bio); 112948debafeSMikulas Patocka goto unlock_return; 113048debafeSMikulas Patocka } 113148debafeSMikulas Patocka } 113248debafeSMikulas Patocka 113348debafeSMikulas Patocka bio->bi_iter.bi_sector = dm_target_offset(ti, bio->bi_iter.bi_sector); 113448debafeSMikulas Patocka 113548debafeSMikulas Patocka if (unlikely((((unsigned)bio->bi_iter.bi_sector | bio_sectors(bio)) & 113648debafeSMikulas Patocka (wc->block_size / 512 - 1)) != 0)) { 113748debafeSMikulas Patocka DMERR("I/O is not aligned, sector %llu, size %u, block size %u", 113848debafeSMikulas Patocka (unsigned long long)bio->bi_iter.bi_sector, 113948debafeSMikulas Patocka bio->bi_iter.bi_size, wc->block_size); 114048debafeSMikulas Patocka goto unlock_error; 114148debafeSMikulas Patocka } 114248debafeSMikulas Patocka 114348debafeSMikulas Patocka if (unlikely(bio_op(bio) == REQ_OP_DISCARD)) { 114448debafeSMikulas Patocka if (writecache_has_error(wc)) 114548debafeSMikulas Patocka goto unlock_error; 114648debafeSMikulas Patocka if (WC_MODE_PMEM(wc)) { 114748debafeSMikulas Patocka writecache_discard(wc, bio->bi_iter.bi_sector, bio_end_sector(bio)); 114848debafeSMikulas Patocka goto unlock_remap_origin; 114948debafeSMikulas Patocka } else { 115048debafeSMikulas Patocka writecache_offload_bio(wc, bio); 115148debafeSMikulas Patocka goto unlock_return; 115248debafeSMikulas Patocka } 115348debafeSMikulas Patocka } 115448debafeSMikulas Patocka 115548debafeSMikulas Patocka if (bio_data_dir(bio) == READ) { 115648debafeSMikulas Patocka read_next_block: 115748debafeSMikulas Patocka e = writecache_find_entry(wc, bio->bi_iter.bi_sector, WFE_RETURN_FOLLOWING); 115848debafeSMikulas Patocka if (e && read_original_sector(wc, e) == bio->bi_iter.bi_sector) { 115948debafeSMikulas Patocka if (WC_MODE_PMEM(wc)) { 116048debafeSMikulas Patocka bio_copy_block(wc, bio, memory_data(wc, e)); 116148debafeSMikulas Patocka if (bio->bi_iter.bi_size) 116248debafeSMikulas Patocka goto read_next_block; 116348debafeSMikulas Patocka goto unlock_submit; 116448debafeSMikulas Patocka } else { 116548debafeSMikulas Patocka dm_accept_partial_bio(bio, wc->block_size >> SECTOR_SHIFT); 116648debafeSMikulas Patocka bio_set_dev(bio, wc->ssd_dev->bdev); 116748debafeSMikulas Patocka bio->bi_iter.bi_sector = cache_sector(wc, e); 116848debafeSMikulas Patocka if (!writecache_entry_is_committed(wc, e)) 116948debafeSMikulas Patocka writecache_wait_for_ios(wc, WRITE); 117048debafeSMikulas Patocka goto unlock_remap; 117148debafeSMikulas Patocka } 117248debafeSMikulas Patocka } else { 117348debafeSMikulas Patocka if (e) { 117448debafeSMikulas Patocka sector_t next_boundary = 117548debafeSMikulas Patocka read_original_sector(wc, e) - bio->bi_iter.bi_sector; 117648debafeSMikulas Patocka if (next_boundary < bio->bi_iter.bi_size >> SECTOR_SHIFT) { 117748debafeSMikulas Patocka dm_accept_partial_bio(bio, next_boundary); 117848debafeSMikulas Patocka } 117948debafeSMikulas Patocka } 118048debafeSMikulas Patocka goto unlock_remap_origin; 118148debafeSMikulas Patocka } 118248debafeSMikulas Patocka } else { 118348debafeSMikulas Patocka do { 118448debafeSMikulas Patocka if (writecache_has_error(wc)) 118548debafeSMikulas Patocka goto unlock_error; 118648debafeSMikulas Patocka e = writecache_find_entry(wc, bio->bi_iter.bi_sector, 0); 118748debafeSMikulas Patocka if (e) { 118848debafeSMikulas Patocka if (!writecache_entry_is_committed(wc, e)) 118948debafeSMikulas Patocka goto bio_copy; 119048debafeSMikulas Patocka if (!WC_MODE_PMEM(wc) && !e->write_in_progress) { 119148debafeSMikulas Patocka wc->overwrote_committed = true; 119248debafeSMikulas Patocka goto bio_copy; 119348debafeSMikulas Patocka } 119448debafeSMikulas Patocka } 119548debafeSMikulas Patocka e = writecache_pop_from_freelist(wc); 119648debafeSMikulas Patocka if (unlikely(!e)) { 119748debafeSMikulas Patocka writecache_wait_on_freelist(wc); 119848debafeSMikulas Patocka continue; 119948debafeSMikulas Patocka } 120048debafeSMikulas Patocka write_original_sector_seq_count(wc, e, bio->bi_iter.bi_sector, wc->seq_count); 120148debafeSMikulas Patocka writecache_insert_entry(wc, e); 120248debafeSMikulas Patocka wc->uncommitted_blocks++; 120348debafeSMikulas Patocka bio_copy: 120448debafeSMikulas Patocka if (WC_MODE_PMEM(wc)) { 120548debafeSMikulas Patocka bio_copy_block(wc, bio, memory_data(wc, e)); 120648debafeSMikulas Patocka } else { 120748debafeSMikulas Patocka dm_accept_partial_bio(bio, wc->block_size >> SECTOR_SHIFT); 120848debafeSMikulas Patocka bio_set_dev(bio, wc->ssd_dev->bdev); 120948debafeSMikulas Patocka bio->bi_iter.bi_sector = cache_sector(wc, e); 121048debafeSMikulas Patocka if (unlikely(wc->uncommitted_blocks >= wc->autocommit_blocks)) { 121148debafeSMikulas Patocka wc->uncommitted_blocks = 0; 121248debafeSMikulas Patocka queue_work(wc->writeback_wq, &wc->flush_work); 121348debafeSMikulas Patocka } else { 121448debafeSMikulas Patocka writecache_schedule_autocommit(wc); 121548debafeSMikulas Patocka } 121648debafeSMikulas Patocka goto unlock_remap; 121748debafeSMikulas Patocka } 121848debafeSMikulas Patocka } while (bio->bi_iter.bi_size); 121948debafeSMikulas Patocka 122048debafeSMikulas Patocka if (unlikely(wc->uncommitted_blocks >= wc->autocommit_blocks)) 122148debafeSMikulas Patocka writecache_flush(wc); 122248debafeSMikulas Patocka else 122348debafeSMikulas Patocka writecache_schedule_autocommit(wc); 122448debafeSMikulas Patocka goto unlock_submit; 122548debafeSMikulas Patocka } 122648debafeSMikulas Patocka 122748debafeSMikulas Patocka unlock_remap_origin: 122848debafeSMikulas Patocka bio_set_dev(bio, wc->dev->bdev); 122948debafeSMikulas Patocka wc_unlock(wc); 123048debafeSMikulas Patocka return DM_MAPIO_REMAPPED; 123148debafeSMikulas Patocka 123248debafeSMikulas Patocka unlock_remap: 123348debafeSMikulas Patocka /* make sure that writecache_end_io decrements bio_in_progress: */ 123448debafeSMikulas Patocka bio->bi_private = (void *)1; 123548debafeSMikulas Patocka atomic_inc(&wc->bio_in_progress[bio_data_dir(bio)]); 123648debafeSMikulas Patocka wc_unlock(wc); 123748debafeSMikulas Patocka return DM_MAPIO_REMAPPED; 123848debafeSMikulas Patocka 123948debafeSMikulas Patocka unlock_submit: 124048debafeSMikulas Patocka wc_unlock(wc); 124148debafeSMikulas Patocka bio_endio(bio); 124248debafeSMikulas Patocka return DM_MAPIO_SUBMITTED; 124348debafeSMikulas Patocka 124448debafeSMikulas Patocka unlock_return: 124548debafeSMikulas Patocka wc_unlock(wc); 124648debafeSMikulas Patocka return DM_MAPIO_SUBMITTED; 124748debafeSMikulas Patocka 124848debafeSMikulas Patocka unlock_error: 124948debafeSMikulas Patocka wc_unlock(wc); 125048debafeSMikulas Patocka bio_io_error(bio); 125148debafeSMikulas Patocka return DM_MAPIO_SUBMITTED; 125248debafeSMikulas Patocka } 125348debafeSMikulas Patocka 125448debafeSMikulas Patocka static int writecache_end_io(struct dm_target *ti, struct bio *bio, blk_status_t *status) 125548debafeSMikulas Patocka { 125648debafeSMikulas Patocka struct dm_writecache *wc = ti->private; 125748debafeSMikulas Patocka 125848debafeSMikulas Patocka if (bio->bi_private != NULL) { 125948debafeSMikulas Patocka int dir = bio_data_dir(bio); 126048debafeSMikulas Patocka if (atomic_dec_and_test(&wc->bio_in_progress[dir])) 126148debafeSMikulas Patocka if (unlikely(waitqueue_active(&wc->bio_in_progress_wait[dir]))) 126248debafeSMikulas Patocka wake_up(&wc->bio_in_progress_wait[dir]); 126348debafeSMikulas Patocka } 126448debafeSMikulas Patocka return 0; 126548debafeSMikulas Patocka } 126648debafeSMikulas Patocka 126748debafeSMikulas Patocka static int writecache_iterate_devices(struct dm_target *ti, 126848debafeSMikulas Patocka iterate_devices_callout_fn fn, void *data) 126948debafeSMikulas Patocka { 127048debafeSMikulas Patocka struct dm_writecache *wc = ti->private; 127148debafeSMikulas Patocka 127248debafeSMikulas Patocka return fn(ti, wc->dev, 0, ti->len, data); 127348debafeSMikulas Patocka } 127448debafeSMikulas Patocka 127548debafeSMikulas Patocka static void writecache_io_hints(struct dm_target *ti, struct queue_limits *limits) 127648debafeSMikulas Patocka { 127748debafeSMikulas Patocka struct dm_writecache *wc = ti->private; 127848debafeSMikulas Patocka 127948debafeSMikulas Patocka if (limits->logical_block_size < wc->block_size) 128048debafeSMikulas Patocka limits->logical_block_size = wc->block_size; 128148debafeSMikulas Patocka 128248debafeSMikulas Patocka if (limits->physical_block_size < wc->block_size) 128348debafeSMikulas Patocka limits->physical_block_size = wc->block_size; 128448debafeSMikulas Patocka 128548debafeSMikulas Patocka if (limits->io_min < wc->block_size) 128648debafeSMikulas Patocka limits->io_min = wc->block_size; 128748debafeSMikulas Patocka } 128848debafeSMikulas Patocka 128948debafeSMikulas Patocka 129048debafeSMikulas Patocka static void writecache_writeback_endio(struct bio *bio) 129148debafeSMikulas Patocka { 129248debafeSMikulas Patocka struct writeback_struct *wb = container_of(bio, struct writeback_struct, bio); 129348debafeSMikulas Patocka struct dm_writecache *wc = wb->wc; 129448debafeSMikulas Patocka unsigned long flags; 129548debafeSMikulas Patocka 129648debafeSMikulas Patocka raw_spin_lock_irqsave(&wc->endio_list_lock, flags); 129748debafeSMikulas Patocka if (unlikely(list_empty(&wc->endio_list))) 129848debafeSMikulas Patocka wake_up_process(wc->endio_thread); 129948debafeSMikulas Patocka list_add_tail(&wb->endio_entry, &wc->endio_list); 130048debafeSMikulas Patocka raw_spin_unlock_irqrestore(&wc->endio_list_lock, flags); 130148debafeSMikulas Patocka } 130248debafeSMikulas Patocka 130348debafeSMikulas Patocka static void writecache_copy_endio(int read_err, unsigned long write_err, void *ptr) 130448debafeSMikulas Patocka { 130548debafeSMikulas Patocka struct copy_struct *c = ptr; 130648debafeSMikulas Patocka struct dm_writecache *wc = c->wc; 130748debafeSMikulas Patocka 130848debafeSMikulas Patocka c->error = likely(!(read_err | write_err)) ? 0 : -EIO; 130948debafeSMikulas Patocka 131048debafeSMikulas Patocka raw_spin_lock_irq(&wc->endio_list_lock); 131148debafeSMikulas Patocka if (unlikely(list_empty(&wc->endio_list))) 131248debafeSMikulas Patocka wake_up_process(wc->endio_thread); 131348debafeSMikulas Patocka list_add_tail(&c->endio_entry, &wc->endio_list); 131448debafeSMikulas Patocka raw_spin_unlock_irq(&wc->endio_list_lock); 131548debafeSMikulas Patocka } 131648debafeSMikulas Patocka 131748debafeSMikulas Patocka static void __writecache_endio_pmem(struct dm_writecache *wc, struct list_head *list) 131848debafeSMikulas Patocka { 131948debafeSMikulas Patocka unsigned i; 132048debafeSMikulas Patocka struct writeback_struct *wb; 132148debafeSMikulas Patocka struct wc_entry *e; 132248debafeSMikulas Patocka unsigned long n_walked = 0; 132348debafeSMikulas Patocka 132448debafeSMikulas Patocka do { 132548debafeSMikulas Patocka wb = list_entry(list->next, struct writeback_struct, endio_entry); 132648debafeSMikulas Patocka list_del(&wb->endio_entry); 132748debafeSMikulas Patocka 132848debafeSMikulas Patocka if (unlikely(wb->bio.bi_status != BLK_STS_OK)) 132948debafeSMikulas Patocka writecache_error(wc, blk_status_to_errno(wb->bio.bi_status), 133048debafeSMikulas Patocka "write error %d", wb->bio.bi_status); 133148debafeSMikulas Patocka i = 0; 133248debafeSMikulas Patocka do { 133348debafeSMikulas Patocka e = wb->wc_list[i]; 133448debafeSMikulas Patocka BUG_ON(!e->write_in_progress); 133548debafeSMikulas Patocka e->write_in_progress = false; 133648debafeSMikulas Patocka INIT_LIST_HEAD(&e->lru); 133748debafeSMikulas Patocka if (!writecache_has_error(wc)) 133848debafeSMikulas Patocka writecache_free_entry(wc, e); 133948debafeSMikulas Patocka BUG_ON(!wc->writeback_size); 134048debafeSMikulas Patocka wc->writeback_size--; 134148debafeSMikulas Patocka n_walked++; 134248debafeSMikulas Patocka if (unlikely(n_walked >= ENDIO_LATENCY)) { 134348debafeSMikulas Patocka writecache_commit_flushed(wc); 134448debafeSMikulas Patocka wc_unlock(wc); 134548debafeSMikulas Patocka wc_lock(wc); 134648debafeSMikulas Patocka n_walked = 0; 134748debafeSMikulas Patocka } 134848debafeSMikulas Patocka } while (++i < wb->wc_list_n); 134948debafeSMikulas Patocka 135048debafeSMikulas Patocka if (wb->wc_list != wb->wc_list_inline) 135148debafeSMikulas Patocka kfree(wb->wc_list); 135248debafeSMikulas Patocka bio_put(&wb->bio); 135348debafeSMikulas Patocka } while (!list_empty(list)); 135448debafeSMikulas Patocka } 135548debafeSMikulas Patocka 135648debafeSMikulas Patocka static void __writecache_endio_ssd(struct dm_writecache *wc, struct list_head *list) 135748debafeSMikulas Patocka { 135848debafeSMikulas Patocka struct copy_struct *c; 135948debafeSMikulas Patocka struct wc_entry *e; 136048debafeSMikulas Patocka 136148debafeSMikulas Patocka do { 136248debafeSMikulas Patocka c = list_entry(list->next, struct copy_struct, endio_entry); 136348debafeSMikulas Patocka list_del(&c->endio_entry); 136448debafeSMikulas Patocka 136548debafeSMikulas Patocka if (unlikely(c->error)) 136648debafeSMikulas Patocka writecache_error(wc, c->error, "copy error"); 136748debafeSMikulas Patocka 136848debafeSMikulas Patocka e = c->e; 136948debafeSMikulas Patocka do { 137048debafeSMikulas Patocka BUG_ON(!e->write_in_progress); 137148debafeSMikulas Patocka e->write_in_progress = false; 137248debafeSMikulas Patocka INIT_LIST_HEAD(&e->lru); 137348debafeSMikulas Patocka if (!writecache_has_error(wc)) 137448debafeSMikulas Patocka writecache_free_entry(wc, e); 137548debafeSMikulas Patocka 137648debafeSMikulas Patocka BUG_ON(!wc->writeback_size); 137748debafeSMikulas Patocka wc->writeback_size--; 137848debafeSMikulas Patocka e++; 137948debafeSMikulas Patocka } while (--c->n_entries); 138048debafeSMikulas Patocka mempool_free(c, &wc->copy_pool); 138148debafeSMikulas Patocka } while (!list_empty(list)); 138248debafeSMikulas Patocka } 138348debafeSMikulas Patocka 138448debafeSMikulas Patocka static int writecache_endio_thread(void *data) 138548debafeSMikulas Patocka { 138648debafeSMikulas Patocka struct dm_writecache *wc = data; 138748debafeSMikulas Patocka 138848debafeSMikulas Patocka while (1) { 138948debafeSMikulas Patocka struct list_head list; 139048debafeSMikulas Patocka 139148debafeSMikulas Patocka raw_spin_lock_irq(&wc->endio_list_lock); 139248debafeSMikulas Patocka if (!list_empty(&wc->endio_list)) 139348debafeSMikulas Patocka goto pop_from_list; 139448debafeSMikulas Patocka set_current_state(TASK_INTERRUPTIBLE); 139548debafeSMikulas Patocka raw_spin_unlock_irq(&wc->endio_list_lock); 139648debafeSMikulas Patocka 139748debafeSMikulas Patocka if (unlikely(kthread_should_stop())) { 139848debafeSMikulas Patocka set_current_state(TASK_RUNNING); 139948debafeSMikulas Patocka break; 140048debafeSMikulas Patocka } 140148debafeSMikulas Patocka 140248debafeSMikulas Patocka schedule(); 140348debafeSMikulas Patocka 140448debafeSMikulas Patocka continue; 140548debafeSMikulas Patocka 140648debafeSMikulas Patocka pop_from_list: 140748debafeSMikulas Patocka list = wc->endio_list; 140848debafeSMikulas Patocka list.next->prev = list.prev->next = &list; 140948debafeSMikulas Patocka INIT_LIST_HEAD(&wc->endio_list); 141048debafeSMikulas Patocka raw_spin_unlock_irq(&wc->endio_list_lock); 141148debafeSMikulas Patocka 141248debafeSMikulas Patocka if (!WC_MODE_FUA(wc)) 141348debafeSMikulas Patocka writecache_disk_flush(wc, wc->dev); 141448debafeSMikulas Patocka 141548debafeSMikulas Patocka wc_lock(wc); 141648debafeSMikulas Patocka 141748debafeSMikulas Patocka if (WC_MODE_PMEM(wc)) { 141848debafeSMikulas Patocka __writecache_endio_pmem(wc, &list); 141948debafeSMikulas Patocka } else { 142048debafeSMikulas Patocka __writecache_endio_ssd(wc, &list); 142148debafeSMikulas Patocka writecache_wait_for_ios(wc, READ); 142248debafeSMikulas Patocka } 142348debafeSMikulas Patocka 142448debafeSMikulas Patocka writecache_commit_flushed(wc); 142548debafeSMikulas Patocka 142648debafeSMikulas Patocka wc_unlock(wc); 142748debafeSMikulas Patocka } 142848debafeSMikulas Patocka 142948debafeSMikulas Patocka return 0; 143048debafeSMikulas Patocka } 143148debafeSMikulas Patocka 143248debafeSMikulas Patocka static bool wc_add_block(struct writeback_struct *wb, struct wc_entry *e, gfp_t gfp) 143348debafeSMikulas Patocka { 143448debafeSMikulas Patocka struct dm_writecache *wc = wb->wc; 143548debafeSMikulas Patocka unsigned block_size = wc->block_size; 143648debafeSMikulas Patocka void *address = memory_data(wc, e); 143748debafeSMikulas Patocka 143848debafeSMikulas Patocka persistent_memory_flush_cache(address, block_size); 143948debafeSMikulas Patocka return bio_add_page(&wb->bio, persistent_memory_page(address), 144048debafeSMikulas Patocka block_size, persistent_memory_page_offset(address)) != 0; 144148debafeSMikulas Patocka } 144248debafeSMikulas Patocka 144348debafeSMikulas Patocka struct writeback_list { 144448debafeSMikulas Patocka struct list_head list; 144548debafeSMikulas Patocka size_t size; 144648debafeSMikulas Patocka }; 144748debafeSMikulas Patocka 144848debafeSMikulas Patocka static void __writeback_throttle(struct dm_writecache *wc, struct writeback_list *wbl) 144948debafeSMikulas Patocka { 145048debafeSMikulas Patocka if (unlikely(wc->max_writeback_jobs)) { 145148debafeSMikulas Patocka if (READ_ONCE(wc->writeback_size) - wbl->size >= wc->max_writeback_jobs) { 145248debafeSMikulas Patocka wc_lock(wc); 145348debafeSMikulas Patocka while (wc->writeback_size - wbl->size >= wc->max_writeback_jobs) 145448debafeSMikulas Patocka writecache_wait_on_freelist(wc); 145548debafeSMikulas Patocka wc_unlock(wc); 145648debafeSMikulas Patocka } 145748debafeSMikulas Patocka } 145848debafeSMikulas Patocka cond_resched(); 145948debafeSMikulas Patocka } 146048debafeSMikulas Patocka 146148debafeSMikulas Patocka static void __writecache_writeback_pmem(struct dm_writecache *wc, struct writeback_list *wbl) 146248debafeSMikulas Patocka { 146348debafeSMikulas Patocka struct wc_entry *e, *f; 146448debafeSMikulas Patocka struct bio *bio; 146548debafeSMikulas Patocka struct writeback_struct *wb; 146648debafeSMikulas Patocka unsigned max_pages; 146748debafeSMikulas Patocka 146848debafeSMikulas Patocka while (wbl->size) { 146948debafeSMikulas Patocka wbl->size--; 147048debafeSMikulas Patocka e = container_of(wbl->list.prev, struct wc_entry, lru); 147148debafeSMikulas Patocka list_del(&e->lru); 147248debafeSMikulas Patocka 147348debafeSMikulas Patocka max_pages = e->wc_list_contiguous; 147448debafeSMikulas Patocka 147548debafeSMikulas Patocka bio = bio_alloc_bioset(GFP_NOIO, max_pages, &wc->bio_set); 147648debafeSMikulas Patocka wb = container_of(bio, struct writeback_struct, bio); 147748debafeSMikulas Patocka wb->wc = wc; 147809f2d656SHuaisheng Ye bio->bi_end_io = writecache_writeback_endio; 147909f2d656SHuaisheng Ye bio_set_dev(bio, wc->dev->bdev); 148009f2d656SHuaisheng Ye bio->bi_iter.bi_sector = read_original_sector(wc, e); 148148debafeSMikulas Patocka if (max_pages <= WB_LIST_INLINE || 148250a7d3baSKees Cook unlikely(!(wb->wc_list = kmalloc_array(max_pages, sizeof(struct wc_entry *), 148348debafeSMikulas Patocka GFP_NOIO | __GFP_NORETRY | 148448debafeSMikulas Patocka __GFP_NOMEMALLOC | __GFP_NOWARN)))) { 148548debafeSMikulas Patocka wb->wc_list = wb->wc_list_inline; 148648debafeSMikulas Patocka max_pages = WB_LIST_INLINE; 148748debafeSMikulas Patocka } 148848debafeSMikulas Patocka 148948debafeSMikulas Patocka BUG_ON(!wc_add_block(wb, e, GFP_NOIO)); 149048debafeSMikulas Patocka 149148debafeSMikulas Patocka wb->wc_list[0] = e; 149248debafeSMikulas Patocka wb->wc_list_n = 1; 149348debafeSMikulas Patocka 149448debafeSMikulas Patocka while (wbl->size && wb->wc_list_n < max_pages) { 149548debafeSMikulas Patocka f = container_of(wbl->list.prev, struct wc_entry, lru); 149648debafeSMikulas Patocka if (read_original_sector(wc, f) != 149748debafeSMikulas Patocka read_original_sector(wc, e) + (wc->block_size >> SECTOR_SHIFT)) 149848debafeSMikulas Patocka break; 149948debafeSMikulas Patocka if (!wc_add_block(wb, f, GFP_NOWAIT | __GFP_NOWARN)) 150048debafeSMikulas Patocka break; 150148debafeSMikulas Patocka wbl->size--; 150248debafeSMikulas Patocka list_del(&f->lru); 150348debafeSMikulas Patocka wb->wc_list[wb->wc_list_n++] = f; 150448debafeSMikulas Patocka e = f; 150548debafeSMikulas Patocka } 150609f2d656SHuaisheng Ye bio_set_op_attrs(bio, REQ_OP_WRITE, WC_MODE_FUA(wc) * REQ_FUA); 150748debafeSMikulas Patocka if (writecache_has_error(wc)) { 150848debafeSMikulas Patocka bio->bi_status = BLK_STS_IOERR; 150909f2d656SHuaisheng Ye bio_endio(bio); 151048debafeSMikulas Patocka } else { 151109f2d656SHuaisheng Ye submit_bio(bio); 151248debafeSMikulas Patocka } 151348debafeSMikulas Patocka 151448debafeSMikulas Patocka __writeback_throttle(wc, wbl); 151548debafeSMikulas Patocka } 151648debafeSMikulas Patocka } 151748debafeSMikulas Patocka 151848debafeSMikulas Patocka static void __writecache_writeback_ssd(struct dm_writecache *wc, struct writeback_list *wbl) 151948debafeSMikulas Patocka { 152048debafeSMikulas Patocka struct wc_entry *e, *f; 152148debafeSMikulas Patocka struct dm_io_region from, to; 152248debafeSMikulas Patocka struct copy_struct *c; 152348debafeSMikulas Patocka 152448debafeSMikulas Patocka while (wbl->size) { 152548debafeSMikulas Patocka unsigned n_sectors; 152648debafeSMikulas Patocka 152748debafeSMikulas Patocka wbl->size--; 152848debafeSMikulas Patocka e = container_of(wbl->list.prev, struct wc_entry, lru); 152948debafeSMikulas Patocka list_del(&e->lru); 153048debafeSMikulas Patocka 153148debafeSMikulas Patocka n_sectors = e->wc_list_contiguous << (wc->block_size_bits - SECTOR_SHIFT); 153248debafeSMikulas Patocka 153348debafeSMikulas Patocka from.bdev = wc->ssd_dev->bdev; 153448debafeSMikulas Patocka from.sector = cache_sector(wc, e); 153548debafeSMikulas Patocka from.count = n_sectors; 153648debafeSMikulas Patocka to.bdev = wc->dev->bdev; 153748debafeSMikulas Patocka to.sector = read_original_sector(wc, e); 153848debafeSMikulas Patocka to.count = n_sectors; 153948debafeSMikulas Patocka 154048debafeSMikulas Patocka c = mempool_alloc(&wc->copy_pool, GFP_NOIO); 154148debafeSMikulas Patocka c->wc = wc; 154248debafeSMikulas Patocka c->e = e; 154348debafeSMikulas Patocka c->n_entries = e->wc_list_contiguous; 154448debafeSMikulas Patocka 154548debafeSMikulas Patocka while ((n_sectors -= wc->block_size >> SECTOR_SHIFT)) { 154648debafeSMikulas Patocka wbl->size--; 154748debafeSMikulas Patocka f = container_of(wbl->list.prev, struct wc_entry, lru); 154848debafeSMikulas Patocka BUG_ON(f != e + 1); 154948debafeSMikulas Patocka list_del(&f->lru); 155048debafeSMikulas Patocka e = f; 155148debafeSMikulas Patocka } 155248debafeSMikulas Patocka 155348debafeSMikulas Patocka dm_kcopyd_copy(wc->dm_kcopyd, &from, 1, &to, 0, writecache_copy_endio, c); 155448debafeSMikulas Patocka 155548debafeSMikulas Patocka __writeback_throttle(wc, wbl); 155648debafeSMikulas Patocka } 155748debafeSMikulas Patocka } 155848debafeSMikulas Patocka 155948debafeSMikulas Patocka static void writecache_writeback(struct work_struct *work) 156048debafeSMikulas Patocka { 156148debafeSMikulas Patocka struct dm_writecache *wc = container_of(work, struct dm_writecache, writeback_work); 156248debafeSMikulas Patocka struct blk_plug plug; 1563*5229b489SHuaisheng Ye struct wc_entry *f, *g, *e = NULL; 156448debafeSMikulas Patocka struct rb_node *node, *next_node; 156548debafeSMikulas Patocka struct list_head skipped; 156648debafeSMikulas Patocka struct writeback_list wbl; 156748debafeSMikulas Patocka unsigned long n_walked; 156848debafeSMikulas Patocka 156948debafeSMikulas Patocka wc_lock(wc); 157048debafeSMikulas Patocka restart: 157148debafeSMikulas Patocka if (writecache_has_error(wc)) { 157248debafeSMikulas Patocka wc_unlock(wc); 157348debafeSMikulas Patocka return; 157448debafeSMikulas Patocka } 157548debafeSMikulas Patocka 157648debafeSMikulas Patocka if (unlikely(wc->writeback_all)) { 157748debafeSMikulas Patocka if (writecache_wait_for_writeback(wc)) 157848debafeSMikulas Patocka goto restart; 157948debafeSMikulas Patocka } 158048debafeSMikulas Patocka 158148debafeSMikulas Patocka if (wc->overwrote_committed) { 158248debafeSMikulas Patocka writecache_wait_for_ios(wc, WRITE); 158348debafeSMikulas Patocka } 158448debafeSMikulas Patocka 158548debafeSMikulas Patocka n_walked = 0; 158648debafeSMikulas Patocka INIT_LIST_HEAD(&skipped); 158748debafeSMikulas Patocka INIT_LIST_HEAD(&wbl.list); 158848debafeSMikulas Patocka wbl.size = 0; 158948debafeSMikulas Patocka while (!list_empty(&wc->lru) && 159048debafeSMikulas Patocka (wc->writeback_all || 159148debafeSMikulas Patocka wc->freelist_size + wc->writeback_size <= wc->freelist_low_watermark)) { 159248debafeSMikulas Patocka 159348debafeSMikulas Patocka n_walked++; 159448debafeSMikulas Patocka if (unlikely(n_walked > WRITEBACK_LATENCY) && 159548debafeSMikulas Patocka likely(!wc->writeback_all) && likely(!dm_suspended(wc->ti))) { 159648debafeSMikulas Patocka queue_work(wc->writeback_wq, &wc->writeback_work); 159748debafeSMikulas Patocka break; 159848debafeSMikulas Patocka } 159948debafeSMikulas Patocka 1600*5229b489SHuaisheng Ye if (unlikely(wc->writeback_all)) { 1601*5229b489SHuaisheng Ye if (unlikely(!e)) { 1602*5229b489SHuaisheng Ye writecache_flush(wc); 1603*5229b489SHuaisheng Ye e = container_of(rb_first(&wc->tree), struct wc_entry, rb_node); 1604*5229b489SHuaisheng Ye } else 1605*5229b489SHuaisheng Ye e = g; 1606*5229b489SHuaisheng Ye } else 160748debafeSMikulas Patocka e = container_of(wc->lru.prev, struct wc_entry, lru); 160848debafeSMikulas Patocka BUG_ON(e->write_in_progress); 160948debafeSMikulas Patocka if (unlikely(!writecache_entry_is_committed(wc, e))) { 161048debafeSMikulas Patocka writecache_flush(wc); 161148debafeSMikulas Patocka } 161248debafeSMikulas Patocka node = rb_prev(&e->rb_node); 161348debafeSMikulas Patocka if (node) { 161448debafeSMikulas Patocka f = container_of(node, struct wc_entry, rb_node); 161548debafeSMikulas Patocka if (unlikely(read_original_sector(wc, f) == 161648debafeSMikulas Patocka read_original_sector(wc, e))) { 161748debafeSMikulas Patocka BUG_ON(!f->write_in_progress); 161848debafeSMikulas Patocka list_del(&e->lru); 161948debafeSMikulas Patocka list_add(&e->lru, &skipped); 162048debafeSMikulas Patocka cond_resched(); 162148debafeSMikulas Patocka continue; 162248debafeSMikulas Patocka } 162348debafeSMikulas Patocka } 162448debafeSMikulas Patocka wc->writeback_size++; 162548debafeSMikulas Patocka list_del(&e->lru); 162648debafeSMikulas Patocka list_add(&e->lru, &wbl.list); 162748debafeSMikulas Patocka wbl.size++; 162848debafeSMikulas Patocka e->write_in_progress = true; 162948debafeSMikulas Patocka e->wc_list_contiguous = 1; 163048debafeSMikulas Patocka 163148debafeSMikulas Patocka f = e; 163248debafeSMikulas Patocka 163348debafeSMikulas Patocka while (1) { 163448debafeSMikulas Patocka next_node = rb_next(&f->rb_node); 163548debafeSMikulas Patocka if (unlikely(!next_node)) 163648debafeSMikulas Patocka break; 163748debafeSMikulas Patocka g = container_of(next_node, struct wc_entry, rb_node); 163862421b38SHuaisheng Ye if (unlikely(read_original_sector(wc, g) == 163962421b38SHuaisheng Ye read_original_sector(wc, f))) { 164048debafeSMikulas Patocka f = g; 164148debafeSMikulas Patocka continue; 164248debafeSMikulas Patocka } 164348debafeSMikulas Patocka if (read_original_sector(wc, g) != 164448debafeSMikulas Patocka read_original_sector(wc, f) + (wc->block_size >> SECTOR_SHIFT)) 164548debafeSMikulas Patocka break; 164648debafeSMikulas Patocka if (unlikely(g->write_in_progress)) 164748debafeSMikulas Patocka break; 164848debafeSMikulas Patocka if (unlikely(!writecache_entry_is_committed(wc, g))) 164948debafeSMikulas Patocka break; 165048debafeSMikulas Patocka 165148debafeSMikulas Patocka if (!WC_MODE_PMEM(wc)) { 165248debafeSMikulas Patocka if (g != f + 1) 165348debafeSMikulas Patocka break; 165448debafeSMikulas Patocka } 165548debafeSMikulas Patocka 165648debafeSMikulas Patocka n_walked++; 165748debafeSMikulas Patocka //if (unlikely(n_walked > WRITEBACK_LATENCY) && likely(!wc->writeback_all)) 165848debafeSMikulas Patocka // break; 165948debafeSMikulas Patocka 166048debafeSMikulas Patocka wc->writeback_size++; 166148debafeSMikulas Patocka list_del(&g->lru); 166248debafeSMikulas Patocka list_add(&g->lru, &wbl.list); 166348debafeSMikulas Patocka wbl.size++; 166448debafeSMikulas Patocka g->write_in_progress = true; 166548debafeSMikulas Patocka g->wc_list_contiguous = BIO_MAX_PAGES; 166648debafeSMikulas Patocka f = g; 166748debafeSMikulas Patocka e->wc_list_contiguous++; 1668*5229b489SHuaisheng Ye if (unlikely(e->wc_list_contiguous == BIO_MAX_PAGES)) { 1669*5229b489SHuaisheng Ye if (unlikely(wc->writeback_all)) { 1670*5229b489SHuaisheng Ye next_node = rb_next(&f->rb_node); 1671*5229b489SHuaisheng Ye if (likely(next_node)) 1672*5229b489SHuaisheng Ye g = container_of(next_node, struct wc_entry, rb_node); 1673*5229b489SHuaisheng Ye } 167448debafeSMikulas Patocka break; 167548debafeSMikulas Patocka } 1676*5229b489SHuaisheng Ye } 167748debafeSMikulas Patocka cond_resched(); 167848debafeSMikulas Patocka } 167948debafeSMikulas Patocka 168048debafeSMikulas Patocka if (!list_empty(&skipped)) { 168148debafeSMikulas Patocka list_splice_tail(&skipped, &wc->lru); 168248debafeSMikulas Patocka /* 168348debafeSMikulas Patocka * If we didn't do any progress, we must wait until some 168448debafeSMikulas Patocka * writeback finishes to avoid burning CPU in a loop 168548debafeSMikulas Patocka */ 168648debafeSMikulas Patocka if (unlikely(!wbl.size)) 168748debafeSMikulas Patocka writecache_wait_for_writeback(wc); 168848debafeSMikulas Patocka } 168948debafeSMikulas Patocka 169048debafeSMikulas Patocka wc_unlock(wc); 169148debafeSMikulas Patocka 169248debafeSMikulas Patocka blk_start_plug(&plug); 169348debafeSMikulas Patocka 169448debafeSMikulas Patocka if (WC_MODE_PMEM(wc)) 169548debafeSMikulas Patocka __writecache_writeback_pmem(wc, &wbl); 169648debafeSMikulas Patocka else 169748debafeSMikulas Patocka __writecache_writeback_ssd(wc, &wbl); 169848debafeSMikulas Patocka 169948debafeSMikulas Patocka blk_finish_plug(&plug); 170048debafeSMikulas Patocka 170148debafeSMikulas Patocka if (unlikely(wc->writeback_all)) { 170248debafeSMikulas Patocka wc_lock(wc); 170348debafeSMikulas Patocka while (writecache_wait_for_writeback(wc)); 170448debafeSMikulas Patocka wc_unlock(wc); 170548debafeSMikulas Patocka } 170648debafeSMikulas Patocka } 170748debafeSMikulas Patocka 170848debafeSMikulas Patocka static int calculate_memory_size(uint64_t device_size, unsigned block_size, 170948debafeSMikulas Patocka size_t *n_blocks_p, size_t *n_metadata_blocks_p) 171048debafeSMikulas Patocka { 171148debafeSMikulas Patocka uint64_t n_blocks, offset; 171248debafeSMikulas Patocka struct wc_entry e; 171348debafeSMikulas Patocka 171448debafeSMikulas Patocka n_blocks = device_size; 171548debafeSMikulas Patocka do_div(n_blocks, block_size + sizeof(struct wc_memory_entry)); 171648debafeSMikulas Patocka 171748debafeSMikulas Patocka while (1) { 171848debafeSMikulas Patocka if (!n_blocks) 171948debafeSMikulas Patocka return -ENOSPC; 172048debafeSMikulas Patocka /* Verify the following entries[n_blocks] won't overflow */ 172148debafeSMikulas Patocka if (n_blocks >= ((size_t)-sizeof(struct wc_memory_superblock) / 172248debafeSMikulas Patocka sizeof(struct wc_memory_entry))) 172348debafeSMikulas Patocka return -EFBIG; 172448debafeSMikulas Patocka offset = offsetof(struct wc_memory_superblock, entries[n_blocks]); 172548debafeSMikulas Patocka offset = (offset + block_size - 1) & ~(uint64_t)(block_size - 1); 172648debafeSMikulas Patocka if (offset + n_blocks * block_size <= device_size) 172748debafeSMikulas Patocka break; 172848debafeSMikulas Patocka n_blocks--; 172948debafeSMikulas Patocka } 173048debafeSMikulas Patocka 173148debafeSMikulas Patocka /* check if the bit field overflows */ 173248debafeSMikulas Patocka e.index = n_blocks; 173348debafeSMikulas Patocka if (e.index != n_blocks) 173448debafeSMikulas Patocka return -EFBIG; 173548debafeSMikulas Patocka 173648debafeSMikulas Patocka if (n_blocks_p) 173748debafeSMikulas Patocka *n_blocks_p = n_blocks; 173848debafeSMikulas Patocka if (n_metadata_blocks_p) 173948debafeSMikulas Patocka *n_metadata_blocks_p = offset >> __ffs(block_size); 174048debafeSMikulas Patocka return 0; 174148debafeSMikulas Patocka } 174248debafeSMikulas Patocka 174348debafeSMikulas Patocka static int init_memory(struct dm_writecache *wc) 174448debafeSMikulas Patocka { 174548debafeSMikulas Patocka size_t b; 174648debafeSMikulas Patocka int r; 174748debafeSMikulas Patocka 174848debafeSMikulas Patocka r = calculate_memory_size(wc->memory_map_size, wc->block_size, &wc->n_blocks, NULL); 174948debafeSMikulas Patocka if (r) 175048debafeSMikulas Patocka return r; 175148debafeSMikulas Patocka 175248debafeSMikulas Patocka r = writecache_alloc_entries(wc); 175348debafeSMikulas Patocka if (r) 175448debafeSMikulas Patocka return r; 175548debafeSMikulas Patocka 175648debafeSMikulas Patocka for (b = 0; b < ARRAY_SIZE(sb(wc)->padding); b++) 175748debafeSMikulas Patocka pmem_assign(sb(wc)->padding[b], cpu_to_le64(0)); 175848debafeSMikulas Patocka pmem_assign(sb(wc)->version, cpu_to_le32(MEMORY_SUPERBLOCK_VERSION)); 175948debafeSMikulas Patocka pmem_assign(sb(wc)->block_size, cpu_to_le32(wc->block_size)); 176048debafeSMikulas Patocka pmem_assign(sb(wc)->n_blocks, cpu_to_le64(wc->n_blocks)); 176148debafeSMikulas Patocka pmem_assign(sb(wc)->seq_count, cpu_to_le64(0)); 176248debafeSMikulas Patocka 176348debafeSMikulas Patocka for (b = 0; b < wc->n_blocks; b++) 176448debafeSMikulas Patocka write_original_sector_seq_count(wc, &wc->entries[b], -1, -1); 176548debafeSMikulas Patocka 176648debafeSMikulas Patocka writecache_flush_all_metadata(wc); 176748debafeSMikulas Patocka writecache_commit_flushed(wc); 176848debafeSMikulas Patocka pmem_assign(sb(wc)->magic, cpu_to_le32(MEMORY_SUPERBLOCK_MAGIC)); 176948debafeSMikulas Patocka writecache_flush_region(wc, &sb(wc)->magic, sizeof sb(wc)->magic); 177048debafeSMikulas Patocka writecache_commit_flushed(wc); 177148debafeSMikulas Patocka 177248debafeSMikulas Patocka return 0; 177348debafeSMikulas Patocka } 177448debafeSMikulas Patocka 177548debafeSMikulas Patocka static void writecache_dtr(struct dm_target *ti) 177648debafeSMikulas Patocka { 177748debafeSMikulas Patocka struct dm_writecache *wc = ti->private; 177848debafeSMikulas Patocka 177948debafeSMikulas Patocka if (!wc) 178048debafeSMikulas Patocka return; 178148debafeSMikulas Patocka 178248debafeSMikulas Patocka if (wc->endio_thread) 178348debafeSMikulas Patocka kthread_stop(wc->endio_thread); 178448debafeSMikulas Patocka 178548debafeSMikulas Patocka if (wc->flush_thread) 178648debafeSMikulas Patocka kthread_stop(wc->flush_thread); 178748debafeSMikulas Patocka 178848debafeSMikulas Patocka bioset_exit(&wc->bio_set); 178948debafeSMikulas Patocka 179048debafeSMikulas Patocka mempool_exit(&wc->copy_pool); 179148debafeSMikulas Patocka 179248debafeSMikulas Patocka if (wc->writeback_wq) 179348debafeSMikulas Patocka destroy_workqueue(wc->writeback_wq); 179448debafeSMikulas Patocka 179548debafeSMikulas Patocka if (wc->dev) 179648debafeSMikulas Patocka dm_put_device(ti, wc->dev); 179748debafeSMikulas Patocka 179848debafeSMikulas Patocka if (wc->ssd_dev) 179948debafeSMikulas Patocka dm_put_device(ti, wc->ssd_dev); 180048debafeSMikulas Patocka 180148debafeSMikulas Patocka if (wc->entries) 180248debafeSMikulas Patocka vfree(wc->entries); 180348debafeSMikulas Patocka 180448debafeSMikulas Patocka if (wc->memory_map) { 180548debafeSMikulas Patocka if (WC_MODE_PMEM(wc)) 180648debafeSMikulas Patocka persistent_memory_release(wc); 180748debafeSMikulas Patocka else 180848debafeSMikulas Patocka vfree(wc->memory_map); 180948debafeSMikulas Patocka } 181048debafeSMikulas Patocka 181148debafeSMikulas Patocka if (wc->dm_kcopyd) 181248debafeSMikulas Patocka dm_kcopyd_client_destroy(wc->dm_kcopyd); 181348debafeSMikulas Patocka 181448debafeSMikulas Patocka if (wc->dm_io) 181548debafeSMikulas Patocka dm_io_client_destroy(wc->dm_io); 181648debafeSMikulas Patocka 181748debafeSMikulas Patocka if (wc->dirty_bitmap) 181848debafeSMikulas Patocka vfree(wc->dirty_bitmap); 181948debafeSMikulas Patocka 182048debafeSMikulas Patocka kfree(wc); 182148debafeSMikulas Patocka } 182248debafeSMikulas Patocka 182348debafeSMikulas Patocka static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv) 182448debafeSMikulas Patocka { 182548debafeSMikulas Patocka struct dm_writecache *wc; 182648debafeSMikulas Patocka struct dm_arg_set as; 182748debafeSMikulas Patocka const char *string; 182848debafeSMikulas Patocka unsigned opt_params; 182948debafeSMikulas Patocka size_t offset, data_size; 183048debafeSMikulas Patocka int i, r; 183148debafeSMikulas Patocka char dummy; 183248debafeSMikulas Patocka int high_wm_percent = HIGH_WATERMARK; 183348debafeSMikulas Patocka int low_wm_percent = LOW_WATERMARK; 183448debafeSMikulas Patocka uint64_t x; 183548debafeSMikulas Patocka struct wc_memory_superblock s; 183648debafeSMikulas Patocka 183748debafeSMikulas Patocka static struct dm_arg _args[] = { 183848debafeSMikulas Patocka {0, 10, "Invalid number of feature args"}, 183948debafeSMikulas Patocka }; 184048debafeSMikulas Patocka 184148debafeSMikulas Patocka as.argc = argc; 184248debafeSMikulas Patocka as.argv = argv; 184348debafeSMikulas Patocka 184448debafeSMikulas Patocka wc = kzalloc(sizeof(struct dm_writecache), GFP_KERNEL); 184548debafeSMikulas Patocka if (!wc) { 184648debafeSMikulas Patocka ti->error = "Cannot allocate writecache structure"; 184748debafeSMikulas Patocka r = -ENOMEM; 184848debafeSMikulas Patocka goto bad; 184948debafeSMikulas Patocka } 185048debafeSMikulas Patocka ti->private = wc; 185148debafeSMikulas Patocka wc->ti = ti; 185248debafeSMikulas Patocka 185348debafeSMikulas Patocka mutex_init(&wc->lock); 185448debafeSMikulas Patocka writecache_poison_lists(wc); 185548debafeSMikulas Patocka init_waitqueue_head(&wc->freelist_wait); 185648debafeSMikulas Patocka timer_setup(&wc->autocommit_timer, writecache_autocommit_timer, 0); 185748debafeSMikulas Patocka 185848debafeSMikulas Patocka for (i = 0; i < 2; i++) { 185948debafeSMikulas Patocka atomic_set(&wc->bio_in_progress[i], 0); 186048debafeSMikulas Patocka init_waitqueue_head(&wc->bio_in_progress_wait[i]); 186148debafeSMikulas Patocka } 186248debafeSMikulas Patocka 186348debafeSMikulas Patocka wc->dm_io = dm_io_client_create(); 186448debafeSMikulas Patocka if (IS_ERR(wc->dm_io)) { 186548debafeSMikulas Patocka r = PTR_ERR(wc->dm_io); 186648debafeSMikulas Patocka ti->error = "Unable to allocate dm-io client"; 186748debafeSMikulas Patocka wc->dm_io = NULL; 186848debafeSMikulas Patocka goto bad; 186948debafeSMikulas Patocka } 187048debafeSMikulas Patocka 1871f87e033bSHuaisheng Ye wc->writeback_wq = alloc_workqueue("writecache-writeback", WQ_MEM_RECLAIM, 1); 187248debafeSMikulas Patocka if (!wc->writeback_wq) { 187348debafeSMikulas Patocka r = -ENOMEM; 187448debafeSMikulas Patocka ti->error = "Could not allocate writeback workqueue"; 187548debafeSMikulas Patocka goto bad; 187648debafeSMikulas Patocka } 187748debafeSMikulas Patocka INIT_WORK(&wc->writeback_work, writecache_writeback); 187848debafeSMikulas Patocka INIT_WORK(&wc->flush_work, writecache_flush_work); 187948debafeSMikulas Patocka 188048debafeSMikulas Patocka raw_spin_lock_init(&wc->endio_list_lock); 188148debafeSMikulas Patocka INIT_LIST_HEAD(&wc->endio_list); 188248debafeSMikulas Patocka wc->endio_thread = kthread_create(writecache_endio_thread, wc, "writecache_endio"); 188348debafeSMikulas Patocka if (IS_ERR(wc->endio_thread)) { 188448debafeSMikulas Patocka r = PTR_ERR(wc->endio_thread); 188548debafeSMikulas Patocka wc->endio_thread = NULL; 188648debafeSMikulas Patocka ti->error = "Couldn't spawn endio thread"; 188748debafeSMikulas Patocka goto bad; 188848debafeSMikulas Patocka } 188948debafeSMikulas Patocka wake_up_process(wc->endio_thread); 189048debafeSMikulas Patocka 189148debafeSMikulas Patocka /* 189248debafeSMikulas Patocka * Parse the mode (pmem or ssd) 189348debafeSMikulas Patocka */ 189448debafeSMikulas Patocka string = dm_shift_arg(&as); 189548debafeSMikulas Patocka if (!string) 189648debafeSMikulas Patocka goto bad_arguments; 189748debafeSMikulas Patocka 189848debafeSMikulas Patocka if (!strcasecmp(string, "s")) { 189948debafeSMikulas Patocka wc->pmem_mode = false; 190048debafeSMikulas Patocka } else if (!strcasecmp(string, "p")) { 190148debafeSMikulas Patocka #ifdef DM_WRITECACHE_HAS_PMEM 190248debafeSMikulas Patocka wc->pmem_mode = true; 190348debafeSMikulas Patocka wc->writeback_fua = true; 190448debafeSMikulas Patocka #else 190548debafeSMikulas Patocka /* 190648debafeSMikulas Patocka * If the architecture doesn't support persistent memory or 190748debafeSMikulas Patocka * the kernel doesn't support any DAX drivers, this driver can 190848debafeSMikulas Patocka * only be used in SSD-only mode. 190948debafeSMikulas Patocka */ 191048debafeSMikulas Patocka r = -EOPNOTSUPP; 191148debafeSMikulas Patocka ti->error = "Persistent memory or DAX not supported on this system"; 191248debafeSMikulas Patocka goto bad; 191348debafeSMikulas Patocka #endif 191448debafeSMikulas Patocka } else { 191548debafeSMikulas Patocka goto bad_arguments; 191648debafeSMikulas Patocka } 191748debafeSMikulas Patocka 191848debafeSMikulas Patocka if (WC_MODE_PMEM(wc)) { 191948debafeSMikulas Patocka r = bioset_init(&wc->bio_set, BIO_POOL_SIZE, 192048debafeSMikulas Patocka offsetof(struct writeback_struct, bio), 192148debafeSMikulas Patocka BIOSET_NEED_BVECS); 192248debafeSMikulas Patocka if (r) { 192348debafeSMikulas Patocka ti->error = "Could not allocate bio set"; 192448debafeSMikulas Patocka goto bad; 192548debafeSMikulas Patocka } 192648debafeSMikulas Patocka } else { 192748debafeSMikulas Patocka r = mempool_init_kmalloc_pool(&wc->copy_pool, 1, sizeof(struct copy_struct)); 192848debafeSMikulas Patocka if (r) { 192948debafeSMikulas Patocka ti->error = "Could not allocate mempool"; 193048debafeSMikulas Patocka goto bad; 193148debafeSMikulas Patocka } 193248debafeSMikulas Patocka } 193348debafeSMikulas Patocka 193448debafeSMikulas Patocka /* 193548debafeSMikulas Patocka * Parse the origin data device 193648debafeSMikulas Patocka */ 193748debafeSMikulas Patocka string = dm_shift_arg(&as); 193848debafeSMikulas Patocka if (!string) 193948debafeSMikulas Patocka goto bad_arguments; 194048debafeSMikulas Patocka r = dm_get_device(ti, string, dm_table_get_mode(ti->table), &wc->dev); 194148debafeSMikulas Patocka if (r) { 194248debafeSMikulas Patocka ti->error = "Origin data device lookup failed"; 194348debafeSMikulas Patocka goto bad; 194448debafeSMikulas Patocka } 194548debafeSMikulas Patocka 194648debafeSMikulas Patocka /* 194748debafeSMikulas Patocka * Parse cache data device (be it pmem or ssd) 194848debafeSMikulas Patocka */ 194948debafeSMikulas Patocka string = dm_shift_arg(&as); 195048debafeSMikulas Patocka if (!string) 195148debafeSMikulas Patocka goto bad_arguments; 195248debafeSMikulas Patocka 195348debafeSMikulas Patocka r = dm_get_device(ti, string, dm_table_get_mode(ti->table), &wc->ssd_dev); 195448debafeSMikulas Patocka if (r) { 195548debafeSMikulas Patocka ti->error = "Cache data device lookup failed"; 195648debafeSMikulas Patocka goto bad; 195748debafeSMikulas Patocka } 195848debafeSMikulas Patocka wc->memory_map_size = i_size_read(wc->ssd_dev->bdev->bd_inode); 195948debafeSMikulas Patocka 196048debafeSMikulas Patocka /* 196148debafeSMikulas Patocka * Parse the cache block size 196248debafeSMikulas Patocka */ 196348debafeSMikulas Patocka string = dm_shift_arg(&as); 196448debafeSMikulas Patocka if (!string) 196548debafeSMikulas Patocka goto bad_arguments; 196648debafeSMikulas Patocka if (sscanf(string, "%u%c", &wc->block_size, &dummy) != 1 || 196748debafeSMikulas Patocka wc->block_size < 512 || wc->block_size > PAGE_SIZE || 196848debafeSMikulas Patocka (wc->block_size & (wc->block_size - 1))) { 196948debafeSMikulas Patocka r = -EINVAL; 197048debafeSMikulas Patocka ti->error = "Invalid block size"; 197148debafeSMikulas Patocka goto bad; 197248debafeSMikulas Patocka } 197348debafeSMikulas Patocka wc->block_size_bits = __ffs(wc->block_size); 197448debafeSMikulas Patocka 197548debafeSMikulas Patocka wc->max_writeback_jobs = MAX_WRITEBACK_JOBS; 197648debafeSMikulas Patocka wc->autocommit_blocks = !WC_MODE_PMEM(wc) ? AUTOCOMMIT_BLOCKS_SSD : AUTOCOMMIT_BLOCKS_PMEM; 197748debafeSMikulas Patocka wc->autocommit_jiffies = msecs_to_jiffies(AUTOCOMMIT_MSEC); 197848debafeSMikulas Patocka 197948debafeSMikulas Patocka /* 198048debafeSMikulas Patocka * Parse optional arguments 198148debafeSMikulas Patocka */ 198248debafeSMikulas Patocka r = dm_read_arg_group(_args, &as, &opt_params, &ti->error); 198348debafeSMikulas Patocka if (r) 198448debafeSMikulas Patocka goto bad; 198548debafeSMikulas Patocka 198648debafeSMikulas Patocka while (opt_params) { 198748debafeSMikulas Patocka string = dm_shift_arg(&as), opt_params--; 1988d284f824SMikulas Patocka if (!strcasecmp(string, "start_sector") && opt_params >= 1) { 1989d284f824SMikulas Patocka unsigned long long start_sector; 1990d284f824SMikulas Patocka string = dm_shift_arg(&as), opt_params--; 1991d284f824SMikulas Patocka if (sscanf(string, "%llu%c", &start_sector, &dummy) != 1) 1992d284f824SMikulas Patocka goto invalid_optional; 1993d284f824SMikulas Patocka wc->start_sector = start_sector; 1994d284f824SMikulas Patocka if (wc->start_sector != start_sector || 1995d284f824SMikulas Patocka wc->start_sector >= wc->memory_map_size >> SECTOR_SHIFT) 1996d284f824SMikulas Patocka goto invalid_optional; 1997d284f824SMikulas Patocka } else if (!strcasecmp(string, "high_watermark") && opt_params >= 1) { 199848debafeSMikulas Patocka string = dm_shift_arg(&as), opt_params--; 199948debafeSMikulas Patocka if (sscanf(string, "%d%c", &high_wm_percent, &dummy) != 1) 200048debafeSMikulas Patocka goto invalid_optional; 200148debafeSMikulas Patocka if (high_wm_percent < 0 || high_wm_percent > 100) 200248debafeSMikulas Patocka goto invalid_optional; 200348debafeSMikulas Patocka wc->high_wm_percent_set = true; 200448debafeSMikulas Patocka } else if (!strcasecmp(string, "low_watermark") && opt_params >= 1) { 200548debafeSMikulas Patocka string = dm_shift_arg(&as), opt_params--; 200648debafeSMikulas Patocka if (sscanf(string, "%d%c", &low_wm_percent, &dummy) != 1) 200748debafeSMikulas Patocka goto invalid_optional; 200848debafeSMikulas Patocka if (low_wm_percent < 0 || low_wm_percent > 100) 200948debafeSMikulas Patocka goto invalid_optional; 201048debafeSMikulas Patocka wc->low_wm_percent_set = true; 201148debafeSMikulas Patocka } else if (!strcasecmp(string, "writeback_jobs") && opt_params >= 1) { 201248debafeSMikulas Patocka string = dm_shift_arg(&as), opt_params--; 201348debafeSMikulas Patocka if (sscanf(string, "%u%c", &wc->max_writeback_jobs, &dummy) != 1) 201448debafeSMikulas Patocka goto invalid_optional; 201548debafeSMikulas Patocka wc->max_writeback_jobs_set = true; 201648debafeSMikulas Patocka } else if (!strcasecmp(string, "autocommit_blocks") && opt_params >= 1) { 201748debafeSMikulas Patocka string = dm_shift_arg(&as), opt_params--; 201848debafeSMikulas Patocka if (sscanf(string, "%u%c", &wc->autocommit_blocks, &dummy) != 1) 201948debafeSMikulas Patocka goto invalid_optional; 202048debafeSMikulas Patocka wc->autocommit_blocks_set = true; 202148debafeSMikulas Patocka } else if (!strcasecmp(string, "autocommit_time") && opt_params >= 1) { 202248debafeSMikulas Patocka unsigned autocommit_msecs; 202348debafeSMikulas Patocka string = dm_shift_arg(&as), opt_params--; 202448debafeSMikulas Patocka if (sscanf(string, "%u%c", &autocommit_msecs, &dummy) != 1) 202548debafeSMikulas Patocka goto invalid_optional; 202648debafeSMikulas Patocka if (autocommit_msecs > 3600000) 202748debafeSMikulas Patocka goto invalid_optional; 202848debafeSMikulas Patocka wc->autocommit_jiffies = msecs_to_jiffies(autocommit_msecs); 202948debafeSMikulas Patocka wc->autocommit_time_set = true; 203048debafeSMikulas Patocka } else if (!strcasecmp(string, "fua")) { 203148debafeSMikulas Patocka if (WC_MODE_PMEM(wc)) { 203248debafeSMikulas Patocka wc->writeback_fua = true; 203348debafeSMikulas Patocka wc->writeback_fua_set = true; 203448debafeSMikulas Patocka } else goto invalid_optional; 203548debafeSMikulas Patocka } else if (!strcasecmp(string, "nofua")) { 203648debafeSMikulas Patocka if (WC_MODE_PMEM(wc)) { 203748debafeSMikulas Patocka wc->writeback_fua = false; 203848debafeSMikulas Patocka wc->writeback_fua_set = true; 203948debafeSMikulas Patocka } else goto invalid_optional; 204048debafeSMikulas Patocka } else { 204148debafeSMikulas Patocka invalid_optional: 204248debafeSMikulas Patocka r = -EINVAL; 204348debafeSMikulas Patocka ti->error = "Invalid optional argument"; 204448debafeSMikulas Patocka goto bad; 204548debafeSMikulas Patocka } 204648debafeSMikulas Patocka } 204748debafeSMikulas Patocka 204848debafeSMikulas Patocka if (high_wm_percent < low_wm_percent) { 204948debafeSMikulas Patocka r = -EINVAL; 205048debafeSMikulas Patocka ti->error = "High watermark must be greater than or equal to low watermark"; 205148debafeSMikulas Patocka goto bad; 205248debafeSMikulas Patocka } 205348debafeSMikulas Patocka 2054d284f824SMikulas Patocka if (WC_MODE_PMEM(wc)) { 2055d284f824SMikulas Patocka r = persistent_memory_claim(wc); 2056d284f824SMikulas Patocka if (r) { 2057d284f824SMikulas Patocka ti->error = "Unable to map persistent memory for cache"; 2058d284f824SMikulas Patocka goto bad; 2059d284f824SMikulas Patocka } 2060d284f824SMikulas Patocka } else { 206148debafeSMikulas Patocka struct dm_io_region region; 206248debafeSMikulas Patocka struct dm_io_request req; 206348debafeSMikulas Patocka size_t n_blocks, n_metadata_blocks; 206448debafeSMikulas Patocka uint64_t n_bitmap_bits; 206548debafeSMikulas Patocka 2066d284f824SMikulas Patocka wc->memory_map_size -= (uint64_t)wc->start_sector << SECTOR_SHIFT; 2067d284f824SMikulas Patocka 206848debafeSMikulas Patocka bio_list_init(&wc->flush_list); 206948debafeSMikulas Patocka wc->flush_thread = kthread_create(writecache_flush_thread, wc, "dm_writecache_flush"); 207048debafeSMikulas Patocka if (IS_ERR(wc->flush_thread)) { 207148debafeSMikulas Patocka r = PTR_ERR(wc->flush_thread); 207248debafeSMikulas Patocka wc->flush_thread = NULL; 2073e8ea141aSShenghui Wang ti->error = "Couldn't spawn flush thread"; 207448debafeSMikulas Patocka goto bad; 207548debafeSMikulas Patocka } 207648debafeSMikulas Patocka wake_up_process(wc->flush_thread); 207748debafeSMikulas Patocka 207848debafeSMikulas Patocka r = calculate_memory_size(wc->memory_map_size, wc->block_size, 207948debafeSMikulas Patocka &n_blocks, &n_metadata_blocks); 208048debafeSMikulas Patocka if (r) { 208148debafeSMikulas Patocka ti->error = "Invalid device size"; 208248debafeSMikulas Patocka goto bad; 208348debafeSMikulas Patocka } 208448debafeSMikulas Patocka 208548debafeSMikulas Patocka n_bitmap_bits = (((uint64_t)n_metadata_blocks << wc->block_size_bits) + 208648debafeSMikulas Patocka BITMAP_GRANULARITY - 1) / BITMAP_GRANULARITY; 208748debafeSMikulas Patocka /* this is limitation of test_bit functions */ 208848debafeSMikulas Patocka if (n_bitmap_bits > 1U << 31) { 208948debafeSMikulas Patocka r = -EFBIG; 209048debafeSMikulas Patocka ti->error = "Invalid device size"; 209148debafeSMikulas Patocka goto bad; 209248debafeSMikulas Patocka } 209348debafeSMikulas Patocka 209448debafeSMikulas Patocka wc->memory_map = vmalloc(n_metadata_blocks << wc->block_size_bits); 209548debafeSMikulas Patocka if (!wc->memory_map) { 209648debafeSMikulas Patocka r = -ENOMEM; 209748debafeSMikulas Patocka ti->error = "Unable to allocate memory for metadata"; 209848debafeSMikulas Patocka goto bad; 209948debafeSMikulas Patocka } 210048debafeSMikulas Patocka 210148debafeSMikulas Patocka wc->dm_kcopyd = dm_kcopyd_client_create(&dm_kcopyd_throttle); 210248debafeSMikulas Patocka if (IS_ERR(wc->dm_kcopyd)) { 210348debafeSMikulas Patocka r = PTR_ERR(wc->dm_kcopyd); 210448debafeSMikulas Patocka ti->error = "Unable to allocate dm-kcopyd client"; 210548debafeSMikulas Patocka wc->dm_kcopyd = NULL; 210648debafeSMikulas Patocka goto bad; 210748debafeSMikulas Patocka } 210848debafeSMikulas Patocka 210948debafeSMikulas Patocka wc->metadata_sectors = n_metadata_blocks << (wc->block_size_bits - SECTOR_SHIFT); 211048debafeSMikulas Patocka wc->dirty_bitmap_size = (n_bitmap_bits + BITS_PER_LONG - 1) / 211148debafeSMikulas Patocka BITS_PER_LONG * sizeof(unsigned long); 211248debafeSMikulas Patocka wc->dirty_bitmap = vzalloc(wc->dirty_bitmap_size); 211348debafeSMikulas Patocka if (!wc->dirty_bitmap) { 211448debafeSMikulas Patocka r = -ENOMEM; 211548debafeSMikulas Patocka ti->error = "Unable to allocate dirty bitmap"; 211648debafeSMikulas Patocka goto bad; 211748debafeSMikulas Patocka } 211848debafeSMikulas Patocka 211948debafeSMikulas Patocka region.bdev = wc->ssd_dev->bdev; 2120d284f824SMikulas Patocka region.sector = wc->start_sector; 212148debafeSMikulas Patocka region.count = wc->metadata_sectors; 212248debafeSMikulas Patocka req.bi_op = REQ_OP_READ; 212348debafeSMikulas Patocka req.bi_op_flags = REQ_SYNC; 212448debafeSMikulas Patocka req.mem.type = DM_IO_VMA; 212548debafeSMikulas Patocka req.mem.ptr.vma = (char *)wc->memory_map; 212648debafeSMikulas Patocka req.client = wc->dm_io; 212748debafeSMikulas Patocka req.notify.fn = NULL; 212848debafeSMikulas Patocka 212948debafeSMikulas Patocka r = dm_io(&req, 1, ®ion, NULL); 213048debafeSMikulas Patocka if (r) { 213148debafeSMikulas Patocka ti->error = "Unable to read metadata"; 213248debafeSMikulas Patocka goto bad; 213348debafeSMikulas Patocka } 213448debafeSMikulas Patocka } 213548debafeSMikulas Patocka 213648debafeSMikulas Patocka r = memcpy_mcsafe(&s, sb(wc), sizeof(struct wc_memory_superblock)); 213748debafeSMikulas Patocka if (r) { 213848debafeSMikulas Patocka ti->error = "Hardware memory error when reading superblock"; 213948debafeSMikulas Patocka goto bad; 214048debafeSMikulas Patocka } 214148debafeSMikulas Patocka if (!le32_to_cpu(s.magic) && !le32_to_cpu(s.version)) { 214248debafeSMikulas Patocka r = init_memory(wc); 214348debafeSMikulas Patocka if (r) { 214448debafeSMikulas Patocka ti->error = "Unable to initialize device"; 214548debafeSMikulas Patocka goto bad; 214648debafeSMikulas Patocka } 214748debafeSMikulas Patocka r = memcpy_mcsafe(&s, sb(wc), sizeof(struct wc_memory_superblock)); 214848debafeSMikulas Patocka if (r) { 214948debafeSMikulas Patocka ti->error = "Hardware memory error when reading superblock"; 215048debafeSMikulas Patocka goto bad; 215148debafeSMikulas Patocka } 215248debafeSMikulas Patocka } 215348debafeSMikulas Patocka 215448debafeSMikulas Patocka if (le32_to_cpu(s.magic) != MEMORY_SUPERBLOCK_MAGIC) { 215548debafeSMikulas Patocka ti->error = "Invalid magic in the superblock"; 215648debafeSMikulas Patocka r = -EINVAL; 215748debafeSMikulas Patocka goto bad; 215848debafeSMikulas Patocka } 215948debafeSMikulas Patocka 216048debafeSMikulas Patocka if (le32_to_cpu(s.version) != MEMORY_SUPERBLOCK_VERSION) { 216148debafeSMikulas Patocka ti->error = "Invalid version in the superblock"; 216248debafeSMikulas Patocka r = -EINVAL; 216348debafeSMikulas Patocka goto bad; 216448debafeSMikulas Patocka } 216548debafeSMikulas Patocka 216648debafeSMikulas Patocka if (le32_to_cpu(s.block_size) != wc->block_size) { 216748debafeSMikulas Patocka ti->error = "Block size does not match superblock"; 216848debafeSMikulas Patocka r = -EINVAL; 216948debafeSMikulas Patocka goto bad; 217048debafeSMikulas Patocka } 217148debafeSMikulas Patocka 217248debafeSMikulas Patocka wc->n_blocks = le64_to_cpu(s.n_blocks); 217348debafeSMikulas Patocka 217448debafeSMikulas Patocka offset = wc->n_blocks * sizeof(struct wc_memory_entry); 217548debafeSMikulas Patocka if (offset / sizeof(struct wc_memory_entry) != le64_to_cpu(sb(wc)->n_blocks)) { 217648debafeSMikulas Patocka overflow: 217748debafeSMikulas Patocka ti->error = "Overflow in size calculation"; 217848debafeSMikulas Patocka r = -EINVAL; 217948debafeSMikulas Patocka goto bad; 218048debafeSMikulas Patocka } 218148debafeSMikulas Patocka offset += sizeof(struct wc_memory_superblock); 218248debafeSMikulas Patocka if (offset < sizeof(struct wc_memory_superblock)) 218348debafeSMikulas Patocka goto overflow; 218448debafeSMikulas Patocka offset = (offset + wc->block_size - 1) & ~(size_t)(wc->block_size - 1); 218548debafeSMikulas Patocka data_size = wc->n_blocks * (size_t)wc->block_size; 218648debafeSMikulas Patocka if (!offset || (data_size / wc->block_size != wc->n_blocks) || 218748debafeSMikulas Patocka (offset + data_size < offset)) 218848debafeSMikulas Patocka goto overflow; 218948debafeSMikulas Patocka if (offset + data_size > wc->memory_map_size) { 219048debafeSMikulas Patocka ti->error = "Memory area is too small"; 219148debafeSMikulas Patocka r = -EINVAL; 219248debafeSMikulas Patocka goto bad; 219348debafeSMikulas Patocka } 219448debafeSMikulas Patocka 219548debafeSMikulas Patocka wc->metadata_sectors = offset >> SECTOR_SHIFT; 219648debafeSMikulas Patocka wc->block_start = (char *)sb(wc) + offset; 219748debafeSMikulas Patocka 219848debafeSMikulas Patocka x = (uint64_t)wc->n_blocks * (100 - high_wm_percent); 219948debafeSMikulas Patocka x += 50; 220048debafeSMikulas Patocka do_div(x, 100); 220148debafeSMikulas Patocka wc->freelist_high_watermark = x; 220248debafeSMikulas Patocka x = (uint64_t)wc->n_blocks * (100 - low_wm_percent); 220348debafeSMikulas Patocka x += 50; 220448debafeSMikulas Patocka do_div(x, 100); 220548debafeSMikulas Patocka wc->freelist_low_watermark = x; 220648debafeSMikulas Patocka 220748debafeSMikulas Patocka r = writecache_alloc_entries(wc); 220848debafeSMikulas Patocka if (r) { 220948debafeSMikulas Patocka ti->error = "Cannot allocate memory"; 221048debafeSMikulas Patocka goto bad; 221148debafeSMikulas Patocka } 221248debafeSMikulas Patocka 221348debafeSMikulas Patocka ti->num_flush_bios = 1; 221448debafeSMikulas Patocka ti->flush_supported = true; 221548debafeSMikulas Patocka ti->num_discard_bios = 1; 221648debafeSMikulas Patocka 221748debafeSMikulas Patocka if (WC_MODE_PMEM(wc)) 221848debafeSMikulas Patocka persistent_memory_flush_cache(wc->memory_map, wc->memory_map_size); 221948debafeSMikulas Patocka 222048debafeSMikulas Patocka return 0; 222148debafeSMikulas Patocka 222248debafeSMikulas Patocka bad_arguments: 222348debafeSMikulas Patocka r = -EINVAL; 222448debafeSMikulas Patocka ti->error = "Bad arguments"; 222548debafeSMikulas Patocka bad: 222648debafeSMikulas Patocka writecache_dtr(ti); 222748debafeSMikulas Patocka return r; 222848debafeSMikulas Patocka } 222948debafeSMikulas Patocka 223048debafeSMikulas Patocka static void writecache_status(struct dm_target *ti, status_type_t type, 223148debafeSMikulas Patocka unsigned status_flags, char *result, unsigned maxlen) 223248debafeSMikulas Patocka { 223348debafeSMikulas Patocka struct dm_writecache *wc = ti->private; 223448debafeSMikulas Patocka unsigned extra_args; 223548debafeSMikulas Patocka unsigned sz = 0; 223648debafeSMikulas Patocka uint64_t x; 223748debafeSMikulas Patocka 223848debafeSMikulas Patocka switch (type) { 223948debafeSMikulas Patocka case STATUSTYPE_INFO: 224048debafeSMikulas Patocka DMEMIT("%ld %llu %llu %llu", writecache_has_error(wc), 224148debafeSMikulas Patocka (unsigned long long)wc->n_blocks, (unsigned long long)wc->freelist_size, 224248debafeSMikulas Patocka (unsigned long long)wc->writeback_size); 224348debafeSMikulas Patocka break; 224448debafeSMikulas Patocka case STATUSTYPE_TABLE: 224548debafeSMikulas Patocka DMEMIT("%c %s %s %u ", WC_MODE_PMEM(wc) ? 'p' : 's', 224648debafeSMikulas Patocka wc->dev->name, wc->ssd_dev->name, wc->block_size); 224748debafeSMikulas Patocka extra_args = 0; 22489ff07e7dSMikulas Patocka if (wc->start_sector) 22499ff07e7dSMikulas Patocka extra_args += 2; 225048debafeSMikulas Patocka if (wc->high_wm_percent_set) 225148debafeSMikulas Patocka extra_args += 2; 225248debafeSMikulas Patocka if (wc->low_wm_percent_set) 225348debafeSMikulas Patocka extra_args += 2; 225448debafeSMikulas Patocka if (wc->max_writeback_jobs_set) 225548debafeSMikulas Patocka extra_args += 2; 225648debafeSMikulas Patocka if (wc->autocommit_blocks_set) 225748debafeSMikulas Patocka extra_args += 2; 225848debafeSMikulas Patocka if (wc->autocommit_time_set) 225948debafeSMikulas Patocka extra_args += 2; 226048debafeSMikulas Patocka if (wc->writeback_fua_set) 226148debafeSMikulas Patocka extra_args++; 226248debafeSMikulas Patocka 226348debafeSMikulas Patocka DMEMIT("%u", extra_args); 22649ff07e7dSMikulas Patocka if (wc->start_sector) 22659ff07e7dSMikulas Patocka DMEMIT(" start_sector %llu", (unsigned long long)wc->start_sector); 226648debafeSMikulas Patocka if (wc->high_wm_percent_set) { 226748debafeSMikulas Patocka x = (uint64_t)wc->freelist_high_watermark * 100; 226848debafeSMikulas Patocka x += wc->n_blocks / 2; 226948debafeSMikulas Patocka do_div(x, (size_t)wc->n_blocks); 227048debafeSMikulas Patocka DMEMIT(" high_watermark %u", 100 - (unsigned)x); 227148debafeSMikulas Patocka } 227248debafeSMikulas Patocka if (wc->low_wm_percent_set) { 227348debafeSMikulas Patocka x = (uint64_t)wc->freelist_low_watermark * 100; 227448debafeSMikulas Patocka x += wc->n_blocks / 2; 227548debafeSMikulas Patocka do_div(x, (size_t)wc->n_blocks); 227648debafeSMikulas Patocka DMEMIT(" low_watermark %u", 100 - (unsigned)x); 227748debafeSMikulas Patocka } 227848debafeSMikulas Patocka if (wc->max_writeback_jobs_set) 227948debafeSMikulas Patocka DMEMIT(" writeback_jobs %u", wc->max_writeback_jobs); 228048debafeSMikulas Patocka if (wc->autocommit_blocks_set) 228148debafeSMikulas Patocka DMEMIT(" autocommit_blocks %u", wc->autocommit_blocks); 228248debafeSMikulas Patocka if (wc->autocommit_time_set) 228348debafeSMikulas Patocka DMEMIT(" autocommit_time %u", jiffies_to_msecs(wc->autocommit_jiffies)); 228448debafeSMikulas Patocka if (wc->writeback_fua_set) 228548debafeSMikulas Patocka DMEMIT(" %sfua", wc->writeback_fua ? "" : "no"); 228648debafeSMikulas Patocka break; 228748debafeSMikulas Patocka } 228848debafeSMikulas Patocka } 228948debafeSMikulas Patocka 229048debafeSMikulas Patocka static struct target_type writecache_target = { 229148debafeSMikulas Patocka .name = "writecache", 22929ff07e7dSMikulas Patocka .version = {1, 1, 1}, 229348debafeSMikulas Patocka .module = THIS_MODULE, 229448debafeSMikulas Patocka .ctr = writecache_ctr, 229548debafeSMikulas Patocka .dtr = writecache_dtr, 229648debafeSMikulas Patocka .status = writecache_status, 229748debafeSMikulas Patocka .postsuspend = writecache_suspend, 229848debafeSMikulas Patocka .resume = writecache_resume, 229948debafeSMikulas Patocka .message = writecache_message, 230048debafeSMikulas Patocka .map = writecache_map, 230148debafeSMikulas Patocka .end_io = writecache_end_io, 230248debafeSMikulas Patocka .iterate_devices = writecache_iterate_devices, 230348debafeSMikulas Patocka .io_hints = writecache_io_hints, 230448debafeSMikulas Patocka }; 230548debafeSMikulas Patocka 230648debafeSMikulas Patocka static int __init dm_writecache_init(void) 230748debafeSMikulas Patocka { 230848debafeSMikulas Patocka int r; 230948debafeSMikulas Patocka 231048debafeSMikulas Patocka r = dm_register_target(&writecache_target); 231148debafeSMikulas Patocka if (r < 0) { 231248debafeSMikulas Patocka DMERR("register failed %d", r); 231348debafeSMikulas Patocka return r; 231448debafeSMikulas Patocka } 231548debafeSMikulas Patocka 231648debafeSMikulas Patocka return 0; 231748debafeSMikulas Patocka } 231848debafeSMikulas Patocka 231948debafeSMikulas Patocka static void __exit dm_writecache_exit(void) 232048debafeSMikulas Patocka { 232148debafeSMikulas Patocka dm_unregister_target(&writecache_target); 232248debafeSMikulas Patocka } 232348debafeSMikulas Patocka 232448debafeSMikulas Patocka module_init(dm_writecache_init); 232548debafeSMikulas Patocka module_exit(dm_writecache_exit); 232648debafeSMikulas Patocka 232748debafeSMikulas Patocka MODULE_DESCRIPTION(DM_NAME " writecache target"); 232848debafeSMikulas Patocka MODULE_AUTHOR("Mikulas Patocka <dm-devel@redhat.com>"); 232948debafeSMikulas Patocka MODULE_LICENSE("GPL"); 2330