Commit d276bb29 authored by Jens Axboe's avatar Jens Axboe
Browse files

Merge tag 'md-next-20230729' of...

Merge tag 'md-next-20230729' of https://git.kernel.org/pub/scm/linux/kernel/git/song/md into for-6.6/block

Pull MD updates from Song:

"1. Deprecate bitmap file support, by Christoph Hellwig;
 2. Fix deadlock with md sync thread, by Yu Kuai;
 3. Refactor md io accounting, by Yu Kuai;
 4. Various non-urgent fixes by Li Nan, Yu Kuai, and Jack Wang."

* tag 'md-next-20230729' of https://git.kernel.org/pub/scm/linux/kernel/git/song/md: (36 commits)
  md/md-bitmap: hold 'reconfig_mutex' in backlog_store()
  md/md-bitmap: remove unnecessary local variable in backlog_store()
  md/raid10: use dereference_rdev_and_rrdev() to get devices
  md/raid10: factor out dereference_rdev_and_rrdev()
  md/raid10: check replacement and rdev to prevent submit the same io twice
  md/raid1: Avoid lock contention from wake_up()
  md: restore 'noio_flag' for the last mddev_resume()
  md: don't quiesce in mddev_suspend()
  md: remove redundant check in fix_read_error()
  md/raid10: optimize fix_read_error
  md/raid1: prioritize adding disk to 'removed' mirror
  md/md-faulty: enable io accounting
  md/md-linear: enable io accounting
  md/md-multipath: enable io accounting
  md/raid10: switch to use md_account_bio() for io accounting
  md/raid1: switch to use md_account_bio() for io accounting
  raid5: fix missing io accounting in raid5_align_endio()
  md: also clone new io if io accounting is disabled
  md: move initialization and destruction of 'io_acct_set' to md.c
  md: deprecate bitmap file support
  ...
parents 51d74ec9 44abfa6a
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -50,6 +50,16 @@ config MD_AUTODETECT

	  If unsure, say Y.

config MD_BITMAP_FILE
	bool "MD bitmap file support (deprecated)"
	default y
	help
	  If you say Y here, support for write intent bitmaps in files on an
	  external file system is enabled.  This is an alternative to the internal
	  bitmaps near the MD superblock, and very problematic code that abuses
	  various kernel APIs and can only work with files on a file system not
	  actually sitting on the MD device.

config MD_LINEAR
	tristate "Linear (append) mode (deprecated)"
	depends on BLK_DEV_MD
