patch-2.4.0-test9 linux/fs/block_dev.c

Next file: linux/fs/buffer.c
Previous file: linux/fs/bfs/inode.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test8/linux/fs/block_dev.c linux/fs/block_dev.c
@@ -30,17 +30,17 @@
 	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)];
@@ -311,6 +311,39 @@
 }
 
 /*
+ * 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 @@
 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_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 @@
 struct file_operations def_blk_fops = {
 	open:		blkdev_open,
 	release:	blkdev_close,
+	llseek:		block_llseek,
 	read:		block_read,
 	write:		block_write,
 	fsync:		block_fsync,

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)