Commit 420edbcc authored by Carsten Otte's avatar Carsten Otte Committed by Linus Torvalds

[PATCH] xip: bdev: execute in place

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: default avatarCarsten Otte <cotte@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 3d41088f
......@@ -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, struct device_attribute *attr, const char * buf,
......@@ -641,6 +644,20 @@ dcssblk_make_request(request_queue_t *q, struct bio *bio)
/* 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 @@ dcssblk_make_request(request_queue_t *q, struct bio *bio)
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;
}
......
......@@ -885,6 +885,7 @@ struct block_device_operations {
int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
long (*unlocked_ioctl) (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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment