diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-10-05 01:18:40 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-10-05 01:18:40 +0000 |
commit | 012bb3e61e5eced6c610f9e036372bf0c8def2d1 (patch) | |
tree | 87efc733f9b164e8c85c0336f92c8fb7eff6d183 /fs/block_dev.c | |
parent | 625a1589d3d6464b5d90b8a0918789e3afffd220 (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.c | 52 |
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, |