aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/block_dev.c55
-rw-r--r--fs/buffer.c14
-rw-r--r--include/linux/fs.h1
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
73sector_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.. */
87void kill_bdev(struct block_device *bdev) 74void kill_bdev(struct block_device *bdev)
88{ 75{
@@ -163,52 +150,12 @@ static int
163blkdev_get_block(struct inode *inode, sector_t iblock, 150blkdev_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
184static int
185blkdev_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
212static ssize_t 159static ssize_t
213blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, 160blkdev_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
223int __sync_blockdev(struct block_device *bdev, int wait) 170int __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
914static 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 *);
2047extern struct block_device *bdget(dev_t); 2047extern struct block_device *bdget(dev_t);
2048extern struct block_device *bdgrab(struct block_device *bdev); 2048extern struct block_device *bdgrab(struct block_device *bdev);
2049extern void bd_set_size(struct block_device *, loff_t size); 2049extern void bd_set_size(struct block_device *, loff_t size);
2050extern sector_t blkdev_max_block(struct block_device *bdev);
2051extern void bd_forget(struct inode *inode); 2050extern void bd_forget(struct inode *inode);
2052extern void bdput(struct block_device *); 2051extern void bdput(struct block_device *);
2053extern void invalidate_bdev(struct block_device *); 2052extern void invalidate_bdev(struct block_device *);