patch-2.4.0-test12 linux/drivers/md/md.c

Next file: linux/drivers/md/raid0.c
Previous file: linux/drivers/md/lvm.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test11/linux/drivers/md/md.c linux/drivers/md/md.c
@@ -179,7 +179,7 @@
 		return mddev->pers->make_request(mddev, rw, bh);
 	else {
 		buffer_IO_error(bh);
-		return -1;
+		return 0;
 	}
 }
 
@@ -203,6 +203,7 @@
 	init_MUTEX(&mddev->resync_sem);
 	MD_INIT_LIST_HEAD(&mddev->disks);
 	MD_INIT_LIST_HEAD(&mddev->all_mddevs);
+	atomic_set(&mddev->active, 0);
 
 	/*
 	 * The 'base' mddev is the one with data NULL.
@@ -656,32 +657,25 @@
 static int lock_rdev (mdk_rdev_t *rdev)
 {
 	int err = 0;
+	struct block_device *bdev;
 
-	/*
-	 * First insert a dummy inode.
-	 */
-	if (rdev->inode)
-		MD_BUG();
-	rdev->inode = get_empty_inode();
-	if (!rdev->inode)
+	bdev = bdget(rdev->dev);
+	if (bdev == NULL)
 		return -ENOMEM;
- 	/*
-	 * we dont care about any other fields
-	 */
-	rdev->inode->i_dev = rdev->inode->i_rdev = rdev->dev;
-	insert_inode_hash(rdev->inode);
-
-	memset(&rdev->filp, 0, sizeof(rdev->filp));
-	rdev->filp.f_mode = 3; /* read write */
+	err = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_FILE);
+	if (!err) {
+		rdev->bdev = bdev;
+	}
 	return err;
 }
 
 static void unlock_rdev (mdk_rdev_t *rdev)
 {
-	if (!rdev->inode)
+	if (!rdev->bdev)
 		MD_BUG();
-	iput(rdev->inode);
-	rdev->inode = NULL;
+	blkdev_put(rdev->bdev, BDEV_FILE);
+	bdput(rdev->bdev);
+	rdev->bdev = NULL;
 }
 
 static void export_rdev (mdk_rdev_t * rdev)
@@ -1149,7 +1143,7 @@
 
 abort_free:
 	if (rdev->sb) {
-		if (rdev->inode)
+		if (rdev->bdev)
 			unlock_rdev(rdev);
 		free_disk_sb(rdev);
 	}
@@ -1718,12 +1712,20 @@
 
 #define STILL_MOUNTED KERN_WARNING \
 "md: md%d still mounted.\n"
