18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * bitmap.c two-level bitmap (C) Peter T. Breuer (ptb@ot.uc3m.es) 2003 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * bitmap_create - sets up the bitmap structure 68c2ecf20Sopenharmony_ci * bitmap_destroy - destroys the bitmap structure 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * additions, Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.: 98c2ecf20Sopenharmony_ci * - added disk storage for bitmap 108c2ecf20Sopenharmony_ci * - changes to allow various bitmap chunk sizes 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* 148c2ecf20Sopenharmony_ci * Still to do: 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * flush after percent set rather than just time based. (maybe both). 178c2ecf20Sopenharmony_ci */ 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 208c2ecf20Sopenharmony_ci#include <linux/module.h> 218c2ecf20Sopenharmony_ci#include <linux/errno.h> 228c2ecf20Sopenharmony_ci#include <linux/slab.h> 238c2ecf20Sopenharmony_ci#include <linux/init.h> 248c2ecf20Sopenharmony_ci#include <linux/timer.h> 258c2ecf20Sopenharmony_ci#include <linux/sched.h> 268c2ecf20Sopenharmony_ci#include <linux/list.h> 278c2ecf20Sopenharmony_ci#include <linux/file.h> 288c2ecf20Sopenharmony_ci#include <linux/mount.h> 298c2ecf20Sopenharmony_ci#include <linux/buffer_head.h> 308c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 318c2ecf20Sopenharmony_ci#include <trace/events/block.h> 328c2ecf20Sopenharmony_ci#include "md.h" 338c2ecf20Sopenharmony_ci#include "md-bitmap.h" 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistatic inline char *bmname(struct bitmap *bitmap) 368c2ecf20Sopenharmony_ci{ 378c2ecf20Sopenharmony_ci return bitmap->mddev ? mdname(bitmap->mddev) : "mdX"; 388c2ecf20Sopenharmony_ci} 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/* 418c2ecf20Sopenharmony_ci * check a page and, if necessary, allocate it (or hijack it if the alloc fails) 428c2ecf20Sopenharmony_ci * 438c2ecf20Sopenharmony_ci * 1) check to see if this page is allocated, if it's not then try to alloc 448c2ecf20Sopenharmony_ci * 2) if the alloc fails, set the page's hijacked flag so we'll use the 458c2ecf20Sopenharmony_ci * page pointer directly as a counter 468c2ecf20Sopenharmony_ci * 478c2ecf20Sopenharmony_ci * if we find our page, we increment the page's refcount so that it stays 488c2ecf20Sopenharmony_ci * allocated while we're using it 498c2ecf20Sopenharmony_ci */ 508c2ecf20Sopenharmony_cistatic int md_bitmap_checkpage(struct bitmap_counts *bitmap, 518c2ecf20Sopenharmony_ci unsigned long page, int create, int no_hijack) 528c2ecf20Sopenharmony_ci__releases(bitmap->lock) 538c2ecf20Sopenharmony_ci__acquires(bitmap->lock) 548c2ecf20Sopenharmony_ci{ 558c2ecf20Sopenharmony_ci unsigned char *mappage; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci WARN_ON_ONCE(page >= bitmap->pages); 588c2ecf20Sopenharmony_ci if (bitmap->bp[page].hijacked) /* it's hijacked, don't try to alloc */ 598c2ecf20Sopenharmony_ci return 0; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci if (bitmap->bp[page].map) /* page is already allocated, just return */ 628c2ecf20Sopenharmony_ci return 0; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci if (!create) 658c2ecf20Sopenharmony_ci return -ENOENT; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci /* this page has not been allocated yet */ 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci spin_unlock_irq(&bitmap->lock); 708c2ecf20Sopenharmony_ci /* It is possible that this is being called inside a 718c2ecf20Sopenharmony_ci * prepare_to_wait/finish_wait loop from raid5c:make_request(). 728c2ecf20Sopenharmony_ci * In general it is not permitted to sleep in that context as it 738c2ecf20Sopenharmony_ci * can cause the loop to spin freely. 748c2ecf20Sopenharmony_ci * That doesn't apply here as we can only reach this point 758c2ecf20Sopenharmony_ci * once with any loop. 768c2ecf20Sopenharmony_ci * When this function completes, either bp[page].map or 778c2ecf20Sopenharmony_ci * bp[page].hijacked. In either case, this function will 788c2ecf20Sopenharmony_ci * abort before getting to this point again. So there is 798c2ecf20Sopenharmony_ci * no risk of a free-spin, and so it is safe to assert 808c2ecf20Sopenharmony_ci * that sleeping here is allowed. 818c2ecf20Sopenharmony_ci */ 828c2ecf20Sopenharmony_ci sched_annotate_sleep(); 838c2ecf20Sopenharmony_ci mappage = kzalloc(PAGE_SIZE, GFP_NOIO); 848c2ecf20Sopenharmony_ci spin_lock_irq(&bitmap->lock); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci if (mappage == NULL) { 878c2ecf20Sopenharmony_ci pr_debug("md/bitmap: map page allocation failed, hijacking\n"); 888c2ecf20Sopenharmony_ci /* We don't support hijack for cluster raid */ 898c2ecf20Sopenharmony_ci if (no_hijack) 908c2ecf20Sopenharmony_ci return -ENOMEM; 918c2ecf20Sopenharmony_ci /* failed - set the hijacked flag so that we can use the 928c2ecf20Sopenharmony_ci * pointer as a counter */ 938c2ecf20Sopenharmony_ci if (!bitmap->bp[page].map) 948c2ecf20Sopenharmony_ci bitmap->bp[page].hijacked = 1; 958c2ecf20Sopenharmony_ci } else if (bitmap->bp[page].map || 968c2ecf20Sopenharmony_ci bitmap->bp[page].hijacked) { 978c2ecf20Sopenharmony_ci /* somebody beat us to getting the page */ 988c2ecf20Sopenharmony_ci kfree(mappage); 998c2ecf20Sopenharmony_ci } else { 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci /* no page was in place and we have one, so install it */ 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci bitmap->bp[page].map = mappage; 1048c2ecf20Sopenharmony_ci bitmap->missing_pages--; 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci return 0; 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci/* if page is completely empty, put it back on the free list, or dealloc it */ 1108c2ecf20Sopenharmony_ci/* if page was hijacked, unmark the flag so it might get alloced next time */ 1118c2ecf20Sopenharmony_ci/* Note: lock should be held when calling this */ 1128c2ecf20Sopenharmony_cistatic void md_bitmap_checkfree(struct bitmap_counts *bitmap, unsigned long page) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci char *ptr; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci if (bitmap->bp[page].count) /* page is still busy */ 1178c2ecf20Sopenharmony_ci return; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci /* page is no longer in use, it can be released */ 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci if (bitmap->bp[page].hijacked) { /* page was hijacked, undo this now */ 1228c2ecf20Sopenharmony_ci bitmap->bp[page].hijacked = 0; 1238c2ecf20Sopenharmony_ci bitmap->bp[page].map = NULL; 1248c2ecf20Sopenharmony_ci } else { 1258c2ecf20Sopenharmony_ci /* normal case, free the page */ 1268c2ecf20Sopenharmony_ci ptr = bitmap->bp[page].map; 1278c2ecf20Sopenharmony_ci bitmap->bp[page].map = NULL; 1288c2ecf20Sopenharmony_ci bitmap->missing_pages++; 1298c2ecf20Sopenharmony_ci kfree(ptr); 1308c2ecf20Sopenharmony_ci } 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci/* 1348c2ecf20Sopenharmony_ci * bitmap file handling - read and write the bitmap file and its superblock 1358c2ecf20Sopenharmony_ci */ 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci/* 1388c2ecf20Sopenharmony_ci * basic page I/O operations 1398c2ecf20Sopenharmony_ci */ 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci/* IO operations when bitmap is stored near all superblocks */ 1428c2ecf20Sopenharmony_cistatic int read_sb_page(struct mddev *mddev, loff_t offset, 1438c2ecf20Sopenharmony_ci struct page *page, 1448c2ecf20Sopenharmony_ci unsigned long index, int size) 1458c2ecf20Sopenharmony_ci{ 1468c2ecf20Sopenharmony_ci /* choose a good rdev and read the page from there */ 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci struct md_rdev *rdev; 1498c2ecf20Sopenharmony_ci sector_t target; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci rdev_for_each(rdev, mddev) { 1528c2ecf20Sopenharmony_ci if (! test_bit(In_sync, &rdev->flags) 1538c2ecf20Sopenharmony_ci || test_bit(Faulty, &rdev->flags) 1548c2ecf20Sopenharmony_ci || test_bit(Bitmap_sync, &rdev->flags)) 1558c2ecf20Sopenharmony_ci continue; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci target = offset + index * (PAGE_SIZE/512); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci if (sync_page_io(rdev, target, 1608c2ecf20Sopenharmony_ci roundup(size, bdev_logical_block_size(rdev->bdev)), 1618c2ecf20Sopenharmony_ci page, REQ_OP_READ, 0, true)) { 1628c2ecf20Sopenharmony_ci page->index = index; 1638c2ecf20Sopenharmony_ci return 0; 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci } 1668c2ecf20Sopenharmony_ci return -EIO; 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic struct md_rdev *next_active_rdev(struct md_rdev *rdev, struct mddev *mddev) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci /* Iterate the disks of an mddev, using rcu to protect access to the 1728c2ecf20Sopenharmony_ci * linked list, and raising the refcount of devices we return to ensure 1738c2ecf20Sopenharmony_ci * they don't disappear while in use. 1748c2ecf20Sopenharmony_ci * As devices are only added or removed when raid_disk is < 0 and 1758c2ecf20Sopenharmony_ci * nr_pending is 0 and In_sync is clear, the entries we return will 1768c2ecf20Sopenharmony_ci * still be in the same position on the list when we re-enter 1778c2ecf20Sopenharmony_ci * list_for_each_entry_continue_rcu. 1788c2ecf20Sopenharmony_ci * 1798c2ecf20Sopenharmony_ci * Note that if entered with 'rdev == NULL' to start at the 1808c2ecf20Sopenharmony_ci * beginning, we temporarily assign 'rdev' to an address which 1818c2ecf20Sopenharmony_ci * isn't really an rdev, but which can be used by 1828c2ecf20Sopenharmony_ci * list_for_each_entry_continue_rcu() to find the first entry. 1838c2ecf20Sopenharmony_ci */ 1848c2ecf20Sopenharmony_ci rcu_read_lock(); 1858c2ecf20Sopenharmony_ci if (rdev == NULL) 1868c2ecf20Sopenharmony_ci /* start at the beginning */ 1878c2ecf20Sopenharmony_ci rdev = list_entry(&mddev->disks, struct md_rdev, same_set); 1888c2ecf20Sopenharmony_ci else { 1898c2ecf20Sopenharmony_ci /* release the previous rdev and start from there. */ 1908c2ecf20Sopenharmony_ci rdev_dec_pending(rdev, mddev); 1918c2ecf20Sopenharmony_ci } 1928c2ecf20Sopenharmony_ci list_for_each_entry_continue_rcu(rdev, &mddev->disks, same_set) { 1938c2ecf20Sopenharmony_ci if (rdev->raid_disk >= 0 && 1948c2ecf20Sopenharmony_ci !test_bit(Faulty, &rdev->flags)) { 1958c2ecf20Sopenharmony_ci /* this is a usable devices */ 1968c2ecf20Sopenharmony_ci atomic_inc(&rdev->nr_pending); 1978c2ecf20Sopenharmony_ci rcu_read_unlock(); 1988c2ecf20Sopenharmony_ci return rdev; 1998c2ecf20Sopenharmony_ci } 2008c2ecf20Sopenharmony_ci } 2018c2ecf20Sopenharmony_ci rcu_read_unlock(); 2028c2ecf20Sopenharmony_ci return NULL; 2038c2ecf20Sopenharmony_ci} 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_cistatic int write_sb_page(struct bitmap *bitmap, struct page *page, int wait) 2068c2ecf20Sopenharmony_ci{ 2078c2ecf20Sopenharmony_ci struct md_rdev *rdev; 2088c2ecf20Sopenharmony_ci struct block_device *bdev; 2098c2ecf20Sopenharmony_ci struct mddev *mddev = bitmap->mddev; 2108c2ecf20Sopenharmony_ci struct bitmap_storage *store = &bitmap->storage; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cirestart: 2138c2ecf20Sopenharmony_ci rdev = NULL; 2148c2ecf20Sopenharmony_ci while ((rdev = next_active_rdev(rdev, mddev)) != NULL) { 2158c2ecf20Sopenharmony_ci int size = PAGE_SIZE; 2168c2ecf20Sopenharmony_ci loff_t offset = mddev->bitmap_info.offset; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci bdev = (rdev->meta_bdev) ? rdev->meta_bdev : rdev->bdev; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci if (page->index == store->file_pages-1) { 2218c2ecf20Sopenharmony_ci int last_page_size = store->bytes & (PAGE_SIZE-1); 2228c2ecf20Sopenharmony_ci if (last_page_size == 0) 2238c2ecf20Sopenharmony_ci last_page_size = PAGE_SIZE; 2248c2ecf20Sopenharmony_ci size = roundup(last_page_size, 2258c2ecf20Sopenharmony_ci bdev_logical_block_size(bdev)); 2268c2ecf20Sopenharmony_ci } 2278c2ecf20Sopenharmony_ci /* Just make sure we aren't corrupting data or 2288c2ecf20Sopenharmony_ci * metadata 2298c2ecf20Sopenharmony_ci */ 2308c2ecf20Sopenharmony_ci if (mddev->external) { 2318c2ecf20Sopenharmony_ci /* Bitmap could be anywhere. */ 2328c2ecf20Sopenharmony_ci if (rdev->sb_start + offset + (page->index 2338c2ecf20Sopenharmony_ci * (PAGE_SIZE/512)) 2348c2ecf20Sopenharmony_ci > rdev->data_offset 2358c2ecf20Sopenharmony_ci && 2368c2ecf20Sopenharmony_ci rdev->sb_start + offset 2378c2ecf20Sopenharmony_ci < (rdev->data_offset + mddev->dev_sectors 2388c2ecf20Sopenharmony_ci + (PAGE_SIZE/512))) 2398c2ecf20Sopenharmony_ci goto bad_alignment; 2408c2ecf20Sopenharmony_ci } else if (offset < 0) { 2418c2ecf20Sopenharmony_ci /* DATA BITMAP METADATA */ 2428c2ecf20Sopenharmony_ci if (offset 2438c2ecf20Sopenharmony_ci + (long)(page->index * (PAGE_SIZE/512)) 2448c2ecf20Sopenharmony_ci + size/512 > 0) 2458c2ecf20Sopenharmony_ci /* bitmap runs in to metadata */ 2468c2ecf20Sopenharmony_ci goto bad_alignment; 2478c2ecf20Sopenharmony_ci if (rdev->data_offset + mddev->dev_sectors 2488c2ecf20Sopenharmony_ci > rdev->sb_start + offset) 2498c2ecf20Sopenharmony_ci /* data runs in to bitmap */ 2508c2ecf20Sopenharmony_ci goto bad_alignment; 2518c2ecf20Sopenharmony_ci } else if (rdev->sb_start < rdev->data_offset) { 2528c2ecf20Sopenharmony_ci /* METADATA BITMAP DATA */ 2538c2ecf20Sopenharmony_ci if (rdev->sb_start 2548c2ecf20Sopenharmony_ci + offset 2558c2ecf20Sopenharmony_ci + page->index*(PAGE_SIZE/512) + size/512 2568c2ecf20Sopenharmony_ci > rdev->data_offset) 2578c2ecf20Sopenharmony_ci /* bitmap runs in to data */ 2588c2ecf20Sopenharmony_ci goto bad_alignment; 2598c2ecf20Sopenharmony_ci } else { 2608c2ecf20Sopenharmony_ci /* DATA METADATA BITMAP - no problems */ 2618c2ecf20Sopenharmony_ci } 2628c2ecf20Sopenharmony_ci md_super_write(mddev, rdev, 2638c2ecf20Sopenharmony_ci rdev->sb_start + offset 2648c2ecf20Sopenharmony_ci + page->index * (PAGE_SIZE/512), 2658c2ecf20Sopenharmony_ci size, 2668c2ecf20Sopenharmony_ci page); 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci if (wait && md_super_wait(mddev) < 0) 2708c2ecf20Sopenharmony_ci goto restart; 2718c2ecf20Sopenharmony_ci return 0; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci bad_alignment: 2748c2ecf20Sopenharmony_ci return -EINVAL; 2758c2ecf20Sopenharmony_ci} 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_cistatic void md_bitmap_file_kick(struct bitmap *bitmap); 2788c2ecf20Sopenharmony_ci/* 2798c2ecf20Sopenharmony_ci * write out a page to a file 2808c2ecf20Sopenharmony_ci */ 2818c2ecf20Sopenharmony_cistatic void write_page(struct bitmap *bitmap, struct page *page, int wait) 2828c2ecf20Sopenharmony_ci{ 2838c2ecf20Sopenharmony_ci struct buffer_head *bh; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci if (bitmap->storage.file == NULL) { 2868c2ecf20Sopenharmony_ci switch (write_sb_page(bitmap, page, wait)) { 2878c2ecf20Sopenharmony_ci case -EINVAL: 2888c2ecf20Sopenharmony_ci set_bit(BITMAP_WRITE_ERROR, &bitmap->flags); 2898c2ecf20Sopenharmony_ci } 2908c2ecf20Sopenharmony_ci } else { 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci bh = page_buffers(page); 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci while (bh && bh->b_blocknr) { 2958c2ecf20Sopenharmony_ci atomic_inc(&bitmap->pending_writes); 2968c2ecf20Sopenharmony_ci set_buffer_locked(bh); 2978c2ecf20Sopenharmony_ci set_buffer_mapped(bh); 2988c2ecf20Sopenharmony_ci submit_bh(REQ_OP_WRITE, REQ_SYNC, bh); 2998c2ecf20Sopenharmony_ci bh = bh->b_this_page; 3008c2ecf20Sopenharmony_ci } 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci if (wait) 3038c2ecf20Sopenharmony_ci wait_event(bitmap->write_wait, 3048c2ecf20Sopenharmony_ci atomic_read(&bitmap->pending_writes)==0); 3058c2ecf20Sopenharmony_ci } 3068c2ecf20Sopenharmony_ci if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags)) 3078c2ecf20Sopenharmony_ci md_bitmap_file_kick(bitmap); 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_cistatic void end_bitmap_write(struct buffer_head *bh, int uptodate) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci struct bitmap *bitmap = bh->b_private; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci if (!uptodate) 3158c2ecf20Sopenharmony_ci set_bit(BITMAP_WRITE_ERROR, &bitmap->flags); 3168c2ecf20Sopenharmony_ci if (atomic_dec_and_test(&bitmap->pending_writes)) 3178c2ecf20Sopenharmony_ci wake_up(&bitmap->write_wait); 3188c2ecf20Sopenharmony_ci} 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_cistatic void free_buffers(struct page *page) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci struct buffer_head *bh; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci if (!PagePrivate(page)) 3258c2ecf20Sopenharmony_ci return; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci bh = page_buffers(page); 3288c2ecf20Sopenharmony_ci while (bh) { 3298c2ecf20Sopenharmony_ci struct buffer_head *next = bh->b_this_page; 3308c2ecf20Sopenharmony_ci free_buffer_head(bh); 3318c2ecf20Sopenharmony_ci bh = next; 3328c2ecf20Sopenharmony_ci } 3338c2ecf20Sopenharmony_ci detach_page_private(page); 3348c2ecf20Sopenharmony_ci put_page(page); 3358c2ecf20Sopenharmony_ci} 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci/* read a page from a file. 3388c2ecf20Sopenharmony_ci * We both read the page, and attach buffers to the page to record the 3398c2ecf20Sopenharmony_ci * address of each block (using bmap). These addresses will be used 3408c2ecf20Sopenharmony_ci * to write the block later, completely bypassing the filesystem. 3418c2ecf20Sopenharmony_ci * This usage is similar to how swap files are handled, and allows us 3428c2ecf20Sopenharmony_ci * to write to a file with no concerns of memory allocation failing. 3438c2ecf20Sopenharmony_ci */ 3448c2ecf20Sopenharmony_cistatic int read_page(struct file *file, unsigned long index, 3458c2ecf20Sopenharmony_ci struct bitmap *bitmap, 3468c2ecf20Sopenharmony_ci unsigned long count, 3478c2ecf20Sopenharmony_ci struct page *page) 3488c2ecf20Sopenharmony_ci{ 3498c2ecf20Sopenharmony_ci int ret = 0; 3508c2ecf20Sopenharmony_ci struct inode *inode = file_inode(file); 3518c2ecf20Sopenharmony_ci struct buffer_head *bh; 3528c2ecf20Sopenharmony_ci sector_t block, blk_cur; 3538c2ecf20Sopenharmony_ci unsigned long blocksize = i_blocksize(inode); 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci pr_debug("read bitmap file (%dB @ %llu)\n", (int)PAGE_SIZE, 3568c2ecf20Sopenharmony_ci (unsigned long long)index << PAGE_SHIFT); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci bh = alloc_page_buffers(page, blocksize, false); 3598c2ecf20Sopenharmony_ci if (!bh) { 3608c2ecf20Sopenharmony_ci ret = -ENOMEM; 3618c2ecf20Sopenharmony_ci goto out; 3628c2ecf20Sopenharmony_ci } 3638c2ecf20Sopenharmony_ci attach_page_private(page, bh); 3648c2ecf20Sopenharmony_ci blk_cur = index << (PAGE_SHIFT - inode->i_blkbits); 3658c2ecf20Sopenharmony_ci while (bh) { 3668c2ecf20Sopenharmony_ci block = blk_cur; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci if (count == 0) 3698c2ecf20Sopenharmony_ci bh->b_blocknr = 0; 3708c2ecf20Sopenharmony_ci else { 3718c2ecf20Sopenharmony_ci ret = bmap(inode, &block); 3728c2ecf20Sopenharmony_ci if (ret || !block) { 3738c2ecf20Sopenharmony_ci ret = -EINVAL; 3748c2ecf20Sopenharmony_ci bh->b_blocknr = 0; 3758c2ecf20Sopenharmony_ci goto out; 3768c2ecf20Sopenharmony_ci } 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci bh->b_blocknr = block; 3798c2ecf20Sopenharmony_ci bh->b_bdev = inode->i_sb->s_bdev; 3808c2ecf20Sopenharmony_ci if (count < blocksize) 3818c2ecf20Sopenharmony_ci count = 0; 3828c2ecf20Sopenharmony_ci else 3838c2ecf20Sopenharmony_ci count -= blocksize; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci bh->b_end_io = end_bitmap_write; 3868c2ecf20Sopenharmony_ci bh->b_private = bitmap; 3878c2ecf20Sopenharmony_ci atomic_inc(&bitmap->pending_writes); 3888c2ecf20Sopenharmony_ci set_buffer_locked(bh); 3898c2ecf20Sopenharmony_ci set_buffer_mapped(bh); 3908c2ecf20Sopenharmony_ci submit_bh(REQ_OP_READ, 0, bh); 3918c2ecf20Sopenharmony_ci } 3928c2ecf20Sopenharmony_ci blk_cur++; 3938c2ecf20Sopenharmony_ci bh = bh->b_this_page; 3948c2ecf20Sopenharmony_ci } 3958c2ecf20Sopenharmony_ci page->index = index; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci wait_event(bitmap->write_wait, 3988c2ecf20Sopenharmony_ci atomic_read(&bitmap->pending_writes)==0); 3998c2ecf20Sopenharmony_ci if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags)) 4008c2ecf20Sopenharmony_ci ret = -EIO; 4018c2ecf20Sopenharmony_ciout: 4028c2ecf20Sopenharmony_ci if (ret) 4038c2ecf20Sopenharmony_ci pr_err("md: bitmap read error: (%dB @ %llu): %d\n", 4048c2ecf20Sopenharmony_ci (int)PAGE_SIZE, 4058c2ecf20Sopenharmony_ci (unsigned long long)index << PAGE_SHIFT, 4068c2ecf20Sopenharmony_ci ret); 4078c2ecf20Sopenharmony_ci return ret; 4088c2ecf20Sopenharmony_ci} 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci/* 4118c2ecf20Sopenharmony_ci * bitmap file superblock operations 4128c2ecf20Sopenharmony_ci */ 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci/* 4158c2ecf20Sopenharmony_ci * md_bitmap_wait_writes() should be called before writing any bitmap 4168c2ecf20Sopenharmony_ci * blocks, to ensure previous writes, particularly from 4178c2ecf20Sopenharmony_ci * md_bitmap_daemon_work(), have completed. 4188c2ecf20Sopenharmony_ci */ 4198c2ecf20Sopenharmony_cistatic void md_bitmap_wait_writes(struct bitmap *bitmap) 4208c2ecf20Sopenharmony_ci{ 4218c2ecf20Sopenharmony_ci if (bitmap->storage.file) 4228c2ecf20Sopenharmony_ci wait_event(bitmap->write_wait, 4238c2ecf20Sopenharmony_ci atomic_read(&bitmap->pending_writes)==0); 4248c2ecf20Sopenharmony_ci else 4258c2ecf20Sopenharmony_ci /* Note that we ignore the return value. The writes 4268c2ecf20Sopenharmony_ci * might have failed, but that would just mean that 4278c2ecf20Sopenharmony_ci * some bits which should be cleared haven't been, 4288c2ecf20Sopenharmony_ci * which is safe. The relevant bitmap blocks will 4298c2ecf20Sopenharmony_ci * probably get written again, but there is no great 4308c2ecf20Sopenharmony_ci * loss if they aren't. 4318c2ecf20Sopenharmony_ci */ 4328c2ecf20Sopenharmony_ci md_super_wait(bitmap->mddev); 4338c2ecf20Sopenharmony_ci} 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci/* update the event counter and sync the superblock to disk */ 4378c2ecf20Sopenharmony_civoid md_bitmap_update_sb(struct bitmap *bitmap) 4388c2ecf20Sopenharmony_ci{ 4398c2ecf20Sopenharmony_ci bitmap_super_t *sb; 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci if (!bitmap || !bitmap->mddev) /* no bitmap for this array */ 4428c2ecf20Sopenharmony_ci return; 4438c2ecf20Sopenharmony_ci if (bitmap->mddev->bitmap_info.external) 4448c2ecf20Sopenharmony_ci return; 4458c2ecf20Sopenharmony_ci if (!bitmap->storage.sb_page) /* no superblock */ 4468c2ecf20Sopenharmony_ci return; 4478c2ecf20Sopenharmony_ci sb = kmap_atomic(bitmap->storage.sb_page); 4488c2ecf20Sopenharmony_ci sb->events = cpu_to_le64(bitmap->mddev->events); 4498c2ecf20Sopenharmony_ci if (bitmap->mddev->events < bitmap->events_cleared) 4508c2ecf20Sopenharmony_ci /* rocking back to read-only */ 4518c2ecf20Sopenharmony_ci bitmap->events_cleared = bitmap->mddev->events; 4528c2ecf20Sopenharmony_ci sb->events_cleared = cpu_to_le64(bitmap->events_cleared); 4538c2ecf20Sopenharmony_ci /* 4548c2ecf20Sopenharmony_ci * clear BITMAP_WRITE_ERROR bit to protect against the case that 4558c2ecf20Sopenharmony_ci * a bitmap write error occurred but the later writes succeeded. 4568c2ecf20Sopenharmony_ci */ 4578c2ecf20Sopenharmony_ci sb->state = cpu_to_le32(bitmap->flags & ~BIT(BITMAP_WRITE_ERROR)); 4588c2ecf20Sopenharmony_ci /* Just in case these have been changed via sysfs: */ 4598c2ecf20Sopenharmony_ci sb->daemon_sleep = cpu_to_le32(bitmap->mddev->bitmap_info.daemon_sleep/HZ); 4608c2ecf20Sopenharmony_ci sb->write_behind = cpu_to_le32(bitmap->mddev->bitmap_info.max_write_behind); 4618c2ecf20Sopenharmony_ci /* This might have been changed by a reshape */ 4628c2ecf20Sopenharmony_ci sb->sync_size = cpu_to_le64(bitmap->mddev->resync_max_sectors); 4638c2ecf20Sopenharmony_ci sb->chunksize = cpu_to_le32(bitmap->mddev->bitmap_info.chunksize); 4648c2ecf20Sopenharmony_ci sb->nodes = cpu_to_le32(bitmap->mddev->bitmap_info.nodes); 4658c2ecf20Sopenharmony_ci sb->sectors_reserved = cpu_to_le32(bitmap->mddev-> 4668c2ecf20Sopenharmony_ci bitmap_info.space); 4678c2ecf20Sopenharmony_ci kunmap_atomic(sb); 4688c2ecf20Sopenharmony_ci write_page(bitmap, bitmap->storage.sb_page, 1); 4698c2ecf20Sopenharmony_ci} 4708c2ecf20Sopenharmony_ciEXPORT_SYMBOL(md_bitmap_update_sb); 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci/* print out the bitmap file superblock */ 4738c2ecf20Sopenharmony_civoid md_bitmap_print_sb(struct bitmap *bitmap) 4748c2ecf20Sopenharmony_ci{ 4758c2ecf20Sopenharmony_ci bitmap_super_t *sb; 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci if (!bitmap || !bitmap->storage.sb_page) 4788c2ecf20Sopenharmony_ci return; 4798c2ecf20Sopenharmony_ci sb = kmap_atomic(bitmap->storage.sb_page); 4808c2ecf20Sopenharmony_ci pr_debug("%s: bitmap file superblock:\n", bmname(bitmap)); 4818c2ecf20Sopenharmony_ci pr_debug(" magic: %08x\n", le32_to_cpu(sb->magic)); 4828c2ecf20Sopenharmony_ci pr_debug(" version: %u\n", le32_to_cpu(sb->version)); 4838c2ecf20Sopenharmony_ci pr_debug(" uuid: %08x.%08x.%08x.%08x\n", 4848c2ecf20Sopenharmony_ci le32_to_cpu(*(__le32 *)(sb->uuid+0)), 4858c2ecf20Sopenharmony_ci le32_to_cpu(*(__le32 *)(sb->uuid+4)), 4868c2ecf20Sopenharmony_ci le32_to_cpu(*(__le32 *)(sb->uuid+8)), 4878c2ecf20Sopenharmony_ci le32_to_cpu(*(__le32 *)(sb->uuid+12))); 4888c2ecf20Sopenharmony_ci pr_debug(" events: %llu\n", 4898c2ecf20Sopenharmony_ci (unsigned long long) le64_to_cpu(sb->events)); 4908c2ecf20Sopenharmony_ci pr_debug("events cleared: %llu\n", 4918c2ecf20Sopenharmony_ci (unsigned long long) le64_to_cpu(sb->events_cleared)); 4928c2ecf20Sopenharmony_ci pr_debug(" state: %08x\n", le32_to_cpu(sb->state)); 4938c2ecf20Sopenharmony_ci pr_debug(" chunksize: %u B\n", le32_to_cpu(sb->chunksize)); 4948c2ecf20Sopenharmony_ci pr_debug(" daemon sleep: %us\n", le32_to_cpu(sb->daemon_sleep)); 4958c2ecf20Sopenharmony_ci pr_debug(" sync size: %llu KB\n", 4968c2ecf20Sopenharmony_ci (unsigned long long)le64_to_cpu(sb->sync_size)/2); 4978c2ecf20Sopenharmony_ci pr_debug("max write behind: %u\n", le32_to_cpu(sb->write_behind)); 4988c2ecf20Sopenharmony_ci kunmap_atomic(sb); 4998c2ecf20Sopenharmony_ci} 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci/* 5028c2ecf20Sopenharmony_ci * bitmap_new_disk_sb 5038c2ecf20Sopenharmony_ci * @bitmap 5048c2ecf20Sopenharmony_ci * 5058c2ecf20Sopenharmony_ci * This function is somewhat the reverse of bitmap_read_sb. bitmap_read_sb 5068c2ecf20Sopenharmony_ci * reads and verifies the on-disk bitmap superblock and populates bitmap_info. 5078c2ecf20Sopenharmony_ci * This function verifies 'bitmap_info' and populates the on-disk bitmap 5088c2ecf20Sopenharmony_ci * structure, which is to be written to disk. 5098c2ecf20Sopenharmony_ci * 5108c2ecf20Sopenharmony_ci * Returns: 0 on success, -Exxx on error 5118c2ecf20Sopenharmony_ci */ 5128c2ecf20Sopenharmony_cistatic int md_bitmap_new_disk_sb(struct bitmap *bitmap) 5138c2ecf20Sopenharmony_ci{ 5148c2ecf20Sopenharmony_ci bitmap_super_t *sb; 5158c2ecf20Sopenharmony_ci unsigned long chunksize, daemon_sleep, write_behind; 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci bitmap->storage.sb_page = alloc_page(GFP_KERNEL | __GFP_ZERO); 5188c2ecf20Sopenharmony_ci if (bitmap->storage.sb_page == NULL) 5198c2ecf20Sopenharmony_ci return -ENOMEM; 5208c2ecf20Sopenharmony_ci bitmap->storage.sb_page->index = 0; 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci sb = kmap_atomic(bitmap->storage.sb_page); 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci sb->magic = cpu_to_le32(BITMAP_MAGIC); 5258c2ecf20Sopenharmony_ci sb->version = cpu_to_le32(BITMAP_MAJOR_HI); 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci chunksize = bitmap->mddev->bitmap_info.chunksize; 5288c2ecf20Sopenharmony_ci BUG_ON(!chunksize); 5298c2ecf20Sopenharmony_ci if (!is_power_of_2(chunksize)) { 5308c2ecf20Sopenharmony_ci kunmap_atomic(sb); 5318c2ecf20Sopenharmony_ci pr_warn("bitmap chunksize not a power of 2\n"); 5328c2ecf20Sopenharmony_ci return -EINVAL; 5338c2ecf20Sopenharmony_ci } 5348c2ecf20Sopenharmony_ci sb->chunksize = cpu_to_le32(chunksize); 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci daemon_sleep = bitmap->mddev->bitmap_info.daemon_sleep; 5378c2ecf20Sopenharmony_ci if (!daemon_sleep || (daemon_sleep > MAX_SCHEDULE_TIMEOUT)) { 5388c2ecf20Sopenharmony_ci pr_debug("Choosing daemon_sleep default (5 sec)\n"); 5398c2ecf20Sopenharmony_ci daemon_sleep = 5 * HZ; 5408c2ecf20Sopenharmony_ci } 5418c2ecf20Sopenharmony_ci sb->daemon_sleep = cpu_to_le32(daemon_sleep); 5428c2ecf20Sopenharmony_ci bitmap->mddev->bitmap_info.daemon_sleep = daemon_sleep; 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci /* 5458c2ecf20Sopenharmony_ci * FIXME: write_behind for RAID1. If not specified, what 5468c2ecf20Sopenharmony_ci * is a good choice? We choose COUNTER_MAX / 2 arbitrarily. 5478c2ecf20Sopenharmony_ci */ 5488c2ecf20Sopenharmony_ci write_behind = bitmap->mddev->bitmap_info.max_write_behind; 5498c2ecf20Sopenharmony_ci if (write_behind > COUNTER_MAX) 5508c2ecf20Sopenharmony_ci write_behind = COUNTER_MAX / 2; 5518c2ecf20Sopenharmony_ci sb->write_behind = cpu_to_le32(write_behind); 5528c2ecf20Sopenharmony_ci bitmap->mddev->bitmap_info.max_write_behind = write_behind; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci /* keep the array size field of the bitmap superblock up to date */ 5558c2ecf20Sopenharmony_ci sb->sync_size = cpu_to_le64(bitmap->mddev->resync_max_sectors); 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci memcpy(sb->uuid, bitmap->mddev->uuid, 16); 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci set_bit(BITMAP_STALE, &bitmap->flags); 5608c2ecf20Sopenharmony_ci sb->state = cpu_to_le32(bitmap->flags); 5618c2ecf20Sopenharmony_ci bitmap->events_cleared = bitmap->mddev->events; 5628c2ecf20Sopenharmony_ci sb->events_cleared = cpu_to_le64(bitmap->mddev->events); 5638c2ecf20Sopenharmony_ci bitmap->mddev->bitmap_info.nodes = 0; 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci kunmap_atomic(sb); 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci return 0; 5688c2ecf20Sopenharmony_ci} 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci/* read the superblock from the bitmap file and initialize some bitmap fields */ 5718c2ecf20Sopenharmony_cistatic int md_bitmap_read_sb(struct bitmap *bitmap) 5728c2ecf20Sopenharmony_ci{ 5738c2ecf20Sopenharmony_ci char *reason = NULL; 5748c2ecf20Sopenharmony_ci bitmap_super_t *sb; 5758c2ecf20Sopenharmony_ci unsigned long chunksize, daemon_sleep, write_behind; 5768c2ecf20Sopenharmony_ci unsigned long long events; 5778c2ecf20Sopenharmony_ci int nodes = 0; 5788c2ecf20Sopenharmony_ci unsigned long sectors_reserved = 0; 5798c2ecf20Sopenharmony_ci int err = -EINVAL; 5808c2ecf20Sopenharmony_ci struct page *sb_page; 5818c2ecf20Sopenharmony_ci loff_t offset = bitmap->mddev->bitmap_info.offset; 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci if (!bitmap->storage.file && !bitmap->mddev->bitmap_info.offset) { 5848c2ecf20Sopenharmony_ci chunksize = 128 * 1024 * 1024; 5858c2ecf20Sopenharmony_ci daemon_sleep = 5 * HZ; 5868c2ecf20Sopenharmony_ci write_behind = 0; 5878c2ecf20Sopenharmony_ci set_bit(BITMAP_STALE, &bitmap->flags); 5888c2ecf20Sopenharmony_ci err = 0; 5898c2ecf20Sopenharmony_ci goto out_no_sb; 5908c2ecf20Sopenharmony_ci } 5918c2ecf20Sopenharmony_ci /* page 0 is the superblock, read it... */ 5928c2ecf20Sopenharmony_ci sb_page = alloc_page(GFP_KERNEL); 5938c2ecf20Sopenharmony_ci if (!sb_page) 5948c2ecf20Sopenharmony_ci return -ENOMEM; 5958c2ecf20Sopenharmony_ci bitmap->storage.sb_page = sb_page; 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_cire_read: 5988c2ecf20Sopenharmony_ci /* If cluster_slot is set, the cluster is setup */ 5998c2ecf20Sopenharmony_ci if (bitmap->cluster_slot >= 0) { 6008c2ecf20Sopenharmony_ci sector_t bm_blocks = bitmap->mddev->resync_max_sectors; 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci bm_blocks = DIV_ROUND_UP_SECTOR_T(bm_blocks, 6038c2ecf20Sopenharmony_ci (bitmap->mddev->bitmap_info.chunksize >> 9)); 6048c2ecf20Sopenharmony_ci /* bits to bytes */ 6058c2ecf20Sopenharmony_ci bm_blocks = ((bm_blocks+7) >> 3) + sizeof(bitmap_super_t); 6068c2ecf20Sopenharmony_ci /* to 4k blocks */ 6078c2ecf20Sopenharmony_ci bm_blocks = DIV_ROUND_UP_SECTOR_T(bm_blocks, 4096); 6088c2ecf20Sopenharmony_ci offset = bitmap->mddev->bitmap_info.offset + (bitmap->cluster_slot * (bm_blocks << 3)); 6098c2ecf20Sopenharmony_ci pr_debug("%s:%d bm slot: %d offset: %llu\n", __func__, __LINE__, 6108c2ecf20Sopenharmony_ci bitmap->cluster_slot, offset); 6118c2ecf20Sopenharmony_ci } 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci if (bitmap->storage.file) { 6148c2ecf20Sopenharmony_ci loff_t isize = i_size_read(bitmap->storage.file->f_mapping->host); 6158c2ecf20Sopenharmony_ci int bytes = isize > PAGE_SIZE ? PAGE_SIZE : isize; 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci err = read_page(bitmap->storage.file, 0, 6188c2ecf20Sopenharmony_ci bitmap, bytes, sb_page); 6198c2ecf20Sopenharmony_ci } else { 6208c2ecf20Sopenharmony_ci err = read_sb_page(bitmap->mddev, 6218c2ecf20Sopenharmony_ci offset, 6228c2ecf20Sopenharmony_ci sb_page, 6238c2ecf20Sopenharmony_ci 0, sizeof(bitmap_super_t)); 6248c2ecf20Sopenharmony_ci } 6258c2ecf20Sopenharmony_ci if (err) 6268c2ecf20Sopenharmony_ci return err; 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci err = -EINVAL; 6298c2ecf20Sopenharmony_ci sb = kmap_atomic(sb_page); 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci chunksize = le32_to_cpu(sb->chunksize); 6328c2ecf20Sopenharmony_ci daemon_sleep = le32_to_cpu(sb->daemon_sleep) * HZ; 6338c2ecf20Sopenharmony_ci write_behind = le32_to_cpu(sb->write_behind); 6348c2ecf20Sopenharmony_ci sectors_reserved = le32_to_cpu(sb->sectors_reserved); 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci /* verify that the bitmap-specific fields are valid */ 6378c2ecf20Sopenharmony_ci if (sb->magic != cpu_to_le32(BITMAP_MAGIC)) 6388c2ecf20Sopenharmony_ci reason = "bad magic"; 6398c2ecf20Sopenharmony_ci else if (le32_to_cpu(sb->version) < BITMAP_MAJOR_LO || 6408c2ecf20Sopenharmony_ci le32_to_cpu(sb->version) > BITMAP_MAJOR_CLUSTERED) 6418c2ecf20Sopenharmony_ci reason = "unrecognized superblock version"; 6428c2ecf20Sopenharmony_ci else if (chunksize < 512) 6438c2ecf20Sopenharmony_ci reason = "bitmap chunksize too small"; 6448c2ecf20Sopenharmony_ci else if (!is_power_of_2(chunksize)) 6458c2ecf20Sopenharmony_ci reason = "bitmap chunksize not a power of 2"; 6468c2ecf20Sopenharmony_ci else if (daemon_sleep < 1 || daemon_sleep > MAX_SCHEDULE_TIMEOUT) 6478c2ecf20Sopenharmony_ci reason = "daemon sleep period out of range"; 6488c2ecf20Sopenharmony_ci else if (write_behind > COUNTER_MAX) 6498c2ecf20Sopenharmony_ci reason = "write-behind limit out of range (0 - 16383)"; 6508c2ecf20Sopenharmony_ci if (reason) { 6518c2ecf20Sopenharmony_ci pr_warn("%s: invalid bitmap file superblock: %s\n", 6528c2ecf20Sopenharmony_ci bmname(bitmap), reason); 6538c2ecf20Sopenharmony_ci goto out; 6548c2ecf20Sopenharmony_ci } 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci /* 6578c2ecf20Sopenharmony_ci * Setup nodes/clustername only if bitmap version is 6588c2ecf20Sopenharmony_ci * cluster-compatible 6598c2ecf20Sopenharmony_ci */ 6608c2ecf20Sopenharmony_ci if (sb->version == cpu_to_le32(BITMAP_MAJOR_CLUSTERED)) { 6618c2ecf20Sopenharmony_ci nodes = le32_to_cpu(sb->nodes); 6628c2ecf20Sopenharmony_ci strlcpy(bitmap->mddev->bitmap_info.cluster_name, 6638c2ecf20Sopenharmony_ci sb->cluster_name, 64); 6648c2ecf20Sopenharmony_ci } 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci /* keep the array size field of the bitmap superblock up to date */ 6678c2ecf20Sopenharmony_ci sb->sync_size = cpu_to_le64(bitmap->mddev->resync_max_sectors); 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci if (bitmap->mddev->persistent) { 6708c2ecf20Sopenharmony_ci /* 6718c2ecf20Sopenharmony_ci * We have a persistent array superblock, so compare the 6728c2ecf20Sopenharmony_ci * bitmap's UUID and event counter to the mddev's 6738c2ecf20Sopenharmony_ci */ 6748c2ecf20Sopenharmony_ci if (memcmp(sb->uuid, bitmap->mddev->uuid, 16)) { 6758c2ecf20Sopenharmony_ci pr_warn("%s: bitmap superblock UUID mismatch\n", 6768c2ecf20Sopenharmony_ci bmname(bitmap)); 6778c2ecf20Sopenharmony_ci goto out; 6788c2ecf20Sopenharmony_ci } 6798c2ecf20Sopenharmony_ci events = le64_to_cpu(sb->events); 6808c2ecf20Sopenharmony_ci if (!nodes && (events < bitmap->mddev->events)) { 6818c2ecf20Sopenharmony_ci pr_warn("%s: bitmap file is out of date (%llu < %llu) -- forcing full recovery\n", 6828c2ecf20Sopenharmony_ci bmname(bitmap), events, 6838c2ecf20Sopenharmony_ci (unsigned long long) bitmap->mddev->events); 6848c2ecf20Sopenharmony_ci set_bit(BITMAP_STALE, &bitmap->flags); 6858c2ecf20Sopenharmony_ci } 6868c2ecf20Sopenharmony_ci } 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci /* assign fields using values from superblock */ 6898c2ecf20Sopenharmony_ci bitmap->flags |= le32_to_cpu(sb->state); 6908c2ecf20Sopenharmony_ci if (le32_to_cpu(sb->version) == BITMAP_MAJOR_HOSTENDIAN) 6918c2ecf20Sopenharmony_ci set_bit(BITMAP_HOSTENDIAN, &bitmap->flags); 6928c2ecf20Sopenharmony_ci bitmap->events_cleared = le64_to_cpu(sb->events_cleared); 6938c2ecf20Sopenharmony_ci strlcpy(bitmap->mddev->bitmap_info.cluster_name, sb->cluster_name, 64); 6948c2ecf20Sopenharmony_ci err = 0; 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ciout: 6978c2ecf20Sopenharmony_ci kunmap_atomic(sb); 6988c2ecf20Sopenharmony_ci if (err == 0 && nodes && (bitmap->cluster_slot < 0)) { 6998c2ecf20Sopenharmony_ci /* Assigning chunksize is required for "re_read" */ 7008c2ecf20Sopenharmony_ci bitmap->mddev->bitmap_info.chunksize = chunksize; 7018c2ecf20Sopenharmony_ci err = md_setup_cluster(bitmap->mddev, nodes); 7028c2ecf20Sopenharmony_ci if (err) { 7038c2ecf20Sopenharmony_ci pr_warn("%s: Could not setup cluster service (%d)\n", 7048c2ecf20Sopenharmony_ci bmname(bitmap), err); 7058c2ecf20Sopenharmony_ci goto out_no_sb; 7068c2ecf20Sopenharmony_ci } 7078c2ecf20Sopenharmony_ci bitmap->cluster_slot = md_cluster_ops->slot_number(bitmap->mddev); 7088c2ecf20Sopenharmony_ci goto re_read; 7098c2ecf20Sopenharmony_ci } 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ciout_no_sb: 7128c2ecf20Sopenharmony_ci if (err == 0) { 7138c2ecf20Sopenharmony_ci if (test_bit(BITMAP_STALE, &bitmap->flags)) 7148c2ecf20Sopenharmony_ci bitmap->events_cleared = bitmap->mddev->events; 7158c2ecf20Sopenharmony_ci bitmap->mddev->bitmap_info.chunksize = chunksize; 7168c2ecf20Sopenharmony_ci bitmap->mddev->bitmap_info.daemon_sleep = daemon_sleep; 7178c2ecf20Sopenharmony_ci bitmap->mddev->bitmap_info.max_write_behind = write_behind; 7188c2ecf20Sopenharmony_ci bitmap->mddev->bitmap_info.nodes = nodes; 7198c2ecf20Sopenharmony_ci if (bitmap->mddev->bitmap_info.space == 0 || 7208c2ecf20Sopenharmony_ci bitmap->mddev->bitmap_info.space > sectors_reserved) 7218c2ecf20Sopenharmony_ci bitmap->mddev->bitmap_info.space = sectors_reserved; 7228c2ecf20Sopenharmony_ci } else { 7238c2ecf20Sopenharmony_ci md_bitmap_print_sb(bitmap); 7248c2ecf20Sopenharmony_ci if (bitmap->cluster_slot < 0) 7258c2ecf20Sopenharmony_ci md_cluster_stop(bitmap->mddev); 7268c2ecf20Sopenharmony_ci } 7278c2ecf20Sopenharmony_ci return err; 7288c2ecf20Sopenharmony_ci} 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci/* 7318c2ecf20Sopenharmony_ci * general bitmap file operations 7328c2ecf20Sopenharmony_ci */ 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci/* 7358c2ecf20Sopenharmony_ci * on-disk bitmap: 7368c2ecf20Sopenharmony_ci * 7378c2ecf20Sopenharmony_ci * Use one bit per "chunk" (block set). We do the disk I/O on the bitmap 7388c2ecf20Sopenharmony_ci * file a page at a time. There's a superblock at the start of the file. 7398c2ecf20Sopenharmony_ci */ 7408c2ecf20Sopenharmony_ci/* calculate the index of the page that contains this bit */ 7418c2ecf20Sopenharmony_cistatic inline unsigned long file_page_index(struct bitmap_storage *store, 7428c2ecf20Sopenharmony_ci unsigned long chunk) 7438c2ecf20Sopenharmony_ci{ 7448c2ecf20Sopenharmony_ci if (store->sb_page) 7458c2ecf20Sopenharmony_ci chunk += sizeof(bitmap_super_t) << 3; 7468c2ecf20Sopenharmony_ci return chunk >> PAGE_BIT_SHIFT; 7478c2ecf20Sopenharmony_ci} 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci/* calculate the (bit) offset of this bit within a page */ 7508c2ecf20Sopenharmony_cistatic inline unsigned long file_page_offset(struct bitmap_storage *store, 7518c2ecf20Sopenharmony_ci unsigned long chunk) 7528c2ecf20Sopenharmony_ci{ 7538c2ecf20Sopenharmony_ci if (store->sb_page) 7548c2ecf20Sopenharmony_ci chunk += sizeof(bitmap_super_t) << 3; 7558c2ecf20Sopenharmony_ci return chunk & (PAGE_BITS - 1); 7568c2ecf20Sopenharmony_ci} 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci/* 7598c2ecf20Sopenharmony_ci * return a pointer to the page in the filemap that contains the given bit 7608c2ecf20Sopenharmony_ci * 7618c2ecf20Sopenharmony_ci */ 7628c2ecf20Sopenharmony_cistatic inline struct page *filemap_get_page(struct bitmap_storage *store, 7638c2ecf20Sopenharmony_ci unsigned long chunk) 7648c2ecf20Sopenharmony_ci{ 7658c2ecf20Sopenharmony_ci if (file_page_index(store, chunk) >= store->file_pages) 7668c2ecf20Sopenharmony_ci return NULL; 7678c2ecf20Sopenharmony_ci return store->filemap[file_page_index(store, chunk)]; 7688c2ecf20Sopenharmony_ci} 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_cistatic int md_bitmap_storage_alloc(struct bitmap_storage *store, 7718c2ecf20Sopenharmony_ci unsigned long chunks, int with_super, 7728c2ecf20Sopenharmony_ci int slot_number) 7738c2ecf20Sopenharmony_ci{ 7748c2ecf20Sopenharmony_ci int pnum, offset = 0; 7758c2ecf20Sopenharmony_ci unsigned long num_pages; 7768c2ecf20Sopenharmony_ci unsigned long bytes; 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci bytes = DIV_ROUND_UP(chunks, 8); 7798c2ecf20Sopenharmony_ci if (with_super) 7808c2ecf20Sopenharmony_ci bytes += sizeof(bitmap_super_t); 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci num_pages = DIV_ROUND_UP(bytes, PAGE_SIZE); 7838c2ecf20Sopenharmony_ci offset = slot_number * num_pages; 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci store->filemap = kmalloc_array(num_pages, sizeof(struct page *), 7868c2ecf20Sopenharmony_ci GFP_KERNEL); 7878c2ecf20Sopenharmony_ci if (!store->filemap) 7888c2ecf20Sopenharmony_ci return -ENOMEM; 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci if (with_super && !store->sb_page) { 7918c2ecf20Sopenharmony_ci store->sb_page = alloc_page(GFP_KERNEL|__GFP_ZERO); 7928c2ecf20Sopenharmony_ci if (store->sb_page == NULL) 7938c2ecf20Sopenharmony_ci return -ENOMEM; 7948c2ecf20Sopenharmony_ci } 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci pnum = 0; 7978c2ecf20Sopenharmony_ci if (store->sb_page) { 7988c2ecf20Sopenharmony_ci store->filemap[0] = store->sb_page; 7998c2ecf20Sopenharmony_ci pnum = 1; 8008c2ecf20Sopenharmony_ci store->sb_page->index = offset; 8018c2ecf20Sopenharmony_ci } 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci for ( ; pnum < num_pages; pnum++) { 8048c2ecf20Sopenharmony_ci store->filemap[pnum] = alloc_page(GFP_KERNEL|__GFP_ZERO); 8058c2ecf20Sopenharmony_ci if (!store->filemap[pnum]) { 8068c2ecf20Sopenharmony_ci store->file_pages = pnum; 8078c2ecf20Sopenharmony_ci return -ENOMEM; 8088c2ecf20Sopenharmony_ci } 8098c2ecf20Sopenharmony_ci store->filemap[pnum]->index = pnum + offset; 8108c2ecf20Sopenharmony_ci } 8118c2ecf20Sopenharmony_ci store->file_pages = pnum; 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci /* We need 4 bits per page, rounded up to a multiple 8148c2ecf20Sopenharmony_ci * of sizeof(unsigned long) */ 8158c2ecf20Sopenharmony_ci store->filemap_attr = kzalloc( 8168c2ecf20Sopenharmony_ci roundup(DIV_ROUND_UP(num_pages*4, 8), sizeof(unsigned long)), 8178c2ecf20Sopenharmony_ci GFP_KERNEL); 8188c2ecf20Sopenharmony_ci if (!store->filemap_attr) 8198c2ecf20Sopenharmony_ci return -ENOMEM; 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci store->bytes = bytes; 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci return 0; 8248c2ecf20Sopenharmony_ci} 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_cistatic void md_bitmap_file_unmap(struct bitmap_storage *store) 8278c2ecf20Sopenharmony_ci{ 8288c2ecf20Sopenharmony_ci struct page **map, *sb_page; 8298c2ecf20Sopenharmony_ci int pages; 8308c2ecf20Sopenharmony_ci struct file *file; 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci file = store->file; 8338c2ecf20Sopenharmony_ci map = store->filemap; 8348c2ecf20Sopenharmony_ci pages = store->file_pages; 8358c2ecf20Sopenharmony_ci sb_page = store->sb_page; 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci while (pages--) 8388c2ecf20Sopenharmony_ci if (map[pages] != sb_page) /* 0 is sb_page, release it below */ 8398c2ecf20Sopenharmony_ci free_buffers(map[pages]); 8408c2ecf20Sopenharmony_ci kfree(map); 8418c2ecf20Sopenharmony_ci kfree(store->filemap_attr); 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci if (sb_page) 8448c2ecf20Sopenharmony_ci free_buffers(sb_page); 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci if (file) { 8478c2ecf20Sopenharmony_ci struct inode *inode = file_inode(file); 8488c2ecf20Sopenharmony_ci invalidate_mapping_pages(inode->i_mapping, 0, -1); 8498c2ecf20Sopenharmony_ci fput(file); 8508c2ecf20Sopenharmony_ci } 8518c2ecf20Sopenharmony_ci} 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci/* 8548c2ecf20Sopenharmony_ci * bitmap_file_kick - if an error occurs while manipulating the bitmap file 8558c2ecf20Sopenharmony_ci * then it is no longer reliable, so we stop using it and we mark the file 8568c2ecf20Sopenharmony_ci * as failed in the superblock 8578c2ecf20Sopenharmony_ci */ 8588c2ecf20Sopenharmony_cistatic void md_bitmap_file_kick(struct bitmap *bitmap) 8598c2ecf20Sopenharmony_ci{ 8608c2ecf20Sopenharmony_ci char *path, *ptr = NULL; 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci if (!test_and_set_bit(BITMAP_STALE, &bitmap->flags)) { 8638c2ecf20Sopenharmony_ci md_bitmap_update_sb(bitmap); 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci if (bitmap->storage.file) { 8668c2ecf20Sopenharmony_ci path = kmalloc(PAGE_SIZE, GFP_KERNEL); 8678c2ecf20Sopenharmony_ci if (path) 8688c2ecf20Sopenharmony_ci ptr = file_path(bitmap->storage.file, 8698c2ecf20Sopenharmony_ci path, PAGE_SIZE); 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci pr_warn("%s: kicking failed bitmap file %s from array!\n", 8728c2ecf20Sopenharmony_ci bmname(bitmap), IS_ERR(ptr) ? "" : ptr); 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci kfree(path); 8758c2ecf20Sopenharmony_ci } else 8768c2ecf20Sopenharmony_ci pr_warn("%s: disabling internal bitmap due to errors\n", 8778c2ecf20Sopenharmony_ci bmname(bitmap)); 8788c2ecf20Sopenharmony_ci } 8798c2ecf20Sopenharmony_ci} 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_cienum bitmap_page_attr { 8828c2ecf20Sopenharmony_ci BITMAP_PAGE_DIRTY = 0, /* there are set bits that need to be synced */ 8838c2ecf20Sopenharmony_ci BITMAP_PAGE_PENDING = 1, /* there are bits that are being cleaned. 8848c2ecf20Sopenharmony_ci * i.e. counter is 1 or 2. */ 8858c2ecf20Sopenharmony_ci BITMAP_PAGE_NEEDWRITE = 2, /* there are cleared bits that need to be synced */ 8868c2ecf20Sopenharmony_ci}; 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_cistatic inline void set_page_attr(struct bitmap *bitmap, int pnum, 8898c2ecf20Sopenharmony_ci enum bitmap_page_attr attr) 8908c2ecf20Sopenharmony_ci{ 8918c2ecf20Sopenharmony_ci set_bit((pnum<<2) + attr, bitmap->storage.filemap_attr); 8928c2ecf20Sopenharmony_ci} 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_cistatic inline void clear_page_attr(struct bitmap *bitmap, int pnum, 8958c2ecf20Sopenharmony_ci enum bitmap_page_attr attr) 8968c2ecf20Sopenharmony_ci{ 8978c2ecf20Sopenharmony_ci clear_bit((pnum<<2) + attr, bitmap->storage.filemap_attr); 8988c2ecf20Sopenharmony_ci} 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_cistatic inline int test_page_attr(struct bitmap *bitmap, int pnum, 9018c2ecf20Sopenharmony_ci enum bitmap_page_attr attr) 9028c2ecf20Sopenharmony_ci{ 9038c2ecf20Sopenharmony_ci return test_bit((pnum<<2) + attr, bitmap->storage.filemap_attr); 9048c2ecf20Sopenharmony_ci} 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_cistatic inline int test_and_clear_page_attr(struct bitmap *bitmap, int pnum, 9078c2ecf20Sopenharmony_ci enum bitmap_page_attr attr) 9088c2ecf20Sopenharmony_ci{ 9098c2ecf20Sopenharmony_ci return test_and_clear_bit((pnum<<2) + attr, 9108c2ecf20Sopenharmony_ci bitmap->storage.filemap_attr); 9118c2ecf20Sopenharmony_ci} 9128c2ecf20Sopenharmony_ci/* 9138c2ecf20Sopenharmony_ci * bitmap_file_set_bit -- called before performing a write to the md device 9148c2ecf20Sopenharmony_ci * to set (and eventually sync) a particular bit in the bitmap file 9158c2ecf20Sopenharmony_ci * 9168c2ecf20Sopenharmony_ci * we set the bit immediately, then we record the page number so that 9178c2ecf20Sopenharmony_ci * when an unplug occurs, we can flush the dirty pages out to disk 9188c2ecf20Sopenharmony_ci */ 9198c2ecf20Sopenharmony_cistatic void md_bitmap_file_set_bit(struct bitmap *bitmap, sector_t block) 9208c2ecf20Sopenharmony_ci{ 9218c2ecf20Sopenharmony_ci unsigned long bit; 9228c2ecf20Sopenharmony_ci struct page *page; 9238c2ecf20Sopenharmony_ci void *kaddr; 9248c2ecf20Sopenharmony_ci unsigned long chunk = block >> bitmap->counts.chunkshift; 9258c2ecf20Sopenharmony_ci struct bitmap_storage *store = &bitmap->storage; 9268c2ecf20Sopenharmony_ci unsigned long node_offset = 0; 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci if (mddev_is_clustered(bitmap->mddev)) 9298c2ecf20Sopenharmony_ci node_offset = bitmap->cluster_slot * store->file_pages; 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci page = filemap_get_page(&bitmap->storage, chunk); 9328c2ecf20Sopenharmony_ci if (!page) 9338c2ecf20Sopenharmony_ci return; 9348c2ecf20Sopenharmony_ci bit = file_page_offset(&bitmap->storage, chunk); 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci /* set the bit */ 9378c2ecf20Sopenharmony_ci kaddr = kmap_atomic(page); 9388c2ecf20Sopenharmony_ci if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags)) 9398c2ecf20Sopenharmony_ci set_bit(bit, kaddr); 9408c2ecf20Sopenharmony_ci else 9418c2ecf20Sopenharmony_ci set_bit_le(bit, kaddr); 9428c2ecf20Sopenharmony_ci kunmap_atomic(kaddr); 9438c2ecf20Sopenharmony_ci pr_debug("set file bit %lu page %lu\n", bit, page->index); 9448c2ecf20Sopenharmony_ci /* record page number so it gets flushed to disk when unplug occurs */ 9458c2ecf20Sopenharmony_ci set_page_attr(bitmap, page->index - node_offset, BITMAP_PAGE_DIRTY); 9468c2ecf20Sopenharmony_ci} 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_cistatic void md_bitmap_file_clear_bit(struct bitmap *bitmap, sector_t block) 9498c2ecf20Sopenharmony_ci{ 9508c2ecf20Sopenharmony_ci unsigned long bit; 9518c2ecf20Sopenharmony_ci struct page *page; 9528c2ecf20Sopenharmony_ci void *paddr; 9538c2ecf20Sopenharmony_ci unsigned long chunk = block >> bitmap->counts.chunkshift; 9548c2ecf20Sopenharmony_ci struct bitmap_storage *store = &bitmap->storage; 9558c2ecf20Sopenharmony_ci unsigned long node_offset = 0; 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci if (mddev_is_clustered(bitmap->mddev)) 9588c2ecf20Sopenharmony_ci node_offset = bitmap->cluster_slot * store->file_pages; 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci page = filemap_get_page(&bitmap->storage, chunk); 9618c2ecf20Sopenharmony_ci if (!page) 9628c2ecf20Sopenharmony_ci return; 9638c2ecf20Sopenharmony_ci bit = file_page_offset(&bitmap->storage, chunk); 9648c2ecf20Sopenharmony_ci paddr = kmap_atomic(page); 9658c2ecf20Sopenharmony_ci if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags)) 9668c2ecf20Sopenharmony_ci clear_bit(bit, paddr); 9678c2ecf20Sopenharmony_ci else 9688c2ecf20Sopenharmony_ci clear_bit_le(bit, paddr); 9698c2ecf20Sopenharmony_ci kunmap_atomic(paddr); 9708c2ecf20Sopenharmony_ci if (!test_page_attr(bitmap, page->index - node_offset, BITMAP_PAGE_NEEDWRITE)) { 9718c2ecf20Sopenharmony_ci set_page_attr(bitmap, page->index - node_offset, BITMAP_PAGE_PENDING); 9728c2ecf20Sopenharmony_ci bitmap->allclean = 0; 9738c2ecf20Sopenharmony_ci } 9748c2ecf20Sopenharmony_ci} 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_cistatic int md_bitmap_file_test_bit(struct bitmap *bitmap, sector_t block) 9778c2ecf20Sopenharmony_ci{ 9788c2ecf20Sopenharmony_ci unsigned long bit; 9798c2ecf20Sopenharmony_ci struct page *page; 9808c2ecf20Sopenharmony_ci void *paddr; 9818c2ecf20Sopenharmony_ci unsigned long chunk = block >> bitmap->counts.chunkshift; 9828c2ecf20Sopenharmony_ci int set = 0; 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci page = filemap_get_page(&bitmap->storage, chunk); 9858c2ecf20Sopenharmony_ci if (!page) 9868c2ecf20Sopenharmony_ci return -EINVAL; 9878c2ecf20Sopenharmony_ci bit = file_page_offset(&bitmap->storage, chunk); 9888c2ecf20Sopenharmony_ci paddr = kmap_atomic(page); 9898c2ecf20Sopenharmony_ci if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags)) 9908c2ecf20Sopenharmony_ci set = test_bit(bit, paddr); 9918c2ecf20Sopenharmony_ci else 9928c2ecf20Sopenharmony_ci set = test_bit_le(bit, paddr); 9938c2ecf20Sopenharmony_ci kunmap_atomic(paddr); 9948c2ecf20Sopenharmony_ci return set; 9958c2ecf20Sopenharmony_ci} 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci/* this gets called when the md device is ready to unplug its underlying 9998c2ecf20Sopenharmony_ci * (slave) device queues -- before we let any writes go down, we need to 10008c2ecf20Sopenharmony_ci * sync the dirty pages of the bitmap file to disk */ 10018c2ecf20Sopenharmony_civoid md_bitmap_unplug(struct bitmap *bitmap) 10028c2ecf20Sopenharmony_ci{ 10038c2ecf20Sopenharmony_ci unsigned long i; 10048c2ecf20Sopenharmony_ci int dirty, need_write; 10058c2ecf20Sopenharmony_ci int writing = 0; 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci if (!bitmap || !bitmap->storage.filemap || 10088c2ecf20Sopenharmony_ci test_bit(BITMAP_STALE, &bitmap->flags)) 10098c2ecf20Sopenharmony_ci return; 10108c2ecf20Sopenharmony_ci 10118c2ecf20Sopenharmony_ci /* look at each page to see if there are any set bits that need to be 10128c2ecf20Sopenharmony_ci * flushed out to disk */ 10138c2ecf20Sopenharmony_ci for (i = 0; i < bitmap->storage.file_pages; i++) { 10148c2ecf20Sopenharmony_ci dirty = test_and_clear_page_attr(bitmap, i, BITMAP_PAGE_DIRTY); 10158c2ecf20Sopenharmony_ci need_write = test_and_clear_page_attr(bitmap, i, 10168c2ecf20Sopenharmony_ci BITMAP_PAGE_NEEDWRITE); 10178c2ecf20Sopenharmony_ci if (dirty || need_write) { 10188c2ecf20Sopenharmony_ci if (!writing) { 10198c2ecf20Sopenharmony_ci md_bitmap_wait_writes(bitmap); 10208c2ecf20Sopenharmony_ci if (bitmap->mddev->queue) 10218c2ecf20Sopenharmony_ci blk_add_trace_msg(bitmap->mddev->queue, 10228c2ecf20Sopenharmony_ci "md bitmap_unplug"); 10238c2ecf20Sopenharmony_ci } 10248c2ecf20Sopenharmony_ci clear_page_attr(bitmap, i, BITMAP_PAGE_PENDING); 10258c2ecf20Sopenharmony_ci write_page(bitmap, bitmap->storage.filemap[i], 0); 10268c2ecf20Sopenharmony_ci writing = 1; 10278c2ecf20Sopenharmony_ci } 10288c2ecf20Sopenharmony_ci } 10298c2ecf20Sopenharmony_ci if (writing) 10308c2ecf20Sopenharmony_ci md_bitmap_wait_writes(bitmap); 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ci if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags)) 10338c2ecf20Sopenharmony_ci md_bitmap_file_kick(bitmap); 10348c2ecf20Sopenharmony_ci} 10358c2ecf20Sopenharmony_ciEXPORT_SYMBOL(md_bitmap_unplug); 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_cistatic void md_bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed); 10388c2ecf20Sopenharmony_ci/* * bitmap_init_from_disk -- called at bitmap_create time to initialize 10398c2ecf20Sopenharmony_ci * the in-memory bitmap from the on-disk bitmap -- also, sets up the 10408c2ecf20Sopenharmony_ci * memory mapping of the bitmap file 10418c2ecf20Sopenharmony_ci * Special cases: 10428c2ecf20Sopenharmony_ci * if there's no bitmap file, or if the bitmap file had been 10438c2ecf20Sopenharmony_ci * previously kicked from the array, we mark all the bits as 10448c2ecf20Sopenharmony_ci * 1's in order to cause a full resync. 10458c2ecf20Sopenharmony_ci * 10468c2ecf20Sopenharmony_ci * We ignore all bits for sectors that end earlier than 'start'. 10478c2ecf20Sopenharmony_ci * This is used when reading an out-of-date bitmap... 10488c2ecf20Sopenharmony_ci */ 10498c2ecf20Sopenharmony_cistatic int md_bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) 10508c2ecf20Sopenharmony_ci{ 10518c2ecf20Sopenharmony_ci unsigned long i, chunks, index, oldindex, bit, node_offset = 0; 10528c2ecf20Sopenharmony_ci struct page *page = NULL; 10538c2ecf20Sopenharmony_ci unsigned long bit_cnt = 0; 10548c2ecf20Sopenharmony_ci struct file *file; 10558c2ecf20Sopenharmony_ci unsigned long offset; 10568c2ecf20Sopenharmony_ci int outofdate; 10578c2ecf20Sopenharmony_ci int ret = -ENOSPC; 10588c2ecf20Sopenharmony_ci void *paddr; 10598c2ecf20Sopenharmony_ci struct bitmap_storage *store = &bitmap->storage; 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci chunks = bitmap->counts.chunks; 10628c2ecf20Sopenharmony_ci file = store->file; 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci if (!file && !bitmap->mddev->bitmap_info.offset) { 10658c2ecf20Sopenharmony_ci /* No permanent bitmap - fill with '1s'. */ 10668c2ecf20Sopenharmony_ci store->filemap = NULL; 10678c2ecf20Sopenharmony_ci store->file_pages = 0; 10688c2ecf20Sopenharmony_ci for (i = 0; i < chunks ; i++) { 10698c2ecf20Sopenharmony_ci /* if the disk bit is set, set the memory bit */ 10708c2ecf20Sopenharmony_ci int needed = ((sector_t)(i+1) << (bitmap->counts.chunkshift) 10718c2ecf20Sopenharmony_ci >= start); 10728c2ecf20Sopenharmony_ci md_bitmap_set_memory_bits(bitmap, 10738c2ecf20Sopenharmony_ci (sector_t)i << bitmap->counts.chunkshift, 10748c2ecf20Sopenharmony_ci needed); 10758c2ecf20Sopenharmony_ci } 10768c2ecf20Sopenharmony_ci return 0; 10778c2ecf20Sopenharmony_ci } 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci outofdate = test_bit(BITMAP_STALE, &bitmap->flags); 10808c2ecf20Sopenharmony_ci if (outofdate) 10818c2ecf20Sopenharmony_ci pr_warn("%s: bitmap file is out of date, doing full recovery\n", bmname(bitmap)); 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci if (file && i_size_read(file->f_mapping->host) < store->bytes) { 10848c2ecf20Sopenharmony_ci pr_warn("%s: bitmap file too short %lu < %lu\n", 10858c2ecf20Sopenharmony_ci bmname(bitmap), 10868c2ecf20Sopenharmony_ci (unsigned long) i_size_read(file->f_mapping->host), 10878c2ecf20Sopenharmony_ci store->bytes); 10888c2ecf20Sopenharmony_ci goto err; 10898c2ecf20Sopenharmony_ci } 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci oldindex = ~0L; 10928c2ecf20Sopenharmony_ci offset = 0; 10938c2ecf20Sopenharmony_ci if (!bitmap->mddev->bitmap_info.external) 10948c2ecf20Sopenharmony_ci offset = sizeof(bitmap_super_t); 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci if (mddev_is_clustered(bitmap->mddev)) 10978c2ecf20Sopenharmony_ci node_offset = bitmap->cluster_slot * (DIV_ROUND_UP(store->bytes, PAGE_SIZE)); 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci for (i = 0; i < chunks; i++) { 11008c2ecf20Sopenharmony_ci int b; 11018c2ecf20Sopenharmony_ci index = file_page_index(&bitmap->storage, i); 11028c2ecf20Sopenharmony_ci bit = file_page_offset(&bitmap->storage, i); 11038c2ecf20Sopenharmony_ci if (index != oldindex) { /* this is a new page, read it in */ 11048c2ecf20Sopenharmony_ci int count; 11058c2ecf20Sopenharmony_ci /* unmap the old page, we're done with it */ 11068c2ecf20Sopenharmony_ci if (index == store->file_pages-1) 11078c2ecf20Sopenharmony_ci count = store->bytes - index * PAGE_SIZE; 11088c2ecf20Sopenharmony_ci else 11098c2ecf20Sopenharmony_ci count = PAGE_SIZE; 11108c2ecf20Sopenharmony_ci page = store->filemap[index]; 11118c2ecf20Sopenharmony_ci if (file) 11128c2ecf20Sopenharmony_ci ret = read_page(file, index, bitmap, 11138c2ecf20Sopenharmony_ci count, page); 11148c2ecf20Sopenharmony_ci else 11158c2ecf20Sopenharmony_ci ret = read_sb_page( 11168c2ecf20Sopenharmony_ci bitmap->mddev, 11178c2ecf20Sopenharmony_ci bitmap->mddev->bitmap_info.offset, 11188c2ecf20Sopenharmony_ci page, 11198c2ecf20Sopenharmony_ci index + node_offset, count); 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci if (ret) 11228c2ecf20Sopenharmony_ci goto err; 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci oldindex = index; 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_ci if (outofdate) { 11278c2ecf20Sopenharmony_ci /* 11288c2ecf20Sopenharmony_ci * if bitmap is out of date, dirty the 11298c2ecf20Sopenharmony_ci * whole page and write it out 11308c2ecf20Sopenharmony_ci */ 11318c2ecf20Sopenharmony_ci paddr = kmap_atomic(page); 11328c2ecf20Sopenharmony_ci memset(paddr + offset, 0xff, 11338c2ecf20Sopenharmony_ci PAGE_SIZE - offset); 11348c2ecf20Sopenharmony_ci kunmap_atomic(paddr); 11358c2ecf20Sopenharmony_ci write_page(bitmap, page, 1); 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_ci ret = -EIO; 11388c2ecf20Sopenharmony_ci if (test_bit(BITMAP_WRITE_ERROR, 11398c2ecf20Sopenharmony_ci &bitmap->flags)) 11408c2ecf20Sopenharmony_ci goto err; 11418c2ecf20Sopenharmony_ci } 11428c2ecf20Sopenharmony_ci } 11438c2ecf20Sopenharmony_ci paddr = kmap_atomic(page); 11448c2ecf20Sopenharmony_ci if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags)) 11458c2ecf20Sopenharmony_ci b = test_bit(bit, paddr); 11468c2ecf20Sopenharmony_ci else 11478c2ecf20Sopenharmony_ci b = test_bit_le(bit, paddr); 11488c2ecf20Sopenharmony_ci kunmap_atomic(paddr); 11498c2ecf20Sopenharmony_ci if (b) { 11508c2ecf20Sopenharmony_ci /* if the disk bit is set, set the memory bit */ 11518c2ecf20Sopenharmony_ci int needed = ((sector_t)(i+1) << bitmap->counts.chunkshift 11528c2ecf20Sopenharmony_ci >= start); 11538c2ecf20Sopenharmony_ci md_bitmap_set_memory_bits(bitmap, 11548c2ecf20Sopenharmony_ci (sector_t)i << bitmap->counts.chunkshift, 11558c2ecf20Sopenharmony_ci needed); 11568c2ecf20Sopenharmony_ci bit_cnt++; 11578c2ecf20Sopenharmony_ci } 11588c2ecf20Sopenharmony_ci offset = 0; 11598c2ecf20Sopenharmony_ci } 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci pr_debug("%s: bitmap initialized from disk: read %lu pages, set %lu of %lu bits\n", 11628c2ecf20Sopenharmony_ci bmname(bitmap), store->file_pages, 11638c2ecf20Sopenharmony_ci bit_cnt, chunks); 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ci return 0; 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci err: 11688c2ecf20Sopenharmony_ci pr_warn("%s: bitmap initialisation failed: %d\n", 11698c2ecf20Sopenharmony_ci bmname(bitmap), ret); 11708c2ecf20Sopenharmony_ci return ret; 11718c2ecf20Sopenharmony_ci} 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_civoid md_bitmap_write_all(struct bitmap *bitmap) 11748c2ecf20Sopenharmony_ci{ 11758c2ecf20Sopenharmony_ci /* We don't actually write all bitmap blocks here, 11768c2ecf20Sopenharmony_ci * just flag them as needing to be written 11778c2ecf20Sopenharmony_ci */ 11788c2ecf20Sopenharmony_ci int i; 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_ci if (!bitmap || !bitmap->storage.filemap) 11818c2ecf20Sopenharmony_ci return; 11828c2ecf20Sopenharmony_ci if (bitmap->storage.file) 11838c2ecf20Sopenharmony_ci /* Only one copy, so nothing needed */ 11848c2ecf20Sopenharmony_ci return; 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci for (i = 0; i < bitmap->storage.file_pages; i++) 11878c2ecf20Sopenharmony_ci set_page_attr(bitmap, i, 11888c2ecf20Sopenharmony_ci BITMAP_PAGE_NEEDWRITE); 11898c2ecf20Sopenharmony_ci bitmap->allclean = 0; 11908c2ecf20Sopenharmony_ci} 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_cistatic void md_bitmap_count_page(struct bitmap_counts *bitmap, 11938c2ecf20Sopenharmony_ci sector_t offset, int inc) 11948c2ecf20Sopenharmony_ci{ 11958c2ecf20Sopenharmony_ci sector_t chunk = offset >> bitmap->chunkshift; 11968c2ecf20Sopenharmony_ci unsigned long page = chunk >> PAGE_COUNTER_SHIFT; 11978c2ecf20Sopenharmony_ci bitmap->bp[page].count += inc; 11988c2ecf20Sopenharmony_ci md_bitmap_checkfree(bitmap, page); 11998c2ecf20Sopenharmony_ci} 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_cistatic void md_bitmap_set_pending(struct bitmap_counts *bitmap, sector_t offset) 12028c2ecf20Sopenharmony_ci{ 12038c2ecf20Sopenharmony_ci sector_t chunk = offset >> bitmap->chunkshift; 12048c2ecf20Sopenharmony_ci unsigned long page = chunk >> PAGE_COUNTER_SHIFT; 12058c2ecf20Sopenharmony_ci struct bitmap_page *bp = &bitmap->bp[page]; 12068c2ecf20Sopenharmony_ci 12078c2ecf20Sopenharmony_ci if (!bp->pending) 12088c2ecf20Sopenharmony_ci bp->pending = 1; 12098c2ecf20Sopenharmony_ci} 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_cistatic bitmap_counter_t *md_bitmap_get_counter(struct bitmap_counts *bitmap, 12128c2ecf20Sopenharmony_ci sector_t offset, sector_t *blocks, 12138c2ecf20Sopenharmony_ci int create); 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_ci/* 12168c2ecf20Sopenharmony_ci * bitmap daemon -- periodically wakes up to clean bits and flush pages 12178c2ecf20Sopenharmony_ci * out to disk 12188c2ecf20Sopenharmony_ci */ 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_civoid md_bitmap_daemon_work(struct mddev *mddev) 12218c2ecf20Sopenharmony_ci{ 12228c2ecf20Sopenharmony_ci struct bitmap *bitmap; 12238c2ecf20Sopenharmony_ci unsigned long j; 12248c2ecf20Sopenharmony_ci unsigned long nextpage; 12258c2ecf20Sopenharmony_ci sector_t blocks; 12268c2ecf20Sopenharmony_ci struct bitmap_counts *counts; 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci /* Use a mutex to guard daemon_work against 12298c2ecf20Sopenharmony_ci * bitmap_destroy. 12308c2ecf20Sopenharmony_ci */ 12318c2ecf20Sopenharmony_ci mutex_lock(&mddev->bitmap_info.mutex); 12328c2ecf20Sopenharmony_ci bitmap = mddev->bitmap; 12338c2ecf20Sopenharmony_ci if (bitmap == NULL) { 12348c2ecf20Sopenharmony_ci mutex_unlock(&mddev->bitmap_info.mutex); 12358c2ecf20Sopenharmony_ci return; 12368c2ecf20Sopenharmony_ci } 12378c2ecf20Sopenharmony_ci if (time_before(jiffies, bitmap->daemon_lastrun 12388c2ecf20Sopenharmony_ci + mddev->bitmap_info.daemon_sleep)) 12398c2ecf20Sopenharmony_ci goto done; 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_ci bitmap->daemon_lastrun = jiffies; 12428c2ecf20Sopenharmony_ci if (bitmap->allclean) { 12438c2ecf20Sopenharmony_ci mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; 12448c2ecf20Sopenharmony_ci goto done; 12458c2ecf20Sopenharmony_ci } 12468c2ecf20Sopenharmony_ci bitmap->allclean = 1; 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci if (bitmap->mddev->queue) 12498c2ecf20Sopenharmony_ci blk_add_trace_msg(bitmap->mddev->queue, 12508c2ecf20Sopenharmony_ci "md bitmap_daemon_work"); 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_ci /* Any file-page which is PENDING now needs to be written. 12538c2ecf20Sopenharmony_ci * So set NEEDWRITE now, then after we make any last-minute changes 12548c2ecf20Sopenharmony_ci * we will write it. 12558c2ecf20Sopenharmony_ci */ 12568c2ecf20Sopenharmony_ci for (j = 0; j < bitmap->storage.file_pages; j++) 12578c2ecf20Sopenharmony_ci if (test_and_clear_page_attr(bitmap, j, 12588c2ecf20Sopenharmony_ci BITMAP_PAGE_PENDING)) 12598c2ecf20Sopenharmony_ci set_page_attr(bitmap, j, 12608c2ecf20Sopenharmony_ci BITMAP_PAGE_NEEDWRITE); 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_ci if (bitmap->need_sync && 12638c2ecf20Sopenharmony_ci mddev->bitmap_info.external == 0) { 12648c2ecf20Sopenharmony_ci /* Arrange for superblock update as well as 12658c2ecf20Sopenharmony_ci * other changes */ 12668c2ecf20Sopenharmony_ci bitmap_super_t *sb; 12678c2ecf20Sopenharmony_ci bitmap->need_sync = 0; 12688c2ecf20Sopenharmony_ci if (bitmap->storage.filemap) { 12698c2ecf20Sopenharmony_ci sb = kmap_atomic(bitmap->storage.sb_page); 12708c2ecf20Sopenharmony_ci sb->events_cleared = 12718c2ecf20Sopenharmony_ci cpu_to_le64(bitmap->events_cleared); 12728c2ecf20Sopenharmony_ci kunmap_atomic(sb); 12738c2ecf20Sopenharmony_ci set_page_attr(bitmap, 0, 12748c2ecf20Sopenharmony_ci BITMAP_PAGE_NEEDWRITE); 12758c2ecf20Sopenharmony_ci } 12768c2ecf20Sopenharmony_ci } 12778c2ecf20Sopenharmony_ci /* Now look at the bitmap counters and if any are '2' or '1', 12788c2ecf20Sopenharmony_ci * decrement and handle accordingly. 12798c2ecf20Sopenharmony_ci */ 12808c2ecf20Sopenharmony_ci counts = &bitmap->counts; 12818c2ecf20Sopenharmony_ci spin_lock_irq(&counts->lock); 12828c2ecf20Sopenharmony_ci nextpage = 0; 12838c2ecf20Sopenharmony_ci for (j = 0; j < counts->chunks; j++) { 12848c2ecf20Sopenharmony_ci bitmap_counter_t *bmc; 12858c2ecf20Sopenharmony_ci sector_t block = (sector_t)j << counts->chunkshift; 12868c2ecf20Sopenharmony_ci 12878c2ecf20Sopenharmony_ci if (j == nextpage) { 12888c2ecf20Sopenharmony_ci nextpage += PAGE_COUNTER_RATIO; 12898c2ecf20Sopenharmony_ci if (!counts->bp[j >> PAGE_COUNTER_SHIFT].pending) { 12908c2ecf20Sopenharmony_ci j |= PAGE_COUNTER_MASK; 12918c2ecf20Sopenharmony_ci continue; 12928c2ecf20Sopenharmony_ci } 12938c2ecf20Sopenharmony_ci counts->bp[j >> PAGE_COUNTER_SHIFT].pending = 0; 12948c2ecf20Sopenharmony_ci } 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_ci bmc = md_bitmap_get_counter(counts, block, &blocks, 0); 12978c2ecf20Sopenharmony_ci if (!bmc) { 12988c2ecf20Sopenharmony_ci j |= PAGE_COUNTER_MASK; 12998c2ecf20Sopenharmony_ci continue; 13008c2ecf20Sopenharmony_ci } 13018c2ecf20Sopenharmony_ci if (*bmc == 1 && !bitmap->need_sync) { 13028c2ecf20Sopenharmony_ci /* We can clear the bit */ 13038c2ecf20Sopenharmony_ci *bmc = 0; 13048c2ecf20Sopenharmony_ci md_bitmap_count_page(counts, block, -1); 13058c2ecf20Sopenharmony_ci md_bitmap_file_clear_bit(bitmap, block); 13068c2ecf20Sopenharmony_ci } else if (*bmc && *bmc <= 2) { 13078c2ecf20Sopenharmony_ci *bmc = 1; 13088c2ecf20Sopenharmony_ci md_bitmap_set_pending(counts, block); 13098c2ecf20Sopenharmony_ci bitmap->allclean = 0; 13108c2ecf20Sopenharmony_ci } 13118c2ecf20Sopenharmony_ci } 13128c2ecf20Sopenharmony_ci spin_unlock_irq(&counts->lock); 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci md_bitmap_wait_writes(bitmap); 13158c2ecf20Sopenharmony_ci /* Now start writeout on any page in NEEDWRITE that isn't DIRTY. 13168c2ecf20Sopenharmony_ci * DIRTY pages need to be written by bitmap_unplug so it can wait 13178c2ecf20Sopenharmony_ci * for them. 13188c2ecf20Sopenharmony_ci * If we find any DIRTY page we stop there and let bitmap_unplug 13198c2ecf20Sopenharmony_ci * handle all the rest. This is important in the case where 13208c2ecf20Sopenharmony_ci * the first blocking holds the superblock and it has been updated. 13218c2ecf20Sopenharmony_ci * We mustn't write any other blocks before the superblock. 13228c2ecf20Sopenharmony_ci */ 13238c2ecf20Sopenharmony_ci for (j = 0; 13248c2ecf20Sopenharmony_ci j < bitmap->storage.file_pages 13258c2ecf20Sopenharmony_ci && !test_bit(BITMAP_STALE, &bitmap->flags); 13268c2ecf20Sopenharmony_ci j++) { 13278c2ecf20Sopenharmony_ci if (test_page_attr(bitmap, j, 13288c2ecf20Sopenharmony_ci BITMAP_PAGE_DIRTY)) 13298c2ecf20Sopenharmony_ci /* bitmap_unplug will handle the rest */ 13308c2ecf20Sopenharmony_ci break; 13318c2ecf20Sopenharmony_ci if (bitmap->storage.filemap && 13328c2ecf20Sopenharmony_ci test_and_clear_page_attr(bitmap, j, 13338c2ecf20Sopenharmony_ci BITMAP_PAGE_NEEDWRITE)) { 13348c2ecf20Sopenharmony_ci write_page(bitmap, bitmap->storage.filemap[j], 0); 13358c2ecf20Sopenharmony_ci } 13368c2ecf20Sopenharmony_ci } 13378c2ecf20Sopenharmony_ci 13388c2ecf20Sopenharmony_ci done: 13398c2ecf20Sopenharmony_ci if (bitmap->allclean == 0) 13408c2ecf20Sopenharmony_ci mddev->thread->timeout = 13418c2ecf20Sopenharmony_ci mddev->bitmap_info.daemon_sleep; 13428c2ecf20Sopenharmony_ci mutex_unlock(&mddev->bitmap_info.mutex); 13438c2ecf20Sopenharmony_ci} 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_cistatic bitmap_counter_t *md_bitmap_get_counter(struct bitmap_counts *bitmap, 13468c2ecf20Sopenharmony_ci sector_t offset, sector_t *blocks, 13478c2ecf20Sopenharmony_ci int create) 13488c2ecf20Sopenharmony_ci__releases(bitmap->lock) 13498c2ecf20Sopenharmony_ci__acquires(bitmap->lock) 13508c2ecf20Sopenharmony_ci{ 13518c2ecf20Sopenharmony_ci /* If 'create', we might release the lock and reclaim it. 13528c2ecf20Sopenharmony_ci * The lock must have been taken with interrupts enabled. 13538c2ecf20Sopenharmony_ci * If !create, we don't release the lock. 13548c2ecf20Sopenharmony_ci */ 13558c2ecf20Sopenharmony_ci sector_t chunk = offset >> bitmap->chunkshift; 13568c2ecf20Sopenharmony_ci unsigned long page = chunk >> PAGE_COUNTER_SHIFT; 13578c2ecf20Sopenharmony_ci unsigned long pageoff = (chunk & PAGE_COUNTER_MASK) << COUNTER_BYTE_SHIFT; 13588c2ecf20Sopenharmony_ci sector_t csize; 13598c2ecf20Sopenharmony_ci int err; 13608c2ecf20Sopenharmony_ci 13618c2ecf20Sopenharmony_ci if (page >= bitmap->pages) { 13628c2ecf20Sopenharmony_ci /* 13638c2ecf20Sopenharmony_ci * This can happen if bitmap_start_sync goes beyond 13648c2ecf20Sopenharmony_ci * End-of-device while looking for a whole page or 13658c2ecf20Sopenharmony_ci * user set a huge number to sysfs bitmap_set_bits. 13668c2ecf20Sopenharmony_ci */ 13678c2ecf20Sopenharmony_ci return NULL; 13688c2ecf20Sopenharmony_ci } 13698c2ecf20Sopenharmony_ci err = md_bitmap_checkpage(bitmap, page, create, 0); 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci if (bitmap->bp[page].hijacked || 13728c2ecf20Sopenharmony_ci bitmap->bp[page].map == NULL) 13738c2ecf20Sopenharmony_ci csize = ((sector_t)1) << (bitmap->chunkshift + 13748c2ecf20Sopenharmony_ci PAGE_COUNTER_SHIFT); 13758c2ecf20Sopenharmony_ci else 13768c2ecf20Sopenharmony_ci csize = ((sector_t)1) << bitmap->chunkshift; 13778c2ecf20Sopenharmony_ci *blocks = csize - (offset & (csize - 1)); 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_ci if (err < 0) 13808c2ecf20Sopenharmony_ci return NULL; 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_ci /* now locked ... */ 13838c2ecf20Sopenharmony_ci 13848c2ecf20Sopenharmony_ci if (bitmap->bp[page].hijacked) { /* hijacked pointer */ 13858c2ecf20Sopenharmony_ci /* should we use the first or second counter field 13868c2ecf20Sopenharmony_ci * of the hijacked pointer? */ 13878c2ecf20Sopenharmony_ci int hi = (pageoff > PAGE_COUNTER_MASK); 13888c2ecf20Sopenharmony_ci return &((bitmap_counter_t *) 13898c2ecf20Sopenharmony_ci &bitmap->bp[page].map)[hi]; 13908c2ecf20Sopenharmony_ci } else /* page is allocated */ 13918c2ecf20Sopenharmony_ci return (bitmap_counter_t *) 13928c2ecf20Sopenharmony_ci &(bitmap->bp[page].map[pageoff]); 13938c2ecf20Sopenharmony_ci} 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ciint md_bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors, int behind) 13968c2ecf20Sopenharmony_ci{ 13978c2ecf20Sopenharmony_ci if (!bitmap) 13988c2ecf20Sopenharmony_ci return 0; 13998c2ecf20Sopenharmony_ci 14008c2ecf20Sopenharmony_ci if (behind) { 14018c2ecf20Sopenharmony_ci int bw; 14028c2ecf20Sopenharmony_ci atomic_inc(&bitmap->behind_writes); 14038c2ecf20Sopenharmony_ci bw = atomic_read(&bitmap->behind_writes); 14048c2ecf20Sopenharmony_ci if (bw > bitmap->behind_writes_used) 14058c2ecf20Sopenharmony_ci bitmap->behind_writes_used = bw; 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ci pr_debug("inc write-behind count %d/%lu\n", 14088c2ecf20Sopenharmony_ci bw, bitmap->mddev->bitmap_info.max_write_behind); 14098c2ecf20Sopenharmony_ci } 14108c2ecf20Sopenharmony_ci 14118c2ecf20Sopenharmony_ci while (sectors) { 14128c2ecf20Sopenharmony_ci sector_t blocks; 14138c2ecf20Sopenharmony_ci bitmap_counter_t *bmc; 14148c2ecf20Sopenharmony_ci 14158c2ecf20Sopenharmony_ci spin_lock_irq(&bitmap->counts.lock); 14168c2ecf20Sopenharmony_ci bmc = md_bitmap_get_counter(&bitmap->counts, offset, &blocks, 1); 14178c2ecf20Sopenharmony_ci if (!bmc) { 14188c2ecf20Sopenharmony_ci spin_unlock_irq(&bitmap->counts.lock); 14198c2ecf20Sopenharmony_ci return 0; 14208c2ecf20Sopenharmony_ci } 14218c2ecf20Sopenharmony_ci 14228c2ecf20Sopenharmony_ci if (unlikely(COUNTER(*bmc) == COUNTER_MAX)) { 14238c2ecf20Sopenharmony_ci DEFINE_WAIT(__wait); 14248c2ecf20Sopenharmony_ci /* note that it is safe to do the prepare_to_wait 14258c2ecf20Sopenharmony_ci * after the test as long as we do it before dropping 14268c2ecf20Sopenharmony_ci * the spinlock. 14278c2ecf20Sopenharmony_ci */ 14288c2ecf20Sopenharmony_ci prepare_to_wait(&bitmap->overflow_wait, &__wait, 14298c2ecf20Sopenharmony_ci TASK_UNINTERRUPTIBLE); 14308c2ecf20Sopenharmony_ci spin_unlock_irq(&bitmap->counts.lock); 14318c2ecf20Sopenharmony_ci schedule(); 14328c2ecf20Sopenharmony_ci finish_wait(&bitmap->overflow_wait, &__wait); 14338c2ecf20Sopenharmony_ci continue; 14348c2ecf20Sopenharmony_ci } 14358c2ecf20Sopenharmony_ci 14368c2ecf20Sopenharmony_ci switch (*bmc) { 14378c2ecf20Sopenharmony_ci case 0: 14388c2ecf20Sopenharmony_ci md_bitmap_file_set_bit(bitmap, offset); 14398c2ecf20Sopenharmony_ci md_bitmap_count_page(&bitmap->counts, offset, 1); 14408c2ecf20Sopenharmony_ci fallthrough; 14418c2ecf20Sopenharmony_ci case 1: 14428c2ecf20Sopenharmony_ci *bmc = 2; 14438c2ecf20Sopenharmony_ci } 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_ci (*bmc)++; 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci spin_unlock_irq(&bitmap->counts.lock); 14488c2ecf20Sopenharmony_ci 14498c2ecf20Sopenharmony_ci offset += blocks; 14508c2ecf20Sopenharmony_ci if (sectors > blocks) 14518c2ecf20Sopenharmony_ci sectors -= blocks; 14528c2ecf20Sopenharmony_ci else 14538c2ecf20Sopenharmony_ci sectors = 0; 14548c2ecf20Sopenharmony_ci } 14558c2ecf20Sopenharmony_ci return 0; 14568c2ecf20Sopenharmony_ci} 14578c2ecf20Sopenharmony_ciEXPORT_SYMBOL(md_bitmap_startwrite); 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_civoid md_bitmap_endwrite(struct bitmap *bitmap, sector_t offset, 14608c2ecf20Sopenharmony_ci unsigned long sectors, int success, int behind) 14618c2ecf20Sopenharmony_ci{ 14628c2ecf20Sopenharmony_ci if (!bitmap) 14638c2ecf20Sopenharmony_ci return; 14648c2ecf20Sopenharmony_ci if (behind) { 14658c2ecf20Sopenharmony_ci if (atomic_dec_and_test(&bitmap->behind_writes)) 14668c2ecf20Sopenharmony_ci wake_up(&bitmap->behind_wait); 14678c2ecf20Sopenharmony_ci pr_debug("dec write-behind count %d/%lu\n", 14688c2ecf20Sopenharmony_ci atomic_read(&bitmap->behind_writes), 14698c2ecf20Sopenharmony_ci bitmap->mddev->bitmap_info.max_write_behind); 14708c2ecf20Sopenharmony_ci } 14718c2ecf20Sopenharmony_ci 14728c2ecf20Sopenharmony_ci while (sectors) { 14738c2ecf20Sopenharmony_ci sector_t blocks; 14748c2ecf20Sopenharmony_ci unsigned long flags; 14758c2ecf20Sopenharmony_ci bitmap_counter_t *bmc; 14768c2ecf20Sopenharmony_ci 14778c2ecf20Sopenharmony_ci spin_lock_irqsave(&bitmap->counts.lock, flags); 14788c2ecf20Sopenharmony_ci bmc = md_bitmap_get_counter(&bitmap->counts, offset, &blocks, 0); 14798c2ecf20Sopenharmony_ci if (!bmc) { 14808c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&bitmap->counts.lock, flags); 14818c2ecf20Sopenharmony_ci return; 14828c2ecf20Sopenharmony_ci } 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci if (success && !bitmap->mddev->degraded && 14858c2ecf20Sopenharmony_ci bitmap->events_cleared < bitmap->mddev->events) { 14868c2ecf20Sopenharmony_ci bitmap->events_cleared = bitmap->mddev->events; 14878c2ecf20Sopenharmony_ci bitmap->need_sync = 1; 14888c2ecf20Sopenharmony_ci sysfs_notify_dirent_safe(bitmap->sysfs_can_clear); 14898c2ecf20Sopenharmony_ci } 14908c2ecf20Sopenharmony_ci 14918c2ecf20Sopenharmony_ci if (!success && !NEEDED(*bmc)) 14928c2ecf20Sopenharmony_ci *bmc |= NEEDED_MASK; 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_ci if (COUNTER(*bmc) == COUNTER_MAX) 14958c2ecf20Sopenharmony_ci wake_up(&bitmap->overflow_wait); 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_ci (*bmc)--; 14988c2ecf20Sopenharmony_ci if (*bmc <= 2) { 14998c2ecf20Sopenharmony_ci md_bitmap_set_pending(&bitmap->counts, offset); 15008c2ecf20Sopenharmony_ci bitmap->allclean = 0; 15018c2ecf20Sopenharmony_ci } 15028c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&bitmap->counts.lock, flags); 15038c2ecf20Sopenharmony_ci offset += blocks; 15048c2ecf20Sopenharmony_ci if (sectors > blocks) 15058c2ecf20Sopenharmony_ci sectors -= blocks; 15068c2ecf20Sopenharmony_ci else 15078c2ecf20Sopenharmony_ci sectors = 0; 15088c2ecf20Sopenharmony_ci } 15098c2ecf20Sopenharmony_ci} 15108c2ecf20Sopenharmony_ciEXPORT_SYMBOL(md_bitmap_endwrite); 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_cistatic int __bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, 15138c2ecf20Sopenharmony_ci int degraded) 15148c2ecf20Sopenharmony_ci{ 15158c2ecf20Sopenharmony_ci bitmap_counter_t *bmc; 15168c2ecf20Sopenharmony_ci int rv; 15178c2ecf20Sopenharmony_ci if (bitmap == NULL) {/* FIXME or bitmap set as 'failed' */ 15188c2ecf20Sopenharmony_ci *blocks = 1024; 15198c2ecf20Sopenharmony_ci return 1; /* always resync if no bitmap */ 15208c2ecf20Sopenharmony_ci } 15218c2ecf20Sopenharmony_ci spin_lock_irq(&bitmap->counts.lock); 15228c2ecf20Sopenharmony_ci bmc = md_bitmap_get_counter(&bitmap->counts, offset, blocks, 0); 15238c2ecf20Sopenharmony_ci rv = 0; 15248c2ecf20Sopenharmony_ci if (bmc) { 15258c2ecf20Sopenharmony_ci /* locked */ 15268c2ecf20Sopenharmony_ci if (RESYNC(*bmc)) 15278c2ecf20Sopenharmony_ci rv = 1; 15288c2ecf20Sopenharmony_ci else if (NEEDED(*bmc)) { 15298c2ecf20Sopenharmony_ci rv = 1; 15308c2ecf20Sopenharmony_ci if (!degraded) { /* don't set/clear bits if degraded */ 15318c2ecf20Sopenharmony_ci *bmc |= RESYNC_MASK; 15328c2ecf20Sopenharmony_ci *bmc &= ~NEEDED_MASK; 15338c2ecf20Sopenharmony_ci } 15348c2ecf20Sopenharmony_ci } 15358c2ecf20Sopenharmony_ci } 15368c2ecf20Sopenharmony_ci spin_unlock_irq(&bitmap->counts.lock); 15378c2ecf20Sopenharmony_ci return rv; 15388c2ecf20Sopenharmony_ci} 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_ciint md_bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, 15418c2ecf20Sopenharmony_ci int degraded) 15428c2ecf20Sopenharmony_ci{ 15438c2ecf20Sopenharmony_ci /* bitmap_start_sync must always report on multiples of whole 15448c2ecf20Sopenharmony_ci * pages, otherwise resync (which is very PAGE_SIZE based) will 15458c2ecf20Sopenharmony_ci * get confused. 15468c2ecf20Sopenharmony_ci * So call __bitmap_start_sync repeatedly (if needed) until 15478c2ecf20Sopenharmony_ci * At least PAGE_SIZE>>9 blocks are covered. 15488c2ecf20Sopenharmony_ci * Return the 'or' of the result. 15498c2ecf20Sopenharmony_ci */ 15508c2ecf20Sopenharmony_ci int rv = 0; 15518c2ecf20Sopenharmony_ci sector_t blocks1; 15528c2ecf20Sopenharmony_ci 15538c2ecf20Sopenharmony_ci *blocks = 0; 15548c2ecf20Sopenharmony_ci while (*blocks < (PAGE_SIZE>>9)) { 15558c2ecf20Sopenharmony_ci rv |= __bitmap_start_sync(bitmap, offset, 15568c2ecf20Sopenharmony_ci &blocks1, degraded); 15578c2ecf20Sopenharmony_ci offset += blocks1; 15588c2ecf20Sopenharmony_ci *blocks += blocks1; 15598c2ecf20Sopenharmony_ci } 15608c2ecf20Sopenharmony_ci return rv; 15618c2ecf20Sopenharmony_ci} 15628c2ecf20Sopenharmony_ciEXPORT_SYMBOL(md_bitmap_start_sync); 15638c2ecf20Sopenharmony_ci 15648c2ecf20Sopenharmony_civoid md_bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, int aborted) 15658c2ecf20Sopenharmony_ci{ 15668c2ecf20Sopenharmony_ci bitmap_counter_t *bmc; 15678c2ecf20Sopenharmony_ci unsigned long flags; 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_ci if (bitmap == NULL) { 15708c2ecf20Sopenharmony_ci *blocks = 1024; 15718c2ecf20Sopenharmony_ci return; 15728c2ecf20Sopenharmony_ci } 15738c2ecf20Sopenharmony_ci spin_lock_irqsave(&bitmap->counts.lock, flags); 15748c2ecf20Sopenharmony_ci bmc = md_bitmap_get_counter(&bitmap->counts, offset, blocks, 0); 15758c2ecf20Sopenharmony_ci if (bmc == NULL) 15768c2ecf20Sopenharmony_ci goto unlock; 15778c2ecf20Sopenharmony_ci /* locked */ 15788c2ecf20Sopenharmony_ci if (RESYNC(*bmc)) { 15798c2ecf20Sopenharmony_ci *bmc &= ~RESYNC_MASK; 15808c2ecf20Sopenharmony_ci 15818c2ecf20Sopenharmony_ci if (!NEEDED(*bmc) && aborted) 15828c2ecf20Sopenharmony_ci *bmc |= NEEDED_MASK; 15838c2ecf20Sopenharmony_ci else { 15848c2ecf20Sopenharmony_ci if (*bmc <= 2) { 15858c2ecf20Sopenharmony_ci md_bitmap_set_pending(&bitmap->counts, offset); 15868c2ecf20Sopenharmony_ci bitmap->allclean = 0; 15878c2ecf20Sopenharmony_ci } 15888c2ecf20Sopenharmony_ci } 15898c2ecf20Sopenharmony_ci } 15908c2ecf20Sopenharmony_ci unlock: 15918c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&bitmap->counts.lock, flags); 15928c2ecf20Sopenharmony_ci} 15938c2ecf20Sopenharmony_ciEXPORT_SYMBOL(md_bitmap_end_sync); 15948c2ecf20Sopenharmony_ci 15958c2ecf20Sopenharmony_civoid md_bitmap_close_sync(struct bitmap *bitmap) 15968c2ecf20Sopenharmony_ci{ 15978c2ecf20Sopenharmony_ci /* Sync has finished, and any bitmap chunks that weren't synced 15988c2ecf20Sopenharmony_ci * properly have been aborted. It remains to us to clear the 15998c2ecf20Sopenharmony_ci * RESYNC bit wherever it is still on 16008c2ecf20Sopenharmony_ci */ 16018c2ecf20Sopenharmony_ci sector_t sector = 0; 16028c2ecf20Sopenharmony_ci sector_t blocks; 16038c2ecf20Sopenharmony_ci if (!bitmap) 16048c2ecf20Sopenharmony_ci return; 16058c2ecf20Sopenharmony_ci while (sector < bitmap->mddev->resync_max_sectors) { 16068c2ecf20Sopenharmony_ci md_bitmap_end_sync(bitmap, sector, &blocks, 0); 16078c2ecf20Sopenharmony_ci sector += blocks; 16088c2ecf20Sopenharmony_ci } 16098c2ecf20Sopenharmony_ci} 16108c2ecf20Sopenharmony_ciEXPORT_SYMBOL(md_bitmap_close_sync); 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_civoid md_bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector, bool force) 16138c2ecf20Sopenharmony_ci{ 16148c2ecf20Sopenharmony_ci sector_t s = 0; 16158c2ecf20Sopenharmony_ci sector_t blocks; 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_ci if (!bitmap) 16188c2ecf20Sopenharmony_ci return; 16198c2ecf20Sopenharmony_ci if (sector == 0) { 16208c2ecf20Sopenharmony_ci bitmap->last_end_sync = jiffies; 16218c2ecf20Sopenharmony_ci return; 16228c2ecf20Sopenharmony_ci } 16238c2ecf20Sopenharmony_ci if (!force && time_before(jiffies, (bitmap->last_end_sync 16248c2ecf20Sopenharmony_ci + bitmap->mddev->bitmap_info.daemon_sleep))) 16258c2ecf20Sopenharmony_ci return; 16268c2ecf20Sopenharmony_ci wait_event(bitmap->mddev->recovery_wait, 16278c2ecf20Sopenharmony_ci atomic_read(&bitmap->mddev->recovery_active) == 0); 16288c2ecf20Sopenharmony_ci 16298c2ecf20Sopenharmony_ci bitmap->mddev->curr_resync_completed = sector; 16308c2ecf20Sopenharmony_ci set_bit(MD_SB_CHANGE_CLEAN, &bitmap->mddev->sb_flags); 16318c2ecf20Sopenharmony_ci sector &= ~((1ULL << bitmap->counts.chunkshift) - 1); 16328c2ecf20Sopenharmony_ci s = 0; 16338c2ecf20Sopenharmony_ci while (s < sector && s < bitmap->mddev->resync_max_sectors) { 16348c2ecf20Sopenharmony_ci md_bitmap_end_sync(bitmap, s, &blocks, 0); 16358c2ecf20Sopenharmony_ci s += blocks; 16368c2ecf20Sopenharmony_ci } 16378c2ecf20Sopenharmony_ci bitmap->last_end_sync = jiffies; 16388c2ecf20Sopenharmony_ci sysfs_notify_dirent_safe(bitmap->mddev->sysfs_completed); 16398c2ecf20Sopenharmony_ci} 16408c2ecf20Sopenharmony_ciEXPORT_SYMBOL(md_bitmap_cond_end_sync); 16418c2ecf20Sopenharmony_ci 16428c2ecf20Sopenharmony_civoid md_bitmap_sync_with_cluster(struct mddev *mddev, 16438c2ecf20Sopenharmony_ci sector_t old_lo, sector_t old_hi, 16448c2ecf20Sopenharmony_ci sector_t new_lo, sector_t new_hi) 16458c2ecf20Sopenharmony_ci{ 16468c2ecf20Sopenharmony_ci struct bitmap *bitmap = mddev->bitmap; 16478c2ecf20Sopenharmony_ci sector_t sector, blocks = 0; 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_ci for (sector = old_lo; sector < new_lo; ) { 16508c2ecf20Sopenharmony_ci md_bitmap_end_sync(bitmap, sector, &blocks, 0); 16518c2ecf20Sopenharmony_ci sector += blocks; 16528c2ecf20Sopenharmony_ci } 16538c2ecf20Sopenharmony_ci WARN((blocks > new_lo) && old_lo, "alignment is not correct for lo\n"); 16548c2ecf20Sopenharmony_ci 16558c2ecf20Sopenharmony_ci for (sector = old_hi; sector < new_hi; ) { 16568c2ecf20Sopenharmony_ci md_bitmap_start_sync(bitmap, sector, &blocks, 0); 16578c2ecf20Sopenharmony_ci sector += blocks; 16588c2ecf20Sopenharmony_ci } 16598c2ecf20Sopenharmony_ci WARN((blocks > new_hi) && old_hi, "alignment is not correct for hi\n"); 16608c2ecf20Sopenharmony_ci} 16618c2ecf20Sopenharmony_ciEXPORT_SYMBOL(md_bitmap_sync_with_cluster); 16628c2ecf20Sopenharmony_ci 16638c2ecf20Sopenharmony_cistatic void md_bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed) 16648c2ecf20Sopenharmony_ci{ 16658c2ecf20Sopenharmony_ci /* For each chunk covered by any of these sectors, set the 16668c2ecf20Sopenharmony_ci * counter to 2 and possibly set resync_needed. They should all 16678c2ecf20Sopenharmony_ci * be 0 at this point 16688c2ecf20Sopenharmony_ci */ 16698c2ecf20Sopenharmony_ci 16708c2ecf20Sopenharmony_ci sector_t secs; 16718c2ecf20Sopenharmony_ci bitmap_counter_t *bmc; 16728c2ecf20Sopenharmony_ci spin_lock_irq(&bitmap->counts.lock); 16738c2ecf20Sopenharmony_ci bmc = md_bitmap_get_counter(&bitmap->counts, offset, &secs, 1); 16748c2ecf20Sopenharmony_ci if (!bmc) { 16758c2ecf20Sopenharmony_ci spin_unlock_irq(&bitmap->counts.lock); 16768c2ecf20Sopenharmony_ci return; 16778c2ecf20Sopenharmony_ci } 16788c2ecf20Sopenharmony_ci if (!*bmc) { 16798c2ecf20Sopenharmony_ci *bmc = 2; 16808c2ecf20Sopenharmony_ci md_bitmap_count_page(&bitmap->counts, offset, 1); 16818c2ecf20Sopenharmony_ci md_bitmap_set_pending(&bitmap->counts, offset); 16828c2ecf20Sopenharmony_ci bitmap->allclean = 0; 16838c2ecf20Sopenharmony_ci } 16848c2ecf20Sopenharmony_ci if (needed) 16858c2ecf20Sopenharmony_ci *bmc |= NEEDED_MASK; 16868c2ecf20Sopenharmony_ci spin_unlock_irq(&bitmap->counts.lock); 16878c2ecf20Sopenharmony_ci} 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_ci/* dirty the memory and file bits for bitmap chunks "s" to "e" */ 16908c2ecf20Sopenharmony_civoid md_bitmap_dirty_bits(struct bitmap *bitmap, unsigned long s, unsigned long e) 16918c2ecf20Sopenharmony_ci{ 16928c2ecf20Sopenharmony_ci unsigned long chunk; 16938c2ecf20Sopenharmony_ci 16948c2ecf20Sopenharmony_ci for (chunk = s; chunk <= e; chunk++) { 16958c2ecf20Sopenharmony_ci sector_t sec = (sector_t)chunk << bitmap->counts.chunkshift; 16968c2ecf20Sopenharmony_ci md_bitmap_set_memory_bits(bitmap, sec, 1); 16978c2ecf20Sopenharmony_ci md_bitmap_file_set_bit(bitmap, sec); 16988c2ecf20Sopenharmony_ci if (sec < bitmap->mddev->recovery_cp) 16998c2ecf20Sopenharmony_ci /* We are asserting that the array is dirty, 17008c2ecf20Sopenharmony_ci * so move the recovery_cp address back so 17018c2ecf20Sopenharmony_ci * that it is obvious that it is dirty 17028c2ecf20Sopenharmony_ci */ 17038c2ecf20Sopenharmony_ci bitmap->mddev->recovery_cp = sec; 17048c2ecf20Sopenharmony_ci } 17058c2ecf20Sopenharmony_ci} 17068c2ecf20Sopenharmony_ci 17078c2ecf20Sopenharmony_ci/* 17088c2ecf20Sopenharmony_ci * flush out any pending updates 17098c2ecf20Sopenharmony_ci */ 17108c2ecf20Sopenharmony_civoid md_bitmap_flush(struct mddev *mddev) 17118c2ecf20Sopenharmony_ci{ 17128c2ecf20Sopenharmony_ci struct bitmap *bitmap = mddev->bitmap; 17138c2ecf20Sopenharmony_ci long sleep; 17148c2ecf20Sopenharmony_ci 17158c2ecf20Sopenharmony_ci if (!bitmap) /* there was no bitmap */ 17168c2ecf20Sopenharmony_ci return; 17178c2ecf20Sopenharmony_ci 17188c2ecf20Sopenharmony_ci /* run the daemon_work three time to ensure everything is flushed 17198c2ecf20Sopenharmony_ci * that can be 17208c2ecf20Sopenharmony_ci */ 17218c2ecf20Sopenharmony_ci sleep = mddev->bitmap_info.daemon_sleep * 2; 17228c2ecf20Sopenharmony_ci bitmap->daemon_lastrun -= sleep; 17238c2ecf20Sopenharmony_ci md_bitmap_daemon_work(mddev); 17248c2ecf20Sopenharmony_ci bitmap->daemon_lastrun -= sleep; 17258c2ecf20Sopenharmony_ci md_bitmap_daemon_work(mddev); 17268c2ecf20Sopenharmony_ci bitmap->daemon_lastrun -= sleep; 17278c2ecf20Sopenharmony_ci md_bitmap_daemon_work(mddev); 17288c2ecf20Sopenharmony_ci if (mddev->bitmap_info.external) 17298c2ecf20Sopenharmony_ci md_super_wait(mddev); 17308c2ecf20Sopenharmony_ci md_bitmap_update_sb(bitmap); 17318c2ecf20Sopenharmony_ci} 17328c2ecf20Sopenharmony_ci 17338c2ecf20Sopenharmony_ci/* 17348c2ecf20Sopenharmony_ci * free memory that was allocated 17358c2ecf20Sopenharmony_ci */ 17368c2ecf20Sopenharmony_civoid md_bitmap_free(struct bitmap *bitmap) 17378c2ecf20Sopenharmony_ci{ 17388c2ecf20Sopenharmony_ci unsigned long k, pages; 17398c2ecf20Sopenharmony_ci struct bitmap_page *bp; 17408c2ecf20Sopenharmony_ci 17418c2ecf20Sopenharmony_ci if (!bitmap) /* there was no bitmap */ 17428c2ecf20Sopenharmony_ci return; 17438c2ecf20Sopenharmony_ci 17448c2ecf20Sopenharmony_ci if (bitmap->sysfs_can_clear) 17458c2ecf20Sopenharmony_ci sysfs_put(bitmap->sysfs_can_clear); 17468c2ecf20Sopenharmony_ci 17478c2ecf20Sopenharmony_ci if (mddev_is_clustered(bitmap->mddev) && bitmap->mddev->cluster_info && 17488c2ecf20Sopenharmony_ci bitmap->cluster_slot == md_cluster_ops->slot_number(bitmap->mddev)) 17498c2ecf20Sopenharmony_ci md_cluster_stop(bitmap->mddev); 17508c2ecf20Sopenharmony_ci 17518c2ecf20Sopenharmony_ci /* Shouldn't be needed - but just in case.... */ 17528c2ecf20Sopenharmony_ci wait_event(bitmap->write_wait, 17538c2ecf20Sopenharmony_ci atomic_read(&bitmap->pending_writes) == 0); 17548c2ecf20Sopenharmony_ci 17558c2ecf20Sopenharmony_ci /* release the bitmap file */ 17568c2ecf20Sopenharmony_ci md_bitmap_file_unmap(&bitmap->storage); 17578c2ecf20Sopenharmony_ci 17588c2ecf20Sopenharmony_ci bp = bitmap->counts.bp; 17598c2ecf20Sopenharmony_ci pages = bitmap->counts.pages; 17608c2ecf20Sopenharmony_ci 17618c2ecf20Sopenharmony_ci /* free all allocated memory */ 17628c2ecf20Sopenharmony_ci 17638c2ecf20Sopenharmony_ci if (bp) /* deallocate the page memory */ 17648c2ecf20Sopenharmony_ci for (k = 0; k < pages; k++) 17658c2ecf20Sopenharmony_ci if (bp[k].map && !bp[k].hijacked) 17668c2ecf20Sopenharmony_ci kfree(bp[k].map); 17678c2ecf20Sopenharmony_ci kfree(bp); 17688c2ecf20Sopenharmony_ci kfree(bitmap); 17698c2ecf20Sopenharmony_ci} 17708c2ecf20Sopenharmony_ciEXPORT_SYMBOL(md_bitmap_free); 17718c2ecf20Sopenharmony_ci 17728c2ecf20Sopenharmony_civoid md_bitmap_wait_behind_writes(struct mddev *mddev) 17738c2ecf20Sopenharmony_ci{ 17748c2ecf20Sopenharmony_ci struct bitmap *bitmap = mddev->bitmap; 17758c2ecf20Sopenharmony_ci 17768c2ecf20Sopenharmony_ci /* wait for behind writes to complete */ 17778c2ecf20Sopenharmony_ci if (bitmap && atomic_read(&bitmap->behind_writes) > 0) { 17788c2ecf20Sopenharmony_ci pr_debug("md:%s: behind writes in progress - waiting to stop.\n", 17798c2ecf20Sopenharmony_ci mdname(mddev)); 17808c2ecf20Sopenharmony_ci /* need to kick something here to make sure I/O goes? */ 17818c2ecf20Sopenharmony_ci wait_event(bitmap->behind_wait, 17828c2ecf20Sopenharmony_ci atomic_read(&bitmap->behind_writes) == 0); 17838c2ecf20Sopenharmony_ci } 17848c2ecf20Sopenharmony_ci} 17858c2ecf20Sopenharmony_ci 17868c2ecf20Sopenharmony_civoid md_bitmap_destroy(struct mddev *mddev) 17878c2ecf20Sopenharmony_ci{ 17888c2ecf20Sopenharmony_ci struct bitmap *bitmap = mddev->bitmap; 17898c2ecf20Sopenharmony_ci 17908c2ecf20Sopenharmony_ci if (!bitmap) /* there was no bitmap */ 17918c2ecf20Sopenharmony_ci return; 17928c2ecf20Sopenharmony_ci 17938c2ecf20Sopenharmony_ci md_bitmap_wait_behind_writes(mddev); 17948c2ecf20Sopenharmony_ci if (!mddev->serialize_policy) 17958c2ecf20Sopenharmony_ci mddev_destroy_serial_pool(mddev, NULL, true); 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_ci mutex_lock(&mddev->bitmap_info.mutex); 17988c2ecf20Sopenharmony_ci spin_lock(&mddev->lock); 17998c2ecf20Sopenharmony_ci mddev->bitmap = NULL; /* disconnect from the md device */ 18008c2ecf20Sopenharmony_ci spin_unlock(&mddev->lock); 18018c2ecf20Sopenharmony_ci mutex_unlock(&mddev->bitmap_info.mutex); 18028c2ecf20Sopenharmony_ci if (mddev->thread) 18038c2ecf20Sopenharmony_ci mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; 18048c2ecf20Sopenharmony_ci 18058c2ecf20Sopenharmony_ci md_bitmap_free(bitmap); 18068c2ecf20Sopenharmony_ci} 18078c2ecf20Sopenharmony_ci 18088c2ecf20Sopenharmony_ci/* 18098c2ecf20Sopenharmony_ci * initialize the bitmap structure 18108c2ecf20Sopenharmony_ci * if this returns an error, bitmap_destroy must be called to do clean up 18118c2ecf20Sopenharmony_ci * once mddev->bitmap is set 18128c2ecf20Sopenharmony_ci */ 18138c2ecf20Sopenharmony_cistruct bitmap *md_bitmap_create(struct mddev *mddev, int slot) 18148c2ecf20Sopenharmony_ci{ 18158c2ecf20Sopenharmony_ci struct bitmap *bitmap; 18168c2ecf20Sopenharmony_ci sector_t blocks = mddev->resync_max_sectors; 18178c2ecf20Sopenharmony_ci struct file *file = mddev->bitmap_info.file; 18188c2ecf20Sopenharmony_ci int err; 18198c2ecf20Sopenharmony_ci struct kernfs_node *bm = NULL; 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(bitmap_super_t) != 256); 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_ci BUG_ON(file && mddev->bitmap_info.offset); 18248c2ecf20Sopenharmony_ci 18258c2ecf20Sopenharmony_ci if (test_bit(MD_HAS_JOURNAL, &mddev->flags)) { 18268c2ecf20Sopenharmony_ci pr_notice("md/raid:%s: array with journal cannot have bitmap\n", 18278c2ecf20Sopenharmony_ci mdname(mddev)); 18288c2ecf20Sopenharmony_ci return ERR_PTR(-EBUSY); 18298c2ecf20Sopenharmony_ci } 18308c2ecf20Sopenharmony_ci 18318c2ecf20Sopenharmony_ci bitmap = kzalloc(sizeof(*bitmap), GFP_KERNEL); 18328c2ecf20Sopenharmony_ci if (!bitmap) 18338c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 18348c2ecf20Sopenharmony_ci 18358c2ecf20Sopenharmony_ci spin_lock_init(&bitmap->counts.lock); 18368c2ecf20Sopenharmony_ci atomic_set(&bitmap->pending_writes, 0); 18378c2ecf20Sopenharmony_ci init_waitqueue_head(&bitmap->write_wait); 18388c2ecf20Sopenharmony_ci init_waitqueue_head(&bitmap->overflow_wait); 18398c2ecf20Sopenharmony_ci init_waitqueue_head(&bitmap->behind_wait); 18408c2ecf20Sopenharmony_ci 18418c2ecf20Sopenharmony_ci bitmap->mddev = mddev; 18428c2ecf20Sopenharmony_ci bitmap->cluster_slot = slot; 18438c2ecf20Sopenharmony_ci 18448c2ecf20Sopenharmony_ci if (mddev->kobj.sd) 18458c2ecf20Sopenharmony_ci bm = sysfs_get_dirent(mddev->kobj.sd, "bitmap"); 18468c2ecf20Sopenharmony_ci if (bm) { 18478c2ecf20Sopenharmony_ci bitmap->sysfs_can_clear = sysfs_get_dirent(bm, "can_clear"); 18488c2ecf20Sopenharmony_ci sysfs_put(bm); 18498c2ecf20Sopenharmony_ci } else 18508c2ecf20Sopenharmony_ci bitmap->sysfs_can_clear = NULL; 18518c2ecf20Sopenharmony_ci 18528c2ecf20Sopenharmony_ci bitmap->storage.file = file; 18538c2ecf20Sopenharmony_ci if (file) { 18548c2ecf20Sopenharmony_ci get_file(file); 18558c2ecf20Sopenharmony_ci /* As future accesses to this file will use bmap, 18568c2ecf20Sopenharmony_ci * and bypass the page cache, we must sync the file 18578c2ecf20Sopenharmony_ci * first. 18588c2ecf20Sopenharmony_ci */ 18598c2ecf20Sopenharmony_ci vfs_fsync(file, 1); 18608c2ecf20Sopenharmony_ci } 18618c2ecf20Sopenharmony_ci /* read superblock from bitmap file (this sets mddev->bitmap_info.chunksize) */ 18628c2ecf20Sopenharmony_ci if (!mddev->bitmap_info.external) { 18638c2ecf20Sopenharmony_ci /* 18648c2ecf20Sopenharmony_ci * If 'MD_ARRAY_FIRST_USE' is set, then device-mapper is 18658c2ecf20Sopenharmony_ci * instructing us to create a new on-disk bitmap instance. 18668c2ecf20Sopenharmony_ci */ 18678c2ecf20Sopenharmony_ci if (test_and_clear_bit(MD_ARRAY_FIRST_USE, &mddev->flags)) 18688c2ecf20Sopenharmony_ci err = md_bitmap_new_disk_sb(bitmap); 18698c2ecf20Sopenharmony_ci else 18708c2ecf20Sopenharmony_ci err = md_bitmap_read_sb(bitmap); 18718c2ecf20Sopenharmony_ci } else { 18728c2ecf20Sopenharmony_ci err = 0; 18738c2ecf20Sopenharmony_ci if (mddev->bitmap_info.chunksize == 0 || 18748c2ecf20Sopenharmony_ci mddev->bitmap_info.daemon_sleep == 0) 18758c2ecf20Sopenharmony_ci /* chunksize and time_base need to be 18768c2ecf20Sopenharmony_ci * set first. */ 18778c2ecf20Sopenharmony_ci err = -EINVAL; 18788c2ecf20Sopenharmony_ci } 18798c2ecf20Sopenharmony_ci if (err) 18808c2ecf20Sopenharmony_ci goto error; 18818c2ecf20Sopenharmony_ci 18828c2ecf20Sopenharmony_ci bitmap->daemon_lastrun = jiffies; 18838c2ecf20Sopenharmony_ci err = md_bitmap_resize(bitmap, blocks, mddev->bitmap_info.chunksize, 1); 18848c2ecf20Sopenharmony_ci if (err) 18858c2ecf20Sopenharmony_ci goto error; 18868c2ecf20Sopenharmony_ci 18878c2ecf20Sopenharmony_ci pr_debug("created bitmap (%lu pages) for device %s\n", 18888c2ecf20Sopenharmony_ci bitmap->counts.pages, bmname(bitmap)); 18898c2ecf20Sopenharmony_ci 18908c2ecf20Sopenharmony_ci err = test_bit(BITMAP_WRITE_ERROR, &bitmap->flags) ? -EIO : 0; 18918c2ecf20Sopenharmony_ci if (err) 18928c2ecf20Sopenharmony_ci goto error; 18938c2ecf20Sopenharmony_ci 18948c2ecf20Sopenharmony_ci return bitmap; 18958c2ecf20Sopenharmony_ci error: 18968c2ecf20Sopenharmony_ci md_bitmap_free(bitmap); 18978c2ecf20Sopenharmony_ci return ERR_PTR(err); 18988c2ecf20Sopenharmony_ci} 18998c2ecf20Sopenharmony_ci 19008c2ecf20Sopenharmony_ciint md_bitmap_load(struct mddev *mddev) 19018c2ecf20Sopenharmony_ci{ 19028c2ecf20Sopenharmony_ci int err = 0; 19038c2ecf20Sopenharmony_ci sector_t start = 0; 19048c2ecf20Sopenharmony_ci sector_t sector = 0; 19058c2ecf20Sopenharmony_ci struct bitmap *bitmap = mddev->bitmap; 19068c2ecf20Sopenharmony_ci struct md_rdev *rdev; 19078c2ecf20Sopenharmony_ci 19088c2ecf20Sopenharmony_ci if (!bitmap) 19098c2ecf20Sopenharmony_ci goto out; 19108c2ecf20Sopenharmony_ci 19118c2ecf20Sopenharmony_ci rdev_for_each(rdev, mddev) 19128c2ecf20Sopenharmony_ci mddev_create_serial_pool(mddev, rdev, true); 19138c2ecf20Sopenharmony_ci 19148c2ecf20Sopenharmony_ci if (mddev_is_clustered(mddev)) 19158c2ecf20Sopenharmony_ci md_cluster_ops->load_bitmaps(mddev, mddev->bitmap_info.nodes); 19168c2ecf20Sopenharmony_ci 19178c2ecf20Sopenharmony_ci /* Clear out old bitmap info first: Either there is none, or we 19188c2ecf20Sopenharmony_ci * are resuming after someone else has possibly changed things, 19198c2ecf20Sopenharmony_ci * so we should forget old cached info. 19208c2ecf20Sopenharmony_ci * All chunks should be clean, but some might need_sync. 19218c2ecf20Sopenharmony_ci */ 19228c2ecf20Sopenharmony_ci while (sector < mddev->resync_max_sectors) { 19238c2ecf20Sopenharmony_ci sector_t blocks; 19248c2ecf20Sopenharmony_ci md_bitmap_start_sync(bitmap, sector, &blocks, 0); 19258c2ecf20Sopenharmony_ci sector += blocks; 19268c2ecf20Sopenharmony_ci } 19278c2ecf20Sopenharmony_ci md_bitmap_close_sync(bitmap); 19288c2ecf20Sopenharmony_ci 19298c2ecf20Sopenharmony_ci if (mddev->degraded == 0 19308c2ecf20Sopenharmony_ci || bitmap->events_cleared == mddev->events) 19318c2ecf20Sopenharmony_ci /* no need to keep dirty bits to optimise a 19328c2ecf20Sopenharmony_ci * re-add of a missing device */ 19338c2ecf20Sopenharmony_ci start = mddev->recovery_cp; 19348c2ecf20Sopenharmony_ci 19358c2ecf20Sopenharmony_ci mutex_lock(&mddev->bitmap_info.mutex); 19368c2ecf20Sopenharmony_ci err = md_bitmap_init_from_disk(bitmap, start); 19378c2ecf20Sopenharmony_ci mutex_unlock(&mddev->bitmap_info.mutex); 19388c2ecf20Sopenharmony_ci 19398c2ecf20Sopenharmony_ci if (err) 19408c2ecf20Sopenharmony_ci goto out; 19418c2ecf20Sopenharmony_ci clear_bit(BITMAP_STALE, &bitmap->flags); 19428c2ecf20Sopenharmony_ci 19438c2ecf20Sopenharmony_ci /* Kick recovery in case any bits were set */ 19448c2ecf20Sopenharmony_ci set_bit(MD_RECOVERY_NEEDED, &bitmap->mddev->recovery); 19458c2ecf20Sopenharmony_ci 19468c2ecf20Sopenharmony_ci mddev->thread->timeout = mddev->bitmap_info.daemon_sleep; 19478c2ecf20Sopenharmony_ci md_wakeup_thread(mddev->thread); 19488c2ecf20Sopenharmony_ci 19498c2ecf20Sopenharmony_ci md_bitmap_update_sb(bitmap); 19508c2ecf20Sopenharmony_ci 19518c2ecf20Sopenharmony_ci if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags)) 19528c2ecf20Sopenharmony_ci err = -EIO; 19538c2ecf20Sopenharmony_ciout: 19548c2ecf20Sopenharmony_ci return err; 19558c2ecf20Sopenharmony_ci} 19568c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(md_bitmap_load); 19578c2ecf20Sopenharmony_ci 19588c2ecf20Sopenharmony_ci/* caller need to free returned bitmap with md_bitmap_free() */ 19598c2ecf20Sopenharmony_cistruct bitmap *get_bitmap_from_slot(struct mddev *mddev, int slot) 19608c2ecf20Sopenharmony_ci{ 19618c2ecf20Sopenharmony_ci int rv = 0; 19628c2ecf20Sopenharmony_ci struct bitmap *bitmap; 19638c2ecf20Sopenharmony_ci 19648c2ecf20Sopenharmony_ci bitmap = md_bitmap_create(mddev, slot); 19658c2ecf20Sopenharmony_ci if (IS_ERR(bitmap)) { 19668c2ecf20Sopenharmony_ci rv = PTR_ERR(bitmap); 19678c2ecf20Sopenharmony_ci return ERR_PTR(rv); 19688c2ecf20Sopenharmony_ci } 19698c2ecf20Sopenharmony_ci 19708c2ecf20Sopenharmony_ci rv = md_bitmap_init_from_disk(bitmap, 0); 19718c2ecf20Sopenharmony_ci if (rv) { 19728c2ecf20Sopenharmony_ci md_bitmap_free(bitmap); 19738c2ecf20Sopenharmony_ci return ERR_PTR(rv); 19748c2ecf20Sopenharmony_ci } 19758c2ecf20Sopenharmony_ci 19768c2ecf20Sopenharmony_ci return bitmap; 19778c2ecf20Sopenharmony_ci} 19788c2ecf20Sopenharmony_ciEXPORT_SYMBOL(get_bitmap_from_slot); 19798c2ecf20Sopenharmony_ci 19808c2ecf20Sopenharmony_ci/* Loads the bitmap associated with slot and copies the resync information 19818c2ecf20Sopenharmony_ci * to our bitmap 19828c2ecf20Sopenharmony_ci */ 19838c2ecf20Sopenharmony_ciint md_bitmap_copy_from_slot(struct mddev *mddev, int slot, 19848c2ecf20Sopenharmony_ci sector_t *low, sector_t *high, bool clear_bits) 19858c2ecf20Sopenharmony_ci{ 19868c2ecf20Sopenharmony_ci int rv = 0, i, j; 19878c2ecf20Sopenharmony_ci sector_t block, lo = 0, hi = 0; 19888c2ecf20Sopenharmony_ci struct bitmap_counts *counts; 19898c2ecf20Sopenharmony_ci struct bitmap *bitmap; 19908c2ecf20Sopenharmony_ci 19918c2ecf20Sopenharmony_ci bitmap = get_bitmap_from_slot(mddev, slot); 19928c2ecf20Sopenharmony_ci if (IS_ERR(bitmap)) { 19938c2ecf20Sopenharmony_ci pr_err("%s can't get bitmap from slot %d\n", __func__, slot); 19948c2ecf20Sopenharmony_ci return -1; 19958c2ecf20Sopenharmony_ci } 19968c2ecf20Sopenharmony_ci 19978c2ecf20Sopenharmony_ci counts = &bitmap->counts; 19988c2ecf20Sopenharmony_ci for (j = 0; j < counts->chunks; j++) { 19998c2ecf20Sopenharmony_ci block = (sector_t)j << counts->chunkshift; 20008c2ecf20Sopenharmony_ci if (md_bitmap_file_test_bit(bitmap, block)) { 20018c2ecf20Sopenharmony_ci if (!lo) 20028c2ecf20Sopenharmony_ci lo = block; 20038c2ecf20Sopenharmony_ci hi = block; 20048c2ecf20Sopenharmony_ci md_bitmap_file_clear_bit(bitmap, block); 20058c2ecf20Sopenharmony_ci md_bitmap_set_memory_bits(mddev->bitmap, block, 1); 20068c2ecf20Sopenharmony_ci md_bitmap_file_set_bit(mddev->bitmap, block); 20078c2ecf20Sopenharmony_ci } 20088c2ecf20Sopenharmony_ci } 20098c2ecf20Sopenharmony_ci 20108c2ecf20Sopenharmony_ci if (clear_bits) { 20118c2ecf20Sopenharmony_ci md_bitmap_update_sb(bitmap); 20128c2ecf20Sopenharmony_ci /* BITMAP_PAGE_PENDING is set, but bitmap_unplug needs 20138c2ecf20Sopenharmony_ci * BITMAP_PAGE_DIRTY or _NEEDWRITE to write ... */ 20148c2ecf20Sopenharmony_ci for (i = 0; i < bitmap->storage.file_pages; i++) 20158c2ecf20Sopenharmony_ci if (test_page_attr(bitmap, i, BITMAP_PAGE_PENDING)) 20168c2ecf20Sopenharmony_ci set_page_attr(bitmap, i, BITMAP_PAGE_NEEDWRITE); 20178c2ecf20Sopenharmony_ci md_bitmap_unplug(bitmap); 20188c2ecf20Sopenharmony_ci } 20198c2ecf20Sopenharmony_ci md_bitmap_unplug(mddev->bitmap); 20208c2ecf20Sopenharmony_ci *low = lo; 20218c2ecf20Sopenharmony_ci *high = hi; 20228c2ecf20Sopenharmony_ci md_bitmap_free(bitmap); 20238c2ecf20Sopenharmony_ci 20248c2ecf20Sopenharmony_ci return rv; 20258c2ecf20Sopenharmony_ci} 20268c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(md_bitmap_copy_from_slot); 20278c2ecf20Sopenharmony_ci 20288c2ecf20Sopenharmony_ci 20298c2ecf20Sopenharmony_civoid md_bitmap_status(struct seq_file *seq, struct bitmap *bitmap) 20308c2ecf20Sopenharmony_ci{ 20318c2ecf20Sopenharmony_ci unsigned long chunk_kb; 20328c2ecf20Sopenharmony_ci struct bitmap_counts *counts; 20338c2ecf20Sopenharmony_ci 20348c2ecf20Sopenharmony_ci if (!bitmap) 20358c2ecf20Sopenharmony_ci return; 20368c2ecf20Sopenharmony_ci 20378c2ecf20Sopenharmony_ci counts = &bitmap->counts; 20388c2ecf20Sopenharmony_ci 20398c2ecf20Sopenharmony_ci chunk_kb = bitmap->mddev->bitmap_info.chunksize >> 10; 20408c2ecf20Sopenharmony_ci seq_printf(seq, "bitmap: %lu/%lu pages [%luKB], " 20418c2ecf20Sopenharmony_ci "%lu%s chunk", 20428c2ecf20Sopenharmony_ci counts->pages - counts->missing_pages, 20438c2ecf20Sopenharmony_ci counts->pages, 20448c2ecf20Sopenharmony_ci (counts->pages - counts->missing_pages) 20458c2ecf20Sopenharmony_ci << (PAGE_SHIFT - 10), 20468c2ecf20Sopenharmony_ci chunk_kb ? chunk_kb : bitmap->mddev->bitmap_info.chunksize, 20478c2ecf20Sopenharmony_ci chunk_kb ? "KB" : "B"); 20488c2ecf20Sopenharmony_ci if (bitmap->storage.file) { 20498c2ecf20Sopenharmony_ci seq_printf(seq, ", file: "); 20508c2ecf20Sopenharmony_ci seq_file_path(seq, bitmap->storage.file, " \t\n"); 20518c2ecf20Sopenharmony_ci } 20528c2ecf20Sopenharmony_ci 20538c2ecf20Sopenharmony_ci seq_printf(seq, "\n"); 20548c2ecf20Sopenharmony_ci} 20558c2ecf20Sopenharmony_ci 20568c2ecf20Sopenharmony_ciint md_bitmap_resize(struct bitmap *bitmap, sector_t blocks, 20578c2ecf20Sopenharmony_ci int chunksize, int init) 20588c2ecf20Sopenharmony_ci{ 20598c2ecf20Sopenharmony_ci /* If chunk_size is 0, choose an appropriate chunk size. 20608c2ecf20Sopenharmony_ci * Then possibly allocate new storage space. 20618c2ecf20Sopenharmony_ci * Then quiesce, copy bits, replace bitmap, and re-start 20628c2ecf20Sopenharmony_ci * 20638c2ecf20Sopenharmony_ci * This function is called both to set up the initial bitmap 20648c2ecf20Sopenharmony_ci * and to resize the bitmap while the array is active. 20658c2ecf20Sopenharmony_ci * If this happens as a result of the array being resized, 20668c2ecf20Sopenharmony_ci * chunksize will be zero, and we need to choose a suitable 20678c2ecf20Sopenharmony_ci * chunksize, otherwise we use what we are given. 20688c2ecf20Sopenharmony_ci */ 20698c2ecf20Sopenharmony_ci struct bitmap_storage store; 20708c2ecf20Sopenharmony_ci struct bitmap_counts old_counts; 20718c2ecf20Sopenharmony_ci unsigned long chunks; 20728c2ecf20Sopenharmony_ci sector_t block; 20738c2ecf20Sopenharmony_ci sector_t old_blocks, new_blocks; 20748c2ecf20Sopenharmony_ci int chunkshift; 20758c2ecf20Sopenharmony_ci int ret = 0; 20768c2ecf20Sopenharmony_ci long pages; 20778c2ecf20Sopenharmony_ci struct bitmap_page *new_bp; 20788c2ecf20Sopenharmony_ci 20798c2ecf20Sopenharmony_ci if (bitmap->storage.file && !init) { 20808c2ecf20Sopenharmony_ci pr_info("md: cannot resize file-based bitmap\n"); 20818c2ecf20Sopenharmony_ci return -EINVAL; 20828c2ecf20Sopenharmony_ci } 20838c2ecf20Sopenharmony_ci 20848c2ecf20Sopenharmony_ci if (chunksize == 0) { 20858c2ecf20Sopenharmony_ci /* If there is enough space, leave the chunk size unchanged, 20868c2ecf20Sopenharmony_ci * else increase by factor of two until there is enough space. 20878c2ecf20Sopenharmony_ci */ 20888c2ecf20Sopenharmony_ci long bytes; 20898c2ecf20Sopenharmony_ci long space = bitmap->mddev->bitmap_info.space; 20908c2ecf20Sopenharmony_ci 20918c2ecf20Sopenharmony_ci if (space == 0) { 20928c2ecf20Sopenharmony_ci /* We don't know how much space there is, so limit 20938c2ecf20Sopenharmony_ci * to current size - in sectors. 20948c2ecf20Sopenharmony_ci */ 20958c2ecf20Sopenharmony_ci bytes = DIV_ROUND_UP(bitmap->counts.chunks, 8); 20968c2ecf20Sopenharmony_ci if (!bitmap->mddev->bitmap_info.external) 20978c2ecf20Sopenharmony_ci bytes += sizeof(bitmap_super_t); 20988c2ecf20Sopenharmony_ci space = DIV_ROUND_UP(bytes, 512); 20998c2ecf20Sopenharmony_ci bitmap->mddev->bitmap_info.space = space; 21008c2ecf20Sopenharmony_ci } 21018c2ecf20Sopenharmony_ci chunkshift = bitmap->counts.chunkshift; 21028c2ecf20Sopenharmony_ci chunkshift--; 21038c2ecf20Sopenharmony_ci do { 21048c2ecf20Sopenharmony_ci /* 'chunkshift' is shift from block size to chunk size */ 21058c2ecf20Sopenharmony_ci chunkshift++; 21068c2ecf20Sopenharmony_ci chunks = DIV_ROUND_UP_SECTOR_T(blocks, 1 << chunkshift); 21078c2ecf20Sopenharmony_ci bytes = DIV_ROUND_UP(chunks, 8); 21088c2ecf20Sopenharmony_ci if (!bitmap->mddev->bitmap_info.external) 21098c2ecf20Sopenharmony_ci bytes += sizeof(bitmap_super_t); 21108c2ecf20Sopenharmony_ci } while (bytes > (space << 9) && (chunkshift + BITMAP_BLOCK_SHIFT) < 21118c2ecf20Sopenharmony_ci (BITS_PER_BYTE * sizeof(((bitmap_super_t *)0)->chunksize) - 1)); 21128c2ecf20Sopenharmony_ci } else 21138c2ecf20Sopenharmony_ci chunkshift = ffz(~chunksize) - BITMAP_BLOCK_SHIFT; 21148c2ecf20Sopenharmony_ci 21158c2ecf20Sopenharmony_ci chunks = DIV_ROUND_UP_SECTOR_T(blocks, 1 << chunkshift); 21168c2ecf20Sopenharmony_ci memset(&store, 0, sizeof(store)); 21178c2ecf20Sopenharmony_ci if (bitmap->mddev->bitmap_info.offset || bitmap->mddev->bitmap_info.file) 21188c2ecf20Sopenharmony_ci ret = md_bitmap_storage_alloc(&store, chunks, 21198c2ecf20Sopenharmony_ci !bitmap->mddev->bitmap_info.external, 21208c2ecf20Sopenharmony_ci mddev_is_clustered(bitmap->mddev) 21218c2ecf20Sopenharmony_ci ? bitmap->cluster_slot : 0); 21228c2ecf20Sopenharmony_ci if (ret) { 21238c2ecf20Sopenharmony_ci md_bitmap_file_unmap(&store); 21248c2ecf20Sopenharmony_ci goto err; 21258c2ecf20Sopenharmony_ci } 21268c2ecf20Sopenharmony_ci 21278c2ecf20Sopenharmony_ci pages = DIV_ROUND_UP(chunks, PAGE_COUNTER_RATIO); 21288c2ecf20Sopenharmony_ci 21298c2ecf20Sopenharmony_ci new_bp = kcalloc(pages, sizeof(*new_bp), GFP_KERNEL); 21308c2ecf20Sopenharmony_ci ret = -ENOMEM; 21318c2ecf20Sopenharmony_ci if (!new_bp) { 21328c2ecf20Sopenharmony_ci md_bitmap_file_unmap(&store); 21338c2ecf20Sopenharmony_ci goto err; 21348c2ecf20Sopenharmony_ci } 21358c2ecf20Sopenharmony_ci 21368c2ecf20Sopenharmony_ci if (!init) 21378c2ecf20Sopenharmony_ci bitmap->mddev->pers->quiesce(bitmap->mddev, 1); 21388c2ecf20Sopenharmony_ci 21398c2ecf20Sopenharmony_ci store.file = bitmap->storage.file; 21408c2ecf20Sopenharmony_ci bitmap->storage.file = NULL; 21418c2ecf20Sopenharmony_ci 21428c2ecf20Sopenharmony_ci if (store.sb_page && bitmap->storage.sb_page) 21438c2ecf20Sopenharmony_ci memcpy(page_address(store.sb_page), 21448c2ecf20Sopenharmony_ci page_address(bitmap->storage.sb_page), 21458c2ecf20Sopenharmony_ci sizeof(bitmap_super_t)); 21468c2ecf20Sopenharmony_ci spin_lock_irq(&bitmap->counts.lock); 21478c2ecf20Sopenharmony_ci md_bitmap_file_unmap(&bitmap->storage); 21488c2ecf20Sopenharmony_ci bitmap->storage = store; 21498c2ecf20Sopenharmony_ci 21508c2ecf20Sopenharmony_ci old_counts = bitmap->counts; 21518c2ecf20Sopenharmony_ci bitmap->counts.bp = new_bp; 21528c2ecf20Sopenharmony_ci bitmap->counts.pages = pages; 21538c2ecf20Sopenharmony_ci bitmap->counts.missing_pages = pages; 21548c2ecf20Sopenharmony_ci bitmap->counts.chunkshift = chunkshift; 21558c2ecf20Sopenharmony_ci bitmap->counts.chunks = chunks; 21568c2ecf20Sopenharmony_ci bitmap->mddev->bitmap_info.chunksize = 1UL << (chunkshift + 21578c2ecf20Sopenharmony_ci BITMAP_BLOCK_SHIFT); 21588c2ecf20Sopenharmony_ci 21598c2ecf20Sopenharmony_ci blocks = min(old_counts.chunks << old_counts.chunkshift, 21608c2ecf20Sopenharmony_ci chunks << chunkshift); 21618c2ecf20Sopenharmony_ci 21628c2ecf20Sopenharmony_ci /* For cluster raid, need to pre-allocate bitmap */ 21638c2ecf20Sopenharmony_ci if (mddev_is_clustered(bitmap->mddev)) { 21648c2ecf20Sopenharmony_ci unsigned long page; 21658c2ecf20Sopenharmony_ci for (page = 0; page < pages; page++) { 21668c2ecf20Sopenharmony_ci ret = md_bitmap_checkpage(&bitmap->counts, page, 1, 1); 21678c2ecf20Sopenharmony_ci if (ret) { 21688c2ecf20Sopenharmony_ci unsigned long k; 21698c2ecf20Sopenharmony_ci 21708c2ecf20Sopenharmony_ci /* deallocate the page memory */ 21718c2ecf20Sopenharmony_ci for (k = 0; k < page; k++) { 21728c2ecf20Sopenharmony_ci kfree(new_bp[k].map); 21738c2ecf20Sopenharmony_ci } 21748c2ecf20Sopenharmony_ci kfree(new_bp); 21758c2ecf20Sopenharmony_ci 21768c2ecf20Sopenharmony_ci /* restore some fields from old_counts */ 21778c2ecf20Sopenharmony_ci bitmap->counts.bp = old_counts.bp; 21788c2ecf20Sopenharmony_ci bitmap->counts.pages = old_counts.pages; 21798c2ecf20Sopenharmony_ci bitmap->counts.missing_pages = old_counts.pages; 21808c2ecf20Sopenharmony_ci bitmap->counts.chunkshift = old_counts.chunkshift; 21818c2ecf20Sopenharmony_ci bitmap->counts.chunks = old_counts.chunks; 21828c2ecf20Sopenharmony_ci bitmap->mddev->bitmap_info.chunksize = 21838c2ecf20Sopenharmony_ci 1UL << (old_counts.chunkshift + BITMAP_BLOCK_SHIFT); 21848c2ecf20Sopenharmony_ci blocks = old_counts.chunks << old_counts.chunkshift; 21858c2ecf20Sopenharmony_ci pr_warn("Could not pre-allocate in-memory bitmap for cluster raid\n"); 21868c2ecf20Sopenharmony_ci break; 21878c2ecf20Sopenharmony_ci } else 21888c2ecf20Sopenharmony_ci bitmap->counts.bp[page].count += 1; 21898c2ecf20Sopenharmony_ci } 21908c2ecf20Sopenharmony_ci } 21918c2ecf20Sopenharmony_ci 21928c2ecf20Sopenharmony_ci for (block = 0; block < blocks; ) { 21938c2ecf20Sopenharmony_ci bitmap_counter_t *bmc_old, *bmc_new; 21948c2ecf20Sopenharmony_ci int set; 21958c2ecf20Sopenharmony_ci 21968c2ecf20Sopenharmony_ci bmc_old = md_bitmap_get_counter(&old_counts, block, &old_blocks, 0); 21978c2ecf20Sopenharmony_ci set = bmc_old && NEEDED(*bmc_old); 21988c2ecf20Sopenharmony_ci 21998c2ecf20Sopenharmony_ci if (set) { 22008c2ecf20Sopenharmony_ci bmc_new = md_bitmap_get_counter(&bitmap->counts, block, &new_blocks, 1); 22018c2ecf20Sopenharmony_ci if (bmc_new) { 22028c2ecf20Sopenharmony_ci if (*bmc_new == 0) { 22038c2ecf20Sopenharmony_ci /* need to set on-disk bits too. */ 22048c2ecf20Sopenharmony_ci sector_t end = block + new_blocks; 22058c2ecf20Sopenharmony_ci sector_t start = block >> chunkshift; 22068c2ecf20Sopenharmony_ci 22078c2ecf20Sopenharmony_ci start <<= chunkshift; 22088c2ecf20Sopenharmony_ci while (start < end) { 22098c2ecf20Sopenharmony_ci md_bitmap_file_set_bit(bitmap, block); 22108c2ecf20Sopenharmony_ci start += 1 << chunkshift; 22118c2ecf20Sopenharmony_ci } 22128c2ecf20Sopenharmony_ci *bmc_new = 2; 22138c2ecf20Sopenharmony_ci md_bitmap_count_page(&bitmap->counts, block, 1); 22148c2ecf20Sopenharmony_ci md_bitmap_set_pending(&bitmap->counts, block); 22158c2ecf20Sopenharmony_ci } 22168c2ecf20Sopenharmony_ci *bmc_new |= NEEDED_MASK; 22178c2ecf20Sopenharmony_ci } 22188c2ecf20Sopenharmony_ci if (new_blocks < old_blocks) 22198c2ecf20Sopenharmony_ci old_blocks = new_blocks; 22208c2ecf20Sopenharmony_ci } 22218c2ecf20Sopenharmony_ci block += old_blocks; 22228c2ecf20Sopenharmony_ci } 22238c2ecf20Sopenharmony_ci 22248c2ecf20Sopenharmony_ci if (bitmap->counts.bp != old_counts.bp) { 22258c2ecf20Sopenharmony_ci unsigned long k; 22268c2ecf20Sopenharmony_ci for (k = 0; k < old_counts.pages; k++) 22278c2ecf20Sopenharmony_ci if (!old_counts.bp[k].hijacked) 22288c2ecf20Sopenharmony_ci kfree(old_counts.bp[k].map); 22298c2ecf20Sopenharmony_ci kfree(old_counts.bp); 22308c2ecf20Sopenharmony_ci } 22318c2ecf20Sopenharmony_ci 22328c2ecf20Sopenharmony_ci if (!init) { 22338c2ecf20Sopenharmony_ci int i; 22348c2ecf20Sopenharmony_ci while (block < (chunks << chunkshift)) { 22358c2ecf20Sopenharmony_ci bitmap_counter_t *bmc; 22368c2ecf20Sopenharmony_ci bmc = md_bitmap_get_counter(&bitmap->counts, block, &new_blocks, 1); 22378c2ecf20Sopenharmony_ci if (bmc) { 22388c2ecf20Sopenharmony_ci /* new space. It needs to be resynced, so 22398c2ecf20Sopenharmony_ci * we set NEEDED_MASK. 22408c2ecf20Sopenharmony_ci */ 22418c2ecf20Sopenharmony_ci if (*bmc == 0) { 22428c2ecf20Sopenharmony_ci *bmc = NEEDED_MASK | 2; 22438c2ecf20Sopenharmony_ci md_bitmap_count_page(&bitmap->counts, block, 1); 22448c2ecf20Sopenharmony_ci md_bitmap_set_pending(&bitmap->counts, block); 22458c2ecf20Sopenharmony_ci } 22468c2ecf20Sopenharmony_ci } 22478c2ecf20Sopenharmony_ci block += new_blocks; 22488c2ecf20Sopenharmony_ci } 22498c2ecf20Sopenharmony_ci for (i = 0; i < bitmap->storage.file_pages; i++) 22508c2ecf20Sopenharmony_ci set_page_attr(bitmap, i, BITMAP_PAGE_DIRTY); 22518c2ecf20Sopenharmony_ci } 22528c2ecf20Sopenharmony_ci spin_unlock_irq(&bitmap->counts.lock); 22538c2ecf20Sopenharmony_ci 22548c2ecf20Sopenharmony_ci if (!init) { 22558c2ecf20Sopenharmony_ci md_bitmap_unplug(bitmap); 22568c2ecf20Sopenharmony_ci bitmap->mddev->pers->quiesce(bitmap->mddev, 0); 22578c2ecf20Sopenharmony_ci } 22588c2ecf20Sopenharmony_ci ret = 0; 22598c2ecf20Sopenharmony_cierr: 22608c2ecf20Sopenharmony_ci return ret; 22618c2ecf20Sopenharmony_ci} 22628c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(md_bitmap_resize); 22638c2ecf20Sopenharmony_ci 22648c2ecf20Sopenharmony_cistatic ssize_t 22658c2ecf20Sopenharmony_cilocation_show(struct mddev *mddev, char *page) 22668c2ecf20Sopenharmony_ci{ 22678c2ecf20Sopenharmony_ci ssize_t len; 22688c2ecf20Sopenharmony_ci if (mddev->bitmap_info.file) 22698c2ecf20Sopenharmony_ci len = sprintf(page, "file"); 22708c2ecf20Sopenharmony_ci else if (mddev->bitmap_info.offset) 22718c2ecf20Sopenharmony_ci len = sprintf(page, "%+lld", (long long)mddev->bitmap_info.offset); 22728c2ecf20Sopenharmony_ci else 22738c2ecf20Sopenharmony_ci len = sprintf(page, "none"); 22748c2ecf20Sopenharmony_ci len += sprintf(page+len, "\n"); 22758c2ecf20Sopenharmony_ci return len; 22768c2ecf20Sopenharmony_ci} 22778c2ecf20Sopenharmony_ci 22788c2ecf20Sopenharmony_cistatic ssize_t 22798c2ecf20Sopenharmony_cilocation_store(struct mddev *mddev, const char *buf, size_t len) 22808c2ecf20Sopenharmony_ci{ 22818c2ecf20Sopenharmony_ci int rv; 22828c2ecf20Sopenharmony_ci 22838c2ecf20Sopenharmony_ci rv = mddev_lock(mddev); 22848c2ecf20Sopenharmony_ci if (rv) 22858c2ecf20Sopenharmony_ci return rv; 22868c2ecf20Sopenharmony_ci if (mddev->pers) { 22878c2ecf20Sopenharmony_ci if (!mddev->pers->quiesce) { 22888c2ecf20Sopenharmony_ci rv = -EBUSY; 22898c2ecf20Sopenharmony_ci goto out; 22908c2ecf20Sopenharmony_ci } 22918c2ecf20Sopenharmony_ci if (mddev->recovery || mddev->sync_thread) { 22928c2ecf20Sopenharmony_ci rv = -EBUSY; 22938c2ecf20Sopenharmony_ci goto out; 22948c2ecf20Sopenharmony_ci } 22958c2ecf20Sopenharmony_ci } 22968c2ecf20Sopenharmony_ci 22978c2ecf20Sopenharmony_ci if (mddev->bitmap || mddev->bitmap_info.file || 22988c2ecf20Sopenharmony_ci mddev->bitmap_info.offset) { 22998c2ecf20Sopenharmony_ci /* bitmap already configured. Only option is to clear it */ 23008c2ecf20Sopenharmony_ci if (strncmp(buf, "none", 4) != 0) { 23018c2ecf20Sopenharmony_ci rv = -EBUSY; 23028c2ecf20Sopenharmony_ci goto out; 23038c2ecf20Sopenharmony_ci } 23048c2ecf20Sopenharmony_ci if (mddev->pers) { 23058c2ecf20Sopenharmony_ci mddev_suspend(mddev); 23068c2ecf20Sopenharmony_ci md_bitmap_destroy(mddev); 23078c2ecf20Sopenharmony_ci mddev_resume(mddev); 23088c2ecf20Sopenharmony_ci } 23098c2ecf20Sopenharmony_ci mddev->bitmap_info.offset = 0; 23108c2ecf20Sopenharmony_ci if (mddev->bitmap_info.file) { 23118c2ecf20Sopenharmony_ci struct file *f = mddev->bitmap_info.file; 23128c2ecf20Sopenharmony_ci mddev->bitmap_info.file = NULL; 23138c2ecf20Sopenharmony_ci fput(f); 23148c2ecf20Sopenharmony_ci } 23158c2ecf20Sopenharmony_ci } else { 23168c2ecf20Sopenharmony_ci /* No bitmap, OK to set a location */ 23178c2ecf20Sopenharmony_ci long long offset; 23188c2ecf20Sopenharmony_ci if (strncmp(buf, "none", 4) == 0) 23198c2ecf20Sopenharmony_ci /* nothing to be done */; 23208c2ecf20Sopenharmony_ci else if (strncmp(buf, "file:", 5) == 0) { 23218c2ecf20Sopenharmony_ci /* Not supported yet */ 23228c2ecf20Sopenharmony_ci rv = -EINVAL; 23238c2ecf20Sopenharmony_ci goto out; 23248c2ecf20Sopenharmony_ci } else { 23258c2ecf20Sopenharmony_ci if (buf[0] == '+') 23268c2ecf20Sopenharmony_ci rv = kstrtoll(buf+1, 10, &offset); 23278c2ecf20Sopenharmony_ci else 23288c2ecf20Sopenharmony_ci rv = kstrtoll(buf, 10, &offset); 23298c2ecf20Sopenharmony_ci if (rv) 23308c2ecf20Sopenharmony_ci goto out; 23318c2ecf20Sopenharmony_ci if (offset == 0) { 23328c2ecf20Sopenharmony_ci rv = -EINVAL; 23338c2ecf20Sopenharmony_ci goto out; 23348c2ecf20Sopenharmony_ci } 23358c2ecf20Sopenharmony_ci if (mddev->bitmap_info.external == 0 && 23368c2ecf20Sopenharmony_ci mddev->major_version == 0 && 23378c2ecf20Sopenharmony_ci offset != mddev->bitmap_info.default_offset) { 23388c2ecf20Sopenharmony_ci rv = -EINVAL; 23398c2ecf20Sopenharmony_ci goto out; 23408c2ecf20Sopenharmony_ci } 23418c2ecf20Sopenharmony_ci mddev->bitmap_info.offset = offset; 23428c2ecf20Sopenharmony_ci if (mddev->pers) { 23438c2ecf20Sopenharmony_ci struct bitmap *bitmap; 23448c2ecf20Sopenharmony_ci bitmap = md_bitmap_create(mddev, -1); 23458c2ecf20Sopenharmony_ci mddev_suspend(mddev); 23468c2ecf20Sopenharmony_ci if (IS_ERR(bitmap)) 23478c2ecf20Sopenharmony_ci rv = PTR_ERR(bitmap); 23488c2ecf20Sopenharmony_ci else { 23498c2ecf20Sopenharmony_ci mddev->bitmap = bitmap; 23508c2ecf20Sopenharmony_ci rv = md_bitmap_load(mddev); 23518c2ecf20Sopenharmony_ci if (rv) 23528c2ecf20Sopenharmony_ci mddev->bitmap_info.offset = 0; 23538c2ecf20Sopenharmony_ci } 23548c2ecf20Sopenharmony_ci if (rv) { 23558c2ecf20Sopenharmony_ci md_bitmap_destroy(mddev); 23568c2ecf20Sopenharmony_ci mddev_resume(mddev); 23578c2ecf20Sopenharmony_ci goto out; 23588c2ecf20Sopenharmony_ci } 23598c2ecf20Sopenharmony_ci mddev_resume(mddev); 23608c2ecf20Sopenharmony_ci } 23618c2ecf20Sopenharmony_ci } 23628c2ecf20Sopenharmony_ci } 23638c2ecf20Sopenharmony_ci if (!mddev->external) { 23648c2ecf20Sopenharmony_ci /* Ensure new bitmap info is stored in 23658c2ecf20Sopenharmony_ci * metadata promptly. 23668c2ecf20Sopenharmony_ci */ 23678c2ecf20Sopenharmony_ci set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags); 23688c2ecf20Sopenharmony_ci md_wakeup_thread(mddev->thread); 23698c2ecf20Sopenharmony_ci } 23708c2ecf20Sopenharmony_ci rv = 0; 23718c2ecf20Sopenharmony_ciout: 23728c2ecf20Sopenharmony_ci mddev_unlock(mddev); 23738c2ecf20Sopenharmony_ci if (rv) 23748c2ecf20Sopenharmony_ci return rv; 23758c2ecf20Sopenharmony_ci return len; 23768c2ecf20Sopenharmony_ci} 23778c2ecf20Sopenharmony_ci 23788c2ecf20Sopenharmony_cistatic struct md_sysfs_entry bitmap_location = 23798c2ecf20Sopenharmony_ci__ATTR(location, S_IRUGO|S_IWUSR, location_show, location_store); 23808c2ecf20Sopenharmony_ci 23818c2ecf20Sopenharmony_ci/* 'bitmap/space' is the space available at 'location' for the 23828c2ecf20Sopenharmony_ci * bitmap. This allows the kernel to know when it is safe to 23838c2ecf20Sopenharmony_ci * resize the bitmap to match a resized array. 23848c2ecf20Sopenharmony_ci */ 23858c2ecf20Sopenharmony_cistatic ssize_t 23868c2ecf20Sopenharmony_cispace_show(struct mddev *mddev, char *page) 23878c2ecf20Sopenharmony_ci{ 23888c2ecf20Sopenharmony_ci return sprintf(page, "%lu\n", mddev->bitmap_info.space); 23898c2ecf20Sopenharmony_ci} 23908c2ecf20Sopenharmony_ci 23918c2ecf20Sopenharmony_cistatic ssize_t 23928c2ecf20Sopenharmony_cispace_store(struct mddev *mddev, const char *buf, size_t len) 23938c2ecf20Sopenharmony_ci{ 23948c2ecf20Sopenharmony_ci unsigned long sectors; 23958c2ecf20Sopenharmony_ci int rv; 23968c2ecf20Sopenharmony_ci 23978c2ecf20Sopenharmony_ci rv = kstrtoul(buf, 10, §ors); 23988c2ecf20Sopenharmony_ci if (rv) 23998c2ecf20Sopenharmony_ci return rv; 24008c2ecf20Sopenharmony_ci 24018c2ecf20Sopenharmony_ci if (sectors == 0) 24028c2ecf20Sopenharmony_ci return -EINVAL; 24038c2ecf20Sopenharmony_ci 24048c2ecf20Sopenharmony_ci if (mddev->bitmap && 24058c2ecf20Sopenharmony_ci sectors < (mddev->bitmap->storage.bytes + 511) >> 9) 24068c2ecf20Sopenharmony_ci return -EFBIG; /* Bitmap is too big for this small space */ 24078c2ecf20Sopenharmony_ci 24088c2ecf20Sopenharmony_ci /* could make sure it isn't too big, but that isn't really 24098c2ecf20Sopenharmony_ci * needed - user-space should be careful. 24108c2ecf20Sopenharmony_ci */ 24118c2ecf20Sopenharmony_ci mddev->bitmap_info.space = sectors; 24128c2ecf20Sopenharmony_ci return len; 24138c2ecf20Sopenharmony_ci} 24148c2ecf20Sopenharmony_ci 24158c2ecf20Sopenharmony_cistatic struct md_sysfs_entry bitmap_space = 24168c2ecf20Sopenharmony_ci__ATTR(space, S_IRUGO|S_IWUSR, space_show, space_store); 24178c2ecf20Sopenharmony_ci 24188c2ecf20Sopenharmony_cistatic ssize_t 24198c2ecf20Sopenharmony_citimeout_show(struct mddev *mddev, char *page) 24208c2ecf20Sopenharmony_ci{ 24218c2ecf20Sopenharmony_ci ssize_t len; 24228c2ecf20Sopenharmony_ci unsigned long secs = mddev->bitmap_info.daemon_sleep / HZ; 24238c2ecf20Sopenharmony_ci unsigned long jifs = mddev->bitmap_info.daemon_sleep % HZ; 24248c2ecf20Sopenharmony_ci 24258c2ecf20Sopenharmony_ci len = sprintf(page, "%lu", secs); 24268c2ecf20Sopenharmony_ci if (jifs) 24278c2ecf20Sopenharmony_ci len += sprintf(page+len, ".%03u", jiffies_to_msecs(jifs)); 24288c2ecf20Sopenharmony_ci len += sprintf(page+len, "\n"); 24298c2ecf20Sopenharmony_ci return len; 24308c2ecf20Sopenharmony_ci} 24318c2ecf20Sopenharmony_ci 24328c2ecf20Sopenharmony_cistatic ssize_t 24338c2ecf20Sopenharmony_citimeout_store(struct mddev *mddev, const char *buf, size_t len) 24348c2ecf20Sopenharmony_ci{ 24358c2ecf20Sopenharmony_ci /* timeout can be set at any time */ 24368c2ecf20Sopenharmony_ci unsigned long timeout; 24378c2ecf20Sopenharmony_ci int rv = strict_strtoul_scaled(buf, &timeout, 4); 24388c2ecf20Sopenharmony_ci if (rv) 24398c2ecf20Sopenharmony_ci return rv; 24408c2ecf20Sopenharmony_ci 24418c2ecf20Sopenharmony_ci /* just to make sure we don't overflow... */ 24428c2ecf20Sopenharmony_ci if (timeout >= LONG_MAX / HZ) 24438c2ecf20Sopenharmony_ci return -EINVAL; 24448c2ecf20Sopenharmony_ci 24458c2ecf20Sopenharmony_ci timeout = timeout * HZ / 10000; 24468c2ecf20Sopenharmony_ci 24478c2ecf20Sopenharmony_ci if (timeout >= MAX_SCHEDULE_TIMEOUT) 24488c2ecf20Sopenharmony_ci timeout = MAX_SCHEDULE_TIMEOUT-1; 24498c2ecf20Sopenharmony_ci if (timeout < 1) 24508c2ecf20Sopenharmony_ci timeout = 1; 24518c2ecf20Sopenharmony_ci mddev->bitmap_info.daemon_sleep = timeout; 24528c2ecf20Sopenharmony_ci if (mddev->thread) { 24538c2ecf20Sopenharmony_ci /* if thread->timeout is MAX_SCHEDULE_TIMEOUT, then 24548c2ecf20Sopenharmony_ci * the bitmap is all clean and we don't need to 24558c2ecf20Sopenharmony_ci * adjust the timeout right now 24568c2ecf20Sopenharmony_ci */ 24578c2ecf20Sopenharmony_ci if (mddev->thread->timeout < MAX_SCHEDULE_TIMEOUT) { 24588c2ecf20Sopenharmony_ci mddev->thread->timeout = timeout; 24598c2ecf20Sopenharmony_ci md_wakeup_thread(mddev->thread); 24608c2ecf20Sopenharmony_ci } 24618c2ecf20Sopenharmony_ci } 24628c2ecf20Sopenharmony_ci return len; 24638c2ecf20Sopenharmony_ci} 24648c2ecf20Sopenharmony_ci 24658c2ecf20Sopenharmony_cistatic struct md_sysfs_entry bitmap_timeout = 24668c2ecf20Sopenharmony_ci__ATTR(time_base, S_IRUGO|S_IWUSR, timeout_show, timeout_store); 24678c2ecf20Sopenharmony_ci 24688c2ecf20Sopenharmony_cistatic ssize_t 24698c2ecf20Sopenharmony_cibacklog_show(struct mddev *mddev, char *page) 24708c2ecf20Sopenharmony_ci{ 24718c2ecf20Sopenharmony_ci return sprintf(page, "%lu\n", mddev->bitmap_info.max_write_behind); 24728c2ecf20Sopenharmony_ci} 24738c2ecf20Sopenharmony_ci 24748c2ecf20Sopenharmony_cistatic ssize_t 24758c2ecf20Sopenharmony_cibacklog_store(struct mddev *mddev, const char *buf, size_t len) 24768c2ecf20Sopenharmony_ci{ 24778c2ecf20Sopenharmony_ci unsigned long backlog; 24788c2ecf20Sopenharmony_ci unsigned long old_mwb = mddev->bitmap_info.max_write_behind; 24798c2ecf20Sopenharmony_ci struct md_rdev *rdev; 24808c2ecf20Sopenharmony_ci bool has_write_mostly = false; 24818c2ecf20Sopenharmony_ci int rv = kstrtoul(buf, 10, &backlog); 24828c2ecf20Sopenharmony_ci if (rv) 24838c2ecf20Sopenharmony_ci return rv; 24848c2ecf20Sopenharmony_ci if (backlog > COUNTER_MAX) 24858c2ecf20Sopenharmony_ci return -EINVAL; 24868c2ecf20Sopenharmony_ci 24878c2ecf20Sopenharmony_ci rv = mddev_lock(mddev); 24888c2ecf20Sopenharmony_ci if (rv) 24898c2ecf20Sopenharmony_ci return rv; 24908c2ecf20Sopenharmony_ci 24918c2ecf20Sopenharmony_ci /* 24928c2ecf20Sopenharmony_ci * Without write mostly device, it doesn't make sense to set 24938c2ecf20Sopenharmony_ci * backlog for max_write_behind. 24948c2ecf20Sopenharmony_ci */ 24958c2ecf20Sopenharmony_ci rdev_for_each(rdev, mddev) { 24968c2ecf20Sopenharmony_ci if (test_bit(WriteMostly, &rdev->flags)) { 24978c2ecf20Sopenharmony_ci has_write_mostly = true; 24988c2ecf20Sopenharmony_ci break; 24998c2ecf20Sopenharmony_ci } 25008c2ecf20Sopenharmony_ci } 25018c2ecf20Sopenharmony_ci if (!has_write_mostly) { 25028c2ecf20Sopenharmony_ci pr_warn_ratelimited("%s: can't set backlog, no write mostly device available\n", 25038c2ecf20Sopenharmony_ci mdname(mddev)); 25048c2ecf20Sopenharmony_ci mddev_unlock(mddev); 25058c2ecf20Sopenharmony_ci return -EINVAL; 25068c2ecf20Sopenharmony_ci } 25078c2ecf20Sopenharmony_ci 25088c2ecf20Sopenharmony_ci mddev->bitmap_info.max_write_behind = backlog; 25098c2ecf20Sopenharmony_ci if (!backlog && mddev->serial_info_pool) { 25108c2ecf20Sopenharmony_ci /* serial_info_pool is not needed if backlog is zero */ 25118c2ecf20Sopenharmony_ci if (!mddev->serialize_policy) 25128c2ecf20Sopenharmony_ci mddev_destroy_serial_pool(mddev, NULL, false); 25138c2ecf20Sopenharmony_ci } else if (backlog && !mddev->serial_info_pool) { 25148c2ecf20Sopenharmony_ci /* serial_info_pool is needed since backlog is not zero */ 25158c2ecf20Sopenharmony_ci rdev_for_each(rdev, mddev) 25168c2ecf20Sopenharmony_ci mddev_create_serial_pool(mddev, rdev, false); 25178c2ecf20Sopenharmony_ci } 25188c2ecf20Sopenharmony_ci if (old_mwb != backlog) 25198c2ecf20Sopenharmony_ci md_bitmap_update_sb(mddev->bitmap); 25208c2ecf20Sopenharmony_ci 25218c2ecf20Sopenharmony_ci mddev_unlock(mddev); 25228c2ecf20Sopenharmony_ci return len; 25238c2ecf20Sopenharmony_ci} 25248c2ecf20Sopenharmony_ci 25258c2ecf20Sopenharmony_cistatic struct md_sysfs_entry bitmap_backlog = 25268c2ecf20Sopenharmony_ci__ATTR(backlog, S_IRUGO|S_IWUSR, backlog_show, backlog_store); 25278c2ecf20Sopenharmony_ci 25288c2ecf20Sopenharmony_cistatic ssize_t 25298c2ecf20Sopenharmony_cichunksize_show(struct mddev *mddev, char *page) 25308c2ecf20Sopenharmony_ci{ 25318c2ecf20Sopenharmony_ci return sprintf(page, "%lu\n", mddev->bitmap_info.chunksize); 25328c2ecf20Sopenharmony_ci} 25338c2ecf20Sopenharmony_ci 25348c2ecf20Sopenharmony_cistatic ssize_t 25358c2ecf20Sopenharmony_cichunksize_store(struct mddev *mddev, const char *buf, size_t len) 25368c2ecf20Sopenharmony_ci{ 25378c2ecf20Sopenharmony_ci /* Can only be changed when no bitmap is active */ 25388c2ecf20Sopenharmony_ci int rv; 25398c2ecf20Sopenharmony_ci unsigned long csize; 25408c2ecf20Sopenharmony_ci if (mddev->bitmap) 25418c2ecf20Sopenharmony_ci return -EBUSY; 25428c2ecf20Sopenharmony_ci rv = kstrtoul(buf, 10, &csize); 25438c2ecf20Sopenharmony_ci if (rv) 25448c2ecf20Sopenharmony_ci return rv; 25458c2ecf20Sopenharmony_ci if (csize < 512 || 25468c2ecf20Sopenharmony_ci !is_power_of_2(csize)) 25478c2ecf20Sopenharmony_ci return -EINVAL; 25488c2ecf20Sopenharmony_ci if (BITS_PER_LONG > 32 && csize >= (1ULL << (BITS_PER_BYTE * 25498c2ecf20Sopenharmony_ci sizeof(((bitmap_super_t *)0)->chunksize)))) 25508c2ecf20Sopenharmony_ci return -EOVERFLOW; 25518c2ecf20Sopenharmony_ci mddev->bitmap_info.chunksize = csize; 25528c2ecf20Sopenharmony_ci return len; 25538c2ecf20Sopenharmony_ci} 25548c2ecf20Sopenharmony_ci 25558c2ecf20Sopenharmony_cistatic struct md_sysfs_entry bitmap_chunksize = 25568c2ecf20Sopenharmony_ci__ATTR(chunksize, S_IRUGO|S_IWUSR, chunksize_show, chunksize_store); 25578c2ecf20Sopenharmony_ci 25588c2ecf20Sopenharmony_cistatic ssize_t metadata_show(struct mddev *mddev, char *page) 25598c2ecf20Sopenharmony_ci{ 25608c2ecf20Sopenharmony_ci if (mddev_is_clustered(mddev)) 25618c2ecf20Sopenharmony_ci return sprintf(page, "clustered\n"); 25628c2ecf20Sopenharmony_ci return sprintf(page, "%s\n", (mddev->bitmap_info.external 25638c2ecf20Sopenharmony_ci ? "external" : "internal")); 25648c2ecf20Sopenharmony_ci} 25658c2ecf20Sopenharmony_ci 25668c2ecf20Sopenharmony_cistatic ssize_t metadata_store(struct mddev *mddev, const char *buf, size_t len) 25678c2ecf20Sopenharmony_ci{ 25688c2ecf20Sopenharmony_ci if (mddev->bitmap || 25698c2ecf20Sopenharmony_ci mddev->bitmap_info.file || 25708c2ecf20Sopenharmony_ci mddev->bitmap_info.offset) 25718c2ecf20Sopenharmony_ci return -EBUSY; 25728c2ecf20Sopenharmony_ci if (strncmp(buf, "external", 8) == 0) 25738c2ecf20Sopenharmony_ci mddev->bitmap_info.external = 1; 25748c2ecf20Sopenharmony_ci else if ((strncmp(buf, "internal", 8) == 0) || 25758c2ecf20Sopenharmony_ci (strncmp(buf, "clustered", 9) == 0)) 25768c2ecf20Sopenharmony_ci mddev->bitmap_info.external = 0; 25778c2ecf20Sopenharmony_ci else 25788c2ecf20Sopenharmony_ci return -EINVAL; 25798c2ecf20Sopenharmony_ci return len; 25808c2ecf20Sopenharmony_ci} 25818c2ecf20Sopenharmony_ci 25828c2ecf20Sopenharmony_cistatic struct md_sysfs_entry bitmap_metadata = 25838c2ecf20Sopenharmony_ci__ATTR(metadata, S_IRUGO|S_IWUSR, metadata_show, metadata_store); 25848c2ecf20Sopenharmony_ci 25858c2ecf20Sopenharmony_cistatic ssize_t can_clear_show(struct mddev *mddev, char *page) 25868c2ecf20Sopenharmony_ci{ 25878c2ecf20Sopenharmony_ci int len; 25888c2ecf20Sopenharmony_ci spin_lock(&mddev->lock); 25898c2ecf20Sopenharmony_ci if (mddev->bitmap) 25908c2ecf20Sopenharmony_ci len = sprintf(page, "%s\n", (mddev->bitmap->need_sync ? 25918c2ecf20Sopenharmony_ci "false" : "true")); 25928c2ecf20Sopenharmony_ci else 25938c2ecf20Sopenharmony_ci len = sprintf(page, "\n"); 25948c2ecf20Sopenharmony_ci spin_unlock(&mddev->lock); 25958c2ecf20Sopenharmony_ci return len; 25968c2ecf20Sopenharmony_ci} 25978c2ecf20Sopenharmony_ci 25988c2ecf20Sopenharmony_cistatic ssize_t can_clear_store(struct mddev *mddev, const char *buf, size_t len) 25998c2ecf20Sopenharmony_ci{ 26008c2ecf20Sopenharmony_ci if (mddev->bitmap == NULL) 26018c2ecf20Sopenharmony_ci return -ENOENT; 26028c2ecf20Sopenharmony_ci if (strncmp(buf, "false", 5) == 0) 26038c2ecf20Sopenharmony_ci mddev->bitmap->need_sync = 1; 26048c2ecf20Sopenharmony_ci else if (strncmp(buf, "true", 4) == 0) { 26058c2ecf20Sopenharmony_ci if (mddev->degraded) 26068c2ecf20Sopenharmony_ci return -EBUSY; 26078c2ecf20Sopenharmony_ci mddev->bitmap->need_sync = 0; 26088c2ecf20Sopenharmony_ci } else 26098c2ecf20Sopenharmony_ci return -EINVAL; 26108c2ecf20Sopenharmony_ci return len; 26118c2ecf20Sopenharmony_ci} 26128c2ecf20Sopenharmony_ci 26138c2ecf20Sopenharmony_cistatic struct md_sysfs_entry bitmap_can_clear = 26148c2ecf20Sopenharmony_ci__ATTR(can_clear, S_IRUGO|S_IWUSR, can_clear_show, can_clear_store); 26158c2ecf20Sopenharmony_ci 26168c2ecf20Sopenharmony_cistatic ssize_t 26178c2ecf20Sopenharmony_cibehind_writes_used_show(struct mddev *mddev, char *page) 26188c2ecf20Sopenharmony_ci{ 26198c2ecf20Sopenharmony_ci ssize_t ret; 26208c2ecf20Sopenharmony_ci spin_lock(&mddev->lock); 26218c2ecf20Sopenharmony_ci if (mddev->bitmap == NULL) 26228c2ecf20Sopenharmony_ci ret = sprintf(page, "0\n"); 26238c2ecf20Sopenharmony_ci else 26248c2ecf20Sopenharmony_ci ret = sprintf(page, "%lu\n", 26258c2ecf20Sopenharmony_ci mddev->bitmap->behind_writes_used); 26268c2ecf20Sopenharmony_ci spin_unlock(&mddev->lock); 26278c2ecf20Sopenharmony_ci return ret; 26288c2ecf20Sopenharmony_ci} 26298c2ecf20Sopenharmony_ci 26308c2ecf20Sopenharmony_cistatic ssize_t 26318c2ecf20Sopenharmony_cibehind_writes_used_reset(struct mddev *mddev, const char *buf, size_t len) 26328c2ecf20Sopenharmony_ci{ 26338c2ecf20Sopenharmony_ci if (mddev->bitmap) 26348c2ecf20Sopenharmony_ci mddev->bitmap->behind_writes_used = 0; 26358c2ecf20Sopenharmony_ci return len; 26368c2ecf20Sopenharmony_ci} 26378c2ecf20Sopenharmony_ci 26388c2ecf20Sopenharmony_cistatic struct md_sysfs_entry max_backlog_used = 26398c2ecf20Sopenharmony_ci__ATTR(max_backlog_used, S_IRUGO | S_IWUSR, 26408c2ecf20Sopenharmony_ci behind_writes_used_show, behind_writes_used_reset); 26418c2ecf20Sopenharmony_ci 26428c2ecf20Sopenharmony_cistatic struct attribute *md_bitmap_attrs[] = { 26438c2ecf20Sopenharmony_ci &bitmap_location.attr, 26448c2ecf20Sopenharmony_ci &bitmap_space.attr, 26458c2ecf20Sopenharmony_ci &bitmap_timeout.attr, 26468c2ecf20Sopenharmony_ci &bitmap_backlog.attr, 26478c2ecf20Sopenharmony_ci &bitmap_chunksize.attr, 26488c2ecf20Sopenharmony_ci &bitmap_metadata.attr, 26498c2ecf20Sopenharmony_ci &bitmap_can_clear.attr, 26508c2ecf20Sopenharmony_ci &max_backlog_used.attr, 26518c2ecf20Sopenharmony_ci NULL 26528c2ecf20Sopenharmony_ci}; 26538c2ecf20Sopenharmony_cistruct attribute_group md_bitmap_group = { 26548c2ecf20Sopenharmony_ci .name = "bitmap", 26558c2ecf20Sopenharmony_ci .attrs = md_bitmap_attrs, 26568c2ecf20Sopenharmony_ci}; 2657