162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * bitmap.c two-level bitmap (C) Peter T. Breuer (ptb@ot.uc3m.es) 2003 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * bitmap_create - sets up the bitmap structure 662306a36Sopenharmony_ci * bitmap_destroy - destroys the bitmap structure 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * additions, Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.: 962306a36Sopenharmony_ci * - added disk storage for bitmap 1062306a36Sopenharmony_ci * - changes to allow various bitmap chunk sizes 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci/* 1462306a36Sopenharmony_ci * Still to do: 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * flush after percent set rather than just time based. (maybe both). 1762306a36Sopenharmony_ci */ 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include <linux/blkdev.h> 2062306a36Sopenharmony_ci#include <linux/module.h> 2162306a36Sopenharmony_ci#include <linux/errno.h> 2262306a36Sopenharmony_ci#include <linux/slab.h> 2362306a36Sopenharmony_ci#include <linux/init.h> 2462306a36Sopenharmony_ci#include <linux/timer.h> 2562306a36Sopenharmony_ci#include <linux/sched.h> 2662306a36Sopenharmony_ci#include <linux/list.h> 2762306a36Sopenharmony_ci#include <linux/file.h> 2862306a36Sopenharmony_ci#include <linux/mount.h> 2962306a36Sopenharmony_ci#include <linux/buffer_head.h> 3062306a36Sopenharmony_ci#include <linux/seq_file.h> 3162306a36Sopenharmony_ci#include <trace/events/block.h> 3262306a36Sopenharmony_ci#include "md.h" 3362306a36Sopenharmony_ci#include "md-bitmap.h" 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic inline char *bmname(struct bitmap *bitmap) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci return bitmap->mddev ? mdname(bitmap->mddev) : "mdX"; 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci/* 4162306a36Sopenharmony_ci * check a page and, if necessary, allocate it (or hijack it if the alloc fails) 4262306a36Sopenharmony_ci * 4362306a36Sopenharmony_ci * 1) check to see if this page is allocated, if it's not then try to alloc 4462306a36Sopenharmony_ci * 2) if the alloc fails, set the page's hijacked flag so we'll use the 4562306a36Sopenharmony_ci * page pointer directly as a counter 4662306a36Sopenharmony_ci * 4762306a36Sopenharmony_ci * if we find our page, we increment the page's refcount so that it stays 4862306a36Sopenharmony_ci * allocated while we're using it 4962306a36Sopenharmony_ci */ 5062306a36Sopenharmony_cistatic int md_bitmap_checkpage(struct bitmap_counts *bitmap, 5162306a36Sopenharmony_ci unsigned long page, int create, int no_hijack) 5262306a36Sopenharmony_ci__releases(bitmap->lock) 5362306a36Sopenharmony_ci__acquires(bitmap->lock) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci unsigned char *mappage; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci WARN_ON_ONCE(page >= bitmap->pages); 5862306a36Sopenharmony_ci if (bitmap->bp[page].hijacked) /* it's hijacked, don't try to alloc */ 5962306a36Sopenharmony_ci return 0; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci if (bitmap->bp[page].map) /* page is already allocated, just return */ 6262306a36Sopenharmony_ci return 0; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci if (!create) 6562306a36Sopenharmony_ci return -ENOENT; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci /* this page has not been allocated yet */ 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci spin_unlock_irq(&bitmap->lock); 7062306a36Sopenharmony_ci /* It is possible that this is being called inside a 7162306a36Sopenharmony_ci * prepare_to_wait/finish_wait loop from raid5c:make_request(). 7262306a36Sopenharmony_ci * In general it is not permitted to sleep in that context as it 7362306a36Sopenharmony_ci * can cause the loop to spin freely. 7462306a36Sopenharmony_ci * That doesn't apply here as we can only reach this point 7562306a36Sopenharmony_ci * once with any loop. 7662306a36Sopenharmony_ci * When this function completes, either bp[page].map or 7762306a36Sopenharmony_ci * bp[page].hijacked. In either case, this function will 7862306a36Sopenharmony_ci * abort before getting to this point again. So there is 7962306a36Sopenharmony_ci * no risk of a free-spin, and so it is safe to assert 8062306a36Sopenharmony_ci * that sleeping here is allowed. 8162306a36Sopenharmony_ci */ 8262306a36Sopenharmony_ci sched_annotate_sleep(); 8362306a36Sopenharmony_ci mappage = kzalloc(PAGE_SIZE, GFP_NOIO); 8462306a36Sopenharmony_ci spin_lock_irq(&bitmap->lock); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci if (mappage == NULL) { 8762306a36Sopenharmony_ci pr_debug("md/bitmap: map page allocation failed, hijacking\n"); 8862306a36Sopenharmony_ci /* We don't support hijack for cluster raid */ 8962306a36Sopenharmony_ci if (no_hijack) 9062306a36Sopenharmony_ci return -ENOMEM; 9162306a36Sopenharmony_ci /* failed - set the hijacked flag so that we can use the 9262306a36Sopenharmony_ci * pointer as a counter */ 9362306a36Sopenharmony_ci if (!bitmap->bp[page].map) 9462306a36Sopenharmony_ci bitmap->bp[page].hijacked = 1; 9562306a36Sopenharmony_ci } else if (bitmap->bp[page].map || 9662306a36Sopenharmony_ci bitmap->bp[page].hijacked) { 9762306a36Sopenharmony_ci /* somebody beat us to getting the page */ 9862306a36Sopenharmony_ci kfree(mappage); 9962306a36Sopenharmony_ci } else { 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci /* no page was in place and we have one, so install it */ 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci bitmap->bp[page].map = mappage; 10462306a36Sopenharmony_ci bitmap->missing_pages--; 10562306a36Sopenharmony_ci } 10662306a36Sopenharmony_ci return 0; 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci/* if page is completely empty, put it back on the free list, or dealloc it */ 11062306a36Sopenharmony_ci/* if page was hijacked, unmark the flag so it might get alloced next time */ 11162306a36Sopenharmony_ci/* Note: lock should be held when calling this */ 11262306a36Sopenharmony_cistatic void md_bitmap_checkfree(struct bitmap_counts *bitmap, unsigned long page) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci char *ptr; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci if (bitmap->bp[page].count) /* page is still busy */ 11762306a36Sopenharmony_ci return; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci /* page is no longer in use, it can be released */ 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci if (bitmap->bp[page].hijacked) { /* page was hijacked, undo this now */ 12262306a36Sopenharmony_ci bitmap->bp[page].hijacked = 0; 12362306a36Sopenharmony_ci bitmap->bp[page].map = NULL; 12462306a36Sopenharmony_ci } else { 12562306a36Sopenharmony_ci /* normal case, free the page */ 12662306a36Sopenharmony_ci ptr = bitmap->bp[page].map; 12762306a36Sopenharmony_ci bitmap->bp[page].map = NULL; 12862306a36Sopenharmony_ci bitmap->missing_pages++; 12962306a36Sopenharmony_ci kfree(ptr); 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci/* 13462306a36Sopenharmony_ci * bitmap file handling - read and write the bitmap file and its superblock 13562306a36Sopenharmony_ci */ 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci/* 13862306a36Sopenharmony_ci * basic page I/O operations 13962306a36Sopenharmony_ci */ 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci/* IO operations when bitmap is stored near all superblocks */ 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci/* choose a good rdev and read the page from there */ 14462306a36Sopenharmony_cistatic int read_sb_page(struct mddev *mddev, loff_t offset, 14562306a36Sopenharmony_ci struct page *page, unsigned long index, int size) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci sector_t sector = mddev->bitmap_info.offset + offset + 14962306a36Sopenharmony_ci index * (PAGE_SIZE / SECTOR_SIZE); 15062306a36Sopenharmony_ci struct md_rdev *rdev; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci rdev_for_each(rdev, mddev) { 15362306a36Sopenharmony_ci u32 iosize = roundup(size, bdev_logical_block_size(rdev->bdev)); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci if (!test_bit(In_sync, &rdev->flags) || 15662306a36Sopenharmony_ci test_bit(Faulty, &rdev->flags) || 15762306a36Sopenharmony_ci test_bit(Bitmap_sync, &rdev->flags)) 15862306a36Sopenharmony_ci continue; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci if (sync_page_io(rdev, sector, iosize, page, REQ_OP_READ, true)) 16162306a36Sopenharmony_ci return 0; 16262306a36Sopenharmony_ci } 16362306a36Sopenharmony_ci return -EIO; 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_cistatic struct md_rdev *next_active_rdev(struct md_rdev *rdev, struct mddev *mddev) 16762306a36Sopenharmony_ci{ 16862306a36Sopenharmony_ci /* Iterate the disks of an mddev, using rcu to protect access to the 16962306a36Sopenharmony_ci * linked list, and raising the refcount of devices we return to ensure 17062306a36Sopenharmony_ci * they don't disappear while in use. 17162306a36Sopenharmony_ci * As devices are only added or removed when raid_disk is < 0 and 17262306a36Sopenharmony_ci * nr_pending is 0 and In_sync is clear, the entries we return will 17362306a36Sopenharmony_ci * still be in the same position on the list when we re-enter 17462306a36Sopenharmony_ci * list_for_each_entry_continue_rcu. 17562306a36Sopenharmony_ci * 17662306a36Sopenharmony_ci * Note that if entered with 'rdev == NULL' to start at the 17762306a36Sopenharmony_ci * beginning, we temporarily assign 'rdev' to an address which 17862306a36Sopenharmony_ci * isn't really an rdev, but which can be used by 17962306a36Sopenharmony_ci * list_for_each_entry_continue_rcu() to find the first entry. 18062306a36Sopenharmony_ci */ 18162306a36Sopenharmony_ci rcu_read_lock(); 18262306a36Sopenharmony_ci if (rdev == NULL) 18362306a36Sopenharmony_ci /* start at the beginning */ 18462306a36Sopenharmony_ci rdev = list_entry(&mddev->disks, struct md_rdev, same_set); 18562306a36Sopenharmony_ci else { 18662306a36Sopenharmony_ci /* release the previous rdev and start from there. */ 18762306a36Sopenharmony_ci rdev_dec_pending(rdev, mddev); 18862306a36Sopenharmony_ci } 18962306a36Sopenharmony_ci list_for_each_entry_continue_rcu(rdev, &mddev->disks, same_set) { 19062306a36Sopenharmony_ci if (rdev->raid_disk >= 0 && 19162306a36Sopenharmony_ci !test_bit(Faulty, &rdev->flags)) { 19262306a36Sopenharmony_ci /* this is a usable devices */ 19362306a36Sopenharmony_ci atomic_inc(&rdev->nr_pending); 19462306a36Sopenharmony_ci rcu_read_unlock(); 19562306a36Sopenharmony_ci return rdev; 19662306a36Sopenharmony_ci } 19762306a36Sopenharmony_ci } 19862306a36Sopenharmony_ci rcu_read_unlock(); 19962306a36Sopenharmony_ci return NULL; 20062306a36Sopenharmony_ci} 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_cistatic unsigned int optimal_io_size(struct block_device *bdev, 20362306a36Sopenharmony_ci unsigned int last_page_size, 20462306a36Sopenharmony_ci unsigned int io_size) 20562306a36Sopenharmony_ci{ 20662306a36Sopenharmony_ci if (bdev_io_opt(bdev) > bdev_logical_block_size(bdev)) 20762306a36Sopenharmony_ci return roundup(last_page_size, bdev_io_opt(bdev)); 20862306a36Sopenharmony_ci return io_size; 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cistatic unsigned int bitmap_io_size(unsigned int io_size, unsigned int opt_size, 21262306a36Sopenharmony_ci loff_t start, loff_t boundary) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci if (io_size != opt_size && 21562306a36Sopenharmony_ci start + opt_size / SECTOR_SIZE <= boundary) 21662306a36Sopenharmony_ci return opt_size; 21762306a36Sopenharmony_ci if (start + io_size / SECTOR_SIZE <= boundary) 21862306a36Sopenharmony_ci return io_size; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci /* Overflows boundary */ 22162306a36Sopenharmony_ci return 0; 22262306a36Sopenharmony_ci} 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistatic int __write_sb_page(struct md_rdev *rdev, struct bitmap *bitmap, 22562306a36Sopenharmony_ci unsigned long pg_index, struct page *page) 22662306a36Sopenharmony_ci{ 22762306a36Sopenharmony_ci struct block_device *bdev; 22862306a36Sopenharmony_ci struct mddev *mddev = bitmap->mddev; 22962306a36Sopenharmony_ci struct bitmap_storage *store = &bitmap->storage; 23062306a36Sopenharmony_ci loff_t sboff, offset = mddev->bitmap_info.offset; 23162306a36Sopenharmony_ci sector_t ps = pg_index * PAGE_SIZE / SECTOR_SIZE; 23262306a36Sopenharmony_ci unsigned int size = PAGE_SIZE; 23362306a36Sopenharmony_ci unsigned int opt_size = PAGE_SIZE; 23462306a36Sopenharmony_ci sector_t doff; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci bdev = (rdev->meta_bdev) ? rdev->meta_bdev : rdev->bdev; 23762306a36Sopenharmony_ci /* we compare length (page numbers), not page offset. */ 23862306a36Sopenharmony_ci if ((pg_index - store->sb_index) == store->file_pages - 1) { 23962306a36Sopenharmony_ci unsigned int last_page_size = store->bytes & (PAGE_SIZE - 1); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci if (last_page_size == 0) 24262306a36Sopenharmony_ci last_page_size = PAGE_SIZE; 24362306a36Sopenharmony_ci size = roundup(last_page_size, bdev_logical_block_size(bdev)); 24462306a36Sopenharmony_ci opt_size = optimal_io_size(bdev, last_page_size, size); 24562306a36Sopenharmony_ci } 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci sboff = rdev->sb_start + offset; 24862306a36Sopenharmony_ci doff = rdev->data_offset; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci /* Just make sure we aren't corrupting data or metadata */ 25162306a36Sopenharmony_ci if (mddev->external) { 25262306a36Sopenharmony_ci /* Bitmap could be anywhere. */ 25362306a36Sopenharmony_ci if (sboff + ps > doff && 25462306a36Sopenharmony_ci sboff < (doff + mddev->dev_sectors + PAGE_SIZE / SECTOR_SIZE)) 25562306a36Sopenharmony_ci return -EINVAL; 25662306a36Sopenharmony_ci } else if (offset < 0) { 25762306a36Sopenharmony_ci /* DATA BITMAP METADATA */ 25862306a36Sopenharmony_ci size = bitmap_io_size(size, opt_size, offset + ps, 0); 25962306a36Sopenharmony_ci if (size == 0) 26062306a36Sopenharmony_ci /* bitmap runs in to metadata */ 26162306a36Sopenharmony_ci return -EINVAL; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci if (doff + mddev->dev_sectors > sboff) 26462306a36Sopenharmony_ci /* data runs in to bitmap */ 26562306a36Sopenharmony_ci return -EINVAL; 26662306a36Sopenharmony_ci } else if (rdev->sb_start < rdev->data_offset) { 26762306a36Sopenharmony_ci /* METADATA BITMAP DATA */ 26862306a36Sopenharmony_ci size = bitmap_io_size(size, opt_size, sboff + ps, doff); 26962306a36Sopenharmony_ci if (size == 0) 27062306a36Sopenharmony_ci /* bitmap runs in to data */ 27162306a36Sopenharmony_ci return -EINVAL; 27262306a36Sopenharmony_ci } else { 27362306a36Sopenharmony_ci /* DATA METADATA BITMAP - no problems */ 27462306a36Sopenharmony_ci } 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci md_super_write(mddev, rdev, sboff + ps, (int) size, page); 27762306a36Sopenharmony_ci return 0; 27862306a36Sopenharmony_ci} 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cistatic void write_sb_page(struct bitmap *bitmap, unsigned long pg_index, 28162306a36Sopenharmony_ci struct page *page, bool wait) 28262306a36Sopenharmony_ci{ 28362306a36Sopenharmony_ci struct mddev *mddev = bitmap->mddev; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci do { 28662306a36Sopenharmony_ci struct md_rdev *rdev = NULL; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci while ((rdev = next_active_rdev(rdev, mddev)) != NULL) { 28962306a36Sopenharmony_ci if (__write_sb_page(rdev, bitmap, pg_index, page) < 0) { 29062306a36Sopenharmony_ci set_bit(BITMAP_WRITE_ERROR, &bitmap->flags); 29162306a36Sopenharmony_ci return; 29262306a36Sopenharmony_ci } 29362306a36Sopenharmony_ci } 29462306a36Sopenharmony_ci } while (wait && md_super_wait(mddev) < 0); 29562306a36Sopenharmony_ci} 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cistatic void md_bitmap_file_kick(struct bitmap *bitmap); 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci#ifdef CONFIG_MD_BITMAP_FILE 30062306a36Sopenharmony_cistatic void write_file_page(struct bitmap *bitmap, struct page *page, int wait) 30162306a36Sopenharmony_ci{ 30262306a36Sopenharmony_ci struct buffer_head *bh = page_buffers(page); 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci while (bh && bh->b_blocknr) { 30562306a36Sopenharmony_ci atomic_inc(&bitmap->pending_writes); 30662306a36Sopenharmony_ci set_buffer_locked(bh); 30762306a36Sopenharmony_ci set_buffer_mapped(bh); 30862306a36Sopenharmony_ci submit_bh(REQ_OP_WRITE | REQ_SYNC, bh); 30962306a36Sopenharmony_ci bh = bh->b_this_page; 31062306a36Sopenharmony_ci } 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci if (wait) 31362306a36Sopenharmony_ci wait_event(bitmap->write_wait, 31462306a36Sopenharmony_ci atomic_read(&bitmap->pending_writes) == 0); 31562306a36Sopenharmony_ci} 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_cistatic void end_bitmap_write(struct buffer_head *bh, int uptodate) 31862306a36Sopenharmony_ci{ 31962306a36Sopenharmony_ci struct bitmap *bitmap = bh->b_private; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci if (!uptodate) 32262306a36Sopenharmony_ci set_bit(BITMAP_WRITE_ERROR, &bitmap->flags); 32362306a36Sopenharmony_ci if (atomic_dec_and_test(&bitmap->pending_writes)) 32462306a36Sopenharmony_ci wake_up(&bitmap->write_wait); 32562306a36Sopenharmony_ci} 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_cistatic void free_buffers(struct page *page) 32862306a36Sopenharmony_ci{ 32962306a36Sopenharmony_ci struct buffer_head *bh; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci if (!PagePrivate(page)) 33262306a36Sopenharmony_ci return; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci bh = page_buffers(page); 33562306a36Sopenharmony_ci while (bh) { 33662306a36Sopenharmony_ci struct buffer_head *next = bh->b_this_page; 33762306a36Sopenharmony_ci free_buffer_head(bh); 33862306a36Sopenharmony_ci bh = next; 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci detach_page_private(page); 34162306a36Sopenharmony_ci put_page(page); 34262306a36Sopenharmony_ci} 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci/* read a page from a file. 34562306a36Sopenharmony_ci * We both read the page, and attach buffers to the page to record the 34662306a36Sopenharmony_ci * address of each block (using bmap). These addresses will be used 34762306a36Sopenharmony_ci * to write the block later, completely bypassing the filesystem. 34862306a36Sopenharmony_ci * This usage is similar to how swap files are handled, and allows us 34962306a36Sopenharmony_ci * to write to a file with no concerns of memory allocation failing. 35062306a36Sopenharmony_ci */ 35162306a36Sopenharmony_cistatic int read_file_page(struct file *file, unsigned long index, 35262306a36Sopenharmony_ci struct bitmap *bitmap, unsigned long count, struct page *page) 35362306a36Sopenharmony_ci{ 35462306a36Sopenharmony_ci int ret = 0; 35562306a36Sopenharmony_ci struct inode *inode = file_inode(file); 35662306a36Sopenharmony_ci struct buffer_head *bh; 35762306a36Sopenharmony_ci sector_t block, blk_cur; 35862306a36Sopenharmony_ci unsigned long blocksize = i_blocksize(inode); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci pr_debug("read bitmap file (%dB @ %llu)\n", (int)PAGE_SIZE, 36162306a36Sopenharmony_ci (unsigned long long)index << PAGE_SHIFT); 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci bh = alloc_page_buffers(page, blocksize, false); 36462306a36Sopenharmony_ci if (!bh) { 36562306a36Sopenharmony_ci ret = -ENOMEM; 36662306a36Sopenharmony_ci goto out; 36762306a36Sopenharmony_ci } 36862306a36Sopenharmony_ci attach_page_private(page, bh); 36962306a36Sopenharmony_ci blk_cur = index << (PAGE_SHIFT - inode->i_blkbits); 37062306a36Sopenharmony_ci while (bh) { 37162306a36Sopenharmony_ci block = blk_cur; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci if (count == 0) 37462306a36Sopenharmony_ci bh->b_blocknr = 0; 37562306a36Sopenharmony_ci else { 37662306a36Sopenharmony_ci ret = bmap(inode, &block); 37762306a36Sopenharmony_ci if (ret || !block) { 37862306a36Sopenharmony_ci ret = -EINVAL; 37962306a36Sopenharmony_ci bh->b_blocknr = 0; 38062306a36Sopenharmony_ci goto out; 38162306a36Sopenharmony_ci } 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci bh->b_blocknr = block; 38462306a36Sopenharmony_ci bh->b_bdev = inode->i_sb->s_bdev; 38562306a36Sopenharmony_ci if (count < blocksize) 38662306a36Sopenharmony_ci count = 0; 38762306a36Sopenharmony_ci else 38862306a36Sopenharmony_ci count -= blocksize; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci bh->b_end_io = end_bitmap_write; 39162306a36Sopenharmony_ci bh->b_private = bitmap; 39262306a36Sopenharmony_ci atomic_inc(&bitmap->pending_writes); 39362306a36Sopenharmony_ci set_buffer_locked(bh); 39462306a36Sopenharmony_ci set_buffer_mapped(bh); 39562306a36Sopenharmony_ci submit_bh(REQ_OP_READ, bh); 39662306a36Sopenharmony_ci } 39762306a36Sopenharmony_ci blk_cur++; 39862306a36Sopenharmony_ci bh = bh->b_this_page; 39962306a36Sopenharmony_ci } 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci wait_event(bitmap->write_wait, 40262306a36Sopenharmony_ci atomic_read(&bitmap->pending_writes)==0); 40362306a36Sopenharmony_ci if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags)) 40462306a36Sopenharmony_ci ret = -EIO; 40562306a36Sopenharmony_ciout: 40662306a36Sopenharmony_ci if (ret) 40762306a36Sopenharmony_ci pr_err("md: bitmap read error: (%dB @ %llu): %d\n", 40862306a36Sopenharmony_ci (int)PAGE_SIZE, 40962306a36Sopenharmony_ci (unsigned long long)index << PAGE_SHIFT, 41062306a36Sopenharmony_ci ret); 41162306a36Sopenharmony_ci return ret; 41262306a36Sopenharmony_ci} 41362306a36Sopenharmony_ci#else /* CONFIG_MD_BITMAP_FILE */ 41462306a36Sopenharmony_cistatic void write_file_page(struct bitmap *bitmap, struct page *page, int wait) 41562306a36Sopenharmony_ci{ 41662306a36Sopenharmony_ci} 41762306a36Sopenharmony_cistatic int read_file_page(struct file *file, unsigned long index, 41862306a36Sopenharmony_ci struct bitmap *bitmap, unsigned long count, struct page *page) 41962306a36Sopenharmony_ci{ 42062306a36Sopenharmony_ci return -EIO; 42162306a36Sopenharmony_ci} 42262306a36Sopenharmony_cistatic void free_buffers(struct page *page) 42362306a36Sopenharmony_ci{ 42462306a36Sopenharmony_ci put_page(page); 42562306a36Sopenharmony_ci} 42662306a36Sopenharmony_ci#endif /* CONFIG_MD_BITMAP_FILE */ 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci/* 42962306a36Sopenharmony_ci * bitmap file superblock operations 43062306a36Sopenharmony_ci */ 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci/* 43362306a36Sopenharmony_ci * write out a page to a file 43462306a36Sopenharmony_ci */ 43562306a36Sopenharmony_cistatic void filemap_write_page(struct bitmap *bitmap, unsigned long pg_index, 43662306a36Sopenharmony_ci bool wait) 43762306a36Sopenharmony_ci{ 43862306a36Sopenharmony_ci struct bitmap_storage *store = &bitmap->storage; 43962306a36Sopenharmony_ci struct page *page = store->filemap[pg_index]; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci if (mddev_is_clustered(bitmap->mddev)) { 44262306a36Sopenharmony_ci /* go to node bitmap area starting point */ 44362306a36Sopenharmony_ci pg_index += store->sb_index; 44462306a36Sopenharmony_ci } 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci if (store->file) 44762306a36Sopenharmony_ci write_file_page(bitmap, page, wait); 44862306a36Sopenharmony_ci else 44962306a36Sopenharmony_ci write_sb_page(bitmap, pg_index, page, wait); 45062306a36Sopenharmony_ci} 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci/* 45362306a36Sopenharmony_ci * md_bitmap_wait_writes() should be called before writing any bitmap 45462306a36Sopenharmony_ci * blocks, to ensure previous writes, particularly from 45562306a36Sopenharmony_ci * md_bitmap_daemon_work(), have completed. 45662306a36Sopenharmony_ci */ 45762306a36Sopenharmony_cistatic void md_bitmap_wait_writes(struct bitmap *bitmap) 45862306a36Sopenharmony_ci{ 45962306a36Sopenharmony_ci if (bitmap->storage.file) 46062306a36Sopenharmony_ci wait_event(bitmap->write_wait, 46162306a36Sopenharmony_ci atomic_read(&bitmap->pending_writes)==0); 46262306a36Sopenharmony_ci else 46362306a36Sopenharmony_ci /* Note that we ignore the return value. The writes 46462306a36Sopenharmony_ci * might have failed, but that would just mean that 46562306a36Sopenharmony_ci * some bits which should be cleared haven't been, 46662306a36Sopenharmony_ci * which is safe. The relevant bitmap blocks will 46762306a36Sopenharmony_ci * probably get written again, but there is no great 46862306a36Sopenharmony_ci * loss if they aren't. 46962306a36Sopenharmony_ci */ 47062306a36Sopenharmony_ci md_super_wait(bitmap->mddev); 47162306a36Sopenharmony_ci} 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci/* update the event counter and sync the superblock to disk */ 47562306a36Sopenharmony_civoid md_bitmap_update_sb(struct bitmap *bitmap) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci bitmap_super_t *sb; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci if (!bitmap || !bitmap->mddev) /* no bitmap for this array */ 48062306a36Sopenharmony_ci return; 48162306a36Sopenharmony_ci if (bitmap->mddev->bitmap_info.external) 48262306a36Sopenharmony_ci return; 48362306a36Sopenharmony_ci if (!bitmap->storage.sb_page) /* no superblock */ 48462306a36Sopenharmony_ci return; 48562306a36Sopenharmony_ci sb = kmap_atomic(bitmap->storage.sb_page); 48662306a36Sopenharmony_ci sb->events = cpu_to_le64(bitmap->mddev->events); 48762306a36Sopenharmony_ci if (bitmap->mddev->events < bitmap->events_cleared) 48862306a36Sopenharmony_ci /* rocking back to read-only */ 48962306a36Sopenharmony_ci bitmap->events_cleared = bitmap->mddev->events; 49062306a36Sopenharmony_ci sb->events_cleared = cpu_to_le64(bitmap->events_cleared); 49162306a36Sopenharmony_ci /* 49262306a36Sopenharmony_ci * clear BITMAP_WRITE_ERROR bit to protect against the case that 49362306a36Sopenharmony_ci * a bitmap write error occurred but the later writes succeeded. 49462306a36Sopenharmony_ci */ 49562306a36Sopenharmony_ci sb->state = cpu_to_le32(bitmap->flags & ~BIT(BITMAP_WRITE_ERROR)); 49662306a36Sopenharmony_ci /* Just in case these have been changed via sysfs: */ 49762306a36Sopenharmony_ci sb->daemon_sleep = cpu_to_le32(bitmap->mddev->bitmap_info.daemon_sleep/HZ); 49862306a36Sopenharmony_ci sb->write_behind = cpu_to_le32(bitmap->mddev->bitmap_info.max_write_behind); 49962306a36Sopenharmony_ci /* This might have been changed by a reshape */ 50062306a36Sopenharmony_ci sb->sync_size = cpu_to_le64(bitmap->mddev->resync_max_sectors); 50162306a36Sopenharmony_ci sb->chunksize = cpu_to_le32(bitmap->mddev->bitmap_info.chunksize); 50262306a36Sopenharmony_ci sb->nodes = cpu_to_le32(bitmap->mddev->bitmap_info.nodes); 50362306a36Sopenharmony_ci sb->sectors_reserved = cpu_to_le32(bitmap->mddev-> 50462306a36Sopenharmony_ci bitmap_info.space); 50562306a36Sopenharmony_ci kunmap_atomic(sb); 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci if (bitmap->storage.file) 50862306a36Sopenharmony_ci write_file_page(bitmap, bitmap->storage.sb_page, 1); 50962306a36Sopenharmony_ci else 51062306a36Sopenharmony_ci write_sb_page(bitmap, bitmap->storage.sb_index, 51162306a36Sopenharmony_ci bitmap->storage.sb_page, 1); 51262306a36Sopenharmony_ci} 51362306a36Sopenharmony_ciEXPORT_SYMBOL(md_bitmap_update_sb); 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci/* print out the bitmap file superblock */ 51662306a36Sopenharmony_civoid md_bitmap_print_sb(struct bitmap *bitmap) 51762306a36Sopenharmony_ci{ 51862306a36Sopenharmony_ci bitmap_super_t *sb; 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci if (!bitmap || !bitmap->storage.sb_page) 52162306a36Sopenharmony_ci return; 52262306a36Sopenharmony_ci sb = kmap_atomic(bitmap->storage.sb_page); 52362306a36Sopenharmony_ci pr_debug("%s: bitmap file superblock:\n", bmname(bitmap)); 52462306a36Sopenharmony_ci pr_debug(" magic: %08x\n", le32_to_cpu(sb->magic)); 52562306a36Sopenharmony_ci pr_debug(" version: %u\n", le32_to_cpu(sb->version)); 52662306a36Sopenharmony_ci pr_debug(" uuid: %08x.%08x.%08x.%08x\n", 52762306a36Sopenharmony_ci le32_to_cpu(*(__le32 *)(sb->uuid+0)), 52862306a36Sopenharmony_ci le32_to_cpu(*(__le32 *)(sb->uuid+4)), 52962306a36Sopenharmony_ci le32_to_cpu(*(__le32 *)(sb->uuid+8)), 53062306a36Sopenharmony_ci le32_to_cpu(*(__le32 *)(sb->uuid+12))); 53162306a36Sopenharmony_ci pr_debug(" events: %llu\n", 53262306a36Sopenharmony_ci (unsigned long long) le64_to_cpu(sb->events)); 53362306a36Sopenharmony_ci pr_debug("events cleared: %llu\n", 53462306a36Sopenharmony_ci (unsigned long long) le64_to_cpu(sb->events_cleared)); 53562306a36Sopenharmony_ci pr_debug(" state: %08x\n", le32_to_cpu(sb->state)); 53662306a36Sopenharmony_ci pr_debug(" chunksize: %u B\n", le32_to_cpu(sb->chunksize)); 53762306a36Sopenharmony_ci pr_debug(" daemon sleep: %us\n", le32_to_cpu(sb->daemon_sleep)); 53862306a36Sopenharmony_ci pr_debug(" sync size: %llu KB\n", 53962306a36Sopenharmony_ci (unsigned long long)le64_to_cpu(sb->sync_size)/2); 54062306a36Sopenharmony_ci pr_debug("max write behind: %u\n", le32_to_cpu(sb->write_behind)); 54162306a36Sopenharmony_ci kunmap_atomic(sb); 54262306a36Sopenharmony_ci} 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci/* 54562306a36Sopenharmony_ci * bitmap_new_disk_sb 54662306a36Sopenharmony_ci * @bitmap 54762306a36Sopenharmony_ci * 54862306a36Sopenharmony_ci * This function is somewhat the reverse of bitmap_read_sb. bitmap_read_sb 54962306a36Sopenharmony_ci * reads and verifies the on-disk bitmap superblock and populates bitmap_info. 55062306a36Sopenharmony_ci * This function verifies 'bitmap_info' and populates the on-disk bitmap 55162306a36Sopenharmony_ci * structure, which is to be written to disk. 55262306a36Sopenharmony_ci * 55362306a36Sopenharmony_ci * Returns: 0 on success, -Exxx on error 55462306a36Sopenharmony_ci */ 55562306a36Sopenharmony_cistatic int md_bitmap_new_disk_sb(struct bitmap *bitmap) 55662306a36Sopenharmony_ci{ 55762306a36Sopenharmony_ci bitmap_super_t *sb; 55862306a36Sopenharmony_ci unsigned long chunksize, daemon_sleep, write_behind; 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci bitmap->storage.sb_page = alloc_page(GFP_KERNEL | __GFP_ZERO); 56162306a36Sopenharmony_ci if (bitmap->storage.sb_page == NULL) 56262306a36Sopenharmony_ci return -ENOMEM; 56362306a36Sopenharmony_ci bitmap->storage.sb_index = 0; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci sb = kmap_atomic(bitmap->storage.sb_page); 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci sb->magic = cpu_to_le32(BITMAP_MAGIC); 56862306a36Sopenharmony_ci sb->version = cpu_to_le32(BITMAP_MAJOR_HI); 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci chunksize = bitmap->mddev->bitmap_info.chunksize; 57162306a36Sopenharmony_ci BUG_ON(!chunksize); 57262306a36Sopenharmony_ci if (!is_power_of_2(chunksize)) { 57362306a36Sopenharmony_ci kunmap_atomic(sb); 57462306a36Sopenharmony_ci pr_warn("bitmap chunksize not a power of 2\n"); 57562306a36Sopenharmony_ci return -EINVAL; 57662306a36Sopenharmony_ci } 57762306a36Sopenharmony_ci sb->chunksize = cpu_to_le32(chunksize); 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci daemon_sleep = bitmap->mddev->bitmap_info.daemon_sleep; 58062306a36Sopenharmony_ci if (!daemon_sleep || (daemon_sleep > MAX_SCHEDULE_TIMEOUT)) { 58162306a36Sopenharmony_ci pr_debug("Choosing daemon_sleep default (5 sec)\n"); 58262306a36Sopenharmony_ci daemon_sleep = 5 * HZ; 58362306a36Sopenharmony_ci } 58462306a36Sopenharmony_ci sb->daemon_sleep = cpu_to_le32(daemon_sleep); 58562306a36Sopenharmony_ci bitmap->mddev->bitmap_info.daemon_sleep = daemon_sleep; 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci /* 58862306a36Sopenharmony_ci * FIXME: write_behind for RAID1. If not specified, what 58962306a36Sopenharmony_ci * is a good choice? We choose COUNTER_MAX / 2 arbitrarily. 59062306a36Sopenharmony_ci */ 59162306a36Sopenharmony_ci write_behind = bitmap->mddev->bitmap_info.max_write_behind; 59262306a36Sopenharmony_ci if (write_behind > COUNTER_MAX) 59362306a36Sopenharmony_ci write_behind = COUNTER_MAX / 2; 59462306a36Sopenharmony_ci sb->write_behind = cpu_to_le32(write_behind); 59562306a36Sopenharmony_ci bitmap->mddev->bitmap_info.max_write_behind = write_behind; 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci /* keep the array size field of the bitmap superblock up to date */ 59862306a36Sopenharmony_ci sb->sync_size = cpu_to_le64(bitmap->mddev->resync_max_sectors); 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci memcpy(sb->uuid, bitmap->mddev->uuid, 16); 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci set_bit(BITMAP_STALE, &bitmap->flags); 60362306a36Sopenharmony_ci sb->state = cpu_to_le32(bitmap->flags); 60462306a36Sopenharmony_ci bitmap->events_cleared = bitmap->mddev->events; 60562306a36Sopenharmony_ci sb->events_cleared = cpu_to_le64(bitmap->mddev->events); 60662306a36Sopenharmony_ci bitmap->mddev->bitmap_info.nodes = 0; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci kunmap_atomic(sb); 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci return 0; 61162306a36Sopenharmony_ci} 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci/* read the superblock from the bitmap file and initialize some bitmap fields */ 61462306a36Sopenharmony_cistatic int md_bitmap_read_sb(struct bitmap *bitmap) 61562306a36Sopenharmony_ci{ 61662306a36Sopenharmony_ci char *reason = NULL; 61762306a36Sopenharmony_ci bitmap_super_t *sb; 61862306a36Sopenharmony_ci unsigned long chunksize, daemon_sleep, write_behind; 61962306a36Sopenharmony_ci unsigned long long events; 62062306a36Sopenharmony_ci int nodes = 0; 62162306a36Sopenharmony_ci unsigned long sectors_reserved = 0; 62262306a36Sopenharmony_ci int err = -EINVAL; 62362306a36Sopenharmony_ci struct page *sb_page; 62462306a36Sopenharmony_ci loff_t offset = 0; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci if (!bitmap->storage.file && !bitmap->mddev->bitmap_info.offset) { 62762306a36Sopenharmony_ci chunksize = 128 * 1024 * 1024; 62862306a36Sopenharmony_ci daemon_sleep = 5 * HZ; 62962306a36Sopenharmony_ci write_behind = 0; 63062306a36Sopenharmony_ci set_bit(BITMAP_STALE, &bitmap->flags); 63162306a36Sopenharmony_ci err = 0; 63262306a36Sopenharmony_ci goto out_no_sb; 63362306a36Sopenharmony_ci } 63462306a36Sopenharmony_ci /* page 0 is the superblock, read it... */ 63562306a36Sopenharmony_ci sb_page = alloc_page(GFP_KERNEL); 63662306a36Sopenharmony_ci if (!sb_page) 63762306a36Sopenharmony_ci return -ENOMEM; 63862306a36Sopenharmony_ci bitmap->storage.sb_page = sb_page; 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_cire_read: 64162306a36Sopenharmony_ci /* If cluster_slot is set, the cluster is setup */ 64262306a36Sopenharmony_ci if (bitmap->cluster_slot >= 0) { 64362306a36Sopenharmony_ci sector_t bm_blocks = bitmap->mddev->resync_max_sectors; 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci bm_blocks = DIV_ROUND_UP_SECTOR_T(bm_blocks, 64662306a36Sopenharmony_ci (bitmap->mddev->bitmap_info.chunksize >> 9)); 64762306a36Sopenharmony_ci /* bits to bytes */ 64862306a36Sopenharmony_ci bm_blocks = ((bm_blocks+7) >> 3) + sizeof(bitmap_super_t); 64962306a36Sopenharmony_ci /* to 4k blocks */ 65062306a36Sopenharmony_ci bm_blocks = DIV_ROUND_UP_SECTOR_T(bm_blocks, 4096); 65162306a36Sopenharmony_ci offset = bitmap->cluster_slot * (bm_blocks << 3); 65262306a36Sopenharmony_ci pr_debug("%s:%d bm slot: %d offset: %llu\n", __func__, __LINE__, 65362306a36Sopenharmony_ci bitmap->cluster_slot, offset); 65462306a36Sopenharmony_ci } 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci if (bitmap->storage.file) { 65762306a36Sopenharmony_ci loff_t isize = i_size_read(bitmap->storage.file->f_mapping->host); 65862306a36Sopenharmony_ci int bytes = isize > PAGE_SIZE ? PAGE_SIZE : isize; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci err = read_file_page(bitmap->storage.file, 0, 66162306a36Sopenharmony_ci bitmap, bytes, sb_page); 66262306a36Sopenharmony_ci } else { 66362306a36Sopenharmony_ci err = read_sb_page(bitmap->mddev, offset, sb_page, 0, 66462306a36Sopenharmony_ci sizeof(bitmap_super_t)); 66562306a36Sopenharmony_ci } 66662306a36Sopenharmony_ci if (err) 66762306a36Sopenharmony_ci return err; 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci err = -EINVAL; 67062306a36Sopenharmony_ci sb = kmap_atomic(sb_page); 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci chunksize = le32_to_cpu(sb->chunksize); 67362306a36Sopenharmony_ci daemon_sleep = le32_to_cpu(sb->daemon_sleep) * HZ; 67462306a36Sopenharmony_ci write_behind = le32_to_cpu(sb->write_behind); 67562306a36Sopenharmony_ci sectors_reserved = le32_to_cpu(sb->sectors_reserved); 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci /* verify that the bitmap-specific fields are valid */ 67862306a36Sopenharmony_ci if (sb->magic != cpu_to_le32(BITMAP_MAGIC)) 67962306a36Sopenharmony_ci reason = "bad magic"; 68062306a36Sopenharmony_ci else if (le32_to_cpu(sb->version) < BITMAP_MAJOR_LO || 68162306a36Sopenharmony_ci le32_to_cpu(sb->version) > BITMAP_MAJOR_CLUSTERED) 68262306a36Sopenharmony_ci reason = "unrecognized superblock version"; 68362306a36Sopenharmony_ci else if (chunksize < 512) 68462306a36Sopenharmony_ci reason = "bitmap chunksize too small"; 68562306a36Sopenharmony_ci else if (!is_power_of_2(chunksize)) 68662306a36Sopenharmony_ci reason = "bitmap chunksize not a power of 2"; 68762306a36Sopenharmony_ci else if (daemon_sleep < 1 || daemon_sleep > MAX_SCHEDULE_TIMEOUT) 68862306a36Sopenharmony_ci reason = "daemon sleep period out of range"; 68962306a36Sopenharmony_ci else if (write_behind > COUNTER_MAX) 69062306a36Sopenharmony_ci reason = "write-behind limit out of range (0 - 16383)"; 69162306a36Sopenharmony_ci if (reason) { 69262306a36Sopenharmony_ci pr_warn("%s: invalid bitmap file superblock: %s\n", 69362306a36Sopenharmony_ci bmname(bitmap), reason); 69462306a36Sopenharmony_ci goto out; 69562306a36Sopenharmony_ci } 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci /* 69862306a36Sopenharmony_ci * Setup nodes/clustername only if bitmap version is 69962306a36Sopenharmony_ci * cluster-compatible 70062306a36Sopenharmony_ci */ 70162306a36Sopenharmony_ci if (sb->version == cpu_to_le32(BITMAP_MAJOR_CLUSTERED)) { 70262306a36Sopenharmony_ci nodes = le32_to_cpu(sb->nodes); 70362306a36Sopenharmony_ci strscpy(bitmap->mddev->bitmap_info.cluster_name, 70462306a36Sopenharmony_ci sb->cluster_name, 64); 70562306a36Sopenharmony_ci } 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci /* keep the array size field of the bitmap superblock up to date */ 70862306a36Sopenharmony_ci sb->sync_size = cpu_to_le64(bitmap->mddev->resync_max_sectors); 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci if (bitmap->mddev->persistent) { 71162306a36Sopenharmony_ci /* 71262306a36Sopenharmony_ci * We have a persistent array superblock, so compare the 71362306a36Sopenharmony_ci * bitmap's UUID and event counter to the mddev's 71462306a36Sopenharmony_ci */ 71562306a36Sopenharmony_ci if (memcmp(sb->uuid, bitmap->mddev->uuid, 16)) { 71662306a36Sopenharmony_ci pr_warn("%s: bitmap superblock UUID mismatch\n", 71762306a36Sopenharmony_ci bmname(bitmap)); 71862306a36Sopenharmony_ci goto out; 71962306a36Sopenharmony_ci } 72062306a36Sopenharmony_ci events = le64_to_cpu(sb->events); 72162306a36Sopenharmony_ci if (!nodes && (events < bitmap->mddev->events)) { 72262306a36Sopenharmony_ci pr_warn("%s: bitmap file is out of date (%llu < %llu) -- forcing full recovery\n", 72362306a36Sopenharmony_ci bmname(bitmap), events, 72462306a36Sopenharmony_ci (unsigned long long) bitmap->mddev->events); 72562306a36Sopenharmony_ci set_bit(BITMAP_STALE, &bitmap->flags); 72662306a36Sopenharmony_ci } 72762306a36Sopenharmony_ci } 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci /* assign fields using values from superblock */ 73062306a36Sopenharmony_ci bitmap->flags |= le32_to_cpu(sb->state); 73162306a36Sopenharmony_ci if (le32_to_cpu(sb->version) == BITMAP_MAJOR_HOSTENDIAN) 73262306a36Sopenharmony_ci set_bit(BITMAP_HOSTENDIAN, &bitmap->flags); 73362306a36Sopenharmony_ci bitmap->events_cleared = le64_to_cpu(sb->events_cleared); 73462306a36Sopenharmony_ci err = 0; 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ciout: 73762306a36Sopenharmony_ci kunmap_atomic(sb); 73862306a36Sopenharmony_ci if (err == 0 && nodes && (bitmap->cluster_slot < 0)) { 73962306a36Sopenharmony_ci /* Assigning chunksize is required for "re_read" */ 74062306a36Sopenharmony_ci bitmap->mddev->bitmap_info.chunksize = chunksize; 74162306a36Sopenharmony_ci err = md_setup_cluster(bitmap->mddev, nodes); 74262306a36Sopenharmony_ci if (err) { 74362306a36Sopenharmony_ci pr_warn("%s: Could not setup cluster service (%d)\n", 74462306a36Sopenharmony_ci bmname(bitmap), err); 74562306a36Sopenharmony_ci goto out_no_sb; 74662306a36Sopenharmony_ci } 74762306a36Sopenharmony_ci bitmap->cluster_slot = md_cluster_ops->slot_number(bitmap->mddev); 74862306a36Sopenharmony_ci goto re_read; 74962306a36Sopenharmony_ci } 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ciout_no_sb: 75262306a36Sopenharmony_ci if (err == 0) { 75362306a36Sopenharmony_ci if (test_bit(BITMAP_STALE, &bitmap->flags)) 75462306a36Sopenharmony_ci bitmap->events_cleared = bitmap->mddev->events; 75562306a36Sopenharmony_ci bitmap->mddev->bitmap_info.chunksize = chunksize; 75662306a36Sopenharmony_ci bitmap->mddev->bitmap_info.daemon_sleep = daemon_sleep; 75762306a36Sopenharmony_ci bitmap->mddev->bitmap_info.max_write_behind = write_behind; 75862306a36Sopenharmony_ci bitmap->mddev->bitmap_info.nodes = nodes; 75962306a36Sopenharmony_ci if (bitmap->mddev->bitmap_info.space == 0 || 76062306a36Sopenharmony_ci bitmap->mddev->bitmap_info.space > sectors_reserved) 76162306a36Sopenharmony_ci bitmap->mddev->bitmap_info.space = sectors_reserved; 76262306a36Sopenharmony_ci } else { 76362306a36Sopenharmony_ci md_bitmap_print_sb(bitmap); 76462306a36Sopenharmony_ci if (bitmap->cluster_slot < 0) 76562306a36Sopenharmony_ci md_cluster_stop(bitmap->mddev); 76662306a36Sopenharmony_ci } 76762306a36Sopenharmony_ci return err; 76862306a36Sopenharmony_ci} 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci/* 77162306a36Sopenharmony_ci * general bitmap file operations 77262306a36Sopenharmony_ci */ 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci/* 77562306a36Sopenharmony_ci * on-disk bitmap: 77662306a36Sopenharmony_ci * 77762306a36Sopenharmony_ci * Use one bit per "chunk" (block set). We do the disk I/O on the bitmap 77862306a36Sopenharmony_ci * file a page at a time. There's a superblock at the start of the file. 77962306a36Sopenharmony_ci */ 78062306a36Sopenharmony_ci/* calculate the index of the page that contains this bit */ 78162306a36Sopenharmony_cistatic inline unsigned long file_page_index(struct bitmap_storage *store, 78262306a36Sopenharmony_ci unsigned long chunk) 78362306a36Sopenharmony_ci{ 78462306a36Sopenharmony_ci if (store->sb_page) 78562306a36Sopenharmony_ci chunk += sizeof(bitmap_super_t) << 3; 78662306a36Sopenharmony_ci return chunk >> PAGE_BIT_SHIFT; 78762306a36Sopenharmony_ci} 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci/* calculate the (bit) offset of this bit within a page */ 79062306a36Sopenharmony_cistatic inline unsigned long file_page_offset(struct bitmap_storage *store, 79162306a36Sopenharmony_ci unsigned long chunk) 79262306a36Sopenharmony_ci{ 79362306a36Sopenharmony_ci if (store->sb_page) 79462306a36Sopenharmony_ci chunk += sizeof(bitmap_super_t) << 3; 79562306a36Sopenharmony_ci return chunk & (PAGE_BITS - 1); 79662306a36Sopenharmony_ci} 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci/* 79962306a36Sopenharmony_ci * return a pointer to the page in the filemap that contains the given bit 80062306a36Sopenharmony_ci * 80162306a36Sopenharmony_ci */ 80262306a36Sopenharmony_cistatic inline struct page *filemap_get_page(struct bitmap_storage *store, 80362306a36Sopenharmony_ci unsigned long chunk) 80462306a36Sopenharmony_ci{ 80562306a36Sopenharmony_ci if (file_page_index(store, chunk) >= store->file_pages) 80662306a36Sopenharmony_ci return NULL; 80762306a36Sopenharmony_ci return store->filemap[file_page_index(store, chunk)]; 80862306a36Sopenharmony_ci} 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_cistatic int md_bitmap_storage_alloc(struct bitmap_storage *store, 81162306a36Sopenharmony_ci unsigned long chunks, int with_super, 81262306a36Sopenharmony_ci int slot_number) 81362306a36Sopenharmony_ci{ 81462306a36Sopenharmony_ci int pnum, offset = 0; 81562306a36Sopenharmony_ci unsigned long num_pages; 81662306a36Sopenharmony_ci unsigned long bytes; 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci bytes = DIV_ROUND_UP(chunks, 8); 81962306a36Sopenharmony_ci if (with_super) 82062306a36Sopenharmony_ci bytes += sizeof(bitmap_super_t); 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci num_pages = DIV_ROUND_UP(bytes, PAGE_SIZE); 82362306a36Sopenharmony_ci offset = slot_number * num_pages; 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci store->filemap = kmalloc_array(num_pages, sizeof(struct page *), 82662306a36Sopenharmony_ci GFP_KERNEL); 82762306a36Sopenharmony_ci if (!store->filemap) 82862306a36Sopenharmony_ci return -ENOMEM; 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci if (with_super && !store->sb_page) { 83162306a36Sopenharmony_ci store->sb_page = alloc_page(GFP_KERNEL|__GFP_ZERO); 83262306a36Sopenharmony_ci if (store->sb_page == NULL) 83362306a36Sopenharmony_ci return -ENOMEM; 83462306a36Sopenharmony_ci } 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci pnum = 0; 83762306a36Sopenharmony_ci if (store->sb_page) { 83862306a36Sopenharmony_ci store->filemap[0] = store->sb_page; 83962306a36Sopenharmony_ci pnum = 1; 84062306a36Sopenharmony_ci store->sb_index = offset; 84162306a36Sopenharmony_ci } 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ci for ( ; pnum < num_pages; pnum++) { 84462306a36Sopenharmony_ci store->filemap[pnum] = alloc_page(GFP_KERNEL|__GFP_ZERO); 84562306a36Sopenharmony_ci if (!store->filemap[pnum]) { 84662306a36Sopenharmony_ci store->file_pages = pnum; 84762306a36Sopenharmony_ci return -ENOMEM; 84862306a36Sopenharmony_ci } 84962306a36Sopenharmony_ci } 85062306a36Sopenharmony_ci store->file_pages = pnum; 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci /* We need 4 bits per page, rounded up to a multiple 85362306a36Sopenharmony_ci * of sizeof(unsigned long) */ 85462306a36Sopenharmony_ci store->filemap_attr = kzalloc( 85562306a36Sopenharmony_ci roundup(DIV_ROUND_UP(num_pages*4, 8), sizeof(unsigned long)), 85662306a36Sopenharmony_ci GFP_KERNEL); 85762306a36Sopenharmony_ci if (!store->filemap_attr) 85862306a36Sopenharmony_ci return -ENOMEM; 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci store->bytes = bytes; 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci return 0; 86362306a36Sopenharmony_ci} 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_cistatic void md_bitmap_file_unmap(struct bitmap_storage *store) 86662306a36Sopenharmony_ci{ 86762306a36Sopenharmony_ci struct file *file = store->file; 86862306a36Sopenharmony_ci struct page *sb_page = store->sb_page; 86962306a36Sopenharmony_ci struct page **map = store->filemap; 87062306a36Sopenharmony_ci int pages = store->file_pages; 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci while (pages--) 87362306a36Sopenharmony_ci if (map[pages] != sb_page) /* 0 is sb_page, release it below */ 87462306a36Sopenharmony_ci free_buffers(map[pages]); 87562306a36Sopenharmony_ci kfree(map); 87662306a36Sopenharmony_ci kfree(store->filemap_attr); 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci if (sb_page) 87962306a36Sopenharmony_ci free_buffers(sb_page); 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ci if (file) { 88262306a36Sopenharmony_ci struct inode *inode = file_inode(file); 88362306a36Sopenharmony_ci invalidate_mapping_pages(inode->i_mapping, 0, -1); 88462306a36Sopenharmony_ci fput(file); 88562306a36Sopenharmony_ci } 88662306a36Sopenharmony_ci} 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ci/* 88962306a36Sopenharmony_ci * bitmap_file_kick - if an error occurs while manipulating the bitmap file 89062306a36Sopenharmony_ci * then it is no longer reliable, so we stop using it and we mark the file 89162306a36Sopenharmony_ci * as failed in the superblock 89262306a36Sopenharmony_ci */ 89362306a36Sopenharmony_cistatic void md_bitmap_file_kick(struct bitmap *bitmap) 89462306a36Sopenharmony_ci{ 89562306a36Sopenharmony_ci if (!test_and_set_bit(BITMAP_STALE, &bitmap->flags)) { 89662306a36Sopenharmony_ci md_bitmap_update_sb(bitmap); 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci if (bitmap->storage.file) { 89962306a36Sopenharmony_ci pr_warn("%s: kicking failed bitmap file %pD4 from array!\n", 90062306a36Sopenharmony_ci bmname(bitmap), bitmap->storage.file); 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_ci } else 90362306a36Sopenharmony_ci pr_warn("%s: disabling internal bitmap due to errors\n", 90462306a36Sopenharmony_ci bmname(bitmap)); 90562306a36Sopenharmony_ci } 90662306a36Sopenharmony_ci} 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_cienum bitmap_page_attr { 90962306a36Sopenharmony_ci BITMAP_PAGE_DIRTY = 0, /* there are set bits that need to be synced */ 91062306a36Sopenharmony_ci BITMAP_PAGE_PENDING = 1, /* there are bits that are being cleaned. 91162306a36Sopenharmony_ci * i.e. counter is 1 or 2. */ 91262306a36Sopenharmony_ci BITMAP_PAGE_NEEDWRITE = 2, /* there are cleared bits that need to be synced */ 91362306a36Sopenharmony_ci}; 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_cistatic inline void set_page_attr(struct bitmap *bitmap, int pnum, 91662306a36Sopenharmony_ci enum bitmap_page_attr attr) 91762306a36Sopenharmony_ci{ 91862306a36Sopenharmony_ci set_bit((pnum<<2) + attr, bitmap->storage.filemap_attr); 91962306a36Sopenharmony_ci} 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_cistatic inline void clear_page_attr(struct bitmap *bitmap, int pnum, 92262306a36Sopenharmony_ci enum bitmap_page_attr attr) 92362306a36Sopenharmony_ci{ 92462306a36Sopenharmony_ci clear_bit((pnum<<2) + attr, bitmap->storage.filemap_attr); 92562306a36Sopenharmony_ci} 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_cistatic inline int test_page_attr(struct bitmap *bitmap, int pnum, 92862306a36Sopenharmony_ci enum bitmap_page_attr attr) 92962306a36Sopenharmony_ci{ 93062306a36Sopenharmony_ci return test_bit((pnum<<2) + attr, bitmap->storage.filemap_attr); 93162306a36Sopenharmony_ci} 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_cistatic inline int test_and_clear_page_attr(struct bitmap *bitmap, int pnum, 93462306a36Sopenharmony_ci enum bitmap_page_attr attr) 93562306a36Sopenharmony_ci{ 93662306a36Sopenharmony_ci return test_and_clear_bit((pnum<<2) + attr, 93762306a36Sopenharmony_ci bitmap->storage.filemap_attr); 93862306a36Sopenharmony_ci} 93962306a36Sopenharmony_ci/* 94062306a36Sopenharmony_ci * bitmap_file_set_bit -- called before performing a write to the md device 94162306a36Sopenharmony_ci * to set (and eventually sync) a particular bit in the bitmap file 94262306a36Sopenharmony_ci * 94362306a36Sopenharmony_ci * we set the bit immediately, then we record the page number so that 94462306a36Sopenharmony_ci * when an unplug occurs, we can flush the dirty pages out to disk 94562306a36Sopenharmony_ci */ 94662306a36Sopenharmony_cistatic void md_bitmap_file_set_bit(struct bitmap *bitmap, sector_t block) 94762306a36Sopenharmony_ci{ 94862306a36Sopenharmony_ci unsigned long bit; 94962306a36Sopenharmony_ci struct page *page; 95062306a36Sopenharmony_ci void *kaddr; 95162306a36Sopenharmony_ci unsigned long chunk = block >> bitmap->counts.chunkshift; 95262306a36Sopenharmony_ci struct bitmap_storage *store = &bitmap->storage; 95362306a36Sopenharmony_ci unsigned long index = file_page_index(store, chunk); 95462306a36Sopenharmony_ci unsigned long node_offset = 0; 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci index += store->sb_index; 95762306a36Sopenharmony_ci if (mddev_is_clustered(bitmap->mddev)) 95862306a36Sopenharmony_ci node_offset = bitmap->cluster_slot * store->file_pages; 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci page = filemap_get_page(&bitmap->storage, chunk); 96162306a36Sopenharmony_ci if (!page) 96262306a36Sopenharmony_ci return; 96362306a36Sopenharmony_ci bit = file_page_offset(&bitmap->storage, chunk); 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci /* set the bit */ 96662306a36Sopenharmony_ci kaddr = kmap_atomic(page); 96762306a36Sopenharmony_ci if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags)) 96862306a36Sopenharmony_ci set_bit(bit, kaddr); 96962306a36Sopenharmony_ci else 97062306a36Sopenharmony_ci set_bit_le(bit, kaddr); 97162306a36Sopenharmony_ci kunmap_atomic(kaddr); 97262306a36Sopenharmony_ci pr_debug("set file bit %lu page %lu\n", bit, index); 97362306a36Sopenharmony_ci /* record page number so it gets flushed to disk when unplug occurs */ 97462306a36Sopenharmony_ci set_page_attr(bitmap, index - node_offset, BITMAP_PAGE_DIRTY); 97562306a36Sopenharmony_ci} 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_cistatic void md_bitmap_file_clear_bit(struct bitmap *bitmap, sector_t block) 97862306a36Sopenharmony_ci{ 97962306a36Sopenharmony_ci unsigned long bit; 98062306a36Sopenharmony_ci struct page *page; 98162306a36Sopenharmony_ci void *paddr; 98262306a36Sopenharmony_ci unsigned long chunk = block >> bitmap->counts.chunkshift; 98362306a36Sopenharmony_ci struct bitmap_storage *store = &bitmap->storage; 98462306a36Sopenharmony_ci unsigned long index = file_page_index(store, chunk); 98562306a36Sopenharmony_ci unsigned long node_offset = 0; 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci index += store->sb_index; 98862306a36Sopenharmony_ci if (mddev_is_clustered(bitmap->mddev)) 98962306a36Sopenharmony_ci node_offset = bitmap->cluster_slot * store->file_pages; 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci page = filemap_get_page(&bitmap->storage, chunk); 99262306a36Sopenharmony_ci if (!page) 99362306a36Sopenharmony_ci return; 99462306a36Sopenharmony_ci bit = file_page_offset(&bitmap->storage, chunk); 99562306a36Sopenharmony_ci paddr = kmap_atomic(page); 99662306a36Sopenharmony_ci if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags)) 99762306a36Sopenharmony_ci clear_bit(bit, paddr); 99862306a36Sopenharmony_ci else 99962306a36Sopenharmony_ci clear_bit_le(bit, paddr); 100062306a36Sopenharmony_ci kunmap_atomic(paddr); 100162306a36Sopenharmony_ci if (!test_page_attr(bitmap, index - node_offset, BITMAP_PAGE_NEEDWRITE)) { 100262306a36Sopenharmony_ci set_page_attr(bitmap, index - node_offset, BITMAP_PAGE_PENDING); 100362306a36Sopenharmony_ci bitmap->allclean = 0; 100462306a36Sopenharmony_ci } 100562306a36Sopenharmony_ci} 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_cistatic int md_bitmap_file_test_bit(struct bitmap *bitmap, sector_t block) 100862306a36Sopenharmony_ci{ 100962306a36Sopenharmony_ci unsigned long bit; 101062306a36Sopenharmony_ci struct page *page; 101162306a36Sopenharmony_ci void *paddr; 101262306a36Sopenharmony_ci unsigned long chunk = block >> bitmap->counts.chunkshift; 101362306a36Sopenharmony_ci int set = 0; 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ci page = filemap_get_page(&bitmap->storage, chunk); 101662306a36Sopenharmony_ci if (!page) 101762306a36Sopenharmony_ci return -EINVAL; 101862306a36Sopenharmony_ci bit = file_page_offset(&bitmap->storage, chunk); 101962306a36Sopenharmony_ci paddr = kmap_atomic(page); 102062306a36Sopenharmony_ci if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags)) 102162306a36Sopenharmony_ci set = test_bit(bit, paddr); 102262306a36Sopenharmony_ci else 102362306a36Sopenharmony_ci set = test_bit_le(bit, paddr); 102462306a36Sopenharmony_ci kunmap_atomic(paddr); 102562306a36Sopenharmony_ci return set; 102662306a36Sopenharmony_ci} 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci/* this gets called when the md device is ready to unplug its underlying 102962306a36Sopenharmony_ci * (slave) device queues -- before we let any writes go down, we need to 103062306a36Sopenharmony_ci * sync the dirty pages of the bitmap file to disk */ 103162306a36Sopenharmony_civoid md_bitmap_unplug(struct bitmap *bitmap) 103262306a36Sopenharmony_ci{ 103362306a36Sopenharmony_ci unsigned long i; 103462306a36Sopenharmony_ci int dirty, need_write; 103562306a36Sopenharmony_ci int writing = 0; 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci if (!md_bitmap_enabled(bitmap)) 103862306a36Sopenharmony_ci return; 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_ci /* look at each page to see if there are any set bits that need to be 104162306a36Sopenharmony_ci * flushed out to disk */ 104262306a36Sopenharmony_ci for (i = 0; i < bitmap->storage.file_pages; i++) { 104362306a36Sopenharmony_ci dirty = test_and_clear_page_attr(bitmap, i, BITMAP_PAGE_DIRTY); 104462306a36Sopenharmony_ci need_write = test_and_clear_page_attr(bitmap, i, 104562306a36Sopenharmony_ci BITMAP_PAGE_NEEDWRITE); 104662306a36Sopenharmony_ci if (dirty || need_write) { 104762306a36Sopenharmony_ci if (!writing) { 104862306a36Sopenharmony_ci md_bitmap_wait_writes(bitmap); 104962306a36Sopenharmony_ci if (bitmap->mddev->queue) 105062306a36Sopenharmony_ci blk_add_trace_msg(bitmap->mddev->queue, 105162306a36Sopenharmony_ci "md bitmap_unplug"); 105262306a36Sopenharmony_ci } 105362306a36Sopenharmony_ci clear_page_attr(bitmap, i, BITMAP_PAGE_PENDING); 105462306a36Sopenharmony_ci filemap_write_page(bitmap, i, false); 105562306a36Sopenharmony_ci writing = 1; 105662306a36Sopenharmony_ci } 105762306a36Sopenharmony_ci } 105862306a36Sopenharmony_ci if (writing) 105962306a36Sopenharmony_ci md_bitmap_wait_writes(bitmap); 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags)) 106262306a36Sopenharmony_ci md_bitmap_file_kick(bitmap); 106362306a36Sopenharmony_ci} 106462306a36Sopenharmony_ciEXPORT_SYMBOL(md_bitmap_unplug); 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_cistruct bitmap_unplug_work { 106762306a36Sopenharmony_ci struct work_struct work; 106862306a36Sopenharmony_ci struct bitmap *bitmap; 106962306a36Sopenharmony_ci struct completion *done; 107062306a36Sopenharmony_ci}; 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_cistatic void md_bitmap_unplug_fn(struct work_struct *work) 107362306a36Sopenharmony_ci{ 107462306a36Sopenharmony_ci struct bitmap_unplug_work *unplug_work = 107562306a36Sopenharmony_ci container_of(work, struct bitmap_unplug_work, work); 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci md_bitmap_unplug(unplug_work->bitmap); 107862306a36Sopenharmony_ci complete(unplug_work->done); 107962306a36Sopenharmony_ci} 108062306a36Sopenharmony_ci 108162306a36Sopenharmony_civoid md_bitmap_unplug_async(struct bitmap *bitmap) 108262306a36Sopenharmony_ci{ 108362306a36Sopenharmony_ci DECLARE_COMPLETION_ONSTACK(done); 108462306a36Sopenharmony_ci struct bitmap_unplug_work unplug_work; 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci INIT_WORK_ONSTACK(&unplug_work.work, md_bitmap_unplug_fn); 108762306a36Sopenharmony_ci unplug_work.bitmap = bitmap; 108862306a36Sopenharmony_ci unplug_work.done = &done; 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci queue_work(md_bitmap_wq, &unplug_work.work); 109162306a36Sopenharmony_ci wait_for_completion(&done); 109262306a36Sopenharmony_ci} 109362306a36Sopenharmony_ciEXPORT_SYMBOL(md_bitmap_unplug_async); 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_cistatic void md_bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed); 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci/* 109862306a36Sopenharmony_ci * Initialize the in-memory bitmap from the on-disk bitmap and set up the memory 109962306a36Sopenharmony_ci * mapping of the bitmap file. 110062306a36Sopenharmony_ci * 110162306a36Sopenharmony_ci * Special case: If there's no bitmap file, or if the bitmap file had been 110262306a36Sopenharmony_ci * previously kicked from the array, we mark all the bits as 1's in order to 110362306a36Sopenharmony_ci * cause a full resync. 110462306a36Sopenharmony_ci * 110562306a36Sopenharmony_ci * We ignore all bits for sectors that end earlier than 'start'. 110662306a36Sopenharmony_ci * This is used when reading an out-of-date bitmap. 110762306a36Sopenharmony_ci */ 110862306a36Sopenharmony_cistatic int md_bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) 110962306a36Sopenharmony_ci{ 111062306a36Sopenharmony_ci bool outofdate = test_bit(BITMAP_STALE, &bitmap->flags); 111162306a36Sopenharmony_ci struct mddev *mddev = bitmap->mddev; 111262306a36Sopenharmony_ci unsigned long chunks = bitmap->counts.chunks; 111362306a36Sopenharmony_ci struct bitmap_storage *store = &bitmap->storage; 111462306a36Sopenharmony_ci struct file *file = store->file; 111562306a36Sopenharmony_ci unsigned long node_offset = 0; 111662306a36Sopenharmony_ci unsigned long bit_cnt = 0; 111762306a36Sopenharmony_ci unsigned long i; 111862306a36Sopenharmony_ci int ret; 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci if (!file && !mddev->bitmap_info.offset) { 112162306a36Sopenharmony_ci /* No permanent bitmap - fill with '1s'. */ 112262306a36Sopenharmony_ci store->filemap = NULL; 112362306a36Sopenharmony_ci store->file_pages = 0; 112462306a36Sopenharmony_ci for (i = 0; i < chunks ; i++) { 112562306a36Sopenharmony_ci /* if the disk bit is set, set the memory bit */ 112662306a36Sopenharmony_ci int needed = ((sector_t)(i+1) << (bitmap->counts.chunkshift) 112762306a36Sopenharmony_ci >= start); 112862306a36Sopenharmony_ci md_bitmap_set_memory_bits(bitmap, 112962306a36Sopenharmony_ci (sector_t)i << bitmap->counts.chunkshift, 113062306a36Sopenharmony_ci needed); 113162306a36Sopenharmony_ci } 113262306a36Sopenharmony_ci return 0; 113362306a36Sopenharmony_ci } 113462306a36Sopenharmony_ci 113562306a36Sopenharmony_ci if (file && i_size_read(file->f_mapping->host) < store->bytes) { 113662306a36Sopenharmony_ci pr_warn("%s: bitmap file too short %lu < %lu\n", 113762306a36Sopenharmony_ci bmname(bitmap), 113862306a36Sopenharmony_ci (unsigned long) i_size_read(file->f_mapping->host), 113962306a36Sopenharmony_ci store->bytes); 114062306a36Sopenharmony_ci ret = -ENOSPC; 114162306a36Sopenharmony_ci goto err; 114262306a36Sopenharmony_ci } 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci if (mddev_is_clustered(mddev)) 114562306a36Sopenharmony_ci node_offset = bitmap->cluster_slot * (DIV_ROUND_UP(store->bytes, PAGE_SIZE)); 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci for (i = 0; i < store->file_pages; i++) { 114862306a36Sopenharmony_ci struct page *page = store->filemap[i]; 114962306a36Sopenharmony_ci int count; 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci /* unmap the old page, we're done with it */ 115262306a36Sopenharmony_ci if (i == store->file_pages - 1) 115362306a36Sopenharmony_ci count = store->bytes - i * PAGE_SIZE; 115462306a36Sopenharmony_ci else 115562306a36Sopenharmony_ci count = PAGE_SIZE; 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ci if (file) 115862306a36Sopenharmony_ci ret = read_file_page(file, i, bitmap, count, page); 115962306a36Sopenharmony_ci else 116062306a36Sopenharmony_ci ret = read_sb_page(mddev, 0, page, i + node_offset, 116162306a36Sopenharmony_ci count); 116262306a36Sopenharmony_ci if (ret) 116362306a36Sopenharmony_ci goto err; 116462306a36Sopenharmony_ci } 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_ci if (outofdate) { 116762306a36Sopenharmony_ci pr_warn("%s: bitmap file is out of date, doing full recovery\n", 116862306a36Sopenharmony_ci bmname(bitmap)); 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci for (i = 0; i < store->file_pages; i++) { 117162306a36Sopenharmony_ci struct page *page = store->filemap[i]; 117262306a36Sopenharmony_ci unsigned long offset = 0; 117362306a36Sopenharmony_ci void *paddr; 117462306a36Sopenharmony_ci 117562306a36Sopenharmony_ci if (i == 0 && !mddev->bitmap_info.external) 117662306a36Sopenharmony_ci offset = sizeof(bitmap_super_t); 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_ci /* 117962306a36Sopenharmony_ci * If the bitmap is out of date, dirty the whole page 118062306a36Sopenharmony_ci * and write it out 118162306a36Sopenharmony_ci */ 118262306a36Sopenharmony_ci paddr = kmap_atomic(page); 118362306a36Sopenharmony_ci memset(paddr + offset, 0xff, PAGE_SIZE - offset); 118462306a36Sopenharmony_ci kunmap_atomic(paddr); 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci filemap_write_page(bitmap, i, true); 118762306a36Sopenharmony_ci if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags)) { 118862306a36Sopenharmony_ci ret = -EIO; 118962306a36Sopenharmony_ci goto err; 119062306a36Sopenharmony_ci } 119162306a36Sopenharmony_ci } 119262306a36Sopenharmony_ci } 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci for (i = 0; i < chunks; i++) { 119562306a36Sopenharmony_ci struct page *page = filemap_get_page(&bitmap->storage, i); 119662306a36Sopenharmony_ci unsigned long bit = file_page_offset(&bitmap->storage, i); 119762306a36Sopenharmony_ci void *paddr; 119862306a36Sopenharmony_ci bool was_set; 119962306a36Sopenharmony_ci 120062306a36Sopenharmony_ci paddr = kmap_atomic(page); 120162306a36Sopenharmony_ci if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags)) 120262306a36Sopenharmony_ci was_set = test_bit(bit, paddr); 120362306a36Sopenharmony_ci else 120462306a36Sopenharmony_ci was_set = test_bit_le(bit, paddr); 120562306a36Sopenharmony_ci kunmap_atomic(paddr); 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci if (was_set) { 120862306a36Sopenharmony_ci /* if the disk bit is set, set the memory bit */ 120962306a36Sopenharmony_ci int needed = ((sector_t)(i+1) << bitmap->counts.chunkshift 121062306a36Sopenharmony_ci >= start); 121162306a36Sopenharmony_ci md_bitmap_set_memory_bits(bitmap, 121262306a36Sopenharmony_ci (sector_t)i << bitmap->counts.chunkshift, 121362306a36Sopenharmony_ci needed); 121462306a36Sopenharmony_ci bit_cnt++; 121562306a36Sopenharmony_ci } 121662306a36Sopenharmony_ci } 121762306a36Sopenharmony_ci 121862306a36Sopenharmony_ci pr_debug("%s: bitmap initialized from disk: read %lu pages, set %lu of %lu bits\n", 121962306a36Sopenharmony_ci bmname(bitmap), store->file_pages, 122062306a36Sopenharmony_ci bit_cnt, chunks); 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_ci return 0; 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_ci err: 122562306a36Sopenharmony_ci pr_warn("%s: bitmap initialisation failed: %d\n", 122662306a36Sopenharmony_ci bmname(bitmap), ret); 122762306a36Sopenharmony_ci return ret; 122862306a36Sopenharmony_ci} 122962306a36Sopenharmony_ci 123062306a36Sopenharmony_civoid md_bitmap_write_all(struct bitmap *bitmap) 123162306a36Sopenharmony_ci{ 123262306a36Sopenharmony_ci /* We don't actually write all bitmap blocks here, 123362306a36Sopenharmony_ci * just flag them as needing to be written 123462306a36Sopenharmony_ci */ 123562306a36Sopenharmony_ci int i; 123662306a36Sopenharmony_ci 123762306a36Sopenharmony_ci if (!bitmap || !bitmap->storage.filemap) 123862306a36Sopenharmony_ci return; 123962306a36Sopenharmony_ci if (bitmap->storage.file) 124062306a36Sopenharmony_ci /* Only one copy, so nothing needed */ 124162306a36Sopenharmony_ci return; 124262306a36Sopenharmony_ci 124362306a36Sopenharmony_ci for (i = 0; i < bitmap->storage.file_pages; i++) 124462306a36Sopenharmony_ci set_page_attr(bitmap, i, 124562306a36Sopenharmony_ci BITMAP_PAGE_NEEDWRITE); 124662306a36Sopenharmony_ci bitmap->allclean = 0; 124762306a36Sopenharmony_ci} 124862306a36Sopenharmony_ci 124962306a36Sopenharmony_cistatic void md_bitmap_count_page(struct bitmap_counts *bitmap, 125062306a36Sopenharmony_ci sector_t offset, int inc) 125162306a36Sopenharmony_ci{ 125262306a36Sopenharmony_ci sector_t chunk = offset >> bitmap->chunkshift; 125362306a36Sopenharmony_ci unsigned long page = chunk >> PAGE_COUNTER_SHIFT; 125462306a36Sopenharmony_ci bitmap->bp[page].count += inc; 125562306a36Sopenharmony_ci md_bitmap_checkfree(bitmap, page); 125662306a36Sopenharmony_ci} 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_cistatic void md_bitmap_set_pending(struct bitmap_counts *bitmap, sector_t offset) 125962306a36Sopenharmony_ci{ 126062306a36Sopenharmony_ci sector_t chunk = offset >> bitmap->chunkshift; 126162306a36Sopenharmony_ci unsigned long page = chunk >> PAGE_COUNTER_SHIFT; 126262306a36Sopenharmony_ci struct bitmap_page *bp = &bitmap->bp[page]; 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ci if (!bp->pending) 126562306a36Sopenharmony_ci bp->pending = 1; 126662306a36Sopenharmony_ci} 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_cistatic bitmap_counter_t *md_bitmap_get_counter(struct bitmap_counts *bitmap, 126962306a36Sopenharmony_ci sector_t offset, sector_t *blocks, 127062306a36Sopenharmony_ci int create); 127162306a36Sopenharmony_ci 127262306a36Sopenharmony_cistatic void mddev_set_timeout(struct mddev *mddev, unsigned long timeout, 127362306a36Sopenharmony_ci bool force) 127462306a36Sopenharmony_ci{ 127562306a36Sopenharmony_ci struct md_thread *thread; 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_ci rcu_read_lock(); 127862306a36Sopenharmony_ci thread = rcu_dereference(mddev->thread); 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_ci if (!thread) 128162306a36Sopenharmony_ci goto out; 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci if (force || thread->timeout < MAX_SCHEDULE_TIMEOUT) 128462306a36Sopenharmony_ci thread->timeout = timeout; 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_ciout: 128762306a36Sopenharmony_ci rcu_read_unlock(); 128862306a36Sopenharmony_ci} 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_ci/* 129162306a36Sopenharmony_ci * bitmap daemon -- periodically wakes up to clean bits and flush pages 129262306a36Sopenharmony_ci * out to disk 129362306a36Sopenharmony_ci */ 129462306a36Sopenharmony_civoid md_bitmap_daemon_work(struct mddev *mddev) 129562306a36Sopenharmony_ci{ 129662306a36Sopenharmony_ci struct bitmap *bitmap; 129762306a36Sopenharmony_ci unsigned long j; 129862306a36Sopenharmony_ci unsigned long nextpage; 129962306a36Sopenharmony_ci sector_t blocks; 130062306a36Sopenharmony_ci struct bitmap_counts *counts; 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_ci /* Use a mutex to guard daemon_work against 130362306a36Sopenharmony_ci * bitmap_destroy. 130462306a36Sopenharmony_ci */ 130562306a36Sopenharmony_ci mutex_lock(&mddev->bitmap_info.mutex); 130662306a36Sopenharmony_ci bitmap = mddev->bitmap; 130762306a36Sopenharmony_ci if (bitmap == NULL) { 130862306a36Sopenharmony_ci mutex_unlock(&mddev->bitmap_info.mutex); 130962306a36Sopenharmony_ci return; 131062306a36Sopenharmony_ci } 131162306a36Sopenharmony_ci if (time_before(jiffies, bitmap->daemon_lastrun 131262306a36Sopenharmony_ci + mddev->bitmap_info.daemon_sleep)) 131362306a36Sopenharmony_ci goto done; 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_ci bitmap->daemon_lastrun = jiffies; 131662306a36Sopenharmony_ci if (bitmap->allclean) { 131762306a36Sopenharmony_ci mddev_set_timeout(mddev, MAX_SCHEDULE_TIMEOUT, true); 131862306a36Sopenharmony_ci goto done; 131962306a36Sopenharmony_ci } 132062306a36Sopenharmony_ci bitmap->allclean = 1; 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci if (bitmap->mddev->queue) 132362306a36Sopenharmony_ci blk_add_trace_msg(bitmap->mddev->queue, 132462306a36Sopenharmony_ci "md bitmap_daemon_work"); 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci /* Any file-page which is PENDING now needs to be written. 132762306a36Sopenharmony_ci * So set NEEDWRITE now, then after we make any last-minute changes 132862306a36Sopenharmony_ci * we will write it. 132962306a36Sopenharmony_ci */ 133062306a36Sopenharmony_ci for (j = 0; j < bitmap->storage.file_pages; j++) 133162306a36Sopenharmony_ci if (test_and_clear_page_attr(bitmap, j, 133262306a36Sopenharmony_ci BITMAP_PAGE_PENDING)) 133362306a36Sopenharmony_ci set_page_attr(bitmap, j, 133462306a36Sopenharmony_ci BITMAP_PAGE_NEEDWRITE); 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_ci if (bitmap->need_sync && 133762306a36Sopenharmony_ci mddev->bitmap_info.external == 0) { 133862306a36Sopenharmony_ci /* Arrange for superblock update as well as 133962306a36Sopenharmony_ci * other changes */ 134062306a36Sopenharmony_ci bitmap_super_t *sb; 134162306a36Sopenharmony_ci bitmap->need_sync = 0; 134262306a36Sopenharmony_ci if (bitmap->storage.filemap) { 134362306a36Sopenharmony_ci sb = kmap_atomic(bitmap->storage.sb_page); 134462306a36Sopenharmony_ci sb->events_cleared = 134562306a36Sopenharmony_ci cpu_to_le64(bitmap->events_cleared); 134662306a36Sopenharmony_ci kunmap_atomic(sb); 134762306a36Sopenharmony_ci set_page_attr(bitmap, 0, 134862306a36Sopenharmony_ci BITMAP_PAGE_NEEDWRITE); 134962306a36Sopenharmony_ci } 135062306a36Sopenharmony_ci } 135162306a36Sopenharmony_ci /* Now look at the bitmap counters and if any are '2' or '1', 135262306a36Sopenharmony_ci * decrement and handle accordingly. 135362306a36Sopenharmony_ci */ 135462306a36Sopenharmony_ci counts = &bitmap->counts; 135562306a36Sopenharmony_ci spin_lock_irq(&counts->lock); 135662306a36Sopenharmony_ci nextpage = 0; 135762306a36Sopenharmony_ci for (j = 0; j < counts->chunks; j++) { 135862306a36Sopenharmony_ci bitmap_counter_t *bmc; 135962306a36Sopenharmony_ci sector_t block = (sector_t)j << counts->chunkshift; 136062306a36Sopenharmony_ci 136162306a36Sopenharmony_ci if (j == nextpage) { 136262306a36Sopenharmony_ci nextpage += PAGE_COUNTER_RATIO; 136362306a36Sopenharmony_ci if (!counts->bp[j >> PAGE_COUNTER_SHIFT].pending) { 136462306a36Sopenharmony_ci j |= PAGE_COUNTER_MASK; 136562306a36Sopenharmony_ci continue; 136662306a36Sopenharmony_ci } 136762306a36Sopenharmony_ci counts->bp[j >> PAGE_COUNTER_SHIFT].pending = 0; 136862306a36Sopenharmony_ci } 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_ci bmc = md_bitmap_get_counter(counts, block, &blocks, 0); 137162306a36Sopenharmony_ci if (!bmc) { 137262306a36Sopenharmony_ci j |= PAGE_COUNTER_MASK; 137362306a36Sopenharmony_ci continue; 137462306a36Sopenharmony_ci } 137562306a36Sopenharmony_ci if (*bmc == 1 && !bitmap->need_sync) { 137662306a36Sopenharmony_ci /* We can clear the bit */ 137762306a36Sopenharmony_ci *bmc = 0; 137862306a36Sopenharmony_ci md_bitmap_count_page(counts, block, -1); 137962306a36Sopenharmony_ci md_bitmap_file_clear_bit(bitmap, block); 138062306a36Sopenharmony_ci } else if (*bmc && *bmc <= 2) { 138162306a36Sopenharmony_ci *bmc = 1; 138262306a36Sopenharmony_ci md_bitmap_set_pending(counts, block); 138362306a36Sopenharmony_ci bitmap->allclean = 0; 138462306a36Sopenharmony_ci } 138562306a36Sopenharmony_ci } 138662306a36Sopenharmony_ci spin_unlock_irq(&counts->lock); 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_ci md_bitmap_wait_writes(bitmap); 138962306a36Sopenharmony_ci /* Now start writeout on any page in NEEDWRITE that isn't DIRTY. 139062306a36Sopenharmony_ci * DIRTY pages need to be written by bitmap_unplug so it can wait 139162306a36Sopenharmony_ci * for them. 139262306a36Sopenharmony_ci * If we find any DIRTY page we stop there and let bitmap_unplug 139362306a36Sopenharmony_ci * handle all the rest. This is important in the case where 139462306a36Sopenharmony_ci * the first blocking holds the superblock and it has been updated. 139562306a36Sopenharmony_ci * We mustn't write any other blocks before the superblock. 139662306a36Sopenharmony_ci */ 139762306a36Sopenharmony_ci for (j = 0; 139862306a36Sopenharmony_ci j < bitmap->storage.file_pages 139962306a36Sopenharmony_ci && !test_bit(BITMAP_STALE, &bitmap->flags); 140062306a36Sopenharmony_ci j++) { 140162306a36Sopenharmony_ci if (test_page_attr(bitmap, j, 140262306a36Sopenharmony_ci BITMAP_PAGE_DIRTY)) 140362306a36Sopenharmony_ci /* bitmap_unplug will handle the rest */ 140462306a36Sopenharmony_ci break; 140562306a36Sopenharmony_ci if (bitmap->storage.filemap && 140662306a36Sopenharmony_ci test_and_clear_page_attr(bitmap, j, 140762306a36Sopenharmony_ci BITMAP_PAGE_NEEDWRITE)) 140862306a36Sopenharmony_ci filemap_write_page(bitmap, j, false); 140962306a36Sopenharmony_ci } 141062306a36Sopenharmony_ci 141162306a36Sopenharmony_ci done: 141262306a36Sopenharmony_ci if (bitmap->allclean == 0) 141362306a36Sopenharmony_ci mddev_set_timeout(mddev, mddev->bitmap_info.daemon_sleep, true); 141462306a36Sopenharmony_ci mutex_unlock(&mddev->bitmap_info.mutex); 141562306a36Sopenharmony_ci} 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_cistatic bitmap_counter_t *md_bitmap_get_counter(struct bitmap_counts *bitmap, 141862306a36Sopenharmony_ci sector_t offset, sector_t *blocks, 141962306a36Sopenharmony_ci int create) 142062306a36Sopenharmony_ci__releases(bitmap->lock) 142162306a36Sopenharmony_ci__acquires(bitmap->lock) 142262306a36Sopenharmony_ci{ 142362306a36Sopenharmony_ci /* If 'create', we might release the lock and reclaim it. 142462306a36Sopenharmony_ci * The lock must have been taken with interrupts enabled. 142562306a36Sopenharmony_ci * If !create, we don't release the lock. 142662306a36Sopenharmony_ci */ 142762306a36Sopenharmony_ci sector_t chunk = offset >> bitmap->chunkshift; 142862306a36Sopenharmony_ci unsigned long page = chunk >> PAGE_COUNTER_SHIFT; 142962306a36Sopenharmony_ci unsigned long pageoff = (chunk & PAGE_COUNTER_MASK) << COUNTER_BYTE_SHIFT; 143062306a36Sopenharmony_ci sector_t csize; 143162306a36Sopenharmony_ci int err; 143262306a36Sopenharmony_ci 143362306a36Sopenharmony_ci if (page >= bitmap->pages) { 143462306a36Sopenharmony_ci /* 143562306a36Sopenharmony_ci * This can happen if bitmap_start_sync goes beyond 143662306a36Sopenharmony_ci * End-of-device while looking for a whole page or 143762306a36Sopenharmony_ci * user set a huge number to sysfs bitmap_set_bits. 143862306a36Sopenharmony_ci */ 143962306a36Sopenharmony_ci return NULL; 144062306a36Sopenharmony_ci } 144162306a36Sopenharmony_ci err = md_bitmap_checkpage(bitmap, page, create, 0); 144262306a36Sopenharmony_ci 144362306a36Sopenharmony_ci if (bitmap->bp[page].hijacked || 144462306a36Sopenharmony_ci bitmap->bp[page].map == NULL) 144562306a36Sopenharmony_ci csize = ((sector_t)1) << (bitmap->chunkshift + 144662306a36Sopenharmony_ci PAGE_COUNTER_SHIFT); 144762306a36Sopenharmony_ci else 144862306a36Sopenharmony_ci csize = ((sector_t)1) << bitmap->chunkshift; 144962306a36Sopenharmony_ci *blocks = csize - (offset & (csize - 1)); 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_ci if (err < 0) 145262306a36Sopenharmony_ci return NULL; 145362306a36Sopenharmony_ci 145462306a36Sopenharmony_ci /* now locked ... */ 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_ci if (bitmap->bp[page].hijacked) { /* hijacked pointer */ 145762306a36Sopenharmony_ci /* should we use the first or second counter field 145862306a36Sopenharmony_ci * of the hijacked pointer? */ 145962306a36Sopenharmony_ci int hi = (pageoff > PAGE_COUNTER_MASK); 146062306a36Sopenharmony_ci return &((bitmap_counter_t *) 146162306a36Sopenharmony_ci &bitmap->bp[page].map)[hi]; 146262306a36Sopenharmony_ci } else /* page is allocated */ 146362306a36Sopenharmony_ci return (bitmap_counter_t *) 146462306a36Sopenharmony_ci &(bitmap->bp[page].map[pageoff]); 146562306a36Sopenharmony_ci} 146662306a36Sopenharmony_ci 146762306a36Sopenharmony_ciint md_bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors, int behind) 146862306a36Sopenharmony_ci{ 146962306a36Sopenharmony_ci if (!bitmap) 147062306a36Sopenharmony_ci return 0; 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_ci if (behind) { 147362306a36Sopenharmony_ci int bw; 147462306a36Sopenharmony_ci atomic_inc(&bitmap->behind_writes); 147562306a36Sopenharmony_ci bw = atomic_read(&bitmap->behind_writes); 147662306a36Sopenharmony_ci if (bw > bitmap->behind_writes_used) 147762306a36Sopenharmony_ci bitmap->behind_writes_used = bw; 147862306a36Sopenharmony_ci 147962306a36Sopenharmony_ci pr_debug("inc write-behind count %d/%lu\n", 148062306a36Sopenharmony_ci bw, bitmap->mddev->bitmap_info.max_write_behind); 148162306a36Sopenharmony_ci } 148262306a36Sopenharmony_ci 148362306a36Sopenharmony_ci while (sectors) { 148462306a36Sopenharmony_ci sector_t blocks; 148562306a36Sopenharmony_ci bitmap_counter_t *bmc; 148662306a36Sopenharmony_ci 148762306a36Sopenharmony_ci spin_lock_irq(&bitmap->counts.lock); 148862306a36Sopenharmony_ci bmc = md_bitmap_get_counter(&bitmap->counts, offset, &blocks, 1); 148962306a36Sopenharmony_ci if (!bmc) { 149062306a36Sopenharmony_ci spin_unlock_irq(&bitmap->counts.lock); 149162306a36Sopenharmony_ci return 0; 149262306a36Sopenharmony_ci } 149362306a36Sopenharmony_ci 149462306a36Sopenharmony_ci if (unlikely(COUNTER(*bmc) == COUNTER_MAX)) { 149562306a36Sopenharmony_ci DEFINE_WAIT(__wait); 149662306a36Sopenharmony_ci /* note that it is safe to do the prepare_to_wait 149762306a36Sopenharmony_ci * after the test as long as we do it before dropping 149862306a36Sopenharmony_ci * the spinlock. 149962306a36Sopenharmony_ci */ 150062306a36Sopenharmony_ci prepare_to_wait(&bitmap->overflow_wait, &__wait, 150162306a36Sopenharmony_ci TASK_UNINTERRUPTIBLE); 150262306a36Sopenharmony_ci spin_unlock_irq(&bitmap->counts.lock); 150362306a36Sopenharmony_ci schedule(); 150462306a36Sopenharmony_ci finish_wait(&bitmap->overflow_wait, &__wait); 150562306a36Sopenharmony_ci continue; 150662306a36Sopenharmony_ci } 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_ci switch (*bmc) { 150962306a36Sopenharmony_ci case 0: 151062306a36Sopenharmony_ci md_bitmap_file_set_bit(bitmap, offset); 151162306a36Sopenharmony_ci md_bitmap_count_page(&bitmap->counts, offset, 1); 151262306a36Sopenharmony_ci fallthrough; 151362306a36Sopenharmony_ci case 1: 151462306a36Sopenharmony_ci *bmc = 2; 151562306a36Sopenharmony_ci } 151662306a36Sopenharmony_ci 151762306a36Sopenharmony_ci (*bmc)++; 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci spin_unlock_irq(&bitmap->counts.lock); 152062306a36Sopenharmony_ci 152162306a36Sopenharmony_ci offset += blocks; 152262306a36Sopenharmony_ci if (sectors > blocks) 152362306a36Sopenharmony_ci sectors -= blocks; 152462306a36Sopenharmony_ci else 152562306a36Sopenharmony_ci sectors = 0; 152662306a36Sopenharmony_ci } 152762306a36Sopenharmony_ci return 0; 152862306a36Sopenharmony_ci} 152962306a36Sopenharmony_ciEXPORT_SYMBOL(md_bitmap_startwrite); 153062306a36Sopenharmony_ci 153162306a36Sopenharmony_civoid md_bitmap_endwrite(struct bitmap *bitmap, sector_t offset, 153262306a36Sopenharmony_ci unsigned long sectors, int success, int behind) 153362306a36Sopenharmony_ci{ 153462306a36Sopenharmony_ci if (!bitmap) 153562306a36Sopenharmony_ci return; 153662306a36Sopenharmony_ci if (behind) { 153762306a36Sopenharmony_ci if (atomic_dec_and_test(&bitmap->behind_writes)) 153862306a36Sopenharmony_ci wake_up(&bitmap->behind_wait); 153962306a36Sopenharmony_ci pr_debug("dec write-behind count %d/%lu\n", 154062306a36Sopenharmony_ci atomic_read(&bitmap->behind_writes), 154162306a36Sopenharmony_ci bitmap->mddev->bitmap_info.max_write_behind); 154262306a36Sopenharmony_ci } 154362306a36Sopenharmony_ci 154462306a36Sopenharmony_ci while (sectors) { 154562306a36Sopenharmony_ci sector_t blocks; 154662306a36Sopenharmony_ci unsigned long flags; 154762306a36Sopenharmony_ci bitmap_counter_t *bmc; 154862306a36Sopenharmony_ci 154962306a36Sopenharmony_ci spin_lock_irqsave(&bitmap->counts.lock, flags); 155062306a36Sopenharmony_ci bmc = md_bitmap_get_counter(&bitmap->counts, offset, &blocks, 0); 155162306a36Sopenharmony_ci if (!bmc) { 155262306a36Sopenharmony_ci spin_unlock_irqrestore(&bitmap->counts.lock, flags); 155362306a36Sopenharmony_ci return; 155462306a36Sopenharmony_ci } 155562306a36Sopenharmony_ci 155662306a36Sopenharmony_ci if (success && !bitmap->mddev->degraded && 155762306a36Sopenharmony_ci bitmap->events_cleared < bitmap->mddev->events) { 155862306a36Sopenharmony_ci bitmap->events_cleared = bitmap->mddev->events; 155962306a36Sopenharmony_ci bitmap->need_sync = 1; 156062306a36Sopenharmony_ci sysfs_notify_dirent_safe(bitmap->sysfs_can_clear); 156162306a36Sopenharmony_ci } 156262306a36Sopenharmony_ci 156362306a36Sopenharmony_ci if (!success && !NEEDED(*bmc)) 156462306a36Sopenharmony_ci *bmc |= NEEDED_MASK; 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_ci if (COUNTER(*bmc) == COUNTER_MAX) 156762306a36Sopenharmony_ci wake_up(&bitmap->overflow_wait); 156862306a36Sopenharmony_ci 156962306a36Sopenharmony_ci (*bmc)--; 157062306a36Sopenharmony_ci if (*bmc <= 2) { 157162306a36Sopenharmony_ci md_bitmap_set_pending(&bitmap->counts, offset); 157262306a36Sopenharmony_ci bitmap->allclean = 0; 157362306a36Sopenharmony_ci } 157462306a36Sopenharmony_ci spin_unlock_irqrestore(&bitmap->counts.lock, flags); 157562306a36Sopenharmony_ci offset += blocks; 157662306a36Sopenharmony_ci if (sectors > blocks) 157762306a36Sopenharmony_ci sectors -= blocks; 157862306a36Sopenharmony_ci else 157962306a36Sopenharmony_ci sectors = 0; 158062306a36Sopenharmony_ci } 158162306a36Sopenharmony_ci} 158262306a36Sopenharmony_ciEXPORT_SYMBOL(md_bitmap_endwrite); 158362306a36Sopenharmony_ci 158462306a36Sopenharmony_cistatic int __bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, 158562306a36Sopenharmony_ci int degraded) 158662306a36Sopenharmony_ci{ 158762306a36Sopenharmony_ci bitmap_counter_t *bmc; 158862306a36Sopenharmony_ci int rv; 158962306a36Sopenharmony_ci if (bitmap == NULL) {/* FIXME or bitmap set as 'failed' */ 159062306a36Sopenharmony_ci *blocks = 1024; 159162306a36Sopenharmony_ci return 1; /* always resync if no bitmap */ 159262306a36Sopenharmony_ci } 159362306a36Sopenharmony_ci spin_lock_irq(&bitmap->counts.lock); 159462306a36Sopenharmony_ci bmc = md_bitmap_get_counter(&bitmap->counts, offset, blocks, 0); 159562306a36Sopenharmony_ci rv = 0; 159662306a36Sopenharmony_ci if (bmc) { 159762306a36Sopenharmony_ci /* locked */ 159862306a36Sopenharmony_ci if (RESYNC(*bmc)) 159962306a36Sopenharmony_ci rv = 1; 160062306a36Sopenharmony_ci else if (NEEDED(*bmc)) { 160162306a36Sopenharmony_ci rv = 1; 160262306a36Sopenharmony_ci if (!degraded) { /* don't set/clear bits if degraded */ 160362306a36Sopenharmony_ci *bmc |= RESYNC_MASK; 160462306a36Sopenharmony_ci *bmc &= ~NEEDED_MASK; 160562306a36Sopenharmony_ci } 160662306a36Sopenharmony_ci } 160762306a36Sopenharmony_ci } 160862306a36Sopenharmony_ci spin_unlock_irq(&bitmap->counts.lock); 160962306a36Sopenharmony_ci return rv; 161062306a36Sopenharmony_ci} 161162306a36Sopenharmony_ci 161262306a36Sopenharmony_ciint md_bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, 161362306a36Sopenharmony_ci int degraded) 161462306a36Sopenharmony_ci{ 161562306a36Sopenharmony_ci /* bitmap_start_sync must always report on multiples of whole 161662306a36Sopenharmony_ci * pages, otherwise resync (which is very PAGE_SIZE based) will 161762306a36Sopenharmony_ci * get confused. 161862306a36Sopenharmony_ci * So call __bitmap_start_sync repeatedly (if needed) until 161962306a36Sopenharmony_ci * At least PAGE_SIZE>>9 blocks are covered. 162062306a36Sopenharmony_ci * Return the 'or' of the result. 162162306a36Sopenharmony_ci */ 162262306a36Sopenharmony_ci int rv = 0; 162362306a36Sopenharmony_ci sector_t blocks1; 162462306a36Sopenharmony_ci 162562306a36Sopenharmony_ci *blocks = 0; 162662306a36Sopenharmony_ci while (*blocks < (PAGE_SIZE>>9)) { 162762306a36Sopenharmony_ci rv |= __bitmap_start_sync(bitmap, offset, 162862306a36Sopenharmony_ci &blocks1, degraded); 162962306a36Sopenharmony_ci offset += blocks1; 163062306a36Sopenharmony_ci *blocks += blocks1; 163162306a36Sopenharmony_ci } 163262306a36Sopenharmony_ci return rv; 163362306a36Sopenharmony_ci} 163462306a36Sopenharmony_ciEXPORT_SYMBOL(md_bitmap_start_sync); 163562306a36Sopenharmony_ci 163662306a36Sopenharmony_civoid md_bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, int aborted) 163762306a36Sopenharmony_ci{ 163862306a36Sopenharmony_ci bitmap_counter_t *bmc; 163962306a36Sopenharmony_ci unsigned long flags; 164062306a36Sopenharmony_ci 164162306a36Sopenharmony_ci if (bitmap == NULL) { 164262306a36Sopenharmony_ci *blocks = 1024; 164362306a36Sopenharmony_ci return; 164462306a36Sopenharmony_ci } 164562306a36Sopenharmony_ci spin_lock_irqsave(&bitmap->counts.lock, flags); 164662306a36Sopenharmony_ci bmc = md_bitmap_get_counter(&bitmap->counts, offset, blocks, 0); 164762306a36Sopenharmony_ci if (bmc == NULL) 164862306a36Sopenharmony_ci goto unlock; 164962306a36Sopenharmony_ci /* locked */ 165062306a36Sopenharmony_ci if (RESYNC(*bmc)) { 165162306a36Sopenharmony_ci *bmc &= ~RESYNC_MASK; 165262306a36Sopenharmony_ci 165362306a36Sopenharmony_ci if (!NEEDED(*bmc) && aborted) 165462306a36Sopenharmony_ci *bmc |= NEEDED_MASK; 165562306a36Sopenharmony_ci else { 165662306a36Sopenharmony_ci if (*bmc <= 2) { 165762306a36Sopenharmony_ci md_bitmap_set_pending(&bitmap->counts, offset); 165862306a36Sopenharmony_ci bitmap->allclean = 0; 165962306a36Sopenharmony_ci } 166062306a36Sopenharmony_ci } 166162306a36Sopenharmony_ci } 166262306a36Sopenharmony_ci unlock: 166362306a36Sopenharmony_ci spin_unlock_irqrestore(&bitmap->counts.lock, flags); 166462306a36Sopenharmony_ci} 166562306a36Sopenharmony_ciEXPORT_SYMBOL(md_bitmap_end_sync); 166662306a36Sopenharmony_ci 166762306a36Sopenharmony_civoid md_bitmap_close_sync(struct bitmap *bitmap) 166862306a36Sopenharmony_ci{ 166962306a36Sopenharmony_ci /* Sync has finished, and any bitmap chunks that weren't synced 167062306a36Sopenharmony_ci * properly have been aborted. It remains to us to clear the 167162306a36Sopenharmony_ci * RESYNC bit wherever it is still on 167262306a36Sopenharmony_ci */ 167362306a36Sopenharmony_ci sector_t sector = 0; 167462306a36Sopenharmony_ci sector_t blocks; 167562306a36Sopenharmony_ci if (!bitmap) 167662306a36Sopenharmony_ci return; 167762306a36Sopenharmony_ci while (sector < bitmap->mddev->resync_max_sectors) { 167862306a36Sopenharmony_ci md_bitmap_end_sync(bitmap, sector, &blocks, 0); 167962306a36Sopenharmony_ci sector += blocks; 168062306a36Sopenharmony_ci } 168162306a36Sopenharmony_ci} 168262306a36Sopenharmony_ciEXPORT_SYMBOL(md_bitmap_close_sync); 168362306a36Sopenharmony_ci 168462306a36Sopenharmony_civoid md_bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector, bool force) 168562306a36Sopenharmony_ci{ 168662306a36Sopenharmony_ci sector_t s = 0; 168762306a36Sopenharmony_ci sector_t blocks; 168862306a36Sopenharmony_ci 168962306a36Sopenharmony_ci if (!bitmap) 169062306a36Sopenharmony_ci return; 169162306a36Sopenharmony_ci if (sector == 0) { 169262306a36Sopenharmony_ci bitmap->last_end_sync = jiffies; 169362306a36Sopenharmony_ci return; 169462306a36Sopenharmony_ci } 169562306a36Sopenharmony_ci if (!force && time_before(jiffies, (bitmap->last_end_sync 169662306a36Sopenharmony_ci + bitmap->mddev->bitmap_info.daemon_sleep))) 169762306a36Sopenharmony_ci return; 169862306a36Sopenharmony_ci wait_event(bitmap->mddev->recovery_wait, 169962306a36Sopenharmony_ci atomic_read(&bitmap->mddev->recovery_active) == 0); 170062306a36Sopenharmony_ci 170162306a36Sopenharmony_ci bitmap->mddev->curr_resync_completed = sector; 170262306a36Sopenharmony_ci set_bit(MD_SB_CHANGE_CLEAN, &bitmap->mddev->sb_flags); 170362306a36Sopenharmony_ci sector &= ~((1ULL << bitmap->counts.chunkshift) - 1); 170462306a36Sopenharmony_ci s = 0; 170562306a36Sopenharmony_ci while (s < sector && s < bitmap->mddev->resync_max_sectors) { 170662306a36Sopenharmony_ci md_bitmap_end_sync(bitmap, s, &blocks, 0); 170762306a36Sopenharmony_ci s += blocks; 170862306a36Sopenharmony_ci } 170962306a36Sopenharmony_ci bitmap->last_end_sync = jiffies; 171062306a36Sopenharmony_ci sysfs_notify_dirent_safe(bitmap->mddev->sysfs_completed); 171162306a36Sopenharmony_ci} 171262306a36Sopenharmony_ciEXPORT_SYMBOL(md_bitmap_cond_end_sync); 171362306a36Sopenharmony_ci 171462306a36Sopenharmony_civoid md_bitmap_sync_with_cluster(struct mddev *mddev, 171562306a36Sopenharmony_ci sector_t old_lo, sector_t old_hi, 171662306a36Sopenharmony_ci sector_t new_lo, sector_t new_hi) 171762306a36Sopenharmony_ci{ 171862306a36Sopenharmony_ci struct bitmap *bitmap = mddev->bitmap; 171962306a36Sopenharmony_ci sector_t sector, blocks = 0; 172062306a36Sopenharmony_ci 172162306a36Sopenharmony_ci for (sector = old_lo; sector < new_lo; ) { 172262306a36Sopenharmony_ci md_bitmap_end_sync(bitmap, sector, &blocks, 0); 172362306a36Sopenharmony_ci sector += blocks; 172462306a36Sopenharmony_ci } 172562306a36Sopenharmony_ci WARN((blocks > new_lo) && old_lo, "alignment is not correct for lo\n"); 172662306a36Sopenharmony_ci 172762306a36Sopenharmony_ci for (sector = old_hi; sector < new_hi; ) { 172862306a36Sopenharmony_ci md_bitmap_start_sync(bitmap, sector, &blocks, 0); 172962306a36Sopenharmony_ci sector += blocks; 173062306a36Sopenharmony_ci } 173162306a36Sopenharmony_ci WARN((blocks > new_hi) && old_hi, "alignment is not correct for hi\n"); 173262306a36Sopenharmony_ci} 173362306a36Sopenharmony_ciEXPORT_SYMBOL(md_bitmap_sync_with_cluster); 173462306a36Sopenharmony_ci 173562306a36Sopenharmony_cistatic void md_bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed) 173662306a36Sopenharmony_ci{ 173762306a36Sopenharmony_ci /* For each chunk covered by any of these sectors, set the 173862306a36Sopenharmony_ci * counter to 2 and possibly set resync_needed. They should all 173962306a36Sopenharmony_ci * be 0 at this point 174062306a36Sopenharmony_ci */ 174162306a36Sopenharmony_ci 174262306a36Sopenharmony_ci sector_t secs; 174362306a36Sopenharmony_ci bitmap_counter_t *bmc; 174462306a36Sopenharmony_ci spin_lock_irq(&bitmap->counts.lock); 174562306a36Sopenharmony_ci bmc = md_bitmap_get_counter(&bitmap->counts, offset, &secs, 1); 174662306a36Sopenharmony_ci if (!bmc) { 174762306a36Sopenharmony_ci spin_unlock_irq(&bitmap->counts.lock); 174862306a36Sopenharmony_ci return; 174962306a36Sopenharmony_ci } 175062306a36Sopenharmony_ci if (!*bmc) { 175162306a36Sopenharmony_ci *bmc = 2; 175262306a36Sopenharmony_ci md_bitmap_count_page(&bitmap->counts, offset, 1); 175362306a36Sopenharmony_ci md_bitmap_set_pending(&bitmap->counts, offset); 175462306a36Sopenharmony_ci bitmap->allclean = 0; 175562306a36Sopenharmony_ci } 175662306a36Sopenharmony_ci if (needed) 175762306a36Sopenharmony_ci *bmc |= NEEDED_MASK; 175862306a36Sopenharmony_ci spin_unlock_irq(&bitmap->counts.lock); 175962306a36Sopenharmony_ci} 176062306a36Sopenharmony_ci 176162306a36Sopenharmony_ci/* dirty the memory and file bits for bitmap chunks "s" to "e" */ 176262306a36Sopenharmony_civoid md_bitmap_dirty_bits(struct bitmap *bitmap, unsigned long s, unsigned long e) 176362306a36Sopenharmony_ci{ 176462306a36Sopenharmony_ci unsigned long chunk; 176562306a36Sopenharmony_ci 176662306a36Sopenharmony_ci for (chunk = s; chunk <= e; chunk++) { 176762306a36Sopenharmony_ci sector_t sec = (sector_t)chunk << bitmap->counts.chunkshift; 176862306a36Sopenharmony_ci md_bitmap_set_memory_bits(bitmap, sec, 1); 176962306a36Sopenharmony_ci md_bitmap_file_set_bit(bitmap, sec); 177062306a36Sopenharmony_ci if (sec < bitmap->mddev->recovery_cp) 177162306a36Sopenharmony_ci /* We are asserting that the array is dirty, 177262306a36Sopenharmony_ci * so move the recovery_cp address back so 177362306a36Sopenharmony_ci * that it is obvious that it is dirty 177462306a36Sopenharmony_ci */ 177562306a36Sopenharmony_ci bitmap->mddev->recovery_cp = sec; 177662306a36Sopenharmony_ci } 177762306a36Sopenharmony_ci} 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_ci/* 178062306a36Sopenharmony_ci * flush out any pending updates 178162306a36Sopenharmony_ci */ 178262306a36Sopenharmony_civoid md_bitmap_flush(struct mddev *mddev) 178362306a36Sopenharmony_ci{ 178462306a36Sopenharmony_ci struct bitmap *bitmap = mddev->bitmap; 178562306a36Sopenharmony_ci long sleep; 178662306a36Sopenharmony_ci 178762306a36Sopenharmony_ci if (!bitmap) /* there was no bitmap */ 178862306a36Sopenharmony_ci return; 178962306a36Sopenharmony_ci 179062306a36Sopenharmony_ci /* run the daemon_work three time to ensure everything is flushed 179162306a36Sopenharmony_ci * that can be 179262306a36Sopenharmony_ci */ 179362306a36Sopenharmony_ci sleep = mddev->bitmap_info.daemon_sleep * 2; 179462306a36Sopenharmony_ci bitmap->daemon_lastrun -= sleep; 179562306a36Sopenharmony_ci md_bitmap_daemon_work(mddev); 179662306a36Sopenharmony_ci bitmap->daemon_lastrun -= sleep; 179762306a36Sopenharmony_ci md_bitmap_daemon_work(mddev); 179862306a36Sopenharmony_ci bitmap->daemon_lastrun -= sleep; 179962306a36Sopenharmony_ci md_bitmap_daemon_work(mddev); 180062306a36Sopenharmony_ci if (mddev->bitmap_info.external) 180162306a36Sopenharmony_ci md_super_wait(mddev); 180262306a36Sopenharmony_ci md_bitmap_update_sb(bitmap); 180362306a36Sopenharmony_ci} 180462306a36Sopenharmony_ci 180562306a36Sopenharmony_ci/* 180662306a36Sopenharmony_ci * free memory that was allocated 180762306a36Sopenharmony_ci */ 180862306a36Sopenharmony_civoid md_bitmap_free(struct bitmap *bitmap) 180962306a36Sopenharmony_ci{ 181062306a36Sopenharmony_ci unsigned long k, pages; 181162306a36Sopenharmony_ci struct bitmap_page *bp; 181262306a36Sopenharmony_ci 181362306a36Sopenharmony_ci if (!bitmap) /* there was no bitmap */ 181462306a36Sopenharmony_ci return; 181562306a36Sopenharmony_ci 181662306a36Sopenharmony_ci if (bitmap->sysfs_can_clear) 181762306a36Sopenharmony_ci sysfs_put(bitmap->sysfs_can_clear); 181862306a36Sopenharmony_ci 181962306a36Sopenharmony_ci if (mddev_is_clustered(bitmap->mddev) && bitmap->mddev->cluster_info && 182062306a36Sopenharmony_ci bitmap->cluster_slot == md_cluster_ops->slot_number(bitmap->mddev)) 182162306a36Sopenharmony_ci md_cluster_stop(bitmap->mddev); 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_ci /* Shouldn't be needed - but just in case.... */ 182462306a36Sopenharmony_ci wait_event(bitmap->write_wait, 182562306a36Sopenharmony_ci atomic_read(&bitmap->pending_writes) == 0); 182662306a36Sopenharmony_ci 182762306a36Sopenharmony_ci /* release the bitmap file */ 182862306a36Sopenharmony_ci md_bitmap_file_unmap(&bitmap->storage); 182962306a36Sopenharmony_ci 183062306a36Sopenharmony_ci bp = bitmap->counts.bp; 183162306a36Sopenharmony_ci pages = bitmap->counts.pages; 183262306a36Sopenharmony_ci 183362306a36Sopenharmony_ci /* free all allocated memory */ 183462306a36Sopenharmony_ci 183562306a36Sopenharmony_ci if (bp) /* deallocate the page memory */ 183662306a36Sopenharmony_ci for (k = 0; k < pages; k++) 183762306a36Sopenharmony_ci if (bp[k].map && !bp[k].hijacked) 183862306a36Sopenharmony_ci kfree(bp[k].map); 183962306a36Sopenharmony_ci kfree(bp); 184062306a36Sopenharmony_ci kfree(bitmap); 184162306a36Sopenharmony_ci} 184262306a36Sopenharmony_ciEXPORT_SYMBOL(md_bitmap_free); 184362306a36Sopenharmony_ci 184462306a36Sopenharmony_civoid md_bitmap_wait_behind_writes(struct mddev *mddev) 184562306a36Sopenharmony_ci{ 184662306a36Sopenharmony_ci struct bitmap *bitmap = mddev->bitmap; 184762306a36Sopenharmony_ci 184862306a36Sopenharmony_ci /* wait for behind writes to complete */ 184962306a36Sopenharmony_ci if (bitmap && atomic_read(&bitmap->behind_writes) > 0) { 185062306a36Sopenharmony_ci pr_debug("md:%s: behind writes in progress - waiting to stop.\n", 185162306a36Sopenharmony_ci mdname(mddev)); 185262306a36Sopenharmony_ci /* need to kick something here to make sure I/O goes? */ 185362306a36Sopenharmony_ci wait_event(bitmap->behind_wait, 185462306a36Sopenharmony_ci atomic_read(&bitmap->behind_writes) == 0); 185562306a36Sopenharmony_ci } 185662306a36Sopenharmony_ci} 185762306a36Sopenharmony_ci 185862306a36Sopenharmony_civoid md_bitmap_destroy(struct mddev *mddev) 185962306a36Sopenharmony_ci{ 186062306a36Sopenharmony_ci struct bitmap *bitmap = mddev->bitmap; 186162306a36Sopenharmony_ci 186262306a36Sopenharmony_ci if (!bitmap) /* there was no bitmap */ 186362306a36Sopenharmony_ci return; 186462306a36Sopenharmony_ci 186562306a36Sopenharmony_ci md_bitmap_wait_behind_writes(mddev); 186662306a36Sopenharmony_ci if (!mddev->serialize_policy) 186762306a36Sopenharmony_ci mddev_destroy_serial_pool(mddev, NULL, true); 186862306a36Sopenharmony_ci 186962306a36Sopenharmony_ci mutex_lock(&mddev->bitmap_info.mutex); 187062306a36Sopenharmony_ci spin_lock(&mddev->lock); 187162306a36Sopenharmony_ci mddev->bitmap = NULL; /* disconnect from the md device */ 187262306a36Sopenharmony_ci spin_unlock(&mddev->lock); 187362306a36Sopenharmony_ci mutex_unlock(&mddev->bitmap_info.mutex); 187462306a36Sopenharmony_ci mddev_set_timeout(mddev, MAX_SCHEDULE_TIMEOUT, true); 187562306a36Sopenharmony_ci 187662306a36Sopenharmony_ci md_bitmap_free(bitmap); 187762306a36Sopenharmony_ci} 187862306a36Sopenharmony_ci 187962306a36Sopenharmony_ci/* 188062306a36Sopenharmony_ci * initialize the bitmap structure 188162306a36Sopenharmony_ci * if this returns an error, bitmap_destroy must be called to do clean up 188262306a36Sopenharmony_ci * once mddev->bitmap is set 188362306a36Sopenharmony_ci */ 188462306a36Sopenharmony_cistruct bitmap *md_bitmap_create(struct mddev *mddev, int slot) 188562306a36Sopenharmony_ci{ 188662306a36Sopenharmony_ci struct bitmap *bitmap; 188762306a36Sopenharmony_ci sector_t blocks = mddev->resync_max_sectors; 188862306a36Sopenharmony_ci struct file *file = mddev->bitmap_info.file; 188962306a36Sopenharmony_ci int err; 189062306a36Sopenharmony_ci struct kernfs_node *bm = NULL; 189162306a36Sopenharmony_ci 189262306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(bitmap_super_t) != 256); 189362306a36Sopenharmony_ci 189462306a36Sopenharmony_ci BUG_ON(file && mddev->bitmap_info.offset); 189562306a36Sopenharmony_ci 189662306a36Sopenharmony_ci if (test_bit(MD_HAS_JOURNAL, &mddev->flags)) { 189762306a36Sopenharmony_ci pr_notice("md/raid:%s: array with journal cannot have bitmap\n", 189862306a36Sopenharmony_ci mdname(mddev)); 189962306a36Sopenharmony_ci return ERR_PTR(-EBUSY); 190062306a36Sopenharmony_ci } 190162306a36Sopenharmony_ci 190262306a36Sopenharmony_ci bitmap = kzalloc(sizeof(*bitmap), GFP_KERNEL); 190362306a36Sopenharmony_ci if (!bitmap) 190462306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 190562306a36Sopenharmony_ci 190662306a36Sopenharmony_ci spin_lock_init(&bitmap->counts.lock); 190762306a36Sopenharmony_ci atomic_set(&bitmap->pending_writes, 0); 190862306a36Sopenharmony_ci init_waitqueue_head(&bitmap->write_wait); 190962306a36Sopenharmony_ci init_waitqueue_head(&bitmap->overflow_wait); 191062306a36Sopenharmony_ci init_waitqueue_head(&bitmap->behind_wait); 191162306a36Sopenharmony_ci 191262306a36Sopenharmony_ci bitmap->mddev = mddev; 191362306a36Sopenharmony_ci bitmap->cluster_slot = slot; 191462306a36Sopenharmony_ci 191562306a36Sopenharmony_ci if (mddev->kobj.sd) 191662306a36Sopenharmony_ci bm = sysfs_get_dirent(mddev->kobj.sd, "bitmap"); 191762306a36Sopenharmony_ci if (bm) { 191862306a36Sopenharmony_ci bitmap->sysfs_can_clear = sysfs_get_dirent(bm, "can_clear"); 191962306a36Sopenharmony_ci sysfs_put(bm); 192062306a36Sopenharmony_ci } else 192162306a36Sopenharmony_ci bitmap->sysfs_can_clear = NULL; 192262306a36Sopenharmony_ci 192362306a36Sopenharmony_ci bitmap->storage.file = file; 192462306a36Sopenharmony_ci if (file) { 192562306a36Sopenharmony_ci get_file(file); 192662306a36Sopenharmony_ci /* As future accesses to this file will use bmap, 192762306a36Sopenharmony_ci * and bypass the page cache, we must sync the file 192862306a36Sopenharmony_ci * first. 192962306a36Sopenharmony_ci */ 193062306a36Sopenharmony_ci vfs_fsync(file, 1); 193162306a36Sopenharmony_ci } 193262306a36Sopenharmony_ci /* read superblock from bitmap file (this sets mddev->bitmap_info.chunksize) */ 193362306a36Sopenharmony_ci if (!mddev->bitmap_info.external) { 193462306a36Sopenharmony_ci /* 193562306a36Sopenharmony_ci * If 'MD_ARRAY_FIRST_USE' is set, then device-mapper is 193662306a36Sopenharmony_ci * instructing us to create a new on-disk bitmap instance. 193762306a36Sopenharmony_ci */ 193862306a36Sopenharmony_ci if (test_and_clear_bit(MD_ARRAY_FIRST_USE, &mddev->flags)) 193962306a36Sopenharmony_ci err = md_bitmap_new_disk_sb(bitmap); 194062306a36Sopenharmony_ci else 194162306a36Sopenharmony_ci err = md_bitmap_read_sb(bitmap); 194262306a36Sopenharmony_ci } else { 194362306a36Sopenharmony_ci err = 0; 194462306a36Sopenharmony_ci if (mddev->bitmap_info.chunksize == 0 || 194562306a36Sopenharmony_ci mddev->bitmap_info.daemon_sleep == 0) 194662306a36Sopenharmony_ci /* chunksize and time_base need to be 194762306a36Sopenharmony_ci * set first. */ 194862306a36Sopenharmony_ci err = -EINVAL; 194962306a36Sopenharmony_ci } 195062306a36Sopenharmony_ci if (err) 195162306a36Sopenharmony_ci goto error; 195262306a36Sopenharmony_ci 195362306a36Sopenharmony_ci bitmap->daemon_lastrun = jiffies; 195462306a36Sopenharmony_ci err = md_bitmap_resize(bitmap, blocks, mddev->bitmap_info.chunksize, 1); 195562306a36Sopenharmony_ci if (err) 195662306a36Sopenharmony_ci goto error; 195762306a36Sopenharmony_ci 195862306a36Sopenharmony_ci pr_debug("created bitmap (%lu pages) for device %s\n", 195962306a36Sopenharmony_ci bitmap->counts.pages, bmname(bitmap)); 196062306a36Sopenharmony_ci 196162306a36Sopenharmony_ci err = test_bit(BITMAP_WRITE_ERROR, &bitmap->flags) ? -EIO : 0; 196262306a36Sopenharmony_ci if (err) 196362306a36Sopenharmony_ci goto error; 196462306a36Sopenharmony_ci 196562306a36Sopenharmony_ci return bitmap; 196662306a36Sopenharmony_ci error: 196762306a36Sopenharmony_ci md_bitmap_free(bitmap); 196862306a36Sopenharmony_ci return ERR_PTR(err); 196962306a36Sopenharmony_ci} 197062306a36Sopenharmony_ci 197162306a36Sopenharmony_ciint md_bitmap_load(struct mddev *mddev) 197262306a36Sopenharmony_ci{ 197362306a36Sopenharmony_ci int err = 0; 197462306a36Sopenharmony_ci sector_t start = 0; 197562306a36Sopenharmony_ci sector_t sector = 0; 197662306a36Sopenharmony_ci struct bitmap *bitmap = mddev->bitmap; 197762306a36Sopenharmony_ci struct md_rdev *rdev; 197862306a36Sopenharmony_ci 197962306a36Sopenharmony_ci if (!bitmap) 198062306a36Sopenharmony_ci goto out; 198162306a36Sopenharmony_ci 198262306a36Sopenharmony_ci rdev_for_each(rdev, mddev) 198362306a36Sopenharmony_ci mddev_create_serial_pool(mddev, rdev, true); 198462306a36Sopenharmony_ci 198562306a36Sopenharmony_ci if (mddev_is_clustered(mddev)) 198662306a36Sopenharmony_ci md_cluster_ops->load_bitmaps(mddev, mddev->bitmap_info.nodes); 198762306a36Sopenharmony_ci 198862306a36Sopenharmony_ci /* Clear out old bitmap info first: Either there is none, or we 198962306a36Sopenharmony_ci * are resuming after someone else has possibly changed things, 199062306a36Sopenharmony_ci * so we should forget old cached info. 199162306a36Sopenharmony_ci * All chunks should be clean, but some might need_sync. 199262306a36Sopenharmony_ci */ 199362306a36Sopenharmony_ci while (sector < mddev->resync_max_sectors) { 199462306a36Sopenharmony_ci sector_t blocks; 199562306a36Sopenharmony_ci md_bitmap_start_sync(bitmap, sector, &blocks, 0); 199662306a36Sopenharmony_ci sector += blocks; 199762306a36Sopenharmony_ci } 199862306a36Sopenharmony_ci md_bitmap_close_sync(bitmap); 199962306a36Sopenharmony_ci 200062306a36Sopenharmony_ci if (mddev->degraded == 0 200162306a36Sopenharmony_ci || bitmap->events_cleared == mddev->events) 200262306a36Sopenharmony_ci /* no need to keep dirty bits to optimise a 200362306a36Sopenharmony_ci * re-add of a missing device */ 200462306a36Sopenharmony_ci start = mddev->recovery_cp; 200562306a36Sopenharmony_ci 200662306a36Sopenharmony_ci mutex_lock(&mddev->bitmap_info.mutex); 200762306a36Sopenharmony_ci err = md_bitmap_init_from_disk(bitmap, start); 200862306a36Sopenharmony_ci mutex_unlock(&mddev->bitmap_info.mutex); 200962306a36Sopenharmony_ci 201062306a36Sopenharmony_ci if (err) 201162306a36Sopenharmony_ci goto out; 201262306a36Sopenharmony_ci clear_bit(BITMAP_STALE, &bitmap->flags); 201362306a36Sopenharmony_ci 201462306a36Sopenharmony_ci /* Kick recovery in case any bits were set */ 201562306a36Sopenharmony_ci set_bit(MD_RECOVERY_NEEDED, &bitmap->mddev->recovery); 201662306a36Sopenharmony_ci 201762306a36Sopenharmony_ci mddev_set_timeout(mddev, mddev->bitmap_info.daemon_sleep, true); 201862306a36Sopenharmony_ci md_wakeup_thread(mddev->thread); 201962306a36Sopenharmony_ci 202062306a36Sopenharmony_ci md_bitmap_update_sb(bitmap); 202162306a36Sopenharmony_ci 202262306a36Sopenharmony_ci if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags)) 202362306a36Sopenharmony_ci err = -EIO; 202462306a36Sopenharmony_ciout: 202562306a36Sopenharmony_ci return err; 202662306a36Sopenharmony_ci} 202762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(md_bitmap_load); 202862306a36Sopenharmony_ci 202962306a36Sopenharmony_ci/* caller need to free returned bitmap with md_bitmap_free() */ 203062306a36Sopenharmony_cistruct bitmap *get_bitmap_from_slot(struct mddev *mddev, int slot) 203162306a36Sopenharmony_ci{ 203262306a36Sopenharmony_ci int rv = 0; 203362306a36Sopenharmony_ci struct bitmap *bitmap; 203462306a36Sopenharmony_ci 203562306a36Sopenharmony_ci bitmap = md_bitmap_create(mddev, slot); 203662306a36Sopenharmony_ci if (IS_ERR(bitmap)) { 203762306a36Sopenharmony_ci rv = PTR_ERR(bitmap); 203862306a36Sopenharmony_ci return ERR_PTR(rv); 203962306a36Sopenharmony_ci } 204062306a36Sopenharmony_ci 204162306a36Sopenharmony_ci rv = md_bitmap_init_from_disk(bitmap, 0); 204262306a36Sopenharmony_ci if (rv) { 204362306a36Sopenharmony_ci md_bitmap_free(bitmap); 204462306a36Sopenharmony_ci return ERR_PTR(rv); 204562306a36Sopenharmony_ci } 204662306a36Sopenharmony_ci 204762306a36Sopenharmony_ci return bitmap; 204862306a36Sopenharmony_ci} 204962306a36Sopenharmony_ciEXPORT_SYMBOL(get_bitmap_from_slot); 205062306a36Sopenharmony_ci 205162306a36Sopenharmony_ci/* Loads the bitmap associated with slot and copies the resync information 205262306a36Sopenharmony_ci * to our bitmap 205362306a36Sopenharmony_ci */ 205462306a36Sopenharmony_ciint md_bitmap_copy_from_slot(struct mddev *mddev, int slot, 205562306a36Sopenharmony_ci sector_t *low, sector_t *high, bool clear_bits) 205662306a36Sopenharmony_ci{ 205762306a36Sopenharmony_ci int rv = 0, i, j; 205862306a36Sopenharmony_ci sector_t block, lo = 0, hi = 0; 205962306a36Sopenharmony_ci struct bitmap_counts *counts; 206062306a36Sopenharmony_ci struct bitmap *bitmap; 206162306a36Sopenharmony_ci 206262306a36Sopenharmony_ci bitmap = get_bitmap_from_slot(mddev, slot); 206362306a36Sopenharmony_ci if (IS_ERR(bitmap)) { 206462306a36Sopenharmony_ci pr_err("%s can't get bitmap from slot %d\n", __func__, slot); 206562306a36Sopenharmony_ci return -1; 206662306a36Sopenharmony_ci } 206762306a36Sopenharmony_ci 206862306a36Sopenharmony_ci counts = &bitmap->counts; 206962306a36Sopenharmony_ci for (j = 0; j < counts->chunks; j++) { 207062306a36Sopenharmony_ci block = (sector_t)j << counts->chunkshift; 207162306a36Sopenharmony_ci if (md_bitmap_file_test_bit(bitmap, block)) { 207262306a36Sopenharmony_ci if (!lo) 207362306a36Sopenharmony_ci lo = block; 207462306a36Sopenharmony_ci hi = block; 207562306a36Sopenharmony_ci md_bitmap_file_clear_bit(bitmap, block); 207662306a36Sopenharmony_ci md_bitmap_set_memory_bits(mddev->bitmap, block, 1); 207762306a36Sopenharmony_ci md_bitmap_file_set_bit(mddev->bitmap, block); 207862306a36Sopenharmony_ci } 207962306a36Sopenharmony_ci } 208062306a36Sopenharmony_ci 208162306a36Sopenharmony_ci if (clear_bits) { 208262306a36Sopenharmony_ci md_bitmap_update_sb(bitmap); 208362306a36Sopenharmony_ci /* BITMAP_PAGE_PENDING is set, but bitmap_unplug needs 208462306a36Sopenharmony_ci * BITMAP_PAGE_DIRTY or _NEEDWRITE to write ... */ 208562306a36Sopenharmony_ci for (i = 0; i < bitmap->storage.file_pages; i++) 208662306a36Sopenharmony_ci if (test_page_attr(bitmap, i, BITMAP_PAGE_PENDING)) 208762306a36Sopenharmony_ci set_page_attr(bitmap, i, BITMAP_PAGE_NEEDWRITE); 208862306a36Sopenharmony_ci md_bitmap_unplug(bitmap); 208962306a36Sopenharmony_ci } 209062306a36Sopenharmony_ci md_bitmap_unplug(mddev->bitmap); 209162306a36Sopenharmony_ci *low = lo; 209262306a36Sopenharmony_ci *high = hi; 209362306a36Sopenharmony_ci md_bitmap_free(bitmap); 209462306a36Sopenharmony_ci 209562306a36Sopenharmony_ci return rv; 209662306a36Sopenharmony_ci} 209762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(md_bitmap_copy_from_slot); 209862306a36Sopenharmony_ci 209962306a36Sopenharmony_ci 210062306a36Sopenharmony_civoid md_bitmap_status(struct seq_file *seq, struct bitmap *bitmap) 210162306a36Sopenharmony_ci{ 210262306a36Sopenharmony_ci unsigned long chunk_kb; 210362306a36Sopenharmony_ci struct bitmap_counts *counts; 210462306a36Sopenharmony_ci 210562306a36Sopenharmony_ci if (!bitmap) 210662306a36Sopenharmony_ci return; 210762306a36Sopenharmony_ci 210862306a36Sopenharmony_ci counts = &bitmap->counts; 210962306a36Sopenharmony_ci 211062306a36Sopenharmony_ci chunk_kb = bitmap->mddev->bitmap_info.chunksize >> 10; 211162306a36Sopenharmony_ci seq_printf(seq, "bitmap: %lu/%lu pages [%luKB], " 211262306a36Sopenharmony_ci "%lu%s chunk", 211362306a36Sopenharmony_ci counts->pages - counts->missing_pages, 211462306a36Sopenharmony_ci counts->pages, 211562306a36Sopenharmony_ci (counts->pages - counts->missing_pages) 211662306a36Sopenharmony_ci << (PAGE_SHIFT - 10), 211762306a36Sopenharmony_ci chunk_kb ? chunk_kb : bitmap->mddev->bitmap_info.chunksize, 211862306a36Sopenharmony_ci chunk_kb ? "KB" : "B"); 211962306a36Sopenharmony_ci if (bitmap->storage.file) { 212062306a36Sopenharmony_ci seq_printf(seq, ", file: "); 212162306a36Sopenharmony_ci seq_file_path(seq, bitmap->storage.file, " \t\n"); 212262306a36Sopenharmony_ci } 212362306a36Sopenharmony_ci 212462306a36Sopenharmony_ci seq_printf(seq, "\n"); 212562306a36Sopenharmony_ci} 212662306a36Sopenharmony_ci 212762306a36Sopenharmony_ciint md_bitmap_resize(struct bitmap *bitmap, sector_t blocks, 212862306a36Sopenharmony_ci int chunksize, int init) 212962306a36Sopenharmony_ci{ 213062306a36Sopenharmony_ci /* If chunk_size is 0, choose an appropriate chunk size. 213162306a36Sopenharmony_ci * Then possibly allocate new storage space. 213262306a36Sopenharmony_ci * Then quiesce, copy bits, replace bitmap, and re-start 213362306a36Sopenharmony_ci * 213462306a36Sopenharmony_ci * This function is called both to set up the initial bitmap 213562306a36Sopenharmony_ci * and to resize the bitmap while the array is active. 213662306a36Sopenharmony_ci * If this happens as a result of the array being resized, 213762306a36Sopenharmony_ci * chunksize will be zero, and we need to choose a suitable 213862306a36Sopenharmony_ci * chunksize, otherwise we use what we are given. 213962306a36Sopenharmony_ci */ 214062306a36Sopenharmony_ci struct bitmap_storage store; 214162306a36Sopenharmony_ci struct bitmap_counts old_counts; 214262306a36Sopenharmony_ci unsigned long chunks; 214362306a36Sopenharmony_ci sector_t block; 214462306a36Sopenharmony_ci sector_t old_blocks, new_blocks; 214562306a36Sopenharmony_ci int chunkshift; 214662306a36Sopenharmony_ci int ret = 0; 214762306a36Sopenharmony_ci long pages; 214862306a36Sopenharmony_ci struct bitmap_page *new_bp; 214962306a36Sopenharmony_ci 215062306a36Sopenharmony_ci if (bitmap->storage.file && !init) { 215162306a36Sopenharmony_ci pr_info("md: cannot resize file-based bitmap\n"); 215262306a36Sopenharmony_ci return -EINVAL; 215362306a36Sopenharmony_ci } 215462306a36Sopenharmony_ci 215562306a36Sopenharmony_ci if (chunksize == 0) { 215662306a36Sopenharmony_ci /* If there is enough space, leave the chunk size unchanged, 215762306a36Sopenharmony_ci * else increase by factor of two until there is enough space. 215862306a36Sopenharmony_ci */ 215962306a36Sopenharmony_ci long bytes; 216062306a36Sopenharmony_ci long space = bitmap->mddev->bitmap_info.space; 216162306a36Sopenharmony_ci 216262306a36Sopenharmony_ci if (space == 0) { 216362306a36Sopenharmony_ci /* We don't know how much space there is, so limit 216462306a36Sopenharmony_ci * to current size - in sectors. 216562306a36Sopenharmony_ci */ 216662306a36Sopenharmony_ci bytes = DIV_ROUND_UP(bitmap->counts.chunks, 8); 216762306a36Sopenharmony_ci if (!bitmap->mddev->bitmap_info.external) 216862306a36Sopenharmony_ci bytes += sizeof(bitmap_super_t); 216962306a36Sopenharmony_ci space = DIV_ROUND_UP(bytes, 512); 217062306a36Sopenharmony_ci bitmap->mddev->bitmap_info.space = space; 217162306a36Sopenharmony_ci } 217262306a36Sopenharmony_ci chunkshift = bitmap->counts.chunkshift; 217362306a36Sopenharmony_ci chunkshift--; 217462306a36Sopenharmony_ci do { 217562306a36Sopenharmony_ci /* 'chunkshift' is shift from block size to chunk size */ 217662306a36Sopenharmony_ci chunkshift++; 217762306a36Sopenharmony_ci chunks = DIV_ROUND_UP_SECTOR_T(blocks, 1 << chunkshift); 217862306a36Sopenharmony_ci bytes = DIV_ROUND_UP(chunks, 8); 217962306a36Sopenharmony_ci if (!bitmap->mddev->bitmap_info.external) 218062306a36Sopenharmony_ci bytes += sizeof(bitmap_super_t); 218162306a36Sopenharmony_ci } while (bytes > (space << 9) && (chunkshift + BITMAP_BLOCK_SHIFT) < 218262306a36Sopenharmony_ci (BITS_PER_BYTE * sizeof(((bitmap_super_t *)0)->chunksize) - 1)); 218362306a36Sopenharmony_ci } else 218462306a36Sopenharmony_ci chunkshift = ffz(~chunksize) - BITMAP_BLOCK_SHIFT; 218562306a36Sopenharmony_ci 218662306a36Sopenharmony_ci chunks = DIV_ROUND_UP_SECTOR_T(blocks, 1 << chunkshift); 218762306a36Sopenharmony_ci memset(&store, 0, sizeof(store)); 218862306a36Sopenharmony_ci if (bitmap->mddev->bitmap_info.offset || bitmap->mddev->bitmap_info.file) 218962306a36Sopenharmony_ci ret = md_bitmap_storage_alloc(&store, chunks, 219062306a36Sopenharmony_ci !bitmap->mddev->bitmap_info.external, 219162306a36Sopenharmony_ci mddev_is_clustered(bitmap->mddev) 219262306a36Sopenharmony_ci ? bitmap->cluster_slot : 0); 219362306a36Sopenharmony_ci if (ret) { 219462306a36Sopenharmony_ci md_bitmap_file_unmap(&store); 219562306a36Sopenharmony_ci goto err; 219662306a36Sopenharmony_ci } 219762306a36Sopenharmony_ci 219862306a36Sopenharmony_ci pages = DIV_ROUND_UP(chunks, PAGE_COUNTER_RATIO); 219962306a36Sopenharmony_ci 220062306a36Sopenharmony_ci new_bp = kcalloc(pages, sizeof(*new_bp), GFP_KERNEL); 220162306a36Sopenharmony_ci ret = -ENOMEM; 220262306a36Sopenharmony_ci if (!new_bp) { 220362306a36Sopenharmony_ci md_bitmap_file_unmap(&store); 220462306a36Sopenharmony_ci goto err; 220562306a36Sopenharmony_ci } 220662306a36Sopenharmony_ci 220762306a36Sopenharmony_ci if (!init) 220862306a36Sopenharmony_ci bitmap->mddev->pers->quiesce(bitmap->mddev, 1); 220962306a36Sopenharmony_ci 221062306a36Sopenharmony_ci store.file = bitmap->storage.file; 221162306a36Sopenharmony_ci bitmap->storage.file = NULL; 221262306a36Sopenharmony_ci 221362306a36Sopenharmony_ci if (store.sb_page && bitmap->storage.sb_page) 221462306a36Sopenharmony_ci memcpy(page_address(store.sb_page), 221562306a36Sopenharmony_ci page_address(bitmap->storage.sb_page), 221662306a36Sopenharmony_ci sizeof(bitmap_super_t)); 221762306a36Sopenharmony_ci spin_lock_irq(&bitmap->counts.lock); 221862306a36Sopenharmony_ci md_bitmap_file_unmap(&bitmap->storage); 221962306a36Sopenharmony_ci bitmap->storage = store; 222062306a36Sopenharmony_ci 222162306a36Sopenharmony_ci old_counts = bitmap->counts; 222262306a36Sopenharmony_ci bitmap->counts.bp = new_bp; 222362306a36Sopenharmony_ci bitmap->counts.pages = pages; 222462306a36Sopenharmony_ci bitmap->counts.missing_pages = pages; 222562306a36Sopenharmony_ci bitmap->counts.chunkshift = chunkshift; 222662306a36Sopenharmony_ci bitmap->counts.chunks = chunks; 222762306a36Sopenharmony_ci bitmap->mddev->bitmap_info.chunksize = 1UL << (chunkshift + 222862306a36Sopenharmony_ci BITMAP_BLOCK_SHIFT); 222962306a36Sopenharmony_ci 223062306a36Sopenharmony_ci blocks = min(old_counts.chunks << old_counts.chunkshift, 223162306a36Sopenharmony_ci chunks << chunkshift); 223262306a36Sopenharmony_ci 223362306a36Sopenharmony_ci /* For cluster raid, need to pre-allocate bitmap */ 223462306a36Sopenharmony_ci if (mddev_is_clustered(bitmap->mddev)) { 223562306a36Sopenharmony_ci unsigned long page; 223662306a36Sopenharmony_ci for (page = 0; page < pages; page++) { 223762306a36Sopenharmony_ci ret = md_bitmap_checkpage(&bitmap->counts, page, 1, 1); 223862306a36Sopenharmony_ci if (ret) { 223962306a36Sopenharmony_ci unsigned long k; 224062306a36Sopenharmony_ci 224162306a36Sopenharmony_ci /* deallocate the page memory */ 224262306a36Sopenharmony_ci for (k = 0; k < page; k++) { 224362306a36Sopenharmony_ci kfree(new_bp[k].map); 224462306a36Sopenharmony_ci } 224562306a36Sopenharmony_ci kfree(new_bp); 224662306a36Sopenharmony_ci 224762306a36Sopenharmony_ci /* restore some fields from old_counts */ 224862306a36Sopenharmony_ci bitmap->counts.bp = old_counts.bp; 224962306a36Sopenharmony_ci bitmap->counts.pages = old_counts.pages; 225062306a36Sopenharmony_ci bitmap->counts.missing_pages = old_counts.pages; 225162306a36Sopenharmony_ci bitmap->counts.chunkshift = old_counts.chunkshift; 225262306a36Sopenharmony_ci bitmap->counts.chunks = old_counts.chunks; 225362306a36Sopenharmony_ci bitmap->mddev->bitmap_info.chunksize = 225462306a36Sopenharmony_ci 1UL << (old_counts.chunkshift + BITMAP_BLOCK_SHIFT); 225562306a36Sopenharmony_ci blocks = old_counts.chunks << old_counts.chunkshift; 225662306a36Sopenharmony_ci pr_warn("Could not pre-allocate in-memory bitmap for cluster raid\n"); 225762306a36Sopenharmony_ci break; 225862306a36Sopenharmony_ci } else 225962306a36Sopenharmony_ci bitmap->counts.bp[page].count += 1; 226062306a36Sopenharmony_ci } 226162306a36Sopenharmony_ci } 226262306a36Sopenharmony_ci 226362306a36Sopenharmony_ci for (block = 0; block < blocks; ) { 226462306a36Sopenharmony_ci bitmap_counter_t *bmc_old, *bmc_new; 226562306a36Sopenharmony_ci int set; 226662306a36Sopenharmony_ci 226762306a36Sopenharmony_ci bmc_old = md_bitmap_get_counter(&old_counts, block, &old_blocks, 0); 226862306a36Sopenharmony_ci set = bmc_old && NEEDED(*bmc_old); 226962306a36Sopenharmony_ci 227062306a36Sopenharmony_ci if (set) { 227162306a36Sopenharmony_ci bmc_new = md_bitmap_get_counter(&bitmap->counts, block, &new_blocks, 1); 227262306a36Sopenharmony_ci if (bmc_new) { 227362306a36Sopenharmony_ci if (*bmc_new == 0) { 227462306a36Sopenharmony_ci /* need to set on-disk bits too. */ 227562306a36Sopenharmony_ci sector_t end = block + new_blocks; 227662306a36Sopenharmony_ci sector_t start = block >> chunkshift; 227762306a36Sopenharmony_ci 227862306a36Sopenharmony_ci start <<= chunkshift; 227962306a36Sopenharmony_ci while (start < end) { 228062306a36Sopenharmony_ci md_bitmap_file_set_bit(bitmap, block); 228162306a36Sopenharmony_ci start += 1 << chunkshift; 228262306a36Sopenharmony_ci } 228362306a36Sopenharmony_ci *bmc_new = 2; 228462306a36Sopenharmony_ci md_bitmap_count_page(&bitmap->counts, block, 1); 228562306a36Sopenharmony_ci md_bitmap_set_pending(&bitmap->counts, block); 228662306a36Sopenharmony_ci } 228762306a36Sopenharmony_ci *bmc_new |= NEEDED_MASK; 228862306a36Sopenharmony_ci } 228962306a36Sopenharmony_ci if (new_blocks < old_blocks) 229062306a36Sopenharmony_ci old_blocks = new_blocks; 229162306a36Sopenharmony_ci } 229262306a36Sopenharmony_ci block += old_blocks; 229362306a36Sopenharmony_ci } 229462306a36Sopenharmony_ci 229562306a36Sopenharmony_ci if (bitmap->counts.bp != old_counts.bp) { 229662306a36Sopenharmony_ci unsigned long k; 229762306a36Sopenharmony_ci for (k = 0; k < old_counts.pages; k++) 229862306a36Sopenharmony_ci if (!old_counts.bp[k].hijacked) 229962306a36Sopenharmony_ci kfree(old_counts.bp[k].map); 230062306a36Sopenharmony_ci kfree(old_counts.bp); 230162306a36Sopenharmony_ci } 230262306a36Sopenharmony_ci 230362306a36Sopenharmony_ci if (!init) { 230462306a36Sopenharmony_ci int i; 230562306a36Sopenharmony_ci while (block < (chunks << chunkshift)) { 230662306a36Sopenharmony_ci bitmap_counter_t *bmc; 230762306a36Sopenharmony_ci bmc = md_bitmap_get_counter(&bitmap->counts, block, &new_blocks, 1); 230862306a36Sopenharmony_ci if (bmc) { 230962306a36Sopenharmony_ci /* new space. It needs to be resynced, so 231062306a36Sopenharmony_ci * we set NEEDED_MASK. 231162306a36Sopenharmony_ci */ 231262306a36Sopenharmony_ci if (*bmc == 0) { 231362306a36Sopenharmony_ci *bmc = NEEDED_MASK | 2; 231462306a36Sopenharmony_ci md_bitmap_count_page(&bitmap->counts, block, 1); 231562306a36Sopenharmony_ci md_bitmap_set_pending(&bitmap->counts, block); 231662306a36Sopenharmony_ci } 231762306a36Sopenharmony_ci } 231862306a36Sopenharmony_ci block += new_blocks; 231962306a36Sopenharmony_ci } 232062306a36Sopenharmony_ci for (i = 0; i < bitmap->storage.file_pages; i++) 232162306a36Sopenharmony_ci set_page_attr(bitmap, i, BITMAP_PAGE_DIRTY); 232262306a36Sopenharmony_ci } 232362306a36Sopenharmony_ci spin_unlock_irq(&bitmap->counts.lock); 232462306a36Sopenharmony_ci 232562306a36Sopenharmony_ci if (!init) { 232662306a36Sopenharmony_ci md_bitmap_unplug(bitmap); 232762306a36Sopenharmony_ci bitmap->mddev->pers->quiesce(bitmap->mddev, 0); 232862306a36Sopenharmony_ci } 232962306a36Sopenharmony_ci ret = 0; 233062306a36Sopenharmony_cierr: 233162306a36Sopenharmony_ci return ret; 233262306a36Sopenharmony_ci} 233362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(md_bitmap_resize); 233462306a36Sopenharmony_ci 233562306a36Sopenharmony_cistatic ssize_t 233662306a36Sopenharmony_cilocation_show(struct mddev *mddev, char *page) 233762306a36Sopenharmony_ci{ 233862306a36Sopenharmony_ci ssize_t len; 233962306a36Sopenharmony_ci if (mddev->bitmap_info.file) 234062306a36Sopenharmony_ci len = sprintf(page, "file"); 234162306a36Sopenharmony_ci else if (mddev->bitmap_info.offset) 234262306a36Sopenharmony_ci len = sprintf(page, "%+lld", (long long)mddev->bitmap_info.offset); 234362306a36Sopenharmony_ci else 234462306a36Sopenharmony_ci len = sprintf(page, "none"); 234562306a36Sopenharmony_ci len += sprintf(page+len, "\n"); 234662306a36Sopenharmony_ci return len; 234762306a36Sopenharmony_ci} 234862306a36Sopenharmony_ci 234962306a36Sopenharmony_cistatic ssize_t 235062306a36Sopenharmony_cilocation_store(struct mddev *mddev, const char *buf, size_t len) 235162306a36Sopenharmony_ci{ 235262306a36Sopenharmony_ci int rv; 235362306a36Sopenharmony_ci 235462306a36Sopenharmony_ci rv = mddev_lock(mddev); 235562306a36Sopenharmony_ci if (rv) 235662306a36Sopenharmony_ci return rv; 235762306a36Sopenharmony_ci if (mddev->pers) { 235862306a36Sopenharmony_ci if (!mddev->pers->quiesce) { 235962306a36Sopenharmony_ci rv = -EBUSY; 236062306a36Sopenharmony_ci goto out; 236162306a36Sopenharmony_ci } 236262306a36Sopenharmony_ci if (mddev->recovery || mddev->sync_thread) { 236362306a36Sopenharmony_ci rv = -EBUSY; 236462306a36Sopenharmony_ci goto out; 236562306a36Sopenharmony_ci } 236662306a36Sopenharmony_ci } 236762306a36Sopenharmony_ci 236862306a36Sopenharmony_ci if (mddev->bitmap || mddev->bitmap_info.file || 236962306a36Sopenharmony_ci mddev->bitmap_info.offset) { 237062306a36Sopenharmony_ci /* bitmap already configured. Only option is to clear it */ 237162306a36Sopenharmony_ci if (strncmp(buf, "none", 4) != 0) { 237262306a36Sopenharmony_ci rv = -EBUSY; 237362306a36Sopenharmony_ci goto out; 237462306a36Sopenharmony_ci } 237562306a36Sopenharmony_ci if (mddev->pers) { 237662306a36Sopenharmony_ci mddev_suspend(mddev); 237762306a36Sopenharmony_ci md_bitmap_destroy(mddev); 237862306a36Sopenharmony_ci mddev_resume(mddev); 237962306a36Sopenharmony_ci } 238062306a36Sopenharmony_ci mddev->bitmap_info.offset = 0; 238162306a36Sopenharmony_ci if (mddev->bitmap_info.file) { 238262306a36Sopenharmony_ci struct file *f = mddev->bitmap_info.file; 238362306a36Sopenharmony_ci mddev->bitmap_info.file = NULL; 238462306a36Sopenharmony_ci fput(f); 238562306a36Sopenharmony_ci } 238662306a36Sopenharmony_ci } else { 238762306a36Sopenharmony_ci /* No bitmap, OK to set a location */ 238862306a36Sopenharmony_ci long long offset; 238962306a36Sopenharmony_ci if (strncmp(buf, "none", 4) == 0) 239062306a36Sopenharmony_ci /* nothing to be done */; 239162306a36Sopenharmony_ci else if (strncmp(buf, "file:", 5) == 0) { 239262306a36Sopenharmony_ci /* Not supported yet */ 239362306a36Sopenharmony_ci rv = -EINVAL; 239462306a36Sopenharmony_ci goto out; 239562306a36Sopenharmony_ci } else { 239662306a36Sopenharmony_ci if (buf[0] == '+') 239762306a36Sopenharmony_ci rv = kstrtoll(buf+1, 10, &offset); 239862306a36Sopenharmony_ci else 239962306a36Sopenharmony_ci rv = kstrtoll(buf, 10, &offset); 240062306a36Sopenharmony_ci if (rv) 240162306a36Sopenharmony_ci goto out; 240262306a36Sopenharmony_ci if (offset == 0) { 240362306a36Sopenharmony_ci rv = -EINVAL; 240462306a36Sopenharmony_ci goto out; 240562306a36Sopenharmony_ci } 240662306a36Sopenharmony_ci if (mddev->bitmap_info.external == 0 && 240762306a36Sopenharmony_ci mddev->major_version == 0 && 240862306a36Sopenharmony_ci offset != mddev->bitmap_info.default_offset) { 240962306a36Sopenharmony_ci rv = -EINVAL; 241062306a36Sopenharmony_ci goto out; 241162306a36Sopenharmony_ci } 241262306a36Sopenharmony_ci mddev->bitmap_info.offset = offset; 241362306a36Sopenharmony_ci if (mddev->pers) { 241462306a36Sopenharmony_ci struct bitmap *bitmap; 241562306a36Sopenharmony_ci bitmap = md_bitmap_create(mddev, -1); 241662306a36Sopenharmony_ci mddev_suspend(mddev); 241762306a36Sopenharmony_ci if (IS_ERR(bitmap)) 241862306a36Sopenharmony_ci rv = PTR_ERR(bitmap); 241962306a36Sopenharmony_ci else { 242062306a36Sopenharmony_ci mddev->bitmap = bitmap; 242162306a36Sopenharmony_ci rv = md_bitmap_load(mddev); 242262306a36Sopenharmony_ci if (rv) 242362306a36Sopenharmony_ci mddev->bitmap_info.offset = 0; 242462306a36Sopenharmony_ci } 242562306a36Sopenharmony_ci if (rv) { 242662306a36Sopenharmony_ci md_bitmap_destroy(mddev); 242762306a36Sopenharmony_ci mddev_resume(mddev); 242862306a36Sopenharmony_ci goto out; 242962306a36Sopenharmony_ci } 243062306a36Sopenharmony_ci mddev_resume(mddev); 243162306a36Sopenharmony_ci } 243262306a36Sopenharmony_ci } 243362306a36Sopenharmony_ci } 243462306a36Sopenharmony_ci if (!mddev->external) { 243562306a36Sopenharmony_ci /* Ensure new bitmap info is stored in 243662306a36Sopenharmony_ci * metadata promptly. 243762306a36Sopenharmony_ci */ 243862306a36Sopenharmony_ci set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags); 243962306a36Sopenharmony_ci md_wakeup_thread(mddev->thread); 244062306a36Sopenharmony_ci } 244162306a36Sopenharmony_ci rv = 0; 244262306a36Sopenharmony_ciout: 244362306a36Sopenharmony_ci mddev_unlock(mddev); 244462306a36Sopenharmony_ci if (rv) 244562306a36Sopenharmony_ci return rv; 244662306a36Sopenharmony_ci return len; 244762306a36Sopenharmony_ci} 244862306a36Sopenharmony_ci 244962306a36Sopenharmony_cistatic struct md_sysfs_entry bitmap_location = 245062306a36Sopenharmony_ci__ATTR(location, S_IRUGO|S_IWUSR, location_show, location_store); 245162306a36Sopenharmony_ci 245262306a36Sopenharmony_ci/* 'bitmap/space' is the space available at 'location' for the 245362306a36Sopenharmony_ci * bitmap. This allows the kernel to know when it is safe to 245462306a36Sopenharmony_ci * resize the bitmap to match a resized array. 245562306a36Sopenharmony_ci */ 245662306a36Sopenharmony_cistatic ssize_t 245762306a36Sopenharmony_cispace_show(struct mddev *mddev, char *page) 245862306a36Sopenharmony_ci{ 245962306a36Sopenharmony_ci return sprintf(page, "%lu\n", mddev->bitmap_info.space); 246062306a36Sopenharmony_ci} 246162306a36Sopenharmony_ci 246262306a36Sopenharmony_cistatic ssize_t 246362306a36Sopenharmony_cispace_store(struct mddev *mddev, const char *buf, size_t len) 246462306a36Sopenharmony_ci{ 246562306a36Sopenharmony_ci unsigned long sectors; 246662306a36Sopenharmony_ci int rv; 246762306a36Sopenharmony_ci 246862306a36Sopenharmony_ci rv = kstrtoul(buf, 10, §ors); 246962306a36Sopenharmony_ci if (rv) 247062306a36Sopenharmony_ci return rv; 247162306a36Sopenharmony_ci 247262306a36Sopenharmony_ci if (sectors == 0) 247362306a36Sopenharmony_ci return -EINVAL; 247462306a36Sopenharmony_ci 247562306a36Sopenharmony_ci if (mddev->bitmap && 247662306a36Sopenharmony_ci sectors < (mddev->bitmap->storage.bytes + 511) >> 9) 247762306a36Sopenharmony_ci return -EFBIG; /* Bitmap is too big for this small space */ 247862306a36Sopenharmony_ci 247962306a36Sopenharmony_ci /* could make sure it isn't too big, but that isn't really 248062306a36Sopenharmony_ci * needed - user-space should be careful. 248162306a36Sopenharmony_ci */ 248262306a36Sopenharmony_ci mddev->bitmap_info.space = sectors; 248362306a36Sopenharmony_ci return len; 248462306a36Sopenharmony_ci} 248562306a36Sopenharmony_ci 248662306a36Sopenharmony_cistatic struct md_sysfs_entry bitmap_space = 248762306a36Sopenharmony_ci__ATTR(space, S_IRUGO|S_IWUSR, space_show, space_store); 248862306a36Sopenharmony_ci 248962306a36Sopenharmony_cistatic ssize_t 249062306a36Sopenharmony_citimeout_show(struct mddev *mddev, char *page) 249162306a36Sopenharmony_ci{ 249262306a36Sopenharmony_ci ssize_t len; 249362306a36Sopenharmony_ci unsigned long secs = mddev->bitmap_info.daemon_sleep / HZ; 249462306a36Sopenharmony_ci unsigned long jifs = mddev->bitmap_info.daemon_sleep % HZ; 249562306a36Sopenharmony_ci 249662306a36Sopenharmony_ci len = sprintf(page, "%lu", secs); 249762306a36Sopenharmony_ci if (jifs) 249862306a36Sopenharmony_ci len += sprintf(page+len, ".%03u", jiffies_to_msecs(jifs)); 249962306a36Sopenharmony_ci len += sprintf(page+len, "\n"); 250062306a36Sopenharmony_ci return len; 250162306a36Sopenharmony_ci} 250262306a36Sopenharmony_ci 250362306a36Sopenharmony_cistatic ssize_t 250462306a36Sopenharmony_citimeout_store(struct mddev *mddev, const char *buf, size_t len) 250562306a36Sopenharmony_ci{ 250662306a36Sopenharmony_ci /* timeout can be set at any time */ 250762306a36Sopenharmony_ci unsigned long timeout; 250862306a36Sopenharmony_ci int rv = strict_strtoul_scaled(buf, &timeout, 4); 250962306a36Sopenharmony_ci if (rv) 251062306a36Sopenharmony_ci return rv; 251162306a36Sopenharmony_ci 251262306a36Sopenharmony_ci /* just to make sure we don't overflow... */ 251362306a36Sopenharmony_ci if (timeout >= LONG_MAX / HZ) 251462306a36Sopenharmony_ci return -EINVAL; 251562306a36Sopenharmony_ci 251662306a36Sopenharmony_ci timeout = timeout * HZ / 10000; 251762306a36Sopenharmony_ci 251862306a36Sopenharmony_ci if (timeout >= MAX_SCHEDULE_TIMEOUT) 251962306a36Sopenharmony_ci timeout = MAX_SCHEDULE_TIMEOUT-1; 252062306a36Sopenharmony_ci if (timeout < 1) 252162306a36Sopenharmony_ci timeout = 1; 252262306a36Sopenharmony_ci 252362306a36Sopenharmony_ci mddev->bitmap_info.daemon_sleep = timeout; 252462306a36Sopenharmony_ci mddev_set_timeout(mddev, timeout, false); 252562306a36Sopenharmony_ci md_wakeup_thread(mddev->thread); 252662306a36Sopenharmony_ci 252762306a36Sopenharmony_ci return len; 252862306a36Sopenharmony_ci} 252962306a36Sopenharmony_ci 253062306a36Sopenharmony_cistatic struct md_sysfs_entry bitmap_timeout = 253162306a36Sopenharmony_ci__ATTR(time_base, S_IRUGO|S_IWUSR, timeout_show, timeout_store); 253262306a36Sopenharmony_ci 253362306a36Sopenharmony_cistatic ssize_t 253462306a36Sopenharmony_cibacklog_show(struct mddev *mddev, char *page) 253562306a36Sopenharmony_ci{ 253662306a36Sopenharmony_ci return sprintf(page, "%lu\n", mddev->bitmap_info.max_write_behind); 253762306a36Sopenharmony_ci} 253862306a36Sopenharmony_ci 253962306a36Sopenharmony_cistatic ssize_t 254062306a36Sopenharmony_cibacklog_store(struct mddev *mddev, const char *buf, size_t len) 254162306a36Sopenharmony_ci{ 254262306a36Sopenharmony_ci unsigned long backlog; 254362306a36Sopenharmony_ci unsigned long old_mwb = mddev->bitmap_info.max_write_behind; 254462306a36Sopenharmony_ci struct md_rdev *rdev; 254562306a36Sopenharmony_ci bool has_write_mostly = false; 254662306a36Sopenharmony_ci int rv = kstrtoul(buf, 10, &backlog); 254762306a36Sopenharmony_ci if (rv) 254862306a36Sopenharmony_ci return rv; 254962306a36Sopenharmony_ci if (backlog > COUNTER_MAX) 255062306a36Sopenharmony_ci return -EINVAL; 255162306a36Sopenharmony_ci 255262306a36Sopenharmony_ci rv = mddev_lock(mddev); 255362306a36Sopenharmony_ci if (rv) 255462306a36Sopenharmony_ci return rv; 255562306a36Sopenharmony_ci 255662306a36Sopenharmony_ci /* 255762306a36Sopenharmony_ci * Without write mostly device, it doesn't make sense to set 255862306a36Sopenharmony_ci * backlog for max_write_behind. 255962306a36Sopenharmony_ci */ 256062306a36Sopenharmony_ci rdev_for_each(rdev, mddev) { 256162306a36Sopenharmony_ci if (test_bit(WriteMostly, &rdev->flags)) { 256262306a36Sopenharmony_ci has_write_mostly = true; 256362306a36Sopenharmony_ci break; 256462306a36Sopenharmony_ci } 256562306a36Sopenharmony_ci } 256662306a36Sopenharmony_ci if (!has_write_mostly) { 256762306a36Sopenharmony_ci pr_warn_ratelimited("%s: can't set backlog, no write mostly device available\n", 256862306a36Sopenharmony_ci mdname(mddev)); 256962306a36Sopenharmony_ci mddev_unlock(mddev); 257062306a36Sopenharmony_ci return -EINVAL; 257162306a36Sopenharmony_ci } 257262306a36Sopenharmony_ci 257362306a36Sopenharmony_ci mddev->bitmap_info.max_write_behind = backlog; 257462306a36Sopenharmony_ci if (!backlog && mddev->serial_info_pool) { 257562306a36Sopenharmony_ci /* serial_info_pool is not needed if backlog is zero */ 257662306a36Sopenharmony_ci if (!mddev->serialize_policy) 257762306a36Sopenharmony_ci mddev_destroy_serial_pool(mddev, NULL, false); 257862306a36Sopenharmony_ci } else if (backlog && !mddev->serial_info_pool) { 257962306a36Sopenharmony_ci /* serial_info_pool is needed since backlog is not zero */ 258062306a36Sopenharmony_ci rdev_for_each(rdev, mddev) 258162306a36Sopenharmony_ci mddev_create_serial_pool(mddev, rdev, false); 258262306a36Sopenharmony_ci } 258362306a36Sopenharmony_ci if (old_mwb != backlog) 258462306a36Sopenharmony_ci md_bitmap_update_sb(mddev->bitmap); 258562306a36Sopenharmony_ci 258662306a36Sopenharmony_ci mddev_unlock(mddev); 258762306a36Sopenharmony_ci return len; 258862306a36Sopenharmony_ci} 258962306a36Sopenharmony_ci 259062306a36Sopenharmony_cistatic struct md_sysfs_entry bitmap_backlog = 259162306a36Sopenharmony_ci__ATTR(backlog, S_IRUGO|S_IWUSR, backlog_show, backlog_store); 259262306a36Sopenharmony_ci 259362306a36Sopenharmony_cistatic ssize_t 259462306a36Sopenharmony_cichunksize_show(struct mddev *mddev, char *page) 259562306a36Sopenharmony_ci{ 259662306a36Sopenharmony_ci return sprintf(page, "%lu\n", mddev->bitmap_info.chunksize); 259762306a36Sopenharmony_ci} 259862306a36Sopenharmony_ci 259962306a36Sopenharmony_cistatic ssize_t 260062306a36Sopenharmony_cichunksize_store(struct mddev *mddev, const char *buf, size_t len) 260162306a36Sopenharmony_ci{ 260262306a36Sopenharmony_ci /* Can only be changed when no bitmap is active */ 260362306a36Sopenharmony_ci int rv; 260462306a36Sopenharmony_ci unsigned long csize; 260562306a36Sopenharmony_ci if (mddev->bitmap) 260662306a36Sopenharmony_ci return -EBUSY; 260762306a36Sopenharmony_ci rv = kstrtoul(buf, 10, &csize); 260862306a36Sopenharmony_ci if (rv) 260962306a36Sopenharmony_ci return rv; 261062306a36Sopenharmony_ci if (csize < 512 || 261162306a36Sopenharmony_ci !is_power_of_2(csize)) 261262306a36Sopenharmony_ci return -EINVAL; 261362306a36Sopenharmony_ci if (BITS_PER_LONG > 32 && csize >= (1ULL << (BITS_PER_BYTE * 261462306a36Sopenharmony_ci sizeof(((bitmap_super_t *)0)->chunksize)))) 261562306a36Sopenharmony_ci return -EOVERFLOW; 261662306a36Sopenharmony_ci mddev->bitmap_info.chunksize = csize; 261762306a36Sopenharmony_ci return len; 261862306a36Sopenharmony_ci} 261962306a36Sopenharmony_ci 262062306a36Sopenharmony_cistatic struct md_sysfs_entry bitmap_chunksize = 262162306a36Sopenharmony_ci__ATTR(chunksize, S_IRUGO|S_IWUSR, chunksize_show, chunksize_store); 262262306a36Sopenharmony_ci 262362306a36Sopenharmony_cistatic ssize_t metadata_show(struct mddev *mddev, char *page) 262462306a36Sopenharmony_ci{ 262562306a36Sopenharmony_ci if (mddev_is_clustered(mddev)) 262662306a36Sopenharmony_ci return sprintf(page, "clustered\n"); 262762306a36Sopenharmony_ci return sprintf(page, "%s\n", (mddev->bitmap_info.external 262862306a36Sopenharmony_ci ? "external" : "internal")); 262962306a36Sopenharmony_ci} 263062306a36Sopenharmony_ci 263162306a36Sopenharmony_cistatic ssize_t metadata_store(struct mddev *mddev, const char *buf, size_t len) 263262306a36Sopenharmony_ci{ 263362306a36Sopenharmony_ci if (mddev->bitmap || 263462306a36Sopenharmony_ci mddev->bitmap_info.file || 263562306a36Sopenharmony_ci mddev->bitmap_info.offset) 263662306a36Sopenharmony_ci return -EBUSY; 263762306a36Sopenharmony_ci if (strncmp(buf, "external", 8) == 0) 263862306a36Sopenharmony_ci mddev->bitmap_info.external = 1; 263962306a36Sopenharmony_ci else if ((strncmp(buf, "internal", 8) == 0) || 264062306a36Sopenharmony_ci (strncmp(buf, "clustered", 9) == 0)) 264162306a36Sopenharmony_ci mddev->bitmap_info.external = 0; 264262306a36Sopenharmony_ci else 264362306a36Sopenharmony_ci return -EINVAL; 264462306a36Sopenharmony_ci return len; 264562306a36Sopenharmony_ci} 264662306a36Sopenharmony_ci 264762306a36Sopenharmony_cistatic struct md_sysfs_entry bitmap_metadata = 264862306a36Sopenharmony_ci__ATTR(metadata, S_IRUGO|S_IWUSR, metadata_show, metadata_store); 264962306a36Sopenharmony_ci 265062306a36Sopenharmony_cistatic ssize_t can_clear_show(struct mddev *mddev, char *page) 265162306a36Sopenharmony_ci{ 265262306a36Sopenharmony_ci int len; 265362306a36Sopenharmony_ci spin_lock(&mddev->lock); 265462306a36Sopenharmony_ci if (mddev->bitmap) 265562306a36Sopenharmony_ci len = sprintf(page, "%s\n", (mddev->bitmap->need_sync ? 265662306a36Sopenharmony_ci "false" : "true")); 265762306a36Sopenharmony_ci else 265862306a36Sopenharmony_ci len = sprintf(page, "\n"); 265962306a36Sopenharmony_ci spin_unlock(&mddev->lock); 266062306a36Sopenharmony_ci return len; 266162306a36Sopenharmony_ci} 266262306a36Sopenharmony_ci 266362306a36Sopenharmony_cistatic ssize_t can_clear_store(struct mddev *mddev, const char *buf, size_t len) 266462306a36Sopenharmony_ci{ 266562306a36Sopenharmony_ci if (mddev->bitmap == NULL) 266662306a36Sopenharmony_ci return -ENOENT; 266762306a36Sopenharmony_ci if (strncmp(buf, "false", 5) == 0) 266862306a36Sopenharmony_ci mddev->bitmap->need_sync = 1; 266962306a36Sopenharmony_ci else if (strncmp(buf, "true", 4) == 0) { 267062306a36Sopenharmony_ci if (mddev->degraded) 267162306a36Sopenharmony_ci return -EBUSY; 267262306a36Sopenharmony_ci mddev->bitmap->need_sync = 0; 267362306a36Sopenharmony_ci } else 267462306a36Sopenharmony_ci return -EINVAL; 267562306a36Sopenharmony_ci return len; 267662306a36Sopenharmony_ci} 267762306a36Sopenharmony_ci 267862306a36Sopenharmony_cistatic struct md_sysfs_entry bitmap_can_clear = 267962306a36Sopenharmony_ci__ATTR(can_clear, S_IRUGO|S_IWUSR, can_clear_show, can_clear_store); 268062306a36Sopenharmony_ci 268162306a36Sopenharmony_cistatic ssize_t 268262306a36Sopenharmony_cibehind_writes_used_show(struct mddev *mddev, char *page) 268362306a36Sopenharmony_ci{ 268462306a36Sopenharmony_ci ssize_t ret; 268562306a36Sopenharmony_ci spin_lock(&mddev->lock); 268662306a36Sopenharmony_ci if (mddev->bitmap == NULL) 268762306a36Sopenharmony_ci ret = sprintf(page, "0\n"); 268862306a36Sopenharmony_ci else 268962306a36Sopenharmony_ci ret = sprintf(page, "%lu\n", 269062306a36Sopenharmony_ci mddev->bitmap->behind_writes_used); 269162306a36Sopenharmony_ci spin_unlock(&mddev->lock); 269262306a36Sopenharmony_ci return ret; 269362306a36Sopenharmony_ci} 269462306a36Sopenharmony_ci 269562306a36Sopenharmony_cistatic ssize_t 269662306a36Sopenharmony_cibehind_writes_used_reset(struct mddev *mddev, const char *buf, size_t len) 269762306a36Sopenharmony_ci{ 269862306a36Sopenharmony_ci if (mddev->bitmap) 269962306a36Sopenharmony_ci mddev->bitmap->behind_writes_used = 0; 270062306a36Sopenharmony_ci return len; 270162306a36Sopenharmony_ci} 270262306a36Sopenharmony_ci 270362306a36Sopenharmony_cistatic struct md_sysfs_entry max_backlog_used = 270462306a36Sopenharmony_ci__ATTR(max_backlog_used, S_IRUGO | S_IWUSR, 270562306a36Sopenharmony_ci behind_writes_used_show, behind_writes_used_reset); 270662306a36Sopenharmony_ci 270762306a36Sopenharmony_cistatic struct attribute *md_bitmap_attrs[] = { 270862306a36Sopenharmony_ci &bitmap_location.attr, 270962306a36Sopenharmony_ci &bitmap_space.attr, 271062306a36Sopenharmony_ci &bitmap_timeout.attr, 271162306a36Sopenharmony_ci &bitmap_backlog.attr, 271262306a36Sopenharmony_ci &bitmap_chunksize.attr, 271362306a36Sopenharmony_ci &bitmap_metadata.attr, 271462306a36Sopenharmony_ci &bitmap_can_clear.attr, 271562306a36Sopenharmony_ci &max_backlog_used.attr, 271662306a36Sopenharmony_ci NULL 271762306a36Sopenharmony_ci}; 271862306a36Sopenharmony_ciconst struct attribute_group md_bitmap_group = { 271962306a36Sopenharmony_ci .name = "bitmap", 272062306a36Sopenharmony_ci .attrs = md_bitmap_attrs, 272162306a36Sopenharmony_ci}; 2722