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

Merge tag 'md-6.14-20250113' of...

Merge tag 'md-6.14-20250113' of https://git.kernel.org/pub/scm/linux/kernel/git/mdraid/linux into for-6.14/block

Pull MD updates from Song:

"1. Reintroduce md-linear, by Yu Kuai.
 2. md-bitmap refactor and fix, by Yu Kuai.
 3. Replace kmap_atomic with kmap_local_page, by David Reaver."

* tag 'md-6.14-20250113' of https://git.kernel.org/pub/scm/linux/kernel/git/mdraid/linux:
  md/md-bitmap: move bitmap_{start, end}write to md upper layer
  md/raid5: implement pers->bitmap_sector()
  md: add a new callback pers->bitmap_sector()
  md/md-bitmap: remove the last parameter for bimtap_ops->endwrite()
  md/md-bitmap: factor behind write counters out from bitmap_{start/end}write()
  md: Replace deprecated kmap_atomic() with kmap_local_page()
  md: reintroduce md-linear
parents 170e086a c9b39e51
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -61,6 +61,19 @@ config MD_BITMAP_FILE
	  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"
	depends on BLK_DEV_MD
	help
	  If you say Y here, then your multiple devices driver will be able to
	  use the so-called linear mode, i.e. it will combine the hard disk
	  partitions by simply appending one to the other.

	  To compile this as a module, choose M here: the module
	  will be called linear.

	  If unsure, say Y.

config MD_RAID0
	tristate "RAID-0 (striping) mode"
	depends on BLK_DEV_MD
+2 −0
Original line number Diff line number Diff line
@@ -29,12 +29,14 @@ dm-zoned-y += dm-zoned-target.o dm-zoned-metadata.o dm-zoned-reclaim.o

md-mod-y	+= md.o md-bitmap.o
raid456-y	+= raid5.o raid5-cache.o raid5-ppl.o
linear-y       += md-linear.o

# Note: link order is important.  All raid personalities
# and must come before md.o, as they each initialise
# themselves, and md.o may use the personalities when it
# auto-initialised.

obj-$(CONFIG_MD_LINEAR)		+= linear.o
obj-$(CONFIG_MD_RAID0)		+= raid0.o
obj-$(CONFIG_MD_RAID1)		+= raid1.o
obj-$(CONFIG_MD_RAID10)		+= raid10.o
+6 −2
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ static int md_setup_ents __initdata;
 *             instead of just one.  -- KTK
 * 18May2000: Added support for persistent-superblock arrays:
 *             md=n,0,factor,fault,device-list   uses RAID0 for device n
 *             md=n,-1,factor,fault,device-list  uses LINEAR for device n
 *             md=n,device-list      reads a RAID superblock from the devices
 *             elements in device-list are read by name_to_kdev_t so can be
 *             a hex number or something like /dev/hda1 /dev/sdb