+#define	STILL_IN_USE \
+"md: md%d still in use.\n"
 
 static int do_md_stop (mddev_t * mddev, int ro)
 {
 	int err = 0, resync_interrupted = 0;
 	kdev_t dev = mddev_to_kdev(mddev);
 
+ 	if (atomic_read(&mddev->active)>1) {
+ 		printk(STILL_IN_USE, mdidx(mddev));
+ 		OUT(-EBUSY);
+ 	}
+ 
+ 	/* this shouldn't be needed as above would have fired */
 	if (!ro && get_super(dev)) {
 		printk (STILL_MOUNTED, mdidx(mddev));
 		OUT(-EBUSY);
@@ -1859,8 +1861,10 @@
  * the 'same_array' list. Then order this list based on superblock
  * update time (freshest comes first), kick out 'old' disks and
  * compare superblocks. If everything's fine then run it.
+ *
+ * If "unit" is allocated, then bump its reference count
  */
-static void autorun_devices (void)
+static void autorun_devices (kdev_t countdev)
 {
 	struct md_list_head candidates;
 	struct md_list_head *tmp;
@@ -1902,6 +1906,12 @@
 			continue;
 		}
 		mddev = alloc_mddev(md_kdev);
+ 		if (mddev == NULL) {
+ 			printk("md: cannot allocate memory for md drive.\n");
+ 			break;
+ 		}
+ 		if (md_kdev == countdev)
+ 			atomic_inc(&mddev->active);
 		printk("created md%d\n", mdidx(mddev));
 		ITERATE_RDEV_GENERIC(candidates,pending,rdev,tmp) {
 			bind_rdev_to_array(rdev, mddev);
@@ -1945,7 +1955,7 @@
 #define AUTORUNNING KERN_INFO \
 "md: auto-running md%d.\n"
 
-static int autostart_array (kdev_t startdev)
+static int autostart_array (kdev_t startdev, kdev_t countdev)
 {
 	int err = -EINVAL, i;
 	mdp_super_t *sb = NULL;
@@ -2002,7 +2012,7 @@
 	/*
 	 * possibly return codes
 	 */
-	autorun_devices();
+	autorun_devices(countdev);
 	return 0;
 
 abort:
@@ -2077,7 +2087,7 @@
 			md_list_add(&rdev->pending, &pending_raid_disks);
 		}
 
-		autorun_devices();
+		autorun_devices(-1);
 	}
 
 	dev_cnt = -1; /* make sure further calls to md_autodetect_dev are ignored */
@@ -2607,6 +2617,8 @@
 				err = -ENOMEM;
 				goto abort;
 			}
+			atomic_inc(&mddev->active);
+
 			/*
 			 * alloc_mddev() should possibly self-lock.
 			 */
@@ -2640,7 +2652,7 @@
 			/*
 			 * possibly make it lock the array ...
 			 */
-			err = autostart_array((kdev_t)arg);
+			err = autostart_array((kdev_t)arg, dev);
 			if (err) {
 				printk("autostart %s failed!\n",
 					partition_name((kdev_t)arg));
@@ -2820,14 +2832,26 @@
 static int md_open (struct inode *inode, struct file *file)
 {
 	/*
-	 * Always succeed
+	 * Always succeed, but increment the usage count
 	 */
+	mddev_t *mddev = kdev_to_mddev(inode->i_rdev);
+	if (mddev)
+		atomic_inc(&mddev->active);
 	return (0);
 }
 
+static int md_release (struct inode *inode, struct file * file)
+{
+	mddev_t *mddev = kdev_to_mddev(inode->i_rdev);
+	if (mddev)
+		atomic_dec(&mddev->active);
+	return 0;
+}
+
 static struct block_device_operations md_fops=
 {
 	open:		md_open,
+	release:	md_release,
 	ioctl:		md_ioctl,
 };
 
@@ -3279,7 +3303,7 @@
 		if (mddev2 == mddev)
 			continue;
 		if (mddev2->curr_resync && match_mddev_units(mddev,mddev2)) {
-			printk(KERN_INFO "md: serializing resync, md%d has overlapping physical units with md%d!\n", mdidx(mddev), mdidx(mddev2));
+			printk(KERN_INFO "md: serializing resync, md%d shares one or more physical units with md%d!\n", mdidx(mddev), mdidx(mddev2));
 			serialize = 1;
 			break;
 		}
@@ -3576,20 +3600,14 @@
 	create_proc_read_entry("mdstat", 0, NULL, md_status_read_proc, NULL);
 #endif
 }
-void hsm_init (void);
-void translucent_init (void);
-void linear_init (void);
-void raid0_init (void);
-void raid1_init (void);
-void raid5_init (void);
 
 int md__init md_init (void)
 {
 	static char * name = "mdrecoveryd";
 	
-	printk (KERN_INFO "md driver %d.%d.%d MAX_MD_DEVS=%d, MAX_REAL=%d\n",
+	printk (KERN_INFO "md driver %d.%d.%d MAX_MD_DEVS=%d, MD_SB_DISKS=%d\n",
 			MD_MAJOR_VERSION, MD_MINOR_VERSION,
-			MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MAX_REAL);
+			MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS);
 
 	if (devfs_register_blkdev (MAJOR_NR, "md", &md_fops))
 	{
@@ -3617,18 +3635,6 @@
 	md_register_reboot_notifier(&md_notifier);
 	raid_table_header = register_sysctl_table(raid_root_table, 1);
 
-#ifdef CONFIG_MD_LINEAR
-	linear_init ();
-#endif
-#ifdef CONFIG_MD_RAID0
-	raid0_init ();
-#endif
-#ifdef CONFIG_MD_RAID1
-	raid1_init ();
-#endif
-#ifdef CONFIG_MD_RAID5
-	raid5_init ();
-#endif
 	md_geninit();
 	return (0);
 }
@@ -3639,7 +3645,7 @@
 	unsigned long set;
 	int pers[MAX_MD_BOOT_DEVS];
 	int chunk[MAX_MD_BOOT_DEVS];
-	kdev_t devices[MAX_MD_BOOT_DEVS][MAX_REAL];
+	kdev_t devices[MAX_MD_BOOT_DEVS][MD_SB_DISKS];
 } md_setup_args md__initdata = { 0, };
 
 /*
@@ -3713,7 +3719,7 @@
 		pername="super-block";
 	}
 	devnames = str;
-	for (; i<MAX_REAL && str; i++) {
+	for (; i<MD_SB_DISKS && str; i++) {
 		if ((device = name_to_kdev_t(str))) {
 			md_setup_args.devices[minor][i] = device;
 		} else {
@@ -3853,7 +3859,7 @@
 #endif
 
 __initcall(md_init);
-#ifdef CONFIG_AUTODETECT_RAID
+#if defined(CONFIG_AUTODETECT_RAID) || defined(CONFIG_MD_BOOT)
 __initcall(md_run_setup);
 #endif
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)