mtd/drivers/mtd mtd_blkdevs.c,1.1,1.2

David Woodhouse dwmw2 at infradead.org
Sun May 18 10:29:20 EDT 2003


Update of /home/cvs/mtd/drivers/mtd
In directory phoenix.infradead.org:/tmp/cvs-serv30154

Modified Files:
	mtd_blkdevs.c 
Log Message:
ioctl support, blkrrpart


Index: mtd_blkdevs.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/mtd_blkdevs.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- mtd_blkdevs.c	18 May 2003 13:10:22 -0000	1.1
+++ mtd_blkdevs.c	18 May 2003 14:29:17 -0000	1.2
@@ -16,6 +16,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/blkdev.h>
 #include <linux/blk.h>
+#include <linux/blkpg.h>
 #include <asm/semaphore.h>
 #include <linux/mtd/compatmac.h>
 
@@ -45,6 +46,21 @@
 	}
 	return NULL;
 }
+
+static inline struct mtd_blktrans_ops *get_tr(int major)
+{
+	struct list_head *this;
+	struct mtd_blktrans_ops *t;
+
+	list_for_each(this, &blktrans_majors) {
+		t = list_entry(this, struct mtd_blktrans_ops, list);
+
+		if (t->major == major)
+			return t;
+	}
+	return NULL;
+}
+
 static int do_blktrans_request(struct mtd_blktrans_ops *tr,
 			       struct mtd_blktrans_dev *dev,
 			       struct request *req)
@@ -141,22 +157,16 @@
 
 int blktrans_open(struct inode *i, struct file *f)
 {
+	struct mtd_blktrans_ops *tr = NULL;
+	struct mtd_blktrans_dev *dev = NULL;
 	int major_nr = MAJOR(i->i_rdev);
 	int minor_nr = MINOR(i->i_rdev);
 	int devnum;
-	struct list_head *this;
-	struct mtd_blktrans_ops *tr = NULL;
-	struct mtd_blktrans_dev *dev = NULL;
 	int ret = -ENODEV;
 
 	down(&mtd_table_mutex);
 
-	list_for_each(this, &blktrans_majors) {
-		struct mtd_blktrans_ops *t = list_entry(this, struct mtd_blktrans_ops, list);
-		if (t->major == major_nr)
-			tr = t;
-		break;
-	}
+	tr = get_tr(major_nr);
 
 	if (!tr)
 		goto out;
@@ -217,11 +227,109 @@
 	return ret;
 }
 
+static int mtd_blktrans_rrpart(kdev_t rdev, struct mtd_blktrans_ops *tr,
+			       struct mtd_blktrans_dev *dev)
+{
+	struct gendisk *gd = &(tr->blkcore_priv->gd);
+	int i;
+	int minor = MINOR(rdev);
+
+	if (minor & ((1<<tr->part_bits)-1)) {
+		/* BLKRRPART on a partition. Go away. */
+		return -ENOTTY;
+	}
+
+	if (!capable(CAP_SYS_ADMIN))
+	    return -EACCES;
+
+	/* We are required to prevent simultaneous open() ourselves.
+	   The core doesn't do that for us. Did I ever mention how
+	   much the Linux block layer sucks? Sledgehammer approach... */
+	down(&mtd_table_mutex);
+
+	if (dev->usecount > 1) {
+		up(&mtd_table_mutex);
+		return -EBUSY;
+	}
+
+	for (i=0; i < (1<<tr->part_bits); i++) {
+		invalidate_device(MKDEV(tr->major, minor+i), 1);
+		gd->part[minor + i].start_sect = 0;
+		gd->part[minor + i].nr_sects = 0;
+	}
+
+	grok_partitions(gd, minor, 1 << tr->part_bits, 
+			tr->blkcore_priv->sizes[minor]);
+
+	up(&mtd_table_mutex);
+	return 0;
+}
+
+static int blktrans_ioctl(struct inode *inode, struct file *file, 
+			      unsigned int cmd, unsigned long arg)
+{
+	struct mtd_blktrans_dev *dev;
+	struct mtd_blktrans_ops *tr;
+
+	switch(cmd) {
+	case BLKGETSIZE:
+        case BLKGETSIZE64:
+        case BLKBSZSET:
+        case BLKBSZGET:
+        case BLKROSET:
+        case BLKROGET:
+        case BLKRASET:
+        case BLKRAGET:
+        case BLKPG:
+        case BLKELVGET:
+        case BLKELVSET:
+		return blk_ioctl(inode->i_rdev, cmd, arg);
+	}
+
+	if (file) {
+		dev = file->private_data;
+		tr = dev->tr;
+	} else {
+		/* Urgh. ioctl_by_bdev() calls us without a file pointer. */
+		int devnum;
+
+		down(&mtd_table_mutex);
+
+		tr = get_tr(MAJOR(inode->i_rdev));
+		if (!tr) {
+			up(&mtd_table_mutex);
+			return -ENODEV;
+		}
+
+		devnum = MINOR(inode->i_rdev) >> tr->part_bits;
+		dev = tr_get_dev(tr, devnum);
+
+		up(&mtd_table_mutex);
+
+		if (!dev)
+			return -ENODEV;
+	}		
+	switch(cmd) {
+	case BLKRRPART:
+		return mtd_blktrans_rrpart(inode->i_rdev, tr, dev);
+		
+        case BLKFLSBUF:
+		blk_ioctl(inode->i_rdev, cmd, arg);
+		if (!tr->ioctl)
+			return 0;
+
+	default:
+		if (!tr->ioctl)
+			return -ENOTTY;
+		return tr->ioctl(dev, inode, file, cmd, arg);
+	}
+}
+
 struct block_device_operations mtd_blktrans_ops = {
 	.owner		= THIS_MODULE,
 	.open		= blktrans_open,
 	.release	= blktrans_release,
-	//	.ioctl		= blktrans_ioctl,
+	.ioctl		= blktrans_ioctl,
 };
 
 
@@ -299,8 +407,10 @@
 	tr->blkcore_priv->sizes[old->devnum << tr->part_bits] = 0;
 
 	for (i = (old->devnum << tr->part_bits); 
-	     i < ((old->devnum+1) << tr->part_bits); i++)
+	     i < ((old->devnum+1) << tr->part_bits); i++) {
 		tr->blkcore_priv->part_table[i].nr_sects = 0;
+		tr->blkcore_priv->part_table[i].start_sect = 0;
+	}
 		
 	return 0;
 }




More information about the linux-mtd-cvs mailing list