+0 −1
Original line number Diff line number Diff line
@@ -3725,7 +3725,6 @@ static int raid_message(struct dm_target *ti, unsigned int argc, char **argv,
	if (!strcasecmp(argv[0], "idle") || !strcasecmp(argv[0], "frozen")) {
		if (mddev->sync_thread) {
			set_bit(MD_RECOVERY_INTR, &mddev->recovery);
			md_unregister_thread(&mddev->sync_thread);
			md_reap_sync_thread(mddev);
		}
	} else if (decipher_sync_action(mddev, mddev->recovery) != st_idle)
+178 −169
Original line number Diff line number Diff line
@@ -139,30 +139,27 @@ static void md_bitmap_checkfree(struct bitmap_counts *bitmap, unsigned long page
 */

/* IO operations when bitmap is stored near all superblocks */

/* choose a good rdev and read the page from there */
static int read_sb_page(struct mddev *mddev, loff_t offset,
			struct page *page,
			unsigned long index, int size)
		struct page *page, unsigned long index, int size)
{
	/* choose a good rdev and read the page from there */

	sector_t sector = mddev->bitmap_info.offset + offset +
		index * (PAGE_SIZE / SECTOR_SIZE);
	struct md_rdev *rdev;
	sector_t target;

	rdev_for_each(rdev, mddev) {
		if (! test_bit(In_sync, &rdev->flags)
		    || test_bit(Faulty, &rdev->flags)
		    || test_bit(Bitmap_sync, &rdev->flags))
			continue;
		u32 iosize = roundup(size, bdev_logical_block_size(rdev->bdev));

		target = offset + index * (PAGE_SIZE/512);
		if (!test_bit(In_sync, &rdev->flags) ||
		    test_bit(Faulty, &rdev->flags) ||
		    test_bit(Bitmap_sync, &rdev->flags))
			continue;

		if (sync_page_io(rdev, target,
				 roundup(size, bdev_logical_block_size(rdev->bdev)),
				 page, REQ_OP_READ, true)) {
			page->index = index;
		if (sync_page_io(rdev, sector, iosize, page, REQ_OP_READ, true))
			return 0;
	}
	}
	return -EIO;
}

@@ -225,18 +222,19 @@ static unsigned int bitmap_io_size(unsigned int io_size, unsigned int opt_size,
}

static int __write_sb_page(struct md_rdev *rdev, struct bitmap *bitmap,
			   struct page *page)
			   unsigned long pg_index, struct page *page)
{
	struct block_device *bdev;
	struct mddev *mddev = bitmap->mddev;
	struct bitmap_storage *store = &bitmap->storage;
	loff_t sboff, offset = mddev->bitmap_info.offset;
	sector_t ps, doff;
	sector_t ps = pg_index * PAGE_SIZE / SECTOR_SIZE;
	unsigned int size = PAGE_SIZE;
	unsigned int opt_size = PAGE_SIZE;
	sector_t doff;

	bdev = (rdev->meta_bdev) ? rdev->meta_bdev : rdev->bdev;
	if (page->index == store->file_pages - 1) {
	if (pg_index == store->file_pages - 1) {
		unsigned int last_page_size = store->bytes & (PAGE_SIZE - 1);

		if (last_page_size == 0)
@@ -245,7 +243,6 @@ static int __write_sb_page(struct md_rdev *rdev, struct bitmap *bitmap,
		opt_size = optimal_io_size(bdev, last_page_size, size);
	}

	ps = page->index * PAGE_SIZE / SECTOR_SIZE;
	sboff = rdev->sb_start + offset;
	doff = rdev->data_offset;

@@ -279,40 +276,29 @@ static int __write_sb_page(struct md_rdev *rdev, struct bitmap *bitmap,
	return 0;
}

static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
static void write_sb_page(struct bitmap *bitmap, unsigned long pg_index,
			  struct page *page, bool wait)
{
	struct md_rdev *rdev;
	struct mddev *mddev = bitmap->mddev;
	int ret;

	do {
		rdev = NULL;
		struct md_rdev *rdev = NULL;

		while ((rdev = next_active_rdev(rdev, mddev)) != NULL) {
			ret = __write_sb_page(rdev, bitmap, page);
			if (ret)
				return ret;
			if (__write_sb_page(rdev, bitmap, pg_index, page) < 0) {
				set_bit(BITMAP_WRITE_ERROR, &bitmap->flags);
				return;
			}
		}
	} while (wait && md_super_wait(mddev) < 0);

	return 0;
}

static void md_bitmap_file_kick(struct bitmap *bitmap);
/*
 * write out a page to a file
 */
static void write_page(struct bitmap *bitmap, struct page *page, int wait)
{
	struct buffer_head *bh;

	if (bitmap->storage.file == NULL) {
		switch (write_sb_page(bitmap, page, wait)) {
		case -EINVAL:
			set_bit(BITMAP_WRITE_ERROR, &bitmap->flags);
		}
	} else {

		bh = page_buffers(page);
#ifdef CONFIG_MD_BITMAP_FILE
static void write_file_page(struct bitmap *bitmap, struct page *page, int wait)
{
	struct buffer_head *bh = page_buffers(page);

	while (bh && bh->b_blocknr) {
		atomic_inc(&bitmap->pending_writes);
@@ -326,9 +312,6 @@ static void write_page(struct bitmap *bitmap, struct page *page, int wait)
		wait_event(bitmap->write_wait,
			   atomic_read(&bitmap->pending_writes) == 0);
}
	if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags))
		md_bitmap_file_kick(bitmap);
}

static void end_bitmap_write(struct buffer_head *bh, int uptodate)
{
@@ -364,10 +347,8 @@ static void free_buffers(struct page *page)
 * This usage is similar to how swap files are handled, and allows us
 * to write to a file with no concerns of memory allocation failing.
 */
static int read_page(struct file *file, unsigned long index,
		     struct bitmap *bitmap,
		     unsigned long count,
		     struct page *page)
static int read_file_page(struct file *file, unsigned long index,
		struct bitmap *bitmap, unsigned long count, struct page *page)
{
	int ret = 0;
	struct inode *inode = file_inode(file);
@@ -415,7 +396,6 @@ static int read_page(struct file *file, unsigned long index,
		blk_cur++;
		bh = bh->b_this_page;
	}
	page->index = index;

	wait_event(bitmap->write_wait,
		   atomic_read(&bitmap->pending_writes)==0);
@@ -429,11 +409,45 @@ static int read_page(struct file *file, unsigned long index,
		       ret);
	return ret;
}
#else /* CONFIG_MD_BITMAP_FILE */
static void write_file_page(struct bitmap *bitmap, struct page *page, int wait)
{
}
static int read_file_page(struct file *file, unsigned long index,
		struct bitmap *bitmap, unsigned long count, struct page *page)
{
	return -EIO;
}
static void free_buffers(struct page *page)
{
	put_page(page);
}
#endif /* CONFIG_MD_BITMAP_FILE */

/*
 * bitmap file superblock operations
 */

/*
 * write out a page to a file
 */
static void filemap_write_page(struct bitmap *bitmap, unsigned long pg_index,
			       bool wait)
{
	struct bitmap_storage *store = &bitmap->storage;
	struct page *page = store->filemap[pg_index];

	if (mddev_is_clustered(bitmap->mddev)) {
		pg_index += bitmap->cluster_slot *
			DIV_ROUND_UP(store->bytes, PAGE_SIZE);
	}

	if (store->file)
		write_file_page(bitmap, page, wait);
	else
		write_sb_page(bitmap, pg_index, page, wait);
}

/*
 * md_bitmap_wait_writes() should be called before writing any bitmap
 * blocks, to ensure previous writes, particularly from
@@ -488,7 +502,12 @@ void md_bitmap_update_sb(struct bitmap *bitmap)
	sb->sectors_reserved = cpu_to_le32(bitmap->mddev->
					   bitmap_info.space);
	kunmap_atomic(sb);
	write_page(bitmap, bitmap->storage.sb_page, 1);

	if (bitmap->storage.file)
		write_file_page(bitmap, bitmap->storage.sb_page, 1);
	else
		write_sb_page(bitmap, bitmap->storage.sb_index,
			      bitmap->storage.sb_page, 1);
}
EXPORT_SYMBOL(md_bitmap_update_sb);

@@ -540,7 +559,7 @@ static int md_bitmap_new_disk_sb(struct bitmap *bitmap)
	bitmap->storage.sb_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
	if (bitmap->storage.sb_page == NULL)
		return -ENOMEM;
	bitmap->storage.sb_page->index = 0;
	bitmap->storage.sb_index = 0;

	sb = kmap_atomic(bitmap->storage.sb_page);

@@ -601,7 +620,7 @@ static int md_bitmap_read_sb(struct bitmap *bitmap)
	unsigned long sectors_reserved = 0;
	int err = -EINVAL;
	struct page *sb_page;
	loff_t offset = bitmap->mddev->bitmap_info.offset;
	loff_t offset = 0;

	if (!bitmap->storage.file && !bitmap->mddev->bitmap_info.offset) {
		chunksize = 128 * 1024 * 1024;
@@ -628,7 +647,7 @@ static int md_bitmap_read_sb(struct bitmap *bitmap)
		bm_blocks = ((bm_blocks+7) >> 3) + sizeof(bitmap_super_t);
		/* to 4k blocks */
		bm_blocks = DIV_ROUND_UP_SECTOR_T(bm_blocks, 4096);
		offset = bitmap->mddev->bitmap_info.offset + (bitmap->cluster_slot * (bm_blocks << 3));
		offset = bitmap->cluster_slot * (bm_blocks << 3);
		pr_debug("%s:%d bm slot: %d offset: %llu\n", __func__, __LINE__,
			bitmap->cluster_slot, offset);
	}
@@ -637,13 +656,11 @@ static int md_bitmap_read_sb(struct bitmap *bitmap)
		loff_t isize = i_size_read(bitmap->storage.file->f_mapping->host);
		int bytes = isize > PAGE_SIZE ? PAGE_SIZE : isize;

		err = read_page(bitmap->storage.file, 0,
		err = read_file_page(bitmap->storage.file, 0,
				bitmap, bytes, sb_page);
	} else {
		err = read_sb_page(bitmap->mddev,
				   offset,
				   sb_page,
				   0, sizeof(bitmap_super_t));
		err = read_sb_page(bitmap->mddev, offset, sb_page, 0,
				   sizeof(bitmap_super_t));
	}
	if (err)
		return err;
@@ -819,7 +836,7 @@ static int md_bitmap_storage_alloc(struct bitmap_storage *store,
	if (store->sb_page) {
		store->filemap[0] = store->sb_page;
		pnum = 1;
		store->sb_page->index = offset;
		store->sb_index = offset;
	}

	for ( ; pnum < num_pages; pnum++) {
@@ -828,7 +845,6 @@ static int md_bitmap_storage_alloc(struct bitmap_storage *store,
			store->file_pages = pnum;
			return -ENOMEM;
		}
		store->filemap[pnum]->index = pnum + offset;
	}
	store->file_pages = pnum;

@@ -847,14 +863,10 @@ static int md_bitmap_storage_alloc(struct bitmap_storage *store,

static void md_bitmap_file_unmap(struct bitmap_storage *store)
{
	struct page **map, *sb_page;
	int pages;
	struct file *file;

	file = store->file;
	map = store->filemap;
	pages = store->file_pages;
	sb_page = store->sb_page;
	struct file *file = store->file;
	struct page *sb_page = store->sb_page;
	struct page **map = store->filemap;
	int pages = store->file_pages;

	while (pages--)
		if (map[pages] != sb_page) /* 0 is sb_page, release it below */
@@ -879,21 +891,13 @@ static void md_bitmap_file_unmap(struct bitmap_storage *store)
 */
static void md_bitmap_file_kick(struct bitmap *bitmap)
{
	char *path, *ptr = NULL;

	if (!test_and_set_bit(BITMAP_STALE, &bitmap->flags)) {
		md_bitmap_update_sb(bitmap);

		if (bitmap->storage.file) {
			path = kmalloc(PAGE_SIZE, GFP_KERNEL);
			if (path)
				ptr = file_path(bitmap->storage.file,
					     path, PAGE_SIZE);

			pr_warn("%s: kicking failed bitmap file %s from array!\n",
				bmname(bitmap), IS_ERR(ptr) ? "" : ptr);
			pr_warn("%s: kicking failed bitmap file %pD4 from array!\n",
				bmname(bitmap), bitmap->storage.file);

			kfree(path);
		} else
			pr_warn("%s: disabling internal bitmap due to errors\n",
				bmname(bitmap));
@@ -945,6 +949,7 @@ static void md_bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
	void *kaddr;
	unsigned long chunk = block >> bitmap->counts.chunkshift;
	struct bitmap_storage *store = &bitmap->storage;
	unsigned long index = file_page_index(store, chunk);
	unsigned long node_offset = 0;

	if (mddev_is_clustered(bitmap->mddev))
@@ -962,9 +967,9 @@ static void md_bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
	else
		set_bit_le(bit, kaddr);
	kunmap_atomic(kaddr);
	pr_debug("set file bit %lu page %lu\n", bit, page->index);
	pr_debug("set file bit %lu page %lu\n", bit, index);
	/* record page number so it gets flushed to disk when unplug occurs */
	set_page_attr(bitmap, page->index - node_offset, BITMAP_PAGE_DIRTY);
	set_page_attr(bitmap, index - node_offset, BITMAP_PAGE_DIRTY);
}

static void md_bitmap_file_clear_bit(struct bitmap *bitmap, sector_t block)
@@ -974,6 +979,7 @@ static void md_bitmap_file_clear_bit(struct bitmap *bitmap, sector_t block)
	void *paddr;
	unsigned long chunk = block >> bitmap->counts.chunkshift;
	struct bitmap_storage *store = &bitmap->storage;
	unsigned long index = file_page_index(store, chunk);
	unsigned long node_offset = 0;

	if (mddev_is_clustered(bitmap->mddev))
@@ -989,8 +995,8 @@ static void md_bitmap_file_clear_bit(struct bitmap *bitmap, sector_t block)
	else
		clear_bit_le(bit, paddr);
	kunmap_atomic(paddr);
	if (!test_page_attr(bitmap, page->index - node_offset, BITMAP_PAGE_NEEDWRITE)) {
		set_page_attr(bitmap, page->index - node_offset, BITMAP_PAGE_PENDING);
	if (!test_page_attr(bitmap, index - node_offset, BITMAP_PAGE_NEEDWRITE)) {
		set_page_attr(bitmap, index - node_offset, BITMAP_PAGE_PENDING);
		bitmap->allclean = 0;
	}
}
@@ -1042,7 +1048,7 @@ void md_bitmap_unplug(struct bitmap *bitmap)
							  "md bitmap_unplug");
			}
			clear_page_attr(bitmap, i, BITMAP_PAGE_PENDING);
			write_page(bitmap, bitmap->storage.filemap[i], 0);
			filemap_write_page(bitmap, i, false);
			writing = 1;
		}
	}
@@ -1084,33 +1090,31 @@ void md_bitmap_unplug_async(struct bitmap *bitmap)
EXPORT_SYMBOL(md_bitmap_unplug_async);

static void md_bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed);
/* * bitmap_init_from_disk -- called at bitmap_create time to initialize
 * the in-memory bitmap from the on-disk bitmap -- also, sets up the
 * memory mapping of the bitmap file
 * Special cases:
 *   if there's no bitmap file, or if the bitmap file had been
 *   previously kicked from the array, we mark all the bits as
 *   1's in order to cause a full resync.

/*
 * Initialize the in-memory bitmap from the on-disk bitmap and set up the memory
 * mapping of the bitmap file.
 *
 * Special case: If there's no bitmap file, or if the bitmap file had been
 * previously kicked from the array, we mark all the bits as 1's in order to
 * cause a full resync.
 *
 * We ignore all bits for sectors that end earlier than 'start'.
 * This is used when reading an out-of-date bitmap...
 * This is used when reading an out-of-date bitmap.
 */
static int md_bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
{
	unsigned long i, chunks, index, oldindex, bit, node_offset = 0;
	struct page *page = NULL;
	unsigned long bit_cnt = 0;
	struct file *file;
	unsigned long offset;
	int outofdate;
	int ret = -ENOSPC;
	void *paddr;
	bool outofdate = test_bit(BITMAP_STALE, &bitmap->flags);
	struct mddev *mddev = bitmap->mddev;
	unsigned long chunks = bitmap->counts.chunks;
	struct bitmap_storage *store = &bitmap->storage;
	struct file *file = store->file;
	unsigned long node_offset = 0;
	unsigned long bit_cnt = 0;
	unsigned long i;
	int ret;

	chunks = bitmap->counts.chunks;
	file = store->file;

	if (!file && !bitmap->mddev->bitmap_info.offset) {
	if (!file && !mddev->bitmap_info.offset) {
		/* No permanent bitmap - fill with '1s'. */
		store->filemap = NULL;
		store->file_pages = 0;
@@ -1125,77 +1129,79 @@ static int md_bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
		return 0;
	}

	outofdate = test_bit(BITMAP_STALE, &bitmap->flags);
	if (outofdate)
		pr_warn("%s: bitmap file is out of date, doing full recovery\n", bmname(bitmap));

	if (file && i_size_read(file->f_mapping->host) < store->bytes) {
		pr_warn("%s: bitmap file too short %lu < %lu\n",
			bmname(bitmap),
			(unsigned long) i_size_read(file->f_mapping->host),
			store->bytes);
		ret = -ENOSPC;
		goto err;
	}

	oldindex = ~0L;
	offset = 0;
	if (!bitmap->mddev->bitmap_info.external)
		offset = sizeof(bitmap_super_t);

	if (mddev_is_clustered(bitmap->mddev))
	if (mddev_is_clustered(mddev))
		node_offset = bitmap->cluster_slot * (DIV_ROUND_UP(store->bytes, PAGE_SIZE));

	for (i = 0; i < chunks; i++) {
		int b;
		index = file_page_index(&bitmap->storage, i);
		bit = file_page_offset(&bitmap->storage, i);
		if (index != oldindex) { /* this is a new page, read it in */
	for (i = 0; i < store->file_pages; i++) {
		struct page *page = store->filemap[i];
		int count;

		/* unmap the old page, we're done with it */
			if (index == store->file_pages-1)
				count = store->bytes - index * PAGE_SIZE;
		if (i == store->file_pages - 1)
			count = store->bytes - i * PAGE_SIZE;
		else
			count = PAGE_SIZE;
			page = store->filemap[index];

		if (file)
				ret = read_page(file, index, bitmap,
						count, page);
			ret = read_file_page(file, i, bitmap, count, page);
		else
				ret = read_sb_page(
					bitmap->mddev,
					bitmap->mddev->bitmap_info.offset,
					page,
					index + node_offset, count);

			ret = read_sb_page(mddev, 0, page, i + node_offset,
					   count);
		if (ret)
			goto err;

			oldindex = index;
	}

	if (outofdate) {
		pr_warn("%s: bitmap file is out of date, doing full recovery\n",
			bmname(bitmap));

		for (i = 0; i < store->file_pages; i++) {
			struct page *page = store->filemap[i];
			unsigned long offset = 0;
			void *paddr;

			if (i == 0 && !mddev->bitmap_info.external)
				offset = sizeof(bitmap_super_t);

			/*
				 * if bitmap is out of date, dirty the
				 * whole page and write it out
			 * If the bitmap is out of date, dirty the whole page
			 * and write it out
			 */
			paddr = kmap_atomic(page);
				memset(paddr + offset, 0xff,
				       PAGE_SIZE - offset);
			memset(paddr + offset, 0xff, PAGE_SIZE - offset);
			kunmap_atomic(paddr);
				write_page(bitmap, page, 1);

			filemap_write_page(bitmap, i, true);
			if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags)) {
				ret = -EIO;
				if (test_bit(BITMAP_WRITE_ERROR,
					     &bitmap->flags))
				goto err;
			}
		}
	}

	for (i = 0; i < chunks; i++) {
		struct page *page = filemap_get_page(&bitmap->storage, i);
		unsigned long bit = file_page_offset(&bitmap->storage, i);
		void *paddr;
		bool was_set;

		paddr = kmap_atomic(page);
		if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags))
			b = test_bit(bit, paddr);
			was_set = test_bit(bit, paddr);
		else
			b = test_bit_le(bit, paddr);
			was_set = test_bit_le(bit, paddr);
		kunmap_atomic(paddr);
		if (b) {

		if (was_set) {
			/* if the disk bit is set, set the memory bit */
			int needed = ((sector_t)(i+1) << bitmap->counts.chunkshift
				      >= start);
@@ -1204,7 +1210,6 @@ static int md_bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
						  needed);
			bit_cnt++;
		}
		offset = 0;
	}

	pr_debug("%s: bitmap initialized from disk: read %lu pages, set %lu of %lu bits\n",
@@ -1396,9 +1401,8 @@ void md_bitmap_daemon_work(struct mddev *mddev)
			break;
		if (bitmap->storage.filemap &&
		    test_and_clear_page_attr(bitmap, j,
					     BITMAP_PAGE_NEEDWRITE)) {
			write_page(bitmap, bitmap->storage.filemap[j], 0);
		}
					     BITMAP_PAGE_NEEDWRITE))
			filemap_write_page(bitmap, j, false);
	}

 done:
