Commit 25883336 authored by David Woodhouse's avatar David Woodhouse

Replace mtd_blktrans ->ioctl() method with ->getgeo() and ->flush()

... and also fix the embarrassing bug where NFTL and INFTL will
barf and exit if the add_mtd_blktrans_dev() function _exists_,
rather than actually calling it and barfing if it returns non-zero :)
parent d0582887
/* This version ported to the Linux-MTD system by dwmw2@infradead.org
* $Id: ftl.c,v 1.50 2003/05/21 10:49:47 dwmw2 Exp $
* $Id: ftl.c,v 1.51 2003/06/23 12:00:08 dwmw2 Exp $
*
* Fixes: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
* - fixes some leaks on failure in build_maps and ftl_notify_add, cleanups
......@@ -984,37 +984,20 @@ static int ftl_write(partition_t *part, caddr_t buffer,
return 0;
} /* ftl_write */
/*======================================================================
IOCTL calls for getting device parameters.
======================================================================*/
static int ftl_ioctl(struct mtd_blktrans_dev *dev, struct inode *inode,
struct file *file, u_int cmd, u_long arg)
static int ftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo)
{
struct hd_geometry *geo = (struct hd_geometry *)arg;
partition_t *part = (void *)dev;
u_long sect;
switch (cmd) {
case HDIO_GETGEO:
/* Sort of arbitrary: round size down to 4K boundary */
/* Sort of arbitrary: round size down to 4KiB boundary */
sect = le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE;
if (put_user(1, (char *)&geo->heads) ||
put_user(8, (char *)&geo->sectors) ||
put_user((sect>>3), (short *)&geo->cylinders) ||
put_user(0, (u_long *)&geo->start))
return -EFAULT;
case BLKFLSBUF:
return 0;
}
return -ENOTTY;
} /* ftl_ioctl */
geo->heads = 1;
geo->sectors = 8;
geo->cylinders = sect >> 3;
/*======================================================================*/
return 0;
}
static int ftl_readsect(struct mtd_blktrans_dev *dev,
unsigned long block, char *buf)
......@@ -1102,7 +1085,7 @@ struct mtd_blktrans_ops ftl_tr = {
.part_bits = PART_BITS,
.readsect = ftl_readsect,
.writesect = ftl_writesect,
.ioctl = ftl_ioctl,
.getgeo = ftl_getgeo,
.add_mtd = ftl_add_mtd,
.remove_dev = ftl_remove_dev,
.owner = THIS_MODULE,
......@@ -1110,7 +1093,7 @@ struct mtd_blktrans_ops ftl_tr = {
int init_ftl(void)
{
DEBUG(0, "$Id: ftl.c,v 1.50 2003/05/21 10:49:47 dwmw2 Exp $\n");
DEBUG(0, "$Id: ftl.c,v 1.51 2003/06/23 12:00:08 dwmw2 Exp $\n");
return register_mtd_blktrans(&ftl_tr);
}
......
......@@ -7,7 +7,7 @@
* (c) 1999 Machine Vision Holdings, Inc.
* Author: David Woodhouse <dwmw2@infradead.org>
*
* $Id: inftlcore.c,v 1.9 2003/05/23 11:41:47 dwmw2 Exp $
* $Id: inftlcore.c,v 1.11 2003/06/23 12:00:08 dwmw2 Exp $
*
* 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
......@@ -113,7 +113,7 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
(long)inftl->sectors );
}
if (add_mtd_blktrans_dev) {
if (add_mtd_blktrans_dev(&inftl->mbd)) {
if (inftl->PUtable)
kfree(inftl->PUtable);
if (inftl->VUtable)
......@@ -835,35 +835,22 @@ static int inftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
return 0;
}
static int inftl_ioctl(struct mtd_blktrans_dev *dev,
struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
static int inftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo)
{
struct NFTLrecord *nftl = (void *)dev;
switch (cmd) {
case HDIO_GETGEO: {
struct hd_geometry g;
g.heads = nftl->heads;
g.sectors = nftl->sectors;
g.cylinders = nftl->cylinders;
g.start = 0;
return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0;
}
geo->heads = nftl->heads;
geo->sectors = nftl->sectors;
geo->cylinders = nftl->cylinders;
default:
return -ENOTTY;
}
return 0;
}
struct mtd_blktrans_ops inftl_tr = {
.name = "inftl",
.major = INFTL_MAJOR,
.part_bits = INFTL_PARTN_BITS,
.ioctl = inftl_ioctl,
.getgeo = inftl_getgeo,
.readsect = inftl_readblock,
.writesect = inftl_writeblock,
.add_mtd = inftl_add_mtd,
......@@ -875,7 +862,7 @@ extern char inftlmountrev[];
int __init init_inftl(void)
{
printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.9 $, "
printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.11 $, "
"inftlmount.c %s\n", inftlmountrev);
return register_mtd_blktrans(&inftl_tr);
......
/*
* $Id: mtd_blkdevs.c,v 1.12 2003/05/21 01:00:59 dwmw2 Exp $
* $Id: mtd_blkdevs.c,v 1.15 2003/06/23 12:00:08 dwmw2 Exp $
*
* (C) 2003 David Woodhouse <dwmw2@infradead.org>
*
......@@ -18,8 +18,10 @@
#include <linux/blk.h>
#include <linux/blkpg.h>
#include <linux/spinlock.h>
#include <linux/hdreg.h>
#include <linux/init.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
#include <linux/devfs_fs_kernel.h>
static LIST_HEAD(blktrans_majors);
......@@ -46,7 +48,7 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr,
nsect = req->current_nr_sectors;
buf = req->buffer;
if (!req->flags & REQ_CMD)
if (!(req->flags & REQ_CMD))
return 0;
if (block + nsect > get_capacity(req->rq_disk))
......@@ -93,14 +95,14 @@ static int mtd_blktrans_thread(void *arg)
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
spin_lock_irq(rq->queue_lock);
while (!tr->blkcore_priv->exiting) {
struct request *req;
struct mtd_blktrans_dev *dev;
int res = 0;
DECLARE_WAITQUEUE(wait, current);
spin_lock_irq(rq->queue_lock);
req = elv_next_request(rq);
if (!req) {
......@@ -112,6 +114,8 @@ static int mtd_blktrans_thread(void *arg)
schedule();
remove_wait_queue(&tr->blkcore_priv->thread_wq, &wait);
spin_lock_irq(rq->queue_lock);
continue;
}
......@@ -159,7 +163,7 @@ int blktrans_open(struct inode *i, struct file *f)
dev->mtd->usecount++;
ret = 0;
if (tr->open && (ret = tr->open(dev, i, f))) {
if (tr->open && (ret = tr->open(dev))) {
dev->mtd->usecount--;
module_put(dev->mtd->owner);
out_tr:
......@@ -179,7 +183,7 @@ int blktrans_release(struct inode *i, struct file *f)
tr = dev->tr;
if (tr->release)
ret = tr->release(dev, i, f);
ret = tr->release(dev);
if (!ret) {
dev->mtd->usecount--;
......@@ -194,21 +198,33 @@ int blktrans_release(struct inode *i, struct file *f)
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;
int ret = -ENOTTY;
struct mtd_blktrans_dev *dev = inode->i_bdev->bd_disk->private_data;
struct mtd_blktrans_ops *tr = dev->tr;
dev = inode->i_bdev->bd_disk->private_data;
tr = dev->tr;
switch (cmd) {
case BLKFLSBUF:
if (tr->flush)
return tr->flush(dev);
/* The core code did the work, we had nothing to do. */
return 0;
if (tr->ioctl)
ret = tr->ioctl(dev, inode, file, cmd, arg);
case HDIO_GETGEO:
if (tr->getgeo) {
struct hd_geometry g;
if (ret == -ENOTTY && (cmd == BLKROSET || cmd == BLKFLSBUF)) {
/* The core code did the work, we had nothing to do. */
ret = 0;
}
memset(&g, 0, sizeof(g));
int ret = tr->getgeo(dev, &g);
if (ret)
return ret;
g.start = get_start_sect(inode->i_bdev);
if (copy_to_user((void *)arg, &g, sizeof(g)))
return -EFAULT;
return 0;
} /* else */
default:
return -ENOTTY;
}
}
struct block_device_operations mtd_blktrans_ops = {
......
/*
* Direct MTD block device access
*
* $Id: mtdblock.c,v 1.61 2003/05/21 10:49:38 dwmw2 Exp $
* $Id: mtdblock.c,v 1.63 2003/06/23 12:00:08 dwmw2 Exp $
*
* (C) 2000-2003 Nicolas Pitre <nico@cam.org>
* (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>
......@@ -248,11 +248,19 @@ static int mtdblock_writesect(struct mtd_blktrans_dev *dev,
unsigned long block, char *buf)
{
struct mtdblk_dev *mtdblk = mtdblks[dev->devnum];
if (unlikely(!mtdblk->cache_data)) {
mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize);
if (!mtdblk->cache_data)
return -EINTR;
/* -EINTR is not really correct, but it is the best match
* documented in man 2 write for all cases. We could also
* return -EAGAIN sometimes, but why bother?
*/
}
return do_cached_write(mtdblk, block<<9, 512, buf);
}
static int mtdblock_open(struct mtd_blktrans_dev *mbd,
struct inode *inode, struct file *file)
static int mtdblock_open(struct mtd_blktrans_dev *mbd)
{
struct mtdblk_dev *mtdblk;
struct mtd_info *mtd = mbd->mtd;
......@@ -279,11 +287,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd,
if ((mtdblk->mtd->flags & MTD_CAP_RAM) != MTD_CAP_RAM &&
mtdblk->mtd->erasesize) {
mtdblk->cache_size = mtdblk->mtd->erasesize;
mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize);
if (!mtdblk->cache_data) {
kfree(mtdblk);
return -ENOMEM;
}
mtdblk->cache_data = NULL;
}
mtdblks[dev] = mtdblk;
......@@ -293,17 +297,13 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd,
return 0;
}
static int mtdblock_release(struct mtd_blktrans_dev *mbd,
struct inode *inode, struct file *file)
static int mtdblock_release(struct mtd_blktrans_dev *mbd)
{
int dev;
struct mtdblk_dev *mtdblk;
int dev = mbd->devnum;
struct mtdblk_dev *mtdblk = mtdblks[dev];
DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n");
dev = minor(inode->i_rdev);
mtdblk = mtdblks[dev];
down(&mtdblk->cache_sem);
write_cached_data(mtdblk);
up(&mtdblk->cache_sem);
......@@ -321,27 +321,17 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd,
return 0;
}
static int mtdblock_ioctl(struct mtd_blktrans_dev *dev,
struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg)
static int mtdblock_flush(struct mtd_blktrans_dev *dev)
{
struct mtdblk_dev *mtdblk;
mtdblk = mtdblks[minor(inode->i_rdev)];
struct mtdblk_dev *mtdblk = mtdblks[dev->devnum];
switch (cmd) {
case BLKFLSBUF:
down(&mtdblk->cache_sem);
write_cached_data(mtdblk);
up(&mtdblk->cache_sem);
if (mtdblk->mtd->sync)
mtdblk->mtd->sync(mtdblk->mtd);
return 0;
default:
return -ENOTTY;
}
}
static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
......@@ -376,7 +366,7 @@ struct mtd_blktrans_ops mtdblock_tr = {
.major = 31,
.part_bits = 0,
.open = mtdblock_open,
.ioctl = mtdblock_ioctl,
.flush = mtdblock_flush,
.release = mtdblock_release,
.readsect = mtdblock_readsect,
.writesect = mtdblock_writesect,
......
/*
* $Id: mtdblock_ro.c,v 1.17 2003/05/18 19:27:27 dwmw2 Exp $
* $Id: mtdblock_ro.c,v 1.18 2003/06/23 12:00:08 dwmw2 Exp $
*
* (C) 2003 David Woodhouse <dwmw2@infradead.org>
*
* Simple read-only (writable only for RAM) mtdblock driver
*/
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/blktrans.h>
......
/* Linux driver for NAND Flash Translation Layer */
/* (c) 1999 Machine Vision Holdings, Inc. */
/* Author: David Woodhouse <dwmw2@infradead.org> */
/* $Id: nftlcore.c,v 1.92 2003/05/23 11:41:47 dwmw2 Exp $ */
/* $Id: nftlcore.c,v 1.94 2003/06/23 12:00:08 dwmw2 Exp $ */
/*
The contents of this file are distributed under the GNU General
......@@ -101,7 +101,7 @@ static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
(long)nftl->sectors );
}
if (add_mtd_blktrans_dev) {
if (add_mtd_blktrans_dev(&nftl->mbd)) {
if (nftl->ReplUnitTable)
kfree(nftl->ReplUnitTable);
if (nftl->EUNtable)
......@@ -699,29 +699,17 @@ static int nftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
return 0;
}
static int nftl_ioctl(struct mtd_blktrans_dev *dev,
struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg)
static int nftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo)
{
struct NFTLrecord *nftl = (void *)dev;
switch (cmd) {
case HDIO_GETGEO: {
struct hd_geometry g;
geo->heads = nftl->heads;
geo->sectors = nftl->sectors;
geo->cylinders = nftl->cylinders;
g.heads = nftl->heads;
g.sectors = nftl->sectors;
g.cylinders = nftl->cylinders;
g.start = 0;
return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0;
}
default:
return -ENOTTY;
}
return 0;
}
/****************************************************************************
*
* Module stuff
......@@ -733,7 +721,7 @@ struct mtd_blktrans_ops nftl_tr = {
.name = "nftl",
.major = NFTL_MAJOR,
.part_bits = NFTL_PARTN_BITS,
.ioctl = nftl_ioctl,
.getgeo = nftl_getgeo,
.readsect = nftl_readblock,
#ifdef CONFIG_NFTL_RW
.writesect = nftl_writeblock,
......@@ -747,7 +735,7 @@ extern char nftlmountrev[];
int __init init_nftl(void)
{
printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.92 $, nftlmount.c %s\n", nftlmountrev);
printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.94 $, nftlmount.c %s\n", nftlmountrev);
return register_mtd_blktrans(&nftl_tr);
}
......
/*
* $Id: blktrans.h,v 1.4 2003/05/21 01:01:32 dwmw2 Exp $
* $Id: blktrans.h,v 1.5 2003/06/23 12:00:08 dwmw2 Exp $
*
* (C) 2003 David Woodhouse <dwmw2@infradead.org>
*
......@@ -12,6 +12,7 @@
#include <asm/semaphore.h>
struct hd_geometry;
struct mtd_info;
struct mtd_blktrans_ops;
struct file;
......@@ -42,17 +43,13 @@ struct mtd_blktrans_ops {
int (*writesect)(struct mtd_blktrans_dev *dev,
unsigned long block, char *buffer);
/* HDIO_GETGEO and HDIO_GETGEO_BIG are the only non-private
ioctls which are expected to be passed through */
int (*ioctl)(struct mtd_blktrans_dev *dev,
struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg);
/* Block layer ioctls */
int (*getgeo)(struct mtd_blktrans_dev *dev, struct hd_geometry *geo);
int (*flush)(struct mtd_blktrans_dev *dev);
/* Called with mtd_table_mutex held; no race with add/remove */
int (*open)(struct mtd_blktrans_dev *dev,
struct inode *i, struct file *f);
int (*release)(struct mtd_blktrans_dev *dev,
struct inode *i, struct file *f);
int (*open)(struct mtd_blktrans_dev *dev);
int (*release)(struct mtd_blktrans_dev *dev);
/* Called on {de,}registration and on subsequent addition/removal
of devices, with mtd_table_mutex held. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment