diff options
-rw-r--r-- | fs/block_dev.c | 55 | ||||
-rw-r--r-- | fs/buffer.c | 14 | ||||
-rw-r--r-- | include/linux/fs.h | 1 |
3 files changed, 14 insertions, 56 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index 47a949d8a07e..a1e09b4fe1ba 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -70,19 +70,6 @@ static void bdev_inode_switch_bdi(struct inode *inode, | |||
70 | spin_unlock(&dst->wb.list_lock); | 70 | spin_unlock(&dst->wb.list_lock); |
71 | } | 71 | } |
72 | 72 | ||
73 | sector_t blkdev_max_block(struct block_device *bdev) | ||
74 | { | ||
75 | sector_t retval = ~((sector_t)0); | ||
76 | loff_t sz = i_size_read(bdev->bd_inode); | ||
77 | |||
78 | if (sz) { | ||
79 | unsigned int size = block_size(bdev); | ||
80 | unsigned int sizebits = blksize_bits(size); | ||
81 | retval = (sz >> sizebits); | ||
82 | } | ||
83 | return retval; | ||
84 | } | ||
85 | |||
86 | /* Kill _all_ buffers and pagecache , dirty or not.. */ | 73 | /* Kill _all_ buffers and pagecache , dirty or not.. */ |
87 | void kill_bdev(struct block_device *bdev) | 74 | void kill_bdev(struct block_device *bdev) |
88 | { | 75 | { |
@@ -163,52 +150,12 @@ static int | |||
163 | blkdev_get_block(struct inode *inode, sector_t iblock, | 150 | blkdev_get_block(struct inode *inode, sector_t iblock, |
164 | struct buffer_head *bh, int create) | 151 | struct buffer_head *bh, int create) |
165 | { | 152 | { |
166 | if (iblock >= blkdev_max_block(I_BDEV(inode))) { | ||
167 | if (create) | ||
168 | return -EIO; | ||
169 | |||
170 | /* | ||
171 | * for reads, we're just trying to fill a partial page. | ||
172 | * return a hole, they will have to call get_block again | ||
173 | * before they can fill it, and they will get -EIO at that | ||
174 | * time | ||
175 | */ | ||
176 | return 0; | ||
177 | } | ||
178 | bh->b_bdev = I_BDEV(inode); | 153 | bh->b_bdev = I_BDEV(inode); |
179 | bh->b_blocknr = iblock; | 154 | bh->b_blocknr = iblock; |
180 | set_buffer_mapped(bh); | 155 | set_buffer_mapped(bh); |
181 | return 0; | 156 | return 0; |
182 | } | 157 | } |
183 | 158 | ||
184 | static int | ||
185 | blkdev_get_blocks(struct inode *inode, sector_t iblock, | ||
186 | struct buffer_head *bh, int create) | ||
187 | { | ||
188 | sector_t end_block = blkdev_max_block(I_BDEV(inode)); | ||
189 | unsigned long max_blocks = bh->b_size >> inode->i_blkbits; | ||
190 | |||
191 | if ((iblock + max_blocks) > end_block) { | ||
192 | max_blocks = end_block - iblock; | ||
193 | if ((long)max_blocks <= 0) { | ||
194 | if (create) | ||
195 | return -EIO; /* write fully beyond EOF */ | ||
196 | /* | ||
197 | * It is a read which is fully beyond EOF. We return | ||
198 | * a !buffer_mapped buffer | ||
199 | */ | ||
200 | max_blocks = 0; | ||
201 | } | ||
202 | } | ||
203 | |||
204 | bh->b_bdev = I_BDEV(inode); | ||
205 | bh->b_blocknr = iblock; | ||
206 | bh->b_size = max_blocks << inode->i_blkbits; | ||
207 | if (max_blocks) | ||
208 | set_buffer_mapped(bh); | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static ssize_t | 159 | static ssize_t |
213 | blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, | 160 | blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, |
214 | loff_t offset, unsigned long nr_segs) | 161 | loff_t offset, unsigned long nr_segs) |
@@ -217,7 +164,7 @@ blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, | |||
217 | struct inode *inode = file->f_mapping->host; | 164 | struct inode *inode = file->f_mapping->host; |
218 | 165 | ||
219 | return __blockdev_direct_IO(rw, iocb, inode, I_BDEV(inode), iov, offset, | 166 | return __blockdev_direct_IO(rw, iocb, inode, I_BDEV(inode), iov, offset, |
220 | nr_segs, blkdev_get_blocks, NULL, NULL, 0); | 167 | nr_segs, blkdev_get_block, NULL, NULL, 0); |
221 | } | 168 | } |
222 | 169 | ||
223 | int __sync_blockdev(struct block_device *bdev, int wait) | 170 | int __sync_blockdev(struct block_device *bdev, int wait) |
diff --git a/fs/buffer.c b/fs/buffer.c index 28a74ff5324b..3586fb05c8ce 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -911,6 +911,18 @@ link_dev_buffers(struct page *page, struct buffer_head *head) | |||
911 | attach_page_buffers(page, head); | 911 | attach_page_buffers(page, head); |
912 | } | 912 | } |
913 | 913 | ||
914 | static sector_t blkdev_max_block(struct block_device *bdev, unsigned int size) | ||
915 | { | ||
916 | sector_t retval = ~((sector_t)0); | ||
917 | loff_t sz = i_size_read(bdev->bd_inode); | ||
918 | |||
919 | if (sz) { | ||
920 | unsigned int sizebits = blksize_bits(size); | ||
921 | retval = (sz >> sizebits); | ||
922 | } | ||
923 | return retval; | ||
924 | } | ||
925 | |||
914 | /* | 926 | /* |
915 | * Initialise the state of a blockdev page's buffers. | 927 | * Initialise the state of a blockdev page's buffers. |
916 | */ | 928 | */ |
@@ -921,7 +933,7 @@ init_page_buffers(struct page *page, struct block_device *bdev, | |||
921 | struct buffer_head *head = page_buffers(page); | 933 | struct buffer_head *head = page_buffers(page); |
922 | struct buffer_head *bh = head; | 934 | struct buffer_head *bh = head; |
923 | int uptodate = PageUptodate(page); | 935 | int uptodate = PageUptodate(page); |
924 | sector_t end_block = blkdev_max_block(I_BDEV(bdev->bd_inode)); | 936 | sector_t end_block = blkdev_max_block(I_BDEV(bdev->bd_inode), size); |
925 | 937 | ||
926 | do { | 938 | do { |
927 | if (!buffer_mapped(bh)) { | 939 | if (!buffer_mapped(bh)) { |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 44f288e9726d..75fe9a134803 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2047,7 +2047,6 @@ extern void unregister_blkdev(unsigned int, const char *); | |||
2047 | extern struct block_device *bdget(dev_t); | 2047 | extern struct block_device *bdget(dev_t); |
2048 | extern struct block_device *bdgrab(struct block_device *bdev); | 2048 | extern struct block_device *bdgrab(struct block_device *bdev); |
2049 | extern void bd_set_size(struct block_device *, loff_t size); | 2049 | extern void bd_set_size(struct block_device *, loff_t size); |
2050 | extern sector_t blkdev_max_block(struct block_device *bdev); | ||
2051 | extern void bd_forget(struct inode *inode); | 2050 | extern void bd_forget(struct inode *inode); |
2052 | extern void bdput(struct block_device *); | 2051 | extern void bdput(struct block_device *); |
2053 | extern void invalidate_bdev(struct block_device *); | 2052 | extern void invalidate_bdev(struct block_device *); |