[PATCH] Re: bug? in using generic read/write functions to read/write block devices in 2.4.11-pre2

From: Alexander Viro (viro@math.psu.edu)
Date: Wed Oct 03 2001 - 08:16:36 EST


On Wed, 3 Oct 2001, Vladimir V. Saveliev wrote:

> Hi
>
> It looks like something wrong happens with writing/reading to block
> device using generic read/write functions when one does:
>
> mke2fs /dev/hda1 (blocksize is 4096)
> mount /dev/hda1
> umount /dev/hda1
> mke2fs /dev/hda1 - FAILS with
> Warning: could not write 8 blocks in inode table starting at 492004:
> Attempt to write block from filesystem resulted in short write
>
> (note that /dev/hda1 should be big enough - 3gb is enogh for example)

Ehh... Linus, both blkdev_get() and blkdev_open() should set ->i_blkbits.
Vladimir, see if the patch below helps:

--- S11-pre2/fs/block_dev.c Mon Oct 1 17:56:00 2001
+++ /tmp/block_dev.c Wed Oct 3 09:12:31 2001
@@ -549,36 +549,23 @@
         return res;
 }
 
-int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, int kind)
+static int do_open(struct block_device *bdev, struct inode *inode, struct file *file)
 {
- int ret = -ENODEV;
- kdev_t rdev = to_kdev_t(bdev->bd_dev); /* this should become bdev */
- down(&bdev->bd_sem);
+ int ret = -ENXIO;
+ kdev_t dev = to_kdev_t(bdev->bd_dev);
 
+ down(&bdev->bd_sem);
         lock_kernel();
         if (!bdev->bd_op)
- bdev->bd_op = get_blkfops(MAJOR(rdev));
+ bdev->bd_op = get_blkfops(MAJOR(dev));
         if (bdev->bd_op) {
- /*
- * This crockload is due to bad choice of ->open() type.
- * It will go away.
- * For now, block device ->open() routine must _not_
- * examine anything in 'inode' argument except ->i_rdev.
- */
- struct file fake_file = {};
- struct dentry fake_dentry = {};
- ret = -ENOMEM;
- fake_file.f_mode = mode;
- fake_file.f_flags = flags;
- fake_file.f_dentry = &fake_dentry;
- fake_dentry.d_inode = bdev->bd_inode;
                 ret = 0;
                 if (bdev->bd_op->open)
- ret = bdev->bd_op->open(bdev->bd_inode, &fake_file);
+ ret = bdev->bd_op->open(inode, file);
                 if (!ret) {
                         bdev->bd_openers++;
- bdev->bd_inode->i_size = blkdev_size(rdev);
- bdev->bd_inode->i_blkbits = blksize_bits(block_size(rdev));
+ bdev->bd_inode->i_size = blkdev_size(dev);
+ bdev->bd_inode->i_blkbits = blksize_bits(block_size(dev));
                 } else if (!bdev->bd_openers)
                         bdev->bd_op = NULL;
         }
@@ -589,9 +576,26 @@
         return ret;
 }
 
+int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, int kind)
+{
+ /*
+ * This crockload is due to bad choice of ->open() type.
+ * It will go away.
+ * For now, block device ->open() routine must _not_
+ * examine anything in 'inode' argument except ->i_rdev.
+ */
+ struct file fake_file = {};
+ struct dentry fake_dentry = {};
+ fake_file.f_mode = mode;
+ fake_file.f_flags = flags;
+ fake_file.f_dentry = &fake_dentry;
+ fake_dentry.d_inode = bdev->bd_inode;
+
+ return do_open(bdev, bdev->bd_inode, &fake_file);
+}
+
 int blkdev_open(struct inode * inode, struct file * filp)
 {
- int ret;
         struct block_device *bdev;
 
         /*
@@ -604,29 +608,8 @@
 
         bd_acquire(inode);
         bdev = inode->i_bdev;
- down(&bdev->bd_sem);
-
- ret = -ENXIO;
- lock_kernel();
- 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) {
- bdev->bd_openers++;
- bdev->bd_inode->i_size = blkdev_size(inode->i_rdev);
- } else if (!bdev->bd_openers)
- bdev->bd_op = NULL;
- }
-
- unlock_kernel();
- up(&bdev->bd_sem);
- if (ret)
- bdput(bdev);
- return ret;
+ return do_open(bdev, inode, filp);
 }
 
 int blkdev_put(struct block_device *bdev, int kind)

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sun Oct 07 2001 - 21:00:27 EST