@@ -2542,6 +2546,10 @@ backlog_store(struct mddev *mddev, const char *buf, size_t len)
	if (backlog > COUNTER_MAX)
		return -EINVAL;

	rv = mddev_lock(mddev);
	if (rv)
		return rv;

	/*
	 * Without write mostly device, it doesn't make sense to set
	 * backlog for max_write_behind.
@@ -2555,6 +2563,7 @@ backlog_store(struct mddev *mddev, const char *buf, size_t len)
	if (!has_write_mostly) {
		pr_warn_ratelimited("%s: can't set backlog, no write mostly device available\n",
				    mdname(mddev));
		mddev_unlock(mddev);
		return -EINVAL;
	}

@@ -2565,13 +2574,13 @@ backlog_store(struct mddev *mddev, const char *buf, size_t len)
			mddev_destroy_serial_pool(mddev, NULL, false);
	} else if (backlog && !mddev->serial_info_pool) {
		/* serial_info_pool is needed since backlog is not zero */
		struct md_rdev *rdev;

		rdev_for_each(rdev, mddev)
			mddev_create_serial_pool(mddev, rdev, false);
	}
	if (old_mwb != backlog)
		md_bitmap_update_sb(mddev->bitmap);

	mddev_unlock(mddev);
	return len;
}

+1 −0
Original line number Diff line number Diff line
@@ -201,6 +201,7 @@ struct bitmap {
		struct file *file;		/* backing disk file */
		struct page *sb_page;		/* cached copy of the bitmap
						 * file superblock */
		unsigned long sb_index;
		struct page **filemap;		/* list of cache pages for
						 * the file */
		unsigned long *filemap_attr;	/* attributes associated
+2 −0
Original line number Diff line number Diff line
@@ -204,6 +204,8 @@ static bool faulty_make_request(struct mddev *mddev, struct bio *bio)
			failit = 1;
		}
	}

	md_account_bio(mddev, &bio);
	if (failit) {
		struct bio *b = bio_alloc_clone(conf->rdev->bdev, bio, GFP_NOIO,
						&mddev->bio_set);
Loading