summaryrefslogtreecommitdiffstats
path: root/fs/block_dev.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-10-05 01:18:40 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-10-05 01:18:40 +0000
commit012bb3e61e5eced6c610f9e036372bf0c8def2d1 (patch)
tree87efc733f9b164e8c85c0336f92c8fb7eff6d183 /fs/block_dev.c
parent625a1589d3d6464b5d90b8a0918789e3afffd220 (diff)
Merge with Linux 2.4.0-test9. Please check DECstation, I had a number
of rejects to fixup while integrating Linus patches. I also found that this kernel will only boot SMP on Origin; the UP kernel freeze soon after bootup with SCSI timeout messages. I commit this anyway since I found that the last CVS versions had the same problem.
Diffstat (limited to 'fs/block_dev.c')
-rw-r--r--fs/block_dev.c52
1 files changed, 42 insertions, 10 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 21bc086e3..103332fc4 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -30,17 +30,17 @@ ssize_t block_write(struct file * filp, const char * buf,
ssize_t block, blocks;
loff_t offset;
ssize_t chars;
- ssize_t written = 0;
+ ssize_t written;
struct buffer_head * bhlist[NBUF];
size_t size;
- kdev_t dev;
+ kdev_t dev = inode->i_rdev;
struct buffer_head * bh, *bufferlist[NBUF];
register char * p;
- write_error = buffercount = 0;
- dev = inode->i_rdev;
- if ( is_read_only( inode->i_rdev ))
+ if (is_read_only(dev))
return -EPERM;
+
+ written = write_error = buffercount = 0;
blocksize = BLOCK_SIZE;
if (blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)])
blocksize = blksize_size[MAJOR(dev)][MINOR(dev)];
@@ -129,7 +129,7 @@ ssize_t block_write(struct file * filp, const char * buf,
p += chars;
buf += chars;
mark_buffer_uptodate(bh, 1);
- mark_buffer_dirty(bh, 0);
+ mark_buffer_dirty(bh);
if (filp->f_flags & O_SYNC)
bufferlist[buffercount++] = bh;
else
@@ -311,6 +311,39 @@ ssize_t block_read(struct file * filp, char * buf, size_t count, loff_t *ppos)
}
/*
+ * private llseek:
+ * for a block special file file->f_dentry->d_inode->i_size is zero
+ * so we compute the size by hand (just as in block_read/write above)
+ */
+static loff_t block_llseek(struct file *file, loff_t offset, int origin)
+{
+ long long retval;
+ kdev_t dev;
+
+ switch (origin) {
+ case 2:
+ dev = file->f_dentry->d_inode->i_rdev;
+ if (blk_size[MAJOR(dev)])
+ offset += (loff_t) blk_size[MAJOR(dev)][MINOR(dev)] << BLOCK_SIZE_BITS;
+ /* else? return -EINVAL? */
+ break;
+ case 1:
+ offset += file->f_pos;
+ }
+ retval = -EINVAL;
+ if (offset >= 0) {
+ if (offset != file->f_pos) {
+ file->f_pos = offset;
+ file->f_reada = 0;
+ file->f_version = ++event;
+ }
+ retval = offset;
+ }
+ return retval;
+}
+
+
+/*
* Filp may be NULL when we are called by an msync of a vma
* since the vma has no handle.
*/
@@ -435,9 +468,7 @@ void bdput(struct block_device *bdev)
static struct {
const char *name;
struct block_device_operations *bdops;
-} blkdevs[MAX_BLKDEV] = {
- { NULL, NULL },
-};
+} blkdevs[MAX_BLKDEV];
int get_blkdev_list(char * p)
{
@@ -612,7 +643,7 @@ int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, int kind)
int blkdev_open(struct inode * inode, struct file * filp)
{
- int ret = -ENODEV;
+ int ret = -ENXIO;
struct block_device *bdev = inode->i_bdev;
down(&bdev->bd_sem);
lock_kernel();
@@ -678,6 +709,7 @@ static int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
struct file_operations def_blk_fops = {
open: blkdev_open,
release: blkdev_close,
+ llseek: block_llseek,
read: block_read,
write: block_write,
fsync: block_fsync,