[RFC/PATCH 1/4] bdev: execute in place (3rd version)

From: Carsten Otte
Date: Mon May 23 2005 - 12:35:37 EST


[RFC/PATCH 1/4] bdev: execute in place (3rd version)

This is the block device related part. The block device operation
direct_access now has a struct block_device as first parameter.

Signed-off-by: Carsten Otte <cotte@xxxxxxxxxx>
---
diff -ruN linux-git/drivers/s390/block/dcssblk.c linux-git-xip/drivers/s390/block/dcssblk.c
--- linux-git/drivers/s390/block/dcssblk.c 2005-05-23 13:50:29.000000000 +0200
+++ linux-git-xip/drivers/s390/block/dcssblk.c 2005-05-23 17:14:15.391098768 +0200
@@ -35,14 +35,17 @@
static int dcssblk_open(struct inode *inode, struct file *filp);
static int dcssblk_release(struct inode *inode, struct file *filp);
static int dcssblk_make_request(struct request_queue *q, struct bio *bio);
+static int dcssblk_direct_access(struct block_device *bdev, sector_t secnum,
+ unsigned long *data);

static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0";

static int dcssblk_major;
static struct block_device_operations dcssblk_devops = {
- .owner = THIS_MODULE,
- .open = dcssblk_open,
- .release = dcssblk_release,
+ .owner = THIS_MODULE,
+ .open = dcssblk_open,
+ .release = dcssblk_release,
+ .direct_access = dcssblk_direct_access,
};

static ssize_t dcssblk_add_store(struct device * dev, const char * buf,
@@ -641,6 +644,20 @@
/* Request beyond end of DCSS segment. */
goto fail;
}
+ /* verify data transfer direction */
+ if (dev_info->is_shared) {
+ switch (dev_info->segment_type) {
+ case SEG_TYPE_SR:
+ case SEG_TYPE_ER:
+ case SEG_TYPE_SC:
+ /* cannot write to these segments */
+ if (bio_data_dir(bio) == WRITE) {
+ PRINT_WARN("rejecting write to ro segment %s\n", dev_info->dev.bus_id);
+ goto fail;
+ }
+ }
+ }
+
index = (bio->bi_sector >> 3);
bio_for_each_segment(bvec, bio, i) {
page_addr = (unsigned long)
@@ -661,7 +678,26 @@
bio_endio(bio, bytes_done, 0);
return 0;
fail:
- bio_io_error(bio, bytes_done);
+ bio_io_error(bio, bio->bi_size);
+ return 0;
+}
+
+static int
+dcssblk_direct_access (struct block_device *bdev, sector_t secnum,
+ unsigned long *data)
+{
+ struct dcssblk_dev_info *dev_info;
+ unsigned long pgoff;
+
+ dev_info = bdev->bd_disk->private_data;
+ if (!dev_info)
+ return -ENODEV;
+ if (secnum % (PAGE_SIZE/512))
+ return -EINVAL;
+ pgoff = secnum / (PAGE_SIZE / 512);
+ if ((pgoff+1)*PAGE_SIZE-1 > dev_info->end - dev_info->start)
+ return -ERANGE;
+ *data = (unsigned long) (dev_info->start+pgoff*PAGE_SIZE);
return 0;
}

diff -ruN linux-git/include/linux/fs.h linux-git-xip/include/linux/fs.h
--- linux-git/include/linux/fs.h 2005-05-23 13:51:10.000000000 +0200
+++ linux-git-xip/include/linux/fs.h 2005-05-23 17:14:15.393098464 +0200
@@ -884,6 +884,7 @@
int (*release) (struct inode *, struct file *);
int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
long (*compat_ioctl) (struct file *, unsigned, unsigned long);
+ int (*direct_access) (struct block_device *, sector_t, unsigned long *);
int (*media_changed) (struct gendisk *);
int (*revalidate_disk) (struct gendisk *);
struct module *owner;


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