]> err.no Git - linux-2.6/commitdiff
[PATCH] xip: bdev: execute in place
authorCarsten Otte <cotte@de.ibm.com>
Fri, 24 Jun 2005 05:05:23 +0000 (22:05 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Fri, 24 Jun 2005 07:06:41 +0000 (00:06 -0700)
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@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
drivers/s390/block/dcssblk.c
include/linux/fs.h

index 16ab8d363ac6ccdab63714ea6920996b7dd8052b..6bc27d52326f11e72e002f364fa53964f318a056 100644 (file)
 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;
 }
 
index 83857d8070d31e637aeaca005c63125663dd9950..929bf8d20c8743e228a819b715355e1051f59bb1 100644 (file)
@@ -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;