patch-2.3.38 linux/fs/block_dev.c
Next file: linux/fs/buffer.c
Previous file: linux/fs/bfs/file.c
Back to the patch index
Back to the overall index
- Lines: 223
- Date:
Fri Jan 7 15:20:58 2000
- Orig file:
v2.3.37/linux/fs/block_dev.c
- Orig date:
Thu Jan 6 12:57:48 2000
diff -u --recursive --new-file v2.3.37/linux/fs/block_dev.c linux/fs/block_dev.c
@@ -4,6 +4,7 @@
* Copyright (C) 1991, 1992 Linus Torvalds
*/
+#include <linux/config.h>
#include <linux/mm.h>
#include <linux/locks.h>
#include <linux/fcntl.h>
@@ -389,6 +390,7 @@
return NULL;
atomic_set(&new_bdev->bd_count,1);
new_bdev->bd_dev = dev;
+ new_bdev->bd_op = NULL;
spin_lock(&bdev_lock);
bdev = bdfind(dev, head);
if (!bdev) {
@@ -415,7 +417,7 @@
static struct {
const char *name;
- struct file_operations *bdops;
+ struct block_device_operations *bdops;
} blkdevs[MAX_BLKDEV] = {
{ NULL, NULL },
};
@@ -438,9 +440,9 @@
Return the function table of a device.
Load the driver if needed.
*/
-struct file_operations * get_blkfops(unsigned int major)
+static const struct block_device_operations * get_blkfops(unsigned int major)
{
- const struct file_operations *ret = NULL;
+ const struct block_device_operations *ret = NULL;
/* major 0 is used for non-device mounts */
if (major && major < MAX_BLKDEV) {
@@ -456,7 +458,7 @@
return ret;
}
-int register_blkdev(unsigned int major, const char * name, struct file_operations *bdops)
+int register_blkdev(unsigned int major, const char * name, struct block_device_operations *bdops)
{
if (major == 0) {
for (major = MAX_BLKDEV-1; major > 0; major--) {
@@ -502,7 +504,7 @@
int check_disk_change(kdev_t dev)
{
int i;
- const struct file_operations * bdops;
+ const struct block_device_operations * bdops;
struct super_block * sb;
i = MAJOR(dev);
@@ -530,17 +532,16 @@
int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)
{
kdev_t rdev = to_kdev_t(bdev->bd_dev);
- struct file_operations *fops = get_blkfops(MAJOR(rdev));
struct inode inode_fake;
int res;
mm_segment_t old_fs = get_fs();
- if (!fops || !fops->ioctl)
+ if (!bdev->bd_op->ioctl)
return -EINVAL;
inode_fake.i_rdev=rdev;
init_waitqueue_head(&inode_fake.i_wait);
set_fs(KERNEL_DS);
- res = fops->ioctl(&inode_fake, NULL, cmd, arg);
+ res = bdev->bd_op->ioctl(&inode_fake, NULL, cmd, arg);
set_fs(old_fs);
return res;
}
@@ -549,9 +550,10 @@
{
int ret = -ENODEV;
kdev_t rdev = to_kdev_t(bdev->bd_dev); /* this should become bdev */
- struct file_operations *fops = get_blkfops(MAJOR(rdev));
down(&bdev->bd_sem);
- if (fops) {
+ if (!bdev->bd_op)
+ bdev->bd_op = get_blkfops(MAJOR(rdev));
+ if (bdev->bd_op) {
/*
* This crockload is due to bad choice of ->open() type.
* It will go away.
@@ -567,8 +569,8 @@
fake_dentry.d_inode = fake_inode;
fake_inode->i_rdev = rdev;
ret = 0;
- if (fops->open)
- ret = fops->open(fake_inode, &fake_file);
+ if (bdev->bd_op->open)
+ ret = bdev->bd_op->open(fake_inode, &fake_file);
if (!ret)
atomic_inc(&bdev->bd_openers);
iput(fake_inode);
@@ -578,74 +580,83 @@
return ret;
}
+int blkdev_open(struct inode * inode, struct file * filp)
+{
+ int ret = -ENODEV;
+ struct block_device *bdev = inode->i_bdev;
+ down(&bdev->bd_sem);
+ if (!bdev->bd_op)
+ bdev->bd_op = get_blkfops(MAJOR(inode->i_rdev));
+ if (bdev->bd_op) {
+ ret = 0;
+ if (bdev->bd_op->open)
+ ret = bdev->bd_op->open(inode,filp);
+ if (!ret)
+ atomic_inc(&bdev->bd_openers);
+ }
+ up(&bdev->bd_sem);
+ return ret;
+}
+
int blkdev_put(struct block_device *bdev, int kind)
{
int ret = 0;
kdev_t rdev = to_kdev_t(bdev->bd_dev); /* this should become bdev */
- struct file_operations *fops = get_blkfops(MAJOR(rdev));
down(&bdev->bd_sem);
/* syncing will go here */
if (atomic_dec_and_test(&bdev->bd_openers)) {
/* invalidating buffers will go here */
}
- if (fops->release) {
+ if (bdev->bd_op->release) {
struct inode * fake_inode = get_empty_inode();
ret = -ENOMEM;
if (fake_inode) {
fake_inode->i_rdev = rdev;
- ret = fops->release(fake_inode, NULL);
+ ret = bdev->bd_op->release(fake_inode, NULL);
iput(fake_inode);
}
}
+ if (!atomic_read(&bdev->bd_openers))
+ bdev->bd_op = NULL; /* we can't rely on driver being */
+ /* kind to stay around. */
up(&bdev->bd_sem);
return ret;
}
-char * bdevname(kdev_t dev)
+static int blkdev_close(struct inode * inode, struct file * filp)
{
- static char buffer[32];
- const char * name = blkdevs[MAJOR(dev)].name;
-
- if (!name)
- name = "unknown-block";
-
- sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev));
- return buffer;
+ return blkdev_put(inode->i_bdev, BDEV_FILE);
}
-/*
- * Called every time a block special file is opened
- */
-int blkdev_open(struct inode * inode, struct file * filp)
+static int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
+ unsigned long arg)
{
- int ret = -ENODEV;
- filp->f_op = get_blkfops(MAJOR(inode->i_rdev));
- if (filp->f_op != NULL){
- ret = 0;
- if (filp->f_op->open != NULL)
- ret = filp->f_op->open(inode,filp);
- }
- return ret;
-}
+ if (inode->i_bdev->bd_op->ioctl)
+ return inode->i_bdev->bd_op->ioctl(inode, file, cmd, arg);
+ return -EINVAL;
+}
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
struct file_operations def_blk_fops = {
- NULL, /* lseek */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* poll */
- NULL, /* ioctl */
- NULL, /* mmap */
- blkdev_open, /* open */
- NULL, /* flush */
- NULL, /* release */
+ open: blkdev_open,
+ release: blkdev_close,
+ read: block_read,
+ write: block_write,
+ fsync: block_fsync,
+ ioctl: blkdev_ioctl,
};
struct inode_operations blkdev_inode_operations = {
&def_blk_fops, /* default file operations */
};
+
+char * bdevname(kdev_t dev)
+{
+ static char buffer[32];
+ const char * name = blkdevs[MAJOR(dev)].name;
+
+ if (!name)
+ name = "unknown-block";
+
+ sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev));
+ return buffer;
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)