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 /* 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: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
* - fixes some leaks on failure in build_maps and ftl_notify_add, cleanups * - 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, ...@@ -984,37 +984,20 @@ static int ftl_write(partition_t *part, caddr_t buffer,
return 0; return 0;
} /* ftl_write */ } /* ftl_write */
/*====================================================================== static int ftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo)
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)
{ {
struct hd_geometry *geo = (struct hd_geometry *)arg;
partition_t *part = (void *)dev; partition_t *part = (void *)dev;
u_long sect; u_long sect;
switch (cmd) { /* Sort of arbitrary: round size down to 4KiB boundary */
case HDIO_GETGEO:
/* Sort of arbitrary: round size down to 4K boundary */
sect = le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE; 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, static int ftl_readsect(struct mtd_blktrans_dev *dev,
unsigned long block, char *buf) unsigned long block, char *buf)
...@@ -1102,7 +1085,7 @@ struct mtd_blktrans_ops ftl_tr = { ...@@ -1102,7 +1085,7 @@ struct mtd_blktrans_ops ftl_tr = {
.part_bits = PART_BITS, .part_bits = PART_BITS,
.readsect = ftl_readsect, .readsect = ftl_readsect,
.writesect = ftl_writesect, .writesect = ftl_writesect,
.ioctl = ftl_ioctl, .getgeo = ftl_getgeo,
.add_mtd = ftl_add_mtd, .add_mtd = ftl_add_mtd,
.remove_dev = ftl_remove_dev, .remove_dev = ftl_remove_dev,
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -1110,7 +1093,7 @@ struct mtd_blktrans_ops ftl_tr = { ...@@ -1110,7 +1093,7 @@ struct mtd_blktrans_ops ftl_tr = {
int init_ftl(void) 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); return register_mtd_blktrans(&ftl_tr);
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* (c) 1999 Machine Vision Holdings, Inc. * (c) 1999 Machine Vision Holdings, Inc.
* Author: David Woodhouse <dwmw2@infradead.org> * 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 * 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 * 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) ...@@ -113,7 +113,7 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
(long)inftl->sectors ); (long)inftl->sectors );
} }
if (add_mtd_blktrans_dev) { if (add_mtd_blktrans_dev(&inftl->mbd)) {
if (inftl->PUtable) if (inftl->PUtable)
kfree(inftl->PUtable); kfree(inftl->PUtable);
if (inftl->VUtable) if (inftl->VUtable)
...@@ -835,35 +835,22 @@ static int inftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block, ...@@ -835,35 +835,22 @@ static int inftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
return 0; return 0;
} }
static int inftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo)
static int inftl_ioctl(struct mtd_blktrans_dev *dev,
struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{ {
struct NFTLrecord *nftl = (void *)dev; struct NFTLrecord *nftl = (void *)dev;
switch (cmd) { geo->heads = nftl->heads;
case HDIO_GETGEO: { geo->sectors = nftl->sectors;
struct hd_geometry g; 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 0;
return -ENOTTY;
}
} }
struct mtd_blktrans_ops inftl_tr = { struct mtd_blktrans_ops inftl_tr = {
.name = "inftl", .name = "inftl",
.major = INFTL_MAJOR, .major = INFTL_MAJOR,
.part_bits = INFTL_PARTN_BITS, .part_bits = INFTL_PARTN_BITS,
.ioctl = inftl_ioctl, .getgeo = inftl_getgeo,
.readsect = inftl_readblock, .readsect = inftl_readblock,
.writesect = inftl_writeblock, .writesect = inftl_writeblock,
.add_mtd = inftl_add_mtd, .add_mtd = inftl_add_mtd,
...@@ -875,7 +862,7 @@ extern char inftlmountrev[]; ...@@ -875,7 +862,7 @@ extern char inftlmountrev[];
int __init init_inftl(void) 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); "inftlmount.c %s\n", inftlmountrev);
return register_mtd_blktrans(&inftl_tr); 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> * (C) 2003 David Woodhouse <dwmw2@infradead.org>
* *
...@@ -18,8 +18,10 @@ ...@@ -18,8 +18,10 @@
#include <linux/blk.h> #include <linux/blk.h>
#include <linux/blkpg.h> #include <linux/blkpg.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/hdreg.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include <asm/uaccess.h>
#include <linux/devfs_fs_kernel.h> #include <linux/devfs_fs_kernel.h>
static LIST_HEAD(blktrans_majors); static LIST_HEAD(blktrans_majors);
...@@ -46,7 +48,7 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr, ...@@ -46,7 +48,7 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr,
nsect = req->current_nr_sectors; nsect = req->current_nr_sectors;
buf = req->buffer; buf = req->buffer;
if (!req->flags & REQ_CMD) if (!(req->flags & REQ_CMD))
return 0; return 0;
if (block + nsect > get_capacity(req->rq_disk)) if (block + nsect > get_capacity(req->rq_disk))
...@@ -93,14 +95,14 @@ static int mtd_blktrans_thread(void *arg) ...@@ -93,14 +95,14 @@ static int mtd_blktrans_thread(void *arg)
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
spin_lock_irq(rq->queue_lock);
while (!tr->blkcore_priv->exiting) { while (!tr->blkcore_priv->exiting) {
struct request *req; struct request *req;
struct mtd_blktrans_dev *dev; struct mtd_blktrans_dev *dev;
int res = 0; int res = 0;
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
spin_lock_irq(rq->queue_lock);
req = elv_next_request(rq); req = elv_next_request(rq);
if (!req) { if (!req) {
...@@ -112,6 +114,8 @@ static int mtd_blktrans_thread(void *arg) ...@@ -112,6 +114,8 @@ static int mtd_blktrans_thread(void *arg)
schedule(); schedule();
remove_wait_queue(&tr->blkcore_priv->thread_wq, &wait); remove_wait_queue(&tr->blkcore_priv->thread_wq, &wait);
spin_lock_irq(rq->queue_lock);
continue; continue;
} }
...@@ -159,7 +163,7 @@ int blktrans_open(struct inode *i, struct file *f) ...@@ -159,7 +163,7 @@ int blktrans_open(struct inode *i, struct file *f)
dev->mtd->usecount++; dev->mtd->usecount++;
ret = 0; ret = 0;
if (tr->open && (ret = tr->open(dev, i, f))) { if (tr->open && (ret = tr->open(dev))) {
dev->mtd->usecount--; dev->mtd->usecount--;
module_put(dev->mtd->owner); module_put(dev->mtd->owner);
out_tr: out_tr:
...@@ -179,7 +183,7 @@ int blktrans_release(struct inode *i, struct file *f) ...@@ -179,7 +183,7 @@ int blktrans_release(struct inode *i, struct file *f)
tr = dev->tr; tr = dev->tr;
if (tr->release) if (tr->release)
ret = tr->release(dev, i, f); ret = tr->release(dev);
if (!ret) { if (!ret) {
dev->mtd->usecount--; dev->mtd->usecount--;
...@@ -194,21 +198,33 @@ int blktrans_release(struct inode *i, struct file *f) ...@@ -194,21 +198,33 @@ int blktrans_release(struct inode *i, struct file *f)
static int blktrans_ioctl(struct inode *inode, struct file *file, static int blktrans_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
struct mtd_blktrans_dev *dev; struct mtd_blktrans_dev *dev = inode->i_bdev->bd_disk->private_data;
struct mtd_blktrans_ops *tr; struct mtd_blktrans_ops *tr = dev->tr;
int ret = -ENOTTY;
dev = inode->i_bdev->bd_disk->private_data; switch (cmd) {
tr = dev->tr; 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) case HDIO_GETGEO:
ret = tr->ioctl(dev, inode, file, cmd, arg); if (tr->getgeo) {
struct hd_geometry g;
if (ret == -ENOTTY && (cmd == BLKROSET || cmd == BLKFLSBUF)) { memset(&g, 0, sizeof(g));
/* The core code did the work, we had nothing to do. */ int ret = tr->getgeo(dev, &g);
ret = 0; if (ret)
}
return 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 = { struct block_device_operations mtd_blktrans_ops = {
......
/* /*
* Direct MTD block device access * 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) 2000-2003 Nicolas Pitre <nico@cam.org>
* (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> * (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>
...@@ -248,11 +248,19 @@ static int mtdblock_writesect(struct mtd_blktrans_dev *dev, ...@@ -248,11 +248,19 @@ static int mtdblock_writesect(struct mtd_blktrans_dev *dev,
unsigned long block, char *buf) unsigned long block, char *buf)
{ {
struct mtdblk_dev *mtdblk = mtdblks[dev->devnum]; 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); return do_cached_write(mtdblk, block<<9, 512, buf);
} }
static int mtdblock_open(struct mtd_blktrans_dev *mbd, static int mtdblock_open(struct mtd_blktrans_dev *mbd)
struct inode *inode, struct file *file)
{ {
struct mtdblk_dev *mtdblk; struct mtdblk_dev *mtdblk;
struct mtd_info *mtd = mbd->mtd; struct mtd_info *mtd = mbd->mtd;
...@@ -279,11 +287,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd, ...@@ -279,11 +287,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd,
if ((mtdblk->mtd->flags & MTD_CAP_RAM) != MTD_CAP_RAM && if ((mtdblk->mtd->flags & MTD_CAP_RAM) != MTD_CAP_RAM &&
mtdblk->mtd->erasesize) { mtdblk->mtd->erasesize) {
mtdblk->cache_size = mtdblk->mtd->erasesize; mtdblk->cache_size = mtdblk->mtd->erasesize;
mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize); mtdblk->cache_data = NULL;
if (!mtdblk->cache_data) {
kfree(mtdblk);
return -ENOMEM;
}
} }
mtdblks[dev] = mtdblk; mtdblks[dev] = mtdblk;
...@@ -293,17 +297,13 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd, ...@@ -293,17 +297,13 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd,
return 0; return 0;
} }
static int mtdblock_release(struct mtd_blktrans_dev *mbd, static int mtdblock_release(struct mtd_blktrans_dev *mbd)
struct inode *inode, struct file *file)
{ {
int dev; int dev = mbd->devnum;
struct mtdblk_dev *mtdblk; struct mtdblk_dev *mtdblk = mtdblks[dev];
DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n"); DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n");
dev = minor(inode->i_rdev);
mtdblk = mtdblks[dev];
down(&mtdblk->cache_sem); down(&mtdblk->cache_sem);
write_cached_data(mtdblk); write_cached_data(mtdblk);
up(&mtdblk->cache_sem); up(&mtdblk->cache_sem);
...@@ -321,27 +321,17 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd, ...@@ -321,27 +321,17 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd,
return 0; return 0;
} }
static int mtdblock_flush(struct mtd_blktrans_dev *dev)
static int mtdblock_ioctl(struct mtd_blktrans_dev *dev,
struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg)
{ {
struct mtdblk_dev *mtdblk; struct mtdblk_dev *mtdblk = mtdblks[dev->devnum];
mtdblk = mtdblks[minor(inode->i_rdev)];
switch (cmd) {
case BLKFLSBUF:
down(&mtdblk->cache_sem); down(&mtdblk->cache_sem);
write_cached_data(mtdblk); write_cached_data(mtdblk);
up(&mtdblk->cache_sem); up(&mtdblk->cache_sem);
if (mtdblk->mtd->sync) if (mtdblk->mtd->sync)
mtdblk->mtd->sync(mtdblk->mtd); mtdblk->mtd->sync(mtdblk->mtd);
return 0; return 0;
default:
return -ENOTTY;
}
} }
static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
...@@ -376,7 +366,7 @@ struct mtd_blktrans_ops mtdblock_tr = { ...@@ -376,7 +366,7 @@ struct mtd_blktrans_ops mtdblock_tr = {
.major = 31, .major = 31,
.part_bits = 0, .part_bits = 0,
.open = mtdblock_open, .open = mtdblock_open,
.ioctl = mtdblock_ioctl, .flush = mtdblock_flush,
.release = mtdblock_release, .release = mtdblock_release,
.readsect = mtdblock_readsect, .readsect = mtdblock_readsect,
.writesect = mtdblock_writesect, .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> * (C) 2003 David Woodhouse <dwmw2@infradead.org>
* *
* Simple read-only (writable only for RAM) mtdblock driver * Simple read-only (writable only for RAM) mtdblock driver
*/ */
#include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
#include <linux/mtd/blktrans.h> #include <linux/mtd/blktrans.h>
......
/* Linux driver for NAND Flash Translation Layer */ /* Linux driver for NAND Flash Translation Layer */
/* (c) 1999 Machine Vision Holdings, Inc. */ /* (c) 1999 Machine Vision Holdings, Inc. */
/* Author: David Woodhouse <dwmw2@infradead.org> */ /* 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 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) ...@@ -101,7 +101,7 @@ static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
(long)nftl->sectors ); (long)nftl->sectors );
} }
if (add_mtd_blktrans_dev) { if (add_mtd_blktrans_dev(&nftl->mbd)) {
if (nftl->ReplUnitTable) if (nftl->ReplUnitTable)
kfree(nftl->ReplUnitTable); kfree(nftl->ReplUnitTable);
if (nftl->EUNtable) if (nftl->EUNtable)
...@@ -699,29 +699,17 @@ static int nftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block, ...@@ -699,29 +699,17 @@ static int nftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
return 0; return 0;
} }
static int nftl_ioctl(struct mtd_blktrans_dev *dev, static int nftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo)
struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg)
{ {
struct NFTLrecord *nftl = (void *)dev; struct NFTLrecord *nftl = (void *)dev;
switch (cmd) { geo->heads = nftl->heads;
case HDIO_GETGEO: { geo->sectors = nftl->sectors;
struct hd_geometry g; geo->cylinders = nftl->cylinders;
g.heads = nftl->heads; return 0;
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;
}
} }
/**************************************************************************** /****************************************************************************
* *
* Module stuff * Module stuff
...@@ -733,7 +721,7 @@ struct mtd_blktrans_ops nftl_tr = { ...@@ -733,7 +721,7 @@ struct mtd_blktrans_ops nftl_tr = {
.name = "nftl", .name = "nftl",
.major = NFTL_MAJOR, .major = NFTL_MAJOR,
.part_bits = NFTL_PARTN_BITS, .part_bits = NFTL_PARTN_BITS,
.ioctl = nftl_ioctl, .getgeo = nftl_getgeo,
.readsect = nftl_readblock, .readsect = nftl_readblock,
#ifdef CONFIG_NFTL_RW #ifdef CONFIG_NFTL_RW
.writesect = nftl_writeblock, .writesect = nftl_writeblock,
...@@ -747,7 +735,7 @@ extern char nftlmountrev[]; ...@@ -747,7 +735,7 @@ extern char nftlmountrev[];
int __init init_nftl(void) 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); 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> * (C) 2003 David Woodhouse <dwmw2@infradead.org>
* *
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <asm/semaphore.h> #include <asm/semaphore.h>
struct hd_geometry;
struct mtd_info; struct mtd_info;
struct mtd_blktrans_ops; struct mtd_blktrans_ops;
struct file; struct file;
...@@ -42,17 +43,13 @@ struct mtd_blktrans_ops { ...@@ -42,17 +43,13 @@ struct mtd_blktrans_ops {
int (*writesect)(struct mtd_blktrans_dev *dev, int (*writesect)(struct mtd_blktrans_dev *dev,
unsigned long block, char *buffer); unsigned long block, char *buffer);
/* HDIO_GETGEO and HDIO_GETGEO_BIG are the only non-private /* Block layer ioctls */
ioctls which are expected to be passed through */ int (*getgeo)(struct mtd_blktrans_dev *dev, struct hd_geometry *geo);
int (*ioctl)(struct mtd_blktrans_dev *dev, int (*flush)(struct mtd_blktrans_dev *dev);
struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg);
/* Called with mtd_table_mutex held; no race with add/remove */ /* Called with mtd_table_mutex held; no race with add/remove */
int (*open)(struct mtd_blktrans_dev *dev, int (*open)(struct mtd_blktrans_dev *dev);
struct inode *i, struct file *f); int (*release)(struct mtd_blktrans_dev *dev);
int (*release)(struct mtd_blktrans_dev *dev,
struct inode *i, struct file *f);
/* Called on {de,}registration and on subsequent addition/removal /* Called on {de,}registration and on subsequent addition/removal
of devices, with mtd_table_mutex held. */ 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