8614 lines · 221.6 KB · C
RawDownload
/*   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.    This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2, or (at your option)   any later version.    You should have received a copy of the GNU General Public License   (for example /usr/src/linux/COPYING); if not, write to the Free   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/ #include <linux/kthread.h>#include <linux/blkdev.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/slab.h>#include "md.h"#include "bitmap.h" #ifndef MODULEstatic void autostart_arrays(int part);#endif /* 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 void md_print_devices(void); static DECLARE_WAIT_QUEUE_HEAD(resync_wait);static struct workqueue_struct *md_wq;static struct workqueue_struct *md_misc_wq; #define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); } /* * 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/* * 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 struct ctl_table_header *raid_table_header; static 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 ctl_table raid_dir_table[] = {	{		.procname	= "raid",		.maxlen		= 0,		.mode		= S_IRUGO|S_IXUGO,		.child		= raid_table,	},	{ }}; static ctl_table raid_root_table[] = {	{		.procname	= "dev",		.maxlen		= 0,		.mode		= 0555,		.child		= raid_dir_table,	},	{  }}; static const struct block_device_operations md_fops; static int start_readonly; /* bio_clone_mddev * like bio_clone, but with a local bio set */ static void mddev_bio_destructor(struct bio *bio){	struct mddev *mddev, **mddevp; 	mddevp = (void*)bio;	mddev = mddevp[-1]; 	bio_free(bio, mddev->bio_set);} struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,			    struct mddev *mddev){	struct bio *b;	struct mddev **mddevp; 	if (!mddev || !mddev->bio_set)		return bio_alloc(gfp_mask, nr_iovecs); 	b = bio_alloc_bioset(gfp_mask, nr_iovecs,			     mddev->bio_set);	if (!b)		return NULL;	mddevp = (void*)b;	mddevp[-1] = mddev;	b->bi_destructor = mddev_bio_destructor;	return b;}EXPORT_SYMBOL_GPL(bio_alloc_mddev); struct bio *bio_clone_mddev(struct bio *bio, gfp_t gfp_mask,			    struct mddev *mddev){	struct bio *b;	struct mddev **mddevp; 	if (!mddev || !mddev->bio_set)		return bio_clone(bio, gfp_mask); 	b = bio_alloc_bioset(gfp_mask, bio->bi_max_vecs,			     mddev->bio_set);	if (!b)		return NULL;	mddevp = (void*)b;	mddevp[-1] = mddev;	b->bi_destructor = mddev_bio_destructor;	__bio_clone(b, bio);	if (bio_integrity(bio)) {		int ret; 		ret = bio_integrity_clone(b, bio, gfp_mask, mddev->bio_set); 		if (ret < 0) {			bio_put(b);			return NULL;		}	} 	return b;}EXPORT_SYMBOL_GPL(bio_clone_mddev); void md_trim_bio(struct bio *bio, int offset, int size){	/* 'bio' is a cloned bio which we need to trim to match	 * the given offset and size.	 * This requires adjusting bi_sector, bi_size, and bi_io_vec	 */	int i;	struct bio_vec *bvec;	int sofar = 0; 	size <<= 9;	if (offset == 0 && size == bio->bi_size)		return; 	bio->bi_sector += offset;	bio->bi_size = size;	offset <<= 9;	clear_bit(BIO_SEG_VALID, &bio->bi_flags); 	while (bio->bi_idx < bio->bi_vcnt &&	       bio->bi_io_vec[bio->bi_idx].bv_len <= offset) {		/* remove this whole bio_vec */		offset -= bio->bi_io_vec[bio->bi_idx].bv_len;		bio->bi_idx++;	}	if (bio->bi_idx < bio->bi_vcnt) {		bio->bi_io_vec[bio->bi_idx].bv_offset += offset;		bio->bi_io_vec[bio->bi_idx].bv_len -= offset;	}	/* avoid any complications with bi_idx being non-zero*/	if (bio->bi_idx) {		memmove(bio->bi_io_vec, bio->bi_io_vec+bio->bi_idx,			(bio->bi_vcnt - bio->bi_idx) * sizeof(struct bio_vec));		bio->bi_vcnt -= bio->bi_idx;		bio->bi_idx = 0;	}	/* Make sure vcnt and last bv are not too big */	bio_for_each_segment(bvec, bio, i) {		if (sofar + bvec->bv_len > size)			bvec->bv_len = size - sofar;		if (bvec->bv_len == 0) {			bio->bi_vcnt = i;			break;		}		sofar += bvec->bv_len;	}}EXPORT_SYMBOL_GPL(md_trim_bio); /* * 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); /* Alternate version that can be called from interrupts * when calling sysfs_notify isn't needed. */static void md_new_event_inintr(struct mddev *mddev){	atomic_inc(&md_event_count);	wake_up(&md_event_waiters);} /* * 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 void md_make_request(struct request_queue *q, struct bio *bio){	const int rw = bio_data_dir(bio);	struct mddev *mddev = q->queuedata;	int cpu;	unsigned int sectors; 	if (mddev == NULL || mddev->pers == NULL	    || !mddev->ready) {		bio_io_error(bio);		return;	}	smp_rmb(); /* Ensure implications of  'active' are visible */	rcu_read_lock();	if (mddev->suspended) {		DEFINE_WAIT(__wait);		for (;;) {			prepare_to_wait(&mddev->sb_wait, &__wait,					TASK_UNINTERRUPTIBLE);			if (!mddev->suspended)				break;			rcu_read_unlock();			schedule();			rcu_read_lock();		}		finish_wait(&mddev->sb_wait, &__wait);	}	atomic_inc(&mddev->active_io);	rcu_read_unlock(); 	/*	 * save the sectors now since our bio can	 * go away inside make_request	 */	sectors = bio_sectors(bio);	mddev->pers->make_request(mddev, bio); 	cpu = part_stat_lock();	part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);	part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw], sectors);	part_stat_unlock(); 	if (atomic_dec_and_test(&mddev->active_io) && mddev->suspended)		wake_up(&mddev->sb_wait);} /* mddev_suspend makes sure no new requests are submitted * to the device, and that any requests that have been submitted * are completely handled. * Once ->stop is called and completes, the module will be completely * unused. */void mddev_suspend(struct mddev *mddev){	BUG_ON(mddev->suspended);	mddev->suspended = 1;	synchronize_rcu();	wait_event(mddev->sb_wait, atomic_read(&mddev->active_io) == 0);	mddev->pers->quiesce(mddev, 1); 	del_timer_sync(&mddev->safemode_timer);}EXPORT_SYMBOL_GPL(mddev_suspend); void mddev_resume(struct mddev *mddev){	mddev->suspended = 0;	wake_up(&mddev->sb_wait);	mddev->pers->quiesce(mddev, 0); 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);	md_wakeup_thread(mddev->thread);	md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */}EXPORT_SYMBOL_GPL(mddev_resume); int mddev_congested(struct mddev *mddev, int bits){	return mddev->suspended;}EXPORT_SYMBOL(mddev_congested); /* * Generic flush handling for md */ static void md_end_flush(struct bio *bio, int err){	struct md_rdev *rdev = bio->bi_private;	struct mddev *mddev = rdev->mddev; 	rdev_dec_pending(rdev, mddev); 	if (atomic_dec_and_test(&mddev->flush_pending)) {		/* The pre-request flush has finished */		queue_work(md_wq, &mddev->flush_work);	}	bio_put(bio);} static void md_submit_flush_data(struct work_struct *ws); static void submit_flushes(struct work_struct *ws){	struct mddev *mddev = container_of(ws, struct mddev, flush_work);	struct md_rdev *rdev; 	INIT_WORK(&mddev->flush_work, md_submit_flush_data);	atomic_set(&mddev->flush_pending, 1);	rcu_read_lock();	rdev_for_each_rcu(rdev, mddev)		if (rdev->raid_disk >= 0 &&		    !test_bit(Faulty, &rdev->flags)) {			/* Take two references, one is dropped			 * when request finishes, one after			 * we reclaim rcu_read_lock			 */			struct bio *bi;			atomic_inc(&rdev->nr_pending);			atomic_inc(&rdev->nr_pending);			rcu_read_unlock();			bi = bio_alloc_mddev(GFP_NOIO, 0, mddev);			bi->bi_end_io = md_end_flush;			bi->bi_private = rdev;			bi->bi_bdev = rdev->bdev;			atomic_inc(&mddev->flush_pending);			submit_bio(WRITE_FLUSH, bi);			rcu_read_lock();			rdev_dec_pending(rdev, mddev);		}	rcu_read_unlock();	if (atomic_dec_and_test(&mddev->flush_pending))		queue_work(md_wq, &mddev->flush_work);} static void md_submit_flush_data(struct work_struct *ws){	struct mddev *mddev = container_of(ws, struct mddev, flush_work);	struct bio *bio = mddev->flush_bio; 	if (bio->bi_size == 0)		/* an empty barrier - all done */		bio_endio(bio, 0);	else {		bio->bi_rw &= ~REQ_FLUSH;		mddev->pers->make_request(mddev, bio);	} 	mddev->flush_bio = NULL;	wake_up(&mddev->sb_wait);} void md_flush_request(struct mddev *mddev, struct bio *bio){	spin_lock_irq(&mddev->write_lock);	wait_event_lock_irq(mddev->sb_wait,			    !mddev->flush_bio,			    mddev->write_lock, /*nothing*/);	mddev->flush_bio = bio;	spin_unlock_irq(&mddev->write_lock); 	INIT_WORK(&mddev->flush_work, submit_flushes);	queue_work(md_wq, &mddev->flush_work);}EXPORT_SYMBOL(md_flush_request); 

Lines 1–500 of 8614.