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