mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	md: Move alloc/free acct bioset in to personality
bioset acct is only needed for raid0 and raid5. Therefore, md_run only
allocates it for raid0 and raid5. However, this does not cover
personality takeover, which may cause uninitialized bioset. For example,
the following repro steps:
  mdadm -CR /dev/md0 -l1 -n2 /dev/loop0 /dev/loop1
  mdadm --wait /dev/md0
  mkfs.xfs /dev/md0
  mdadm /dev/md0 --grow -l5
  mount /dev/md0 /mnt
causes panic like:
[  225.933939] BUG: kernel NULL pointer dereference, address: 0000000000000000
[  225.934903] #PF: supervisor instruction fetch in kernel mode
[  225.935639] #PF: error_code(0x0010) - not-present page
[  225.936361] PGD 0 P4D 0
[  225.936677] Oops: 0010 [#1] PREEMPT SMP DEBUG_PAGEALLOC KASAN PTI
[  225.937525] CPU: 27 PID: 1133 Comm: mount Not tainted 5.16.0-rc3+ #706
[  225.938416] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-2.module_el8.4.0+547+a85d02ba 04/01/2014
[  225.939922] RIP: 0010:0x0
[  225.940289] Code: Unable to access opcode bytes at RIP 0xffffffffffffffd6.
[  225.941196] RSP: 0018:ffff88815897eff0 EFLAGS: 00010246
[  225.941897] RAX: 0000000000000000 RBX: 0000000000092800 RCX: ffffffff81370a39
[  225.942813] RDX: dffffc0000000000 RSI: 0000000000000000 RDI: 0000000000092800
[  225.943772] RBP: 1ffff1102b12fe04 R08: fffffbfff0b43c01 R09: fffffbfff0b43c01
[  225.944807] R10: ffffffff85a1e007 R11: fffffbfff0b43c00 R12: ffff88810eaaaf58
[  225.945757] R13: 0000000000000000 R14: ffff88810eaaafb8 R15: ffff88815897f040
[  225.946709] FS:  00007ff3f2505080(0000) GS:ffff888fb5e00000(0000) knlGS:0000000000000000
[  225.947814] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  225.948556] CR2: ffffffffffffffd6 CR3: 000000015aa5a006 CR4: 0000000000370ee0
[  225.949537] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[  225.950455] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[  225.951414] Call Trace:
[  225.951787]  <TASK>
[  225.952120]  mempool_alloc+0xe5/0x250
[  225.952625]  ? mempool_resize+0x370/0x370
[  225.953187]  ? rcu_read_lock_sched_held+0xa1/0xd0
[  225.953862]  ? rcu_read_lock_bh_held+0xb0/0xb0
[  225.954464]  ? sched_clock_cpu+0x15/0x120
[  225.955019]  ? find_held_lock+0xac/0xd0
[  225.955564]  bio_alloc_bioset+0x1ed/0x2a0
[  225.956080]  ? lock_downgrade+0x3a0/0x3a0
[  225.956644]  ? bvec_alloc+0xc0/0xc0
[  225.957135]  bio_clone_fast+0x19/0x80
[  225.957651]  raid5_make_request+0x1370/0x1b70
[  225.958286]  ? sched_clock_cpu+0x15/0x120
[  225.958797]  ? __lock_acquire+0x8b2/0x3510
[  225.959339]  ? raid5_get_active_stripe+0xce0/0xce0
[  225.959986]  ? lock_is_held_type+0xd8/0x130
[  225.960528]  ? rcu_read_lock_sched_held+0xa1/0xd0
[  225.961135]  ? rcu_read_lock_bh_held+0xb0/0xb0
[  225.961703]  ? sched_clock_cpu+0x15/0x120
[  225.962232]  ? lock_release+0x27a/0x6c0
[  225.962746]  ? do_wait_intr_irq+0x130/0x130
[  225.963302]  ? lock_downgrade+0x3a0/0x3a0
[  225.963815]  ? lock_release+0x6c0/0x6c0
[  225.964348]  md_handle_request+0x342/0x530
[  225.964888]  ? set_in_sync+0x170/0x170
[  225.965397]  ? blk_queue_split+0x133/0x150
[  225.965988]  ? __blk_queue_split+0x8b0/0x8b0
[  225.966524]  ? submit_bio_checks+0x3b2/0x9d0
[  225.967069]  md_submit_bio+0x127/0x1c0
[...]
Fix this by moving alloc/free of acct bioset to pers->run and pers->free.
While we are on this, properly handle md_integrity_register() error in
raid0_run().
Fixes: daee202471 (md: check level before create and exit io_acct_set)
Cc: stable@vger.kernel.org
Acked-by: Guoqing Jiang <guoqing.jiang@linux.dev>
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Song Liu <song@kernel.org>
			
			
This commit is contained in:
		
							parent
							
								
									36dacddbf0
								
							
						
					
					
						commit
						0c031fd37f
					
				
					 4 changed files with 77 additions and 31 deletions
				
			
		| 
						 | 
					@ -5881,13 +5881,6 @@ int md_run(struct mddev *mddev)
 | 
				
			||||||
		if (err)
 | 
							if (err)
 | 
				
			||||||
			goto exit_bio_set;
 | 
								goto exit_bio_set;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (mddev->level != 1 && mddev->level != 10 &&
 | 
					 | 
				
			||||||
	    !bioset_initialized(&mddev->io_acct_set)) {
 | 
					 | 
				
			||||||
		err = bioset_init(&mddev->io_acct_set, BIO_POOL_SIZE,
 | 
					 | 
				
			||||||
				  offsetof(struct md_io_acct, bio_clone), 0);
 | 
					 | 
				
			||||||
		if (err)
 | 
					 | 
				
			||||||
			goto exit_sync_set;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock(&pers_lock);
 | 
						spin_lock(&pers_lock);
 | 
				
			||||||
	pers = find_pers(mddev->level, mddev->clevel);
 | 
						pers = find_pers(mddev->level, mddev->clevel);
 | 
				
			||||||
| 
						 | 
					@ -6064,9 +6057,6 @@ int md_run(struct mddev *mddev)
 | 
				
			||||||
	module_put(pers->owner);
 | 
						module_put(pers->owner);
 | 
				
			||||||
	md_bitmap_destroy(mddev);
 | 
						md_bitmap_destroy(mddev);
 | 
				
			||||||
abort:
 | 
					abort:
 | 
				
			||||||
	if (mddev->level != 1 && mddev->level != 10)
 | 
					 | 
				
			||||||
		bioset_exit(&mddev->io_acct_set);
 | 
					 | 
				
			||||||
exit_sync_set:
 | 
					 | 
				
			||||||
	bioset_exit(&mddev->sync_set);
 | 
						bioset_exit(&mddev->sync_set);
 | 
				
			||||||
exit_bio_set:
 | 
					exit_bio_set:
 | 
				
			||||||
	bioset_exit(&mddev->bio_set);
 | 
						bioset_exit(&mddev->bio_set);
 | 
				
			||||||
| 
						 | 
					@ -8608,6 +8598,23 @@ void md_submit_discard_bio(struct mddev *mddev, struct md_rdev *rdev,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(md_submit_discard_bio);
 | 
					EXPORT_SYMBOL_GPL(md_submit_discard_bio);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int acct_bioset_init(struct mddev *mddev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int err = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!bioset_initialized(&mddev->io_acct_set))
 | 
				
			||||||
 | 
							err = bioset_init(&mddev->io_acct_set, BIO_POOL_SIZE,
 | 
				
			||||||
 | 
								offsetof(struct md_io_acct, bio_clone), 0);
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(acct_bioset_init);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void acct_bioset_exit(struct mddev *mddev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						bioset_exit(&mddev->io_acct_set);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(acct_bioset_exit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void md_end_io_acct(struct bio *bio)
 | 
					static void md_end_io_acct(struct bio *bio)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct md_io_acct *md_io_acct = bio->bi_private;
 | 
						struct md_io_acct *md_io_acct = bio->bi_private;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -721,6 +721,8 @@ extern void md_error(struct mddev *mddev, struct md_rdev *rdev);
 | 
				
			||||||
extern void md_finish_reshape(struct mddev *mddev);
 | 
					extern void md_finish_reshape(struct mddev *mddev);
 | 
				
			||||||
void md_submit_discard_bio(struct mddev *mddev, struct md_rdev *rdev,
 | 
					void md_submit_discard_bio(struct mddev *mddev, struct md_rdev *rdev,
 | 
				
			||||||
			struct bio *bio, sector_t start, sector_t size);
 | 
								struct bio *bio, sector_t start, sector_t size);
 | 
				
			||||||
 | 
					int acct_bioset_init(struct mddev *mddev);
 | 
				
			||||||
 | 
					void acct_bioset_exit(struct mddev *mddev);
 | 
				
			||||||
void md_account_bio(struct mddev *mddev, struct bio **bio);
 | 
					void md_account_bio(struct mddev *mddev, struct bio **bio);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern bool __must_check md_flush_request(struct mddev *mddev, struct bio *bio);
 | 
					extern bool __must_check md_flush_request(struct mddev *mddev, struct bio *bio);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -356,7 +356,21 @@ static sector_t raid0_size(struct mddev *mddev, sector_t sectors, int raid_disks
 | 
				
			||||||
	return array_sectors;
 | 
						return array_sectors;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void raid0_free(struct mddev *mddev, void *priv);
 | 
					static void free_conf(struct mddev *mddev, struct r0conf *conf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						kfree(conf->strip_zone);
 | 
				
			||||||
 | 
						kfree(conf->devlist);
 | 
				
			||||||
 | 
						kfree(conf);
 | 
				
			||||||
 | 
						mddev->private = NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void raid0_free(struct mddev *mddev, void *priv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct r0conf *conf = priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free_conf(mddev, conf);
 | 
				
			||||||
 | 
						acct_bioset_exit(mddev);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int raid0_run(struct mddev *mddev)
 | 
					static int raid0_run(struct mddev *mddev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -370,11 +384,16 @@ static int raid0_run(struct mddev *mddev)
 | 
				
			||||||
	if (md_check_no_bitmap(mddev))
 | 
						if (md_check_no_bitmap(mddev))
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (acct_bioset_init(mddev)) {
 | 
				
			||||||
 | 
							pr_err("md/raid0:%s: alloc acct bioset failed.\n", mdname(mddev));
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* if private is not null, we are here after takeover */
 | 
						/* if private is not null, we are here after takeover */
 | 
				
			||||||
	if (mddev->private == NULL) {
 | 
						if (mddev->private == NULL) {
 | 
				
			||||||
		ret = create_strip_zones(mddev, &conf);
 | 
							ret = create_strip_zones(mddev, &conf);
 | 
				
			||||||
		if (ret < 0)
 | 
							if (ret < 0)
 | 
				
			||||||
			return ret;
 | 
								goto exit_acct_set;
 | 
				
			||||||
		mddev->private = conf;
 | 
							mddev->private = conf;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	conf = mddev->private;
 | 
						conf = mddev->private;
 | 
				
			||||||
| 
						 | 
					@ -413,17 +432,16 @@ static int raid0_run(struct mddev *mddev)
 | 
				
			||||||
	dump_zones(mddev);
 | 
						dump_zones(mddev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = md_integrity_register(mddev);
 | 
						ret = md_integrity_register(mddev);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							goto free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void raid0_free(struct mddev *mddev, void *priv)
 | 
					free:
 | 
				
			||||||
{
 | 
						free_conf(mddev, conf);
 | 
				
			||||||
	struct r0conf *conf = priv;
 | 
					exit_acct_set:
 | 
				
			||||||
 | 
						acct_bioset_exit(mddev);
 | 
				
			||||||
	kfree(conf->strip_zone);
 | 
						return ret;
 | 
				
			||||||
	kfree(conf->devlist);
 | 
					 | 
				
			||||||
	kfree(conf);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void raid0_handle_discard(struct mddev *mddev, struct bio *bio)
 | 
					static void raid0_handle_discard(struct mddev *mddev, struct bio *bio)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7462,12 +7462,19 @@ static int raid5_run(struct mddev *mddev)
 | 
				
			||||||
	struct md_rdev *rdev;
 | 
						struct md_rdev *rdev;
 | 
				
			||||||
	struct md_rdev *journal_dev = NULL;
 | 
						struct md_rdev *journal_dev = NULL;
 | 
				
			||||||
	sector_t reshape_offset = 0;
 | 
						sector_t reshape_offset = 0;
 | 
				
			||||||
	int i;
 | 
						int i, ret = 0;
 | 
				
			||||||
	long long min_offset_diff = 0;
 | 
						long long min_offset_diff = 0;
 | 
				
			||||||
	int first = 1;
 | 
						int first = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (mddev_init_writes_pending(mddev) < 0)
 | 
						if (acct_bioset_init(mddev)) {
 | 
				
			||||||
 | 
							pr_err("md/raid456:%s: alloc acct bioset failed.\n", mdname(mddev));
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (mddev_init_writes_pending(mddev) < 0) {
 | 
				
			||||||
 | 
							ret = -ENOMEM;
 | 
				
			||||||
 | 
							goto exit_acct_set;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (mddev->recovery_cp != MaxSector)
 | 
						if (mddev->recovery_cp != MaxSector)
 | 
				
			||||||
		pr_notice("md/raid:%s: not clean -- starting background reconstruction\n",
 | 
							pr_notice("md/raid:%s: not clean -- starting background reconstruction\n",
 | 
				
			||||||
| 
						 | 
					@ -7498,7 +7505,8 @@ static int raid5_run(struct mddev *mddev)
 | 
				
			||||||
	    (mddev->bitmap_info.offset || mddev->bitmap_info.file)) {
 | 
						    (mddev->bitmap_info.offset || mddev->bitmap_info.file)) {
 | 
				
			||||||
		pr_notice("md/raid:%s: array cannot have both journal and bitmap\n",
 | 
							pr_notice("md/raid:%s: array cannot have both journal and bitmap\n",
 | 
				
			||||||
			  mdname(mddev));
 | 
								  mdname(mddev));
 | 
				
			||||||
		return -EINVAL;
 | 
							ret = -EINVAL;
 | 
				
			||||||
 | 
							goto exit_acct_set;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (mddev->reshape_position != MaxSector) {
 | 
						if (mddev->reshape_position != MaxSector) {
 | 
				
			||||||
| 
						 | 
					@ -7523,13 +7531,15 @@ static int raid5_run(struct mddev *mddev)
 | 
				
			||||||
		if (journal_dev) {
 | 
							if (journal_dev) {
 | 
				
			||||||
			pr_warn("md/raid:%s: don't support reshape with journal - aborting.\n",
 | 
								pr_warn("md/raid:%s: don't support reshape with journal - aborting.\n",
 | 
				
			||||||
				mdname(mddev));
 | 
									mdname(mddev));
 | 
				
			||||||
			return -EINVAL;
 | 
								ret = -EINVAL;
 | 
				
			||||||
 | 
								goto exit_acct_set;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (mddev->new_level != mddev->level) {
 | 
							if (mddev->new_level != mddev->level) {
 | 
				
			||||||
			pr_warn("md/raid:%s: unsupported reshape required - aborting.\n",
 | 
								pr_warn("md/raid:%s: unsupported reshape required - aborting.\n",
 | 
				
			||||||
				mdname(mddev));
 | 
									mdname(mddev));
 | 
				
			||||||
			return -EINVAL;
 | 
								ret = -EINVAL;
 | 
				
			||||||
 | 
								goto exit_acct_set;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		old_disks = mddev->raid_disks - mddev->delta_disks;
 | 
							old_disks = mddev->raid_disks - mddev->delta_disks;
 | 
				
			||||||
		/* reshape_position must be on a new-stripe boundary, and one
 | 
							/* reshape_position must be on a new-stripe boundary, and one
 | 
				
			||||||
| 
						 | 
					@ -7545,7 +7555,8 @@ static int raid5_run(struct mddev *mddev)
 | 
				
			||||||
		if (sector_div(here_new, chunk_sectors * new_data_disks)) {
 | 
							if (sector_div(here_new, chunk_sectors * new_data_disks)) {
 | 
				
			||||||
			pr_warn("md/raid:%s: reshape_position not on a stripe boundary\n",
 | 
								pr_warn("md/raid:%s: reshape_position not on a stripe boundary\n",
 | 
				
			||||||
				mdname(mddev));
 | 
									mdname(mddev));
 | 
				
			||||||
			return -EINVAL;
 | 
								ret = -EINVAL;
 | 
				
			||||||
 | 
								goto exit_acct_set;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		reshape_offset = here_new * chunk_sectors;
 | 
							reshape_offset = here_new * chunk_sectors;
 | 
				
			||||||
		/* here_new is the stripe we will write to */
 | 
							/* here_new is the stripe we will write to */
 | 
				
			||||||
| 
						 | 
					@ -7567,7 +7578,8 @@ static int raid5_run(struct mddev *mddev)
 | 
				
			||||||
			else if (mddev->ro == 0) {
 | 
								else if (mddev->ro == 0) {
 | 
				
			||||||
				pr_warn("md/raid:%s: in-place reshape must be started in read-only mode - aborting\n",
 | 
									pr_warn("md/raid:%s: in-place reshape must be started in read-only mode - aborting\n",
 | 
				
			||||||
					mdname(mddev));
 | 
										mdname(mddev));
 | 
				
			||||||
				return -EINVAL;
 | 
									ret = -EINVAL;
 | 
				
			||||||
 | 
									goto exit_acct_set;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else if (mddev->reshape_backwards
 | 
							} else if (mddev->reshape_backwards
 | 
				
			||||||
		    ? (here_new * chunk_sectors + min_offset_diff <=
 | 
							    ? (here_new * chunk_sectors + min_offset_diff <=
 | 
				
			||||||
| 
						 | 
					@ -7577,7 +7589,8 @@ static int raid5_run(struct mddev *mddev)
 | 
				
			||||||
			/* Reading from the same stripe as writing to - bad */
 | 
								/* Reading from the same stripe as writing to - bad */
 | 
				
			||||||
			pr_warn("md/raid:%s: reshape_position too early for auto-recovery - aborting.\n",
 | 
								pr_warn("md/raid:%s: reshape_position too early for auto-recovery - aborting.\n",
 | 
				
			||||||
				mdname(mddev));
 | 
									mdname(mddev));
 | 
				
			||||||
			return -EINVAL;
 | 
								ret = -EINVAL;
 | 
				
			||||||
 | 
								goto exit_acct_set;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		pr_debug("md/raid:%s: reshape will continue\n", mdname(mddev));
 | 
							pr_debug("md/raid:%s: reshape will continue\n", mdname(mddev));
 | 
				
			||||||
		/* OK, we should be able to continue; */
 | 
							/* OK, we should be able to continue; */
 | 
				
			||||||
| 
						 | 
					@ -7601,8 +7614,10 @@ static int raid5_run(struct mddev *mddev)
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		conf = mddev->private;
 | 
							conf = mddev->private;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (IS_ERR(conf))
 | 
						if (IS_ERR(conf)) {
 | 
				
			||||||
		return PTR_ERR(conf);
 | 
							ret = PTR_ERR(conf);
 | 
				
			||||||
 | 
							goto exit_acct_set;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (test_bit(MD_HAS_JOURNAL, &mddev->flags)) {
 | 
						if (test_bit(MD_HAS_JOURNAL, &mddev->flags)) {
 | 
				
			||||||
		if (!journal_dev) {
 | 
							if (!journal_dev) {
 | 
				
			||||||
| 
						 | 
					@ -7799,7 +7814,10 @@ static int raid5_run(struct mddev *mddev)
 | 
				
			||||||
	free_conf(conf);
 | 
						free_conf(conf);
 | 
				
			||||||
	mddev->private = NULL;
 | 
						mddev->private = NULL;
 | 
				
			||||||
	pr_warn("md/raid:%s: failed to run raid set.\n", mdname(mddev));
 | 
						pr_warn("md/raid:%s: failed to run raid set.\n", mdname(mddev));
 | 
				
			||||||
	return -EIO;
 | 
						ret = -EIO;
 | 
				
			||||||
 | 
					exit_acct_set:
 | 
				
			||||||
 | 
						acct_bioset_exit(mddev);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void raid5_free(struct mddev *mddev, void *priv)
 | 
					static void raid5_free(struct mddev *mddev, void *priv)
 | 
				
			||||||
| 
						 | 
					@ -7807,6 +7825,7 @@ static void raid5_free(struct mddev *mddev, void *priv)
 | 
				
			||||||
	struct r5conf *conf = priv;
 | 
						struct r5conf *conf = priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free_conf(conf);
 | 
						free_conf(conf);
 | 
				
			||||||
 | 
						acct_bioset_exit(mddev);
 | 
				
			||||||
	mddev->to_remove = &raid5_attrs_group;
 | 
						mddev->to_remove = &raid5_attrs_group;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue