⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 raid1.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
static void end_sync_read(struct buffer_head *bh, int uptodate){	struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_private);	/* we have read a block, now it needs to be re-written,	 * or re-read if the read failed.	 * We don't do much here, just schedule handling by raid1d	 */	if (!uptodate)		md_error (mddev_to_kdev(r1_bh->mddev), bh->b_dev);	else		set_bit(R1BH_Uptodate, &r1_bh->state);	raid1_reschedule_retry(r1_bh);}static void end_sync_write(struct buffer_head *bh, int uptodate){ 	struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_private);		if (!uptodate) 		md_error (mddev_to_kdev(r1_bh->mddev), bh->b_dev);	if (atomic_dec_and_test(&r1_bh->remaining)) {		mddev_t *mddev = r1_bh->mddev; 		unsigned long sect = bh->b_blocknr * (bh->b_size>>9);		int size = bh->b_size;		raid1_free_buf(r1_bh);		sync_request_done(sect, mddev_to_conf(mddev));		md_done_sync(mddev,size>>10, uptodate);	}}/* * This will catch the scenario in which one of the mirrors was * mounted as a normal device rather than as a part of a raid set. * * check_consistency is very personality-dependent, eg. RAID5 cannot * do this check, it uses another method. */static int __check_consistency (mddev_t *mddev, int row){	raid1_conf_t *conf = mddev_to_conf(mddev);	int disks = MD_SB_DISKS;	kdev_t dev;	struct buffer_head *bh = NULL;	int i, rc = 0;	char *buffer = NULL;	for (i = 0; i < disks; i++) {		printk("(checking disk %d)\n",i);		if (!conf->mirrors[i].operational)			continue;		printk("(really checking disk %d)\n",i);		dev = conf->mirrors[i].dev;		set_blocksize(dev, 4096);		if ((bh = bread(dev, row / 4, 4096)) == NULL)			break;		if (!buffer) {			buffer = (char *) __get_free_page(GFP_KERNEL);			if (!buffer)				break;			memcpy(buffer, bh->b_data, 4096);		} else if (memcmp(buffer, bh->b_data, 4096)) {			rc = 1;			break;		}		bforget(bh);		fsync_dev(dev);		invalidate_buffers(dev);		bh = NULL;	}	if (buffer)		free_page((unsigned long) buffer);	if (bh) {		dev = bh->b_dev;		bforget(bh);		fsync_dev(dev);		invalidate_buffers(dev);	}	return rc;}static int check_consistency (mddev_t *mddev){	if (__check_consistency(mddev, 0))/* * we do not do this currently, as it's perfectly possible to * have an inconsistent array when it's freshly created. Only * newly written data has to be consistent. */		return 0;	return 0;}#define INVALID_LEVEL KERN_WARNING \"raid1: md%d: raid level not set to mirroring (%d)\n"#define NO_SB KERN_ERR \"raid1: disabled mirror %s (couldn't access raid superblock)\n"#define ERRORS KERN_ERR \"raid1: disabled mirror %s (errors detected)\n"#define NOT_IN_SYNC KERN_ERR \"raid1: disabled mirror %s (not in sync)\n"#define INCONSISTENT KERN_ERR \"raid1: disabled mirror %s (inconsistent descriptor)\n"#define ALREADY_RUNNING KERN_ERR \"raid1: disabled mirror %s (mirror %d already operational)\n"#define OPERATIONAL KERN_INFO \"raid1: device %s operational as mirror %d\n"#define MEM_ERROR KERN_ERR \"raid1: couldn't allocate memory for md%d\n"#define SPARE KERN_INFO \"raid1: spare disk %s\n"#define NONE_OPERATIONAL KERN_ERR \"raid1: no operational mirrors for md%d\n"#define RUNNING_CKRAID KERN_ERR \"raid1: detected mirror differences -- running resync\n"#define ARRAY_IS_ACTIVE KERN_INFO \"raid1: raid set md%d active with %d out of %d mirrors\n"#define THREAD_ERROR KERN_ERR \"raid1: couldn't allocate thread for md%d\n"#define START_RESYNC KERN_WARNING \"raid1: raid set md%d not clean; reconstructing mirrors\n"static int raid1_run (mddev_t *mddev){	raid1_conf_t *conf;	int i, j, disk_idx;	struct mirror_info *disk;	mdp_super_t *sb = mddev->sb;	mdp_disk_t *descriptor;	mdk_rdev_t *rdev;	struct md_list_head *tmp;	int start_recovery = 0;	MOD_INC_USE_COUNT;	if (sb->level != 1) {		printk(INVALID_LEVEL, mdidx(mddev), sb->level);		goto out;	}	/*	 * copy the already verified devices into our private RAID1	 * bookkeeping area. [whatever we allocate in raid1_run(),	 * should be freed in raid1_stop()]	 */	conf = kmalloc(sizeof(raid1_conf_t), GFP_KERNEL);	mddev->private = conf;	if (!conf) {		printk(MEM_ERROR, mdidx(mddev));		goto out;	}	memset(conf, 0, sizeof(*conf));	ITERATE_RDEV(mddev,rdev,tmp) {		if (rdev->faulty) {			printk(ERRORS, partition_name(rdev->dev));		} else {			if (!rdev->sb) {				MD_BUG();				continue;			}		}		if (rdev->desc_nr == -1) {			MD_BUG();			continue;		}		descriptor = &sb->disks[rdev->desc_nr];		disk_idx = descriptor->raid_disk;		disk = conf->mirrors + disk_idx;		if (disk_faulty(descriptor)) {			disk->number = descriptor->number;			disk->raid_disk = disk_idx;			disk->dev = rdev->dev;			disk->sect_limit = MAX_WORK_PER_DISK;			disk->operational = 0;			disk->write_only = 0;			disk->spare = 0;			disk->used_slot = 1;			disk->head_position = 0;			continue;		}		if (disk_active(descriptor)) {			if (!disk_sync(descriptor)) {				printk(NOT_IN_SYNC,					partition_name(rdev->dev));				continue;			}			if ((descriptor->number > MD_SB_DISKS) ||					 (disk_idx > sb->raid_disks)) {				printk(INCONSISTENT,					partition_name(rdev->dev));				continue;			}			if (disk->operational) {				printk(ALREADY_RUNNING,					partition_name(rdev->dev),					disk_idx);				continue;			}			printk(OPERATIONAL, partition_name(rdev->dev), 					disk_idx);			disk->number = descriptor->number;			disk->raid_disk = disk_idx;			disk->dev = rdev->dev;			disk->sect_limit = MAX_WORK_PER_DISK;			disk->operational = 1;			disk->write_only = 0;			disk->spare = 0;			disk->used_slot = 1;			disk->head_position = 0;			conf->working_disks++;		} else {		/*		 * Must be a spare disk ..		 */			printk(SPARE, partition_name(rdev->dev));			disk->number = descriptor->number;			disk->raid_disk = disk_idx;			disk->dev = rdev->dev;			disk->sect_limit = MAX_WORK_PER_DISK;			disk->operational = 0;			disk->write_only = 0;			disk->spare = 1;			disk->used_slot = 1;			disk->head_position = 0;		}	}	conf->raid_disks = sb->raid_disks;	conf->nr_disks = sb->nr_disks;	conf->mddev = mddev;	conf->device_lock = MD_SPIN_LOCK_UNLOCKED;	conf->segment_lock = MD_SPIN_LOCK_UNLOCKED;	init_waitqueue_head(&conf->wait_buffer);	init_waitqueue_head(&conf->wait_done);	init_waitqueue_head(&conf->wait_ready);	if (!conf->working_disks) {		printk(NONE_OPERATIONAL, mdidx(mddev));		goto out_free_conf;	}	/* pre-allocate some buffer_head structures.	 * As a minimum, 1 r1bh and raid_disks buffer_heads	 * would probably get us by in tight memory situations,	 * but a few more is probably a good idea.	 * For now, try 16 r1bh and 16*raid_disks bufferheads	 * This will allow at least 16 concurrent reads or writes	 * even if kmalloc starts failing	 */	if (raid1_grow_r1bh(conf, 16) < 16 ||	    raid1_grow_bh(conf, 16*conf->raid_disks)< 16*conf->raid_disks) {		printk(MEM_ERROR, mdidx(mddev));		goto out_free_conf;	}	for (i = 0; i < MD_SB_DISKS; i++) {				descriptor = sb->disks+i;		disk_idx = descriptor->raid_disk;		disk = conf->mirrors + disk_idx;		if (disk_faulty(descriptor) && (disk_idx < conf->raid_disks) &&				!disk->used_slot) {			disk->number = descriptor->number;			disk->raid_disk = disk_idx;			disk->dev = MKDEV(0,0);			disk->operational = 0;			disk->write_only = 0;			disk->spare = 0;			disk->used_slot = 1;			disk->head_position = 0;		}	}	/*	 * find the first working one and use it as a starting point	 * to read balancing.	 */	for (j = 0; !conf->mirrors[j].operational && j < MD_SB_DISKS; j++)		/* nothing */;	conf->last_used = j;	if (conf->working_disks != sb->raid_disks) {		printk(KERN_ALERT "raid1: md%d, not all disks are operational -- trying to recover array\n", mdidx(mddev));		start_recovery = 1;	}	if (!start_recovery && (sb->state & (1 << MD_SB_CLEAN))) {		/*		 * we do sanity checks even if the device says		 * it's clean ...		 */		if (check_consistency(mddev)) {			printk(RUNNING_CKRAID);			sb->state &= ~(1 << MD_SB_CLEAN);		}	}	{		const char * name = "raid1d";		conf->thread = md_register_thread(raid1d, conf, name);		if (!conf->thread) {			printk(THREAD_ERROR, mdidx(mddev));			goto out_free_conf;		}	}	if (!start_recovery && !(sb->state & (1 << MD_SB_CLEAN))) {		const char * name = "raid1syncd";		conf->resync_thread = md_register_thread(raid1syncd, conf,name);		if (!conf->resync_thread) {			printk(THREAD_ERROR, mdidx(mddev));			goto out_free_conf;		}		printk(START_RESYNC, mdidx(mddev));		conf->resync_mirrors = 1;		md_wakeup_thread(conf->resync_thread);	}	/*	 * Regenerate the "device is in sync with the raid set" bit for	 * each device.	 */	for (i = 0; i < MD_SB_DISKS; i++) {		mark_disk_nonsync(sb->disks+i);		for (j = 0; j < sb->raid_disks; j++) {			if (!conf->mirrors[j].operational)				continue;			if (sb->disks[i].number == conf->mirrors[j].number)				mark_disk_sync(sb->disks+i);		}	}	sb->active_disks = conf->working_disks;	if (start_recovery)		md_recover_arrays();	printk(ARRAY_IS_ACTIVE, mdidx(mddev), sb->active_disks, sb->raid_disks);	/*	 * Ok, everything is just fine now	 */	return 0;out_free_conf:	raid1_shrink_r1bh(conf);	raid1_shrink_bh(conf, conf->freebh_cnt);	raid1_shrink_buffers(conf);	kfree(conf);	mddev->private = NULL;out:	MOD_DEC_USE_COUNT;	return -EIO;}#undef INVALID_LEVEL#undef NO_SB#undef ERRORS#undef NOT_IN_SYNC#undef INCONSISTENT#undef ALREADY_RUNNING#undef OPERATIONAL#undef SPARE#undef NONE_OPERATIONAL#undef RUNNING_CKRAID#undef ARRAY_IS_ACTIVEstatic int raid1_stop_resync (mddev_t *mddev){	raid1_conf_t *conf = mddev_to_conf(mddev);	if (conf->resync_thread) {		if (conf->resync_mirrors) {			conf->resync_mirrors = 2;			md_interrupt_thread(conf->resync_thread);			printk(KERN_INFO "raid1: mirror resync was not fully finished, restarting next time.\n");			return 1;		}		return 0;	}	return 0;}static int raid1_restart_resync (mddev_t *mddev){	raid1_conf_t *conf = mddev_to_conf(mddev);	if (conf->resync_mirrors) {		if (!conf->resync_thread) {			MD_BUG();			return 0;		}		conf->resync_mirrors = 1;		md_wakeup_thread(conf->resync_thread);		return 1;	}	return 0;}static int raid1_stop (mddev_t *mddev){	raid1_conf_t *conf = mddev_to_conf(mddev);	md_unregister_thread(conf->thread);	if (conf->resync_thread)		md_unregister_thread(conf->resync_thread);	raid1_shrink_r1bh(conf);	raid1_shrink_bh(conf, conf->freebh_cnt);	raid1_shrink_buffers(conf);	kfree(conf);	mddev->private = NULL;	MOD_DEC_USE_COUNT;	return 0;}static mdk_personality_t raid1_personality={	name:		"raid1",	make_request:	raid1_make_request,	run:		raid1_run,	stop:		raid1_stop,	status:		raid1_status,	error_handler:	raid1_error,	diskop:		raid1_diskop,	stop_resync:	raid1_stop_resync,	restart_resync:	raid1_restart_resync,	sync_request:	raid1_sync_request};static int md__init raid1_init (void){	return register_md_personality (RAID1, &raid1_personality);}static void raid1_exit (void){	unregister_md_personality (RAID1);}module_init(raid1_init);module_exit(raid1_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -