diff options
author | Carsten Otte <cotte@de.ibm.com> | 2005-06-24 01:05:23 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-24 03:06:41 -0400 |
commit | 420edbcc09008342c7b2665453f6b370739aadb0 (patch) | |
tree | 9eae7b2d378d4e280dcc5c1b6b159e18e5e5dbe0 | |
parent | 3d41088fa327782b14b5659dbcfff62ec704c23c (diff) |
[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: Carsten Otte <cotte@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/s390/block/dcssblk.c | 44 | ||||
-rw-r--r-- | include/linux/fs.h | 1 |
2 files changed, 41 insertions, 4 deletions
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 16ab8d363ac6..6bc27d52326f 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c | |||
@@ -35,14 +35,17 @@ | |||
35 | static int dcssblk_open(struct inode *inode, struct file *filp); | 35 | static int dcssblk_open(struct inode *inode, struct file *filp); |
36 | static int dcssblk_release(struct inode *inode, struct file *filp); | 36 | static int dcssblk_release(struct inode *inode, struct file *filp); |
37 | static int dcssblk_make_request(struct request_queue *q, struct bio *bio); | 37 | static int dcssblk_make_request(struct request_queue *q, struct bio *bio); |
38 | static int dcssblk_direct_access(struct block_device *bdev, sector_t secnum, | ||
39 | unsigned long *data); | ||
38 | 40 | ||
39 | static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0"; | 41 | static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0"; |
40 | 42 | ||
41 | static int dcssblk_major; | 43 | static int dcssblk_major; |
42 | static struct block_device_operations dcssblk_devops = { | 44 | static struct block_device_operations dcssblk_devops = { |
43 | .owner = THIS_MODULE, | 45 | .owner = THIS_MODULE, |
44 | .open = dcssblk_open, | 46 | .open = dcssblk_open, |
45 | .release = dcssblk_release, | 47 | .release = dcssblk_release, |
48 | .direct_access = dcssblk_direct_access, | ||
46 | }; | 49 | }; |
47 | 50 | ||
48 | static ssize_t dcssblk_add_store(struct device * dev, struct device_attribute *attr, const char * buf, | 51 | 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) | |||
641 | /* Request beyond end of DCSS segment. */ | 644 | /* Request beyond end of DCSS segment. */ |
642 | goto fail; | 645 | goto fail; |
643 | } | 646 | } |
647 | /* verify data transfer direction */ | ||
648 | if (dev_info->is_shared) { | ||
649 | switch (dev_info->segment_type) { | ||
650 | case SEG_TYPE_SR: | ||
651 | case SEG_TYPE_ER: | ||
652 | case SEG_TYPE_SC: | ||
653 | /* cannot write to these segments */ | ||
654 | if (bio_data_dir(bio) == WRITE) { | ||
655 | PRINT_WARN("rejecting write to ro segment %s\n", dev_info->dev.bus_id); | ||
656 | goto fail; | ||
657 | } | ||
658 | } | ||
659 | } | ||
660 | |||
644 | index = (bio->bi_sector >> 3); | 661 | index = (bio->bi_sector >> 3); |
645 | bio_for_each_segment(bvec, bio, i) { | 662 | bio_for_each_segment(bvec, bio, i) { |
646 | page_addr = (unsigned long) | 663 | page_addr = (unsigned long) |
@@ -661,7 +678,26 @@ dcssblk_make_request(request_queue_t *q, struct bio *bio) | |||
661 | bio_endio(bio, bytes_done, 0); | 678 | bio_endio(bio, bytes_done, 0); |
662 | return 0; | 679 | return 0; |
663 | fail: | 680 | fail: |
664 | bio_io_error(bio, bytes_done); | 681 | bio_io_error(bio, bio->bi_size); |
682 | return 0; | ||
683 | } | ||
684 | |||
685 | static int | ||
686 | dcssblk_direct_access (struct block_device *bdev, sector_t secnum, | ||
687 | unsigned long *data) | ||
688 | { | ||
689 | struct dcssblk_dev_info *dev_info; | ||
690 | unsigned long pgoff; | ||
691 | |||
692 | dev_info = bdev->bd_disk->private_data; | ||
693 | if (!dev_info) | ||
694 | return -ENODEV; | ||
695 | if (secnum % (PAGE_SIZE/512)) | ||
696 | return -EINVAL; | ||
697 | pgoff = secnum / (PAGE_SIZE / 512); | ||
698 | if ((pgoff+1)*PAGE_SIZE-1 > dev_info->end - dev_info->start) | ||
699 | return -ERANGE; | ||
700 | *data = (unsigned long) (dev_info->start+pgoff*PAGE_SIZE); | ||
665 | return 0; | 701 | return 0; |
666 | } | 702 | } |
667 | 703 | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index 83857d8070d3..929bf8d20c87 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -885,6 +885,7 @@ struct block_device_operations { | |||
885 | int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long); | 885 | int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long); |
886 | long (*unlocked_ioctl) (struct file *, unsigned, unsigned long); | 886 | long (*unlocked_ioctl) (struct file *, unsigned, unsigned long); |
887 | long (*compat_ioctl) (struct file *, unsigned, unsigned long); | 887 | long (*compat_ioctl) (struct file *, unsigned, unsigned long); |
888 | int (*direct_access) (struct block_device *, sector_t, unsigned long *); | ||
888 | int (*media_changed) (struct gendisk *); | 889 | int (*media_changed) (struct gendisk *); |
889 | int (*revalidate_disk) (struct gendisk *); | 890 | int (*revalidate_disk) (struct gendisk *); |
890 | struct module *owner; | 891 | struct module *owner; |