9885 lines · 258.2 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-or-later/*   md.c : Multiple Devices driver for Linux     Copyright (C) 1998, 1999, 2000 Ingo Molnar      completely rewritten, based on the MD driver code from Marc Zyngier    Changes:    - RAID-1/RAID-5 extensions by Miguel de Icaza, Gadi Oxman, Ingo Molnar   - RAID-6 extensions by H. Peter Anvin <hpa@zytor.com>   - boot support for linear and striped mode by Harald Hoyer <HarryH@Royal.Net>   - kerneld support by Boris Tobotras <boris@xtalk.msk.su>   - kmod support by: Cyrus Durgin   - RAID0 bugfixes: Mark Anthony Lisher <markal@iname.com>   - Devfs support by Richard Gooch <rgooch@atnf.csiro.au>    - lots of fixes and improvements to the RAID1/RAID5 and generic     RAID code (such as request based resynchronization):      Neil Brown <neilb@cse.unsw.edu.au>.    - persistent bitmap code     Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.     Errors, Warnings, etc.   Please use:     pr_crit() for error conditions that risk data loss     pr_err() for error conditions that are unexpected, like an IO error         or internal inconsistency     pr_warn() for error conditions that could have been predicated, like         adding a device to an array when it has incompatible metadata     pr_info() for every interesting, very rare events, like an array starting         or stopping, or resync starting or stopping     pr_debug() for everything else. */ #include <linux/sched/mm.h>#include <linux/sched/signal.h>#include <linux/kthread.h>#include <linux/blkdev.h>#include <linux/badblocks.h>#include <linux/sysctl.h>#include <linux/seq_file.h>#include <linux/fs.h>#include <linux/poll.h>#include <linux/ctype.h>#include <linux/string.h>#include <linux/hdreg.h>#include <linux/proc_fs.h>#include <linux/random.h>#include <linux/module.h>#include <linux/reboot.h>#include <linux/file.h>#include <linux/compat.h>#include <linux/delay.h>#include <linux/raid/md_p.h>#include <linux/raid/md_u.h>#include <linux/raid/detect.h>#include <linux/slab.h>#include <linux/percpu-refcount.h>#include <linux/part_stat.h> #include <trace/events/block.h>#include "md.h"#include "md-bitmap.h"#include "md-cluster.h" /* pers_list is a list of registered personalities protected * by pers_lock. * pers_lock does extra service to protect accesses to * mddev->thread when the mutex cannot be held. */static LIST_HEAD(pers_list);static DEFINE_SPINLOCK(pers_lock); static struct kobj_type md_ktype; struct md_cluster_operations *md_cluster_ops;EXPORT_SYMBOL(md_cluster_ops);static struct module *md_cluster_mod; static DECLARE_WAIT_QUEUE_HEAD(resync_wait);static struct workqueue_struct *md_wq;static struct workqueue_struct *md_misc_wq;static struct workqueue_struct *md_rdev_misc_wq; static int remove_and_add_spares(struct mddev *mddev,				 struct md_rdev *this);static void mddev_detach(struct mddev *mddev); /* * Default number of read corrections we'll attempt on an rdev * before ejecting it from the array. We divide the read error * count by 2 for every hour elapsed between read errors. */#define MD_DEFAULT_MAX_CORRECTED_READ_ERRORS 20/* Default safemode delay: 200 msec */#define DEFAULT_SAFEMODE_DELAY ((200 * HZ)/1000 +1)/* * Current RAID-1,4,5 parallel reconstruction 'guaranteed speed limit' * is 1000 KB/sec, so the extra system load does not show up that much. * Increase it if you want to have more _guaranteed_ speed. Note that * the RAID driver will use the maximum available bandwidth if the IO * subsystem is idle. There is also an 'absolute maximum' reconstruction * speed limit - in case reconstruction slows down your system despite * idle IO detection. * * you can change it via /proc/sys/dev/raid/speed_limit_min and _max. * or /sys/block/mdX/md/sync_speed_{min,max} */ static int sysctl_speed_limit_min = 1000;static int sysctl_speed_limit_max = 200000;static inline int speed_min(struct mddev *mddev){	return mddev->sync_speed_min ?		mddev->sync_speed_min : sysctl_speed_limit_min;} static inline int speed_max(struct mddev *mddev){	return mddev->sync_speed_max ?		mddev->sync_speed_max : sysctl_speed_limit_max;} static void rdev_uninit_serial(struct md_rdev *rdev){	if (!test_and_clear_bit(CollisionCheck, &rdev->flags))		return; 	kvfree(rdev->serial);	rdev->serial = NULL;} static void rdevs_uninit_serial(struct mddev *mddev){	struct md_rdev *rdev; 	rdev_for_each(rdev, mddev)		rdev_uninit_serial(rdev);} static int rdev_init_serial(struct md_rdev *rdev){	/* serial_nums equals with BARRIER_BUCKETS_NR */	int i, serial_nums = 1 << ((PAGE_SHIFT - ilog2(sizeof(atomic_t))));	struct serial_in_rdev *serial = NULL; 	if (test_bit(CollisionCheck, &rdev->flags))		return 0; 	serial = kvmalloc(sizeof(struct serial_in_rdev) * serial_nums,			  GFP_KERNEL);	if (!serial)		return -ENOMEM; 	for (i = 0; i < serial_nums; i++) {		struct serial_in_rdev *serial_tmp = &serial[i]; 		spin_lock_init(&serial_tmp->serial_lock);		serial_tmp->serial_rb = RB_ROOT_CACHED;		init_waitqueue_head(&serial_tmp->serial_io_wait);	} 	rdev->serial = serial;	set_bit(CollisionCheck, &rdev->flags); 	return 0;} static int rdevs_init_serial(struct mddev *mddev){	struct md_rdev *rdev;	int ret = 0; 	rdev_for_each(rdev, mddev) {		ret = rdev_init_serial(rdev);		if (ret)			break;	} 	/* Free all resources if pool is not existed */	if (ret && !mddev->serial_info_pool)		rdevs_uninit_serial(mddev); 	return ret;} /* * rdev needs to enable serial stuffs if it meets the conditions: * 1. it is multi-queue device flaged with writemostly. * 2. the write-behind mode is enabled. */static int rdev_need_serial(struct md_rdev *rdev){	return (rdev && rdev->mddev->bitmap_info.max_write_behind > 0 &&		rdev->bdev->bd_disk->queue->nr_hw_queues != 1 &&		test_bit(WriteMostly, &rdev->flags));} /* * Init resource for rdev(s), then create serial_info_pool if: * 1. rdev is the first device which return true from rdev_enable_serial. * 2. rdev is NULL, means we want to enable serialization for all rdevs. */void mddev_create_serial_pool(struct mddev *mddev, struct md_rdev *rdev,			      bool is_suspend){	int ret = 0; 	if (rdev && !rdev_need_serial(rdev) &&	    !test_bit(CollisionCheck, &rdev->flags))		return; 	if (!is_suspend)		mddev_suspend(mddev); 	if (!rdev)		ret = rdevs_init_serial(mddev);	else		ret = rdev_init_serial(rdev);	if (ret)		goto abort; 	if (mddev->serial_info_pool == NULL) {		/*		 * already in memalloc noio context by		 * mddev_suspend()		 */		mddev->serial_info_pool =			mempool_create_kmalloc_pool(NR_SERIAL_INFOS,						sizeof(struct serial_info));		if (!mddev->serial_info_pool) {			rdevs_uninit_serial(mddev);			pr_err("can't alloc memory pool for serialization\n");		}	} abort:	if (!is_suspend)		mddev_resume(mddev);} /* * Free resource from rdev(s), and destroy serial_info_pool under conditions: * 1. rdev is the last device flaged with CollisionCheck. * 2. when bitmap is destroyed while policy is not enabled. * 3. for disable policy, the pool is destroyed only when no rdev needs it. */void mddev_destroy_serial_pool(struct mddev *mddev, struct md_rdev *rdev,			       bool is_suspend){	if (rdev && !test_bit(CollisionCheck, &rdev->flags))		return; 	if (mddev->serial_info_pool) {		struct md_rdev *temp;		int num = 0; /* used to track if other rdevs need the pool */ 		if (!is_suspend)			mddev_suspend(mddev);		rdev_for_each(temp, mddev) {			if (!rdev) {				if (!mddev->serialize_policy ||				    !rdev_need_serial(temp))					rdev_uninit_serial(temp);				else					num++;			} else if (temp != rdev &&				   test_bit(CollisionCheck, &temp->flags))				num++;		} 		if (rdev)			rdev_uninit_serial(rdev); 		if (num)			pr_info("The mempool could be used by other devices\n");		else {			mempool_destroy(mddev->serial_info_pool);			mddev->serial_info_pool = NULL;		}		if (!is_suspend)			mddev_resume(mddev);	}} static struct ctl_table_header *raid_table_header; static struct ctl_table raid_table[] = {	{		.procname	= "speed_limit_min",		.data		= &sysctl_speed_limit_min,		.maxlen		= sizeof(int),		.mode		= S_IRUGO|S_IWUSR,		.proc_handler	= proc_dointvec,	},	{		.procname	= "speed_limit_max",		.data		= &sysctl_speed_limit_max,		.maxlen		= sizeof(int),		.mode		= S_IRUGO|S_IWUSR,		.proc_handler	= proc_dointvec,	},	{ }}; static struct ctl_table raid_dir_table[] = {	{		.procname	= "raid",		.maxlen		= 0,		.mode		= S_IRUGO|S_IXUGO,		.child		= raid_table,	},	{ }}; static struct ctl_table raid_root_table[] = {	{		.procname	= "dev",		.maxlen		= 0,		.mode		= 0555,		.child		= raid_dir_table,	},	{  }}; static int start_readonly; /* * The original mechanism for creating an md device is to create * a device node in /dev and to open it.  This causes races with device-close. * The preferred method is to write to the "new_array" module parameter. * This can avoid races. * Setting create_on_open to false disables the original mechanism * so all the races disappear. */static bool create_on_open = true; struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,			    struct mddev *mddev){	if (!mddev || !bioset_initialized(&mddev->bio_set))		return bio_alloc(gfp_mask, nr_iovecs); 	return bio_alloc_bioset(gfp_mask, nr_iovecs, &mddev->bio_set);}EXPORT_SYMBOL_GPL(bio_alloc_mddev); static struct bio *md_bio_alloc_sync(struct mddev *mddev){	if (!mddev || !bioset_initialized(&mddev->sync_set))		return bio_alloc(GFP_NOIO, 1); 	return bio_alloc_bioset(GFP_NOIO, 1, &mddev->sync_set);} /* * We have a system wide 'event count' that is incremented * on any 'interesting' event, and readers of /proc/mdstat * can use 'poll' or 'select' to find out when the event * count increases. * * Events are: *  start array, stop array, error, add device, remove device, *  start build, activate spare */static DECLARE_WAIT_QUEUE_HEAD(md_event_waiters);static atomic_t md_event_count;void md_new_event(struct mddev *mddev){	atomic_inc(&md_event_count);	wake_up(&md_event_waiters);}EXPORT_SYMBOL_GPL(md_new_event); /* * Enables to iterate over all existing md arrays * all_mddevs_lock protects this list. */static LIST_HEAD(all_mddevs);static DEFINE_SPINLOCK(all_mddevs_lock); /* * iterates through all used mddevs in the system. * We take care to grab the all_mddevs_lock whenever navigating * the list, and to always hold a refcount when unlocked. * Any code which breaks out of this loop while own * a reference to the current mddev and must mddev_put it. */#define for_each_mddev(_mddev,_tmp)					\									\	for (({ spin_lock(&all_mddevs_lock);				\		_tmp = all_mddevs.next;					\		_mddev = NULL;});					\	     ({ if (_tmp != &all_mddevs)				\			mddev_get(list_entry(_tmp, struct mddev, all_mddevs));\		spin_unlock(&all_mddevs_lock);				\		if (_mddev) mddev_put(_mddev);				\		_mddev = list_entry(_tmp, struct mddev, all_mddevs);	\		_tmp != &all_mddevs;});					\	     ({ spin_lock(&all_mddevs_lock);				\		_tmp = _tmp->next;})					\		) /* Rather than calling directly into the personality make_request function, * IO requests come here first so that we can check if the device is * being suspended pending a reconfiguration. * We hold a refcount over the call to ->make_request.  By the time that * call has finished, the bio has been linked into some internal structure * and so is visible to ->quiesce(), so we don't need the refcount any more. */static bool is_suspended(struct mddev *mddev, struct bio *bio){	if (mddev->suspended)		return true;	if (bio_data_dir(bio) != WRITE)		return false;	if (mddev->suspend_lo >= mddev->suspend_hi)		return false;	if (bio->bi_iter.bi_sector >= mddev->suspend_hi)		return false;	if (bio_end_sector(bio) < mddev->suspend_lo)		return false;	return true;} void md_handle_request(struct mddev *mddev, struct bio *bio){check_suspended:	rcu_read_lock();	if (is_suspended(mddev, bio)) {		DEFINE_WAIT(__wait);		for (;;) {			prepare_to_wait(&mddev->sb_wait, &__wait,					TASK_UNINTERRUPTIBLE);			if (!is_suspended(mddev, bio))				break;			rcu_read_unlock();			schedule();			rcu_read_lock();		}		finish_wait(&mddev->sb_wait, &__wait);	}	atomic_inc(&mddev->active_io);	rcu_read_unlock(); 	if (!mddev->pers->make_request(mddev, bio)) {		atomic_dec(&mddev->active_io);		wake_up(&mddev->sb_wait);		goto check_suspended;	} 	if (atomic_dec_and_test(&mddev->active_io) && mddev->suspended)		wake_up(&mddev->sb_wait);}EXPORT_SYMBOL(md_handle_request); struct md_io {	struct mddev *mddev;	bio_end_io_t *orig_bi_end_io;	void *orig_bi_private;	unsigned long start_time;}; static void md_end_io(struct bio *bio){	struct md_io *md_io = bio->bi_private;	struct mddev *mddev = md_io->mddev; 	disk_end_io_acct(mddev->gendisk, bio_op(bio), md_io->start_time); 	bio->bi_end_io = md_io->orig_bi_end_io;	bio->bi_private = md_io->orig_bi_private; 	mempool_free(md_io, &mddev->md_io_pool); 	if (bio->bi_end_io)		bio->bi_end_io(bio);} static blk_qc_t md_submit_bio(struct bio *bio){	const int rw = bio_data_dir(bio);	struct mddev *mddev = bio->bi_disk->private_data; 	if (mddev == NULL || mddev->pers == NULL) {		bio_io_error(bio);		return BLK_QC_T_NONE;	} 	if (unlikely(test_bit(MD_BROKEN, &mddev->flags)) && (rw == WRITE)) {		bio_io_error(bio);		return BLK_QC_T_NONE;	} 	blk_queue_split(&bio);

Lines 1–500 of 9885.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t