@@ -87,7 +88,7 @@ static int __init md_setup(char *str)
		md_setup_ents++;
	switch (get_option(&str, &level)) {	/* RAID level */
	case 2: /* could be 0 or -1.. */
		if (level == 0) {
		if (level == 0 || level == LEVEL_LINEAR) {
			if (get_option(&str, &factor) != 2 ||	/* Chunk Size */
					get_option(&str, &fault) != 2) {
				printk(KERN_WARNING "md: Too few arguments supplied to md=.\n");
@@ -95,6 +96,9 @@ static int __init md_setup(char *str)
			}
			md_setup_args[ent].level = level;
			md_setup_args[ent].chunk = 1 << (factor+12);
			if (level ==  LEVEL_LINEAR)
				pername = "linear";
			else
				pername = "raid0";
			break;
		}
+66 −50
Original line number Diff line number Diff line
@@ -682,7 +682,7 @@ static void bitmap_update_sb(void *data)
		return;
	if (!bitmap->storage.sb_page) /* no superblock */
		return;
	sb = kmap_atomic(bitmap->storage.sb_page);
	sb = kmap_local_page(bitmap->storage.sb_page);
	sb->events = cpu_to_le64(bitmap->mddev->events);
	if (bitmap->mddev->events < bitmap->events_cleared)
		/* rocking back to read-only */
@@ -702,7 +702,7 @@ static void bitmap_update_sb(void *data)
	sb->nodes = cpu_to_le32(bitmap->mddev->bitmap_info.nodes);
	sb->sectors_reserved = cpu_to_le32(bitmap->mddev->
					   bitmap_info.space);
	kunmap_atomic(sb);
	kunmap_local(sb);

	if (bitmap->storage.file)
		write_file_page(bitmap, bitmap->storage.sb_page, 1);
@@ -717,7 +717,7 @@ static void bitmap_print_sb(struct bitmap *bitmap)

	if (!bitmap || !bitmap->storage.sb_page)
		return;
	sb = kmap_atomic(bitmap->storage.sb_page);
	sb = kmap_local_page(bitmap->storage.sb_page);
	pr_debug("%s: bitmap file superblock:\n", bmname(bitmap));
	pr_debug("         magic: %08x\n", le32_to_cpu(sb->magic));
	pr_debug("       version: %u\n", le32_to_cpu(sb->version));
@@ -736,7 +736,7 @@ static void bitmap_print_sb(struct bitmap *bitmap)
	pr_debug("     sync size: %llu KB\n",
		 (unsigned long long)le64_to_cpu(sb->sync_size)/2);
	pr_debug("max write behind: %u\n", le32_to_cpu(sb->write_behind));
	kunmap_atomic(sb);
	kunmap_local(sb);
}

/*
@@ -760,7 +760,7 @@ static int md_bitmap_new_disk_sb(struct bitmap *bitmap)
		return -ENOMEM;
	bitmap->storage.sb_index = 0;

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

	sb->magic = cpu_to_le32(BITMAP_MAGIC);
	sb->version = cpu_to_le32(BITMAP_MAJOR_HI);
@@ -768,7 +768,7 @@ static int md_bitmap_new_disk_sb(struct bitmap *bitmap)
	chunksize = bitmap->mddev->bitmap_info.chunksize;
	BUG_ON(!chunksize);
	if (!is_power_of_2(chunksize)) {
		kunmap_atomic(sb);
		kunmap_local(sb);
		pr_warn("bitmap chunksize not a power of 2\n");
		return -EINVAL;
	}
@@ -803,7 +803,7 @@ static int md_bitmap_new_disk_sb(struct bitmap *bitmap)
	sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
	bitmap->mddev->bitmap_info.nodes = 0;

	kunmap_atomic(sb);
	kunmap_local(sb);

	return 0;
}
@@ -865,7 +865,7 @@ static int md_bitmap_read_sb(struct bitmap *bitmap)
		return err;

	err = -EINVAL;
	sb = kmap_atomic(sb_page);
	sb = kmap_local_page(sb_page);

	chunksize = le32_to_cpu(sb->chunksize);
	daemon_sleep = le32_to_cpu(sb->daemon_sleep) * HZ;
@@ -932,7 +932,7 @@ static int md_bitmap_read_sb(struct bitmap *bitmap)
	err = 0;

out:
	kunmap_atomic(sb);
	kunmap_local(sb);
	if (err == 0 && nodes && (bitmap->cluster_slot < 0)) {
		/* Assigning chunksize is required for "re_read" */
		bitmap->mddev->bitmap_info.chunksize = chunksize;
@@ -1161,12 +1161,12 @@ static void md_bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
	bit = file_page_offset(&bitmap->storage, chunk);

	/* set the bit */
	kaddr = kmap_atomic(page);
	kaddr = kmap_local_page(page);
	if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags))
		set_bit(bit, kaddr);
	else
		set_bit_le(bit, kaddr);
	kunmap_atomic(kaddr);
	kunmap_local(kaddr);
	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, index - node_offset, BITMAP_PAGE_DIRTY);
@@ -1190,12 +1190,12 @@ static void md_bitmap_file_clear_bit(struct bitmap *bitmap, sector_t block)
	if (!page)
		return;
	bit = file_page_offset(&bitmap->storage, chunk);
	paddr = kmap_atomic(page);
	paddr = kmap_local_page(page);
	if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags))
		clear_bit(bit, paddr);
	else
		clear_bit_le(bit, paddr);
	kunmap_atomic(paddr);
	kunmap_local(paddr);
	if (!test_page_attr(bitmap, index - node_offset, BITMAP_PAGE_NEEDWRITE)) {
		set_page_attr(bitmap, index - node_offset, BITMAP_PAGE_PENDING);
		bitmap->allclean = 0;
@@ -1214,12 +1214,12 @@ static int md_bitmap_file_test_bit(struct bitmap *bitmap, sector_t block)
	if (!page)
		return -EINVAL;
	bit = file_page_offset(&bitmap->storage, chunk);
	paddr = kmap_atomic(page);
	paddr = kmap_local_page(page);
	if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags))
		set = test_bit(bit, paddr);
	else
		set = test_bit_le(bit, paddr);
	kunmap_atomic(paddr);
	kunmap_local(paddr);
	return set;
}

@@ -1388,9 +1388,9 @@ static int md_bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
			 * If the bitmap is out of date, dirty the whole page
			 * and write it out
			 */
			paddr = kmap_atomic(page);
			paddr = kmap_local_page(page);
			memset(paddr + offset, 0xff, PAGE_SIZE - offset);
			kunmap_atomic(paddr);
			kunmap_local(paddr);

			filemap_write_page(bitmap, i, true);
			if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags)) {
@@ -1406,12 +1406,12 @@ static int md_bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
		void *paddr;
		bool was_set;

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

		if (was_set) {
			/* if the disk bit is set, set the memory bit */
@@ -1546,10 +1546,10 @@ static void bitmap_daemon_work(struct mddev *mddev)
		bitmap_super_t *sb;
		bitmap->need_sync = 0;
		if (bitmap->storage.filemap) {
			sb = kmap_atomic(bitmap->storage.sb_page);
			sb = kmap_local_page(bitmap->storage.sb_page);
			sb->events_cleared =
				cpu_to_le64(bitmap->events_cleared);
			kunmap_atomic(sb);
			kunmap_local(sb);
			set_page_attr(bitmap, 0,
				      BITMAP_PAGE_NEEDWRITE);
		}
@@ -1671,24 +1671,13 @@ __acquires(bitmap->lock)
}

static int bitmap_startwrite(struct mddev *mddev, sector_t offset,
			     unsigned long sectors, bool behind)
			     unsigned long sectors)
{
	struct bitmap *bitmap = mddev->bitmap;

	if (!bitmap)
		return 0;

	if (behind) {
		int bw;
		atomic_inc(&bitmap->behind_writes);
		bw = atomic_read(&bitmap->behind_writes);
		if (bw > bitmap->behind_writes_used)
			bitmap->behind_writes_used = bw;

		pr_debug("inc write-behind count %d/%lu\n",
			 bw, bitmap->mddev->bitmap_info.max_write_behind);
	}

	while (sectors) {
		sector_t blocks;
		bitmap_counter_t *bmc;
@@ -1737,21 +1726,13 @@ static int bitmap_startwrite(struct mddev *mddev, sector_t offset,
}

static void bitmap_endwrite(struct mddev *mddev, sector_t offset,
			    unsigned long sectors, bool success, bool behind)
			    unsigned long sectors)
{
	struct bitmap *bitmap = mddev->bitmap;

	if (!bitmap)
		return;

	if (behind) {
		if (atomic_dec_and_test(&bitmap->behind_writes))
			wake_up(&bitmap->behind_wait);
		pr_debug("dec write-behind count %d/%lu\n",
			 atomic_read(&bitmap->behind_writes),
			 bitmap->mddev->bitmap_info.max_write_behind);
	}

	while (sectors) {
		sector_t blocks;
		unsigned long flags;
@@ -1764,15 +1745,16 @@ static void bitmap_endwrite(struct mddev *mddev, sector_t offset,
			return;
		}

		if (success && !bitmap->mddev->degraded &&
		    bitmap->events_cleared < bitmap->mddev->events) {
		if (!bitmap->mddev->degraded) {
			if (bitmap->events_cleared < bitmap->mddev->events) {
				bitmap->events_cleared = bitmap->mddev->events;
				bitmap->need_sync = 1;
			sysfs_notify_dirent_safe(bitmap->sysfs_can_clear);
				sysfs_notify_dirent_safe(
						bitmap->sysfs_can_clear);
			}

		if (!success && !NEEDED(*bmc))
		} else if (!NEEDED(*bmc)) {
			*bmc |= NEEDED_MASK;
		}

		if (COUNTER(*bmc) == COUNTER_MAX)
			wake_up(&bitmap->overflow_wait);
@@ -2062,6 +2044,37 @@ static void md_bitmap_free(void *data)
	kfree(bitmap);
}

static void bitmap_start_behind_write(struct mddev *mddev)
{
	struct bitmap *bitmap = mddev->bitmap;
	int bw;

	if (!bitmap)
		return;

	atomic_inc(&bitmap->behind_writes);
	bw = atomic_read(&bitmap->behind_writes);
	if (bw > bitmap->behind_writes_used)
		bitmap->behind_writes_used = bw;

	pr_debug("inc write-behind count %d/%lu\n",
		 bw, bitmap->mddev->bitmap_info.max_write_behind);
}

static void bitmap_end_behind_write(struct mddev *mddev)
{
	struct bitmap *bitmap = mddev->bitmap;

	if (!bitmap)
		return;

	if (atomic_dec_and_test(&bitmap->behind_writes))
		wake_up(&bitmap->behind_wait);
	pr_debug("dec write-behind count %d/%lu\n",
		 atomic_read(&bitmap->behind_writes),
		 bitmap->mddev->bitmap_info.max_write_behind);
}

static void bitmap_wait_behind_writes(struct mddev *mddev)
{
	struct bitmap *bitmap = mddev->bitmap;
@@ -2981,6 +2994,9 @@ static struct bitmap_operations bitmap_ops = {
	.dirty_bits		= bitmap_dirty_bits,
	.unplug			= bitmap_unplug,
	.daemon_work		= bitmap_daemon_work,

	.start_behind_write	= bitmap_start_behind_write,
	.end_behind_write	= bitmap_end_behind_write,
	.wait_behind_writes	= bitmap_wait_behind_writes,

	.startwrite		= bitmap_startwrite,
+5 −2
Original line number Diff line number Diff line
@@ -84,12 +84,15 @@ struct bitmap_operations {
			   unsigned long e);
	void (*unplug)(struct mddev *mddev, bool sync);
	void (*daemon_work)(struct mddev *mddev);

	void (*start_behind_write)(struct mddev *mddev);
	void (*end_behind_write)(struct mddev *mddev);
	void (*wait_behind_writes)(struct mddev *mddev);

	int (*startwrite)(struct mddev *mddev, sector_t offset,
			  unsigned long sectors, bool behind);
			  unsigned long sectors);
	void (*endwrite)(struct mddev *mddev, sector_t offset,
			 unsigned long sectors, bool success, bool behind);
			 unsigned long sectors);
	bool (*start_sync)(struct mddev *mddev, sector_t offset,
			   sector_t *blocks, bool degraded);
	void (*end_sync)(struct mddev *mddev, sector_t offset, sector_t *blocks);
Loading