diff options
author | Christoph Hellwig <hch@lst.de> | 2010-06-04 05:29:53 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-08-09 16:47:29 -0400 |
commit | eafdc7d190a944c755a9fe68573c193e6e0217e7 (patch) | |
tree | 915c3cc8004706fabf88eae1ab123a3fa0147516 | |
parent | 256249584bda1a9357e2d29987a37f5b2df035f6 (diff) |
sort out blockdev_direct_IO variants
Move the call to vmtruncate to get rid of accessive blocks to the callers
in prepearation of the new truncate calling sequence. This was only done
for DIO_LOCKING filesystems, so the __blockdev_direct_IO_newtrunc variant
was not needed anyway. Get rid of blockdev_direct_IO_no_locking and
its _newtrunc variant while at it as just opencoding the two additional
paramters is shorted than the name suffix.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/block_dev.c | 5 | ||||
-rw-r--r-- | fs/direct-io.c | 74 | ||||
-rw-r--r-- | fs/ext2/inode.c | 2 | ||||
-rw-r--r-- | fs/ext3/inode.c | 11 | ||||
-rw-r--r-- | fs/ext4/inode.c | 15 | ||||
-rw-r--r-- | fs/fat/inode.c | 4 | ||||
-rw-r--r-- | fs/gfs2/aops.c | 6 | ||||
-rw-r--r-- | fs/hfs/inode.c | 17 | ||||
-rw-r--r-- | fs/hfsplus/inode.c | 17 | ||||
-rw-r--r-- | fs/jfs/inode.c | 17 | ||||
-rw-r--r-- | fs/nilfs2/inode.c | 13 | ||||
-rw-r--r-- | fs/ocfs2/aops.c | 9 | ||||
-rw-r--r-- | fs/reiserfs/inode.c | 17 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.c | 16 | ||||
-rw-r--r-- | include/linux/fs.h | 42 |
15 files changed, 146 insertions, 119 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index 99d6af811747..65a0c26508e5 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -172,9 +172,8 @@ blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, | |||
172 | struct file *file = iocb->ki_filp; | 172 | struct file *file = iocb->ki_filp; |
173 | struct inode *inode = file->f_mapping->host; | 173 | struct inode *inode = file->f_mapping->host; |
174 | 174 | ||
175 | return blockdev_direct_IO_no_locking_newtrunc(rw, iocb, inode, | 175 | return __blockdev_direct_IO(rw, iocb, inode, I_BDEV(inode), iov, offset, |
176 | I_BDEV(inode), iov, offset, nr_segs, | 176 | nr_segs, blkdev_get_blocks, NULL, NULL, 0); |
177 | blkdev_get_blocks, NULL); | ||
178 | } | 177 | } |
179 | 178 | ||
180 | int __sync_blockdev(struct block_device *bdev, int wait) | 179 | int __sync_blockdev(struct block_device *bdev, int wait) |
diff --git a/fs/direct-io.c b/fs/direct-io.c index a10cb91cadea..51f270b479b6 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c | |||
@@ -1136,8 +1136,27 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, | |||
1136 | return ret; | 1136 | return ret; |
1137 | } | 1137 | } |
1138 | 1138 | ||
1139 | /* | ||
1140 | * This is a library function for use by filesystem drivers. | ||
1141 | * | ||
1142 | * The locking rules are governed by the flags parameter: | ||
1143 | * - if the flags value contains DIO_LOCKING we use a fancy locking | ||
1144 | * scheme for dumb filesystems. | ||
1145 | * For writes this function is called under i_mutex and returns with | ||
1146 | * i_mutex held, for reads, i_mutex is not held on entry, but it is | ||
1147 | * taken and dropped again before returning. | ||
1148 | * For reads and writes i_alloc_sem is taken in shared mode and released | ||
1149 | * on I/O completion (which may happen asynchronously after returning to | ||
1150 | * the caller). | ||
1151 | * | ||
1152 | * - if the flags value does NOT contain DIO_LOCKING we don't use any | ||
1153 | * internal locking but rather rely on the filesystem to synchronize | ||
1154 | * direct I/O reads/writes versus each other and truncate. | ||
1155 | * For reads and writes both i_mutex and i_alloc_sem are not held on | ||
1156 | * entry and are never taken. | ||
1157 | */ | ||
1139 | ssize_t | 1158 | ssize_t |
1140 | __blockdev_direct_IO_newtrunc(int rw, struct kiocb *iocb, struct inode *inode, | 1159 | __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, |
1141 | struct block_device *bdev, const struct iovec *iov, loff_t offset, | 1160 | struct block_device *bdev, const struct iovec *iov, loff_t offset, |
1142 | unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io, | 1161 | unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io, |
1143 | dio_submit_t submit_io, int flags) | 1162 | dio_submit_t submit_io, int flags) |
@@ -1233,57 +1252,4 @@ __blockdev_direct_IO_newtrunc(int rw, struct kiocb *iocb, struct inode *inode, | |||
1233 | out: | 1252 | out: |
1234 | return retval; | 1253 | return retval; |
1235 | } | 1254 | } |
1236 | EXPORT_SYMBOL(__blockdev_direct_IO_newtrunc); | ||
1237 | |||
1238 | /* | ||
1239 | * This is a library function for use by filesystem drivers. | ||
1240 | * | ||
1241 | * The locking rules are governed by the flags parameter: | ||
1242 | * - if the flags value contains DIO_LOCKING we use a fancy locking | ||
1243 | * scheme for dumb filesystems. | ||
1244 | * For writes this function is called under i_mutex and returns with | ||
1245 | * i_mutex held, for reads, i_mutex is not held on entry, but it is | ||
1246 | * taken and dropped again before returning. | ||
1247 | * For reads and writes i_alloc_sem is taken in shared mode and released | ||
1248 | * on I/O completion (which may happen asynchronously after returning to | ||
1249 | * the caller). | ||
1250 | * | ||
1251 | * - if the flags value does NOT contain DIO_LOCKING we don't use any | ||
1252 | * internal locking but rather rely on the filesystem to synchronize | ||
1253 | * direct I/O reads/writes versus each other and truncate. | ||
1254 | * For reads and writes both i_mutex and i_alloc_sem are not held on | ||
1255 | * entry and are never taken. | ||
1256 | */ | ||
1257 | ssize_t | ||
1258 | __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, | ||
1259 | struct block_device *bdev, const struct iovec *iov, loff_t offset, | ||
1260 | unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io, | ||
1261 | dio_submit_t submit_io, int flags) | ||
1262 | { | ||
1263 | ssize_t retval; | ||
1264 | |||
1265 | retval = __blockdev_direct_IO_newtrunc(rw, iocb, inode, bdev, iov, | ||
1266 | offset, nr_segs, get_block, end_io, submit_io, flags); | ||
1267 | /* | ||
1268 | * In case of error extending write may have instantiated a few | ||
1269 | * blocks outside i_size. Trim these off again for DIO_LOCKING. | ||
1270 | * NOTE: DIO_NO_LOCK/DIO_OWN_LOCK callers have to handle this in | ||
1271 | * their own manner. This is a further example of where the old | ||
1272 | * truncate sequence is inadequate. | ||
1273 | * | ||
1274 | * NOTE: filesystems with their own locking have to handle this | ||
1275 | * on their own. | ||
1276 | */ | ||
1277 | if (flags & DIO_LOCKING) { | ||
1278 | if (unlikely((rw & WRITE) && retval < 0)) { | ||
1279 | loff_t isize = i_size_read(inode); | ||
1280 | loff_t end = offset + iov_length(iov, nr_segs); | ||
1281 | |||
1282 | if (end > isize) | ||
1283 | vmtruncate(inode, isize); | ||
1284 | } | ||
1285 | } | ||
1286 | |||
1287 | return retval; | ||
1288 | } | ||
1289 | EXPORT_SYMBOL(__blockdev_direct_IO); | 1255 | EXPORT_SYMBOL(__blockdev_direct_IO); |
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 3675088cb88c..f36e967e4fde 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c | |||
@@ -838,7 +838,7 @@ ext2_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, | |||
838 | struct inode *inode = mapping->host; | 838 | struct inode *inode = mapping->host; |
839 | ssize_t ret; | 839 | ssize_t ret; |
840 | 840 | ||
841 | ret = blockdev_direct_IO_newtrunc(rw, iocb, inode, inode->i_sb->s_bdev, | 841 | ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, |
842 | iov, offset, nr_segs, ext2_get_block, NULL); | 842 | iov, offset, nr_segs, ext2_get_block, NULL); |
843 | if (ret < 0 && (rw & WRITE)) | 843 | if (ret < 0 && (rw & WRITE)) |
844 | ext2_write_failed(mapping, offset + iov_length(iov, nr_segs)); | 844 | ext2_write_failed(mapping, offset + iov_length(iov, nr_segs)); |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 735f0190ec2a..a66f3fe33672 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -1785,6 +1785,17 @@ retry: | |||
1785 | ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, | 1785 | ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, |
1786 | offset, nr_segs, | 1786 | offset, nr_segs, |
1787 | ext3_get_block, NULL); | 1787 | ext3_get_block, NULL); |
1788 | /* | ||
1789 | * In case of error extending write may have instantiated a few | ||
1790 | * blocks outside i_size. Trim these off again. | ||
1791 | */ | ||
1792 | if (unlikely((rw & WRITE) && ret < 0)) { | ||
1793 | loff_t isize = i_size_read(inode); | ||
1794 | loff_t end = offset + iov_length(iov, nr_segs); | ||
1795 | |||
1796 | if (end > isize) | ||
1797 | vmtruncate(inode, isize); | ||
1798 | } | ||
1788 | if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries)) | 1799 | if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries)) |
1789 | goto retry; | 1800 | goto retry; |
1790 | 1801 | ||
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 0afc8c1d8cf3..d6a7701018a6 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -3545,15 +3545,24 @@ static ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb, | |||
3545 | 3545 | ||
3546 | retry: | 3546 | retry: |
3547 | if (rw == READ && ext4_should_dioread_nolock(inode)) | 3547 | if (rw == READ && ext4_should_dioread_nolock(inode)) |
3548 | ret = blockdev_direct_IO_no_locking(rw, iocb, inode, | 3548 | ret = __blockdev_direct_IO(rw, iocb, inode, |
3549 | inode->i_sb->s_bdev, iov, | 3549 | inode->i_sb->s_bdev, iov, |
3550 | offset, nr_segs, | 3550 | offset, nr_segs, |
3551 | ext4_get_block, NULL); | 3551 | ext4_get_block, NULL, NULL, 0); |
3552 | else | 3552 | else { |
3553 | ret = blockdev_direct_IO(rw, iocb, inode, | 3553 | ret = blockdev_direct_IO(rw, iocb, inode, |
3554 | inode->i_sb->s_bdev, iov, | 3554 | inode->i_sb->s_bdev, iov, |
3555 | offset, nr_segs, | 3555 | offset, nr_segs, |
3556 | ext4_get_block, NULL); | 3556 | ext4_get_block, NULL); |
3557 | |||
3558 | if (unlikely((rw & WRITE) && ret < 0)) { | ||
3559 | loff_t isize = i_size_read(inode); | ||
3560 | loff_t end = offset + iov_length(iov, nr_segs); | ||
3561 | |||
3562 | if (end > isize) | ||
3563 | vmtruncate(inode, isize); | ||
3564 | } | ||
3565 | } | ||
3557 | if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) | 3566 | if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) |
3558 | goto retry; | 3567 | goto retry; |
3559 | 3568 | ||
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 7bf45aee56d7..ffe7c6fdc1ec 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
@@ -212,8 +212,8 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb, | |||
212 | * FAT need to use the DIO_LOCKING for avoiding the race | 212 | * FAT need to use the DIO_LOCKING for avoiding the race |
213 | * condition of fat_get_block() and ->truncate(). | 213 | * condition of fat_get_block() and ->truncate(). |
214 | */ | 214 | */ |
215 | ret = blockdev_direct_IO_newtrunc(rw, iocb, inode, inode->i_sb->s_bdev, | 215 | ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, |
216 | iov, offset, nr_segs, fat_get_block, NULL); | 216 | iov, offset, nr_segs, fat_get_block, NULL); |
217 | if (ret < 0 && (rw & WRITE)) | 217 | if (ret < 0 && (rw & WRITE)) |
218 | fat_write_failed(mapping, offset + iov_length(iov, nr_segs)); | 218 | fat_write_failed(mapping, offset + iov_length(iov, nr_segs)); |
219 | 219 | ||
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 9f8b52500d63..703000d6e4d2 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c | |||
@@ -1047,9 +1047,9 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb, | |||
1047 | if (rv != 1) | 1047 | if (rv != 1) |
1048 | goto out; /* dio not valid, fall back to buffered i/o */ | 1048 | goto out; /* dio not valid, fall back to buffered i/o */ |
1049 | 1049 | ||
1050 | rv = blockdev_direct_IO_no_locking(rw, iocb, inode, inode->i_sb->s_bdev, | 1050 | rv = __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, |
1051 | iov, offset, nr_segs, | 1051 | offset, nr_segs, gfs2_get_block_direct, |
1052 | gfs2_get_block_direct, NULL); | 1052 | NULL, NULL, 0); |
1053 | out: | 1053 | out: |
1054 | gfs2_glock_dq_m(1, &gh); | 1054 | gfs2_glock_dq_m(1, &gh); |
1055 | gfs2_holder_uninit(&gh); | 1055 | gfs2_holder_uninit(&gh); |
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 14f5cb1b9fdc..07b2464b5716 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c | |||
@@ -112,9 +112,24 @@ static ssize_t hfs_direct_IO(int rw, struct kiocb *iocb, | |||
112 | { | 112 | { |
113 | struct file *file = iocb->ki_filp; | 113 | struct file *file = iocb->ki_filp; |
114 | struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host; | 114 | struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host; |
115 | ssize_t ret; | ||
115 | 116 | ||
116 | return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, | 117 | ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, |
117 | offset, nr_segs, hfs_get_block, NULL); | 118 | offset, nr_segs, hfs_get_block, NULL); |
119 | |||
120 | /* | ||
121 | * In case of error extending write may have instantiated a few | ||
122 | * blocks outside i_size. Trim these off again. | ||
123 | */ | ||
124 | if (unlikely((rw & WRITE) && ret < 0)) { | ||
125 | loff_t isize = i_size_read(inode); | ||
126 | loff_t end = offset + iov_length(iov, nr_segs); | ||
127 | |||
128 | if (end > isize) | ||
129 | vmtruncate(inode, isize); | ||
130 | } | ||
131 | |||
132 | return ret; | ||
118 | } | 133 | } |
119 | 134 | ||
120 | static int hfs_writepages(struct address_space *mapping, | 135 | static int hfs_writepages(struct address_space *mapping, |
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 9bbb82924a22..486021773911 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c | |||
@@ -105,9 +105,24 @@ static ssize_t hfsplus_direct_IO(int rw, struct kiocb *iocb, | |||
105 | { | 105 | { |
106 | struct file *file = iocb->ki_filp; | 106 | struct file *file = iocb->ki_filp; |
107 | struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host; | 107 | struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host; |
108 | ssize_t ret; | ||
108 | 109 | ||
109 | return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, | 110 | ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, |
110 | offset, nr_segs, hfsplus_get_block, NULL); | 111 | offset, nr_segs, hfsplus_get_block, NULL); |
112 | |||
113 | /* | ||
114 | * In case of error extending write may have instantiated a few | ||
115 | * blocks outside i_size. Trim these off again. | ||
116 | */ | ||
117 | if (unlikely((rw & WRITE) && ret < 0)) { | ||
118 | loff_t isize = i_size_read(inode); | ||
119 | loff_t end = offset + iov_length(iov, nr_segs); | ||
120 | |||
121 | if (end > isize) | ||
122 | vmtruncate(inode, isize); | ||
123 | } | ||
124 | |||
125 | return ret; | ||
111 | } | 126 | } |
112 | 127 | ||
113 | static int hfsplus_writepages(struct address_space *mapping, | 128 | static int hfsplus_writepages(struct address_space *mapping, |
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index ed9ba6fe04f5..79e6cda28181 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c | |||
@@ -317,9 +317,24 @@ static ssize_t jfs_direct_IO(int rw, struct kiocb *iocb, | |||
317 | { | 317 | { |
318 | struct file *file = iocb->ki_filp; | 318 | struct file *file = iocb->ki_filp; |
319 | struct inode *inode = file->f_mapping->host; | 319 | struct inode *inode = file->f_mapping->host; |
320 | ssize_t ret; | ||
320 | 321 | ||
321 | return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, | 322 | ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, |
322 | offset, nr_segs, jfs_get_block, NULL); | 323 | offset, nr_segs, jfs_get_block, NULL); |
324 | |||
325 | /* | ||
326 | * In case of error extending write may have instantiated a few | ||
327 | * blocks outside i_size. Trim these off again. | ||
328 | */ | ||
329 | if (unlikely((rw & WRITE) && ret < 0)) { | ||
330 | loff_t isize = i_size_read(inode); | ||
331 | loff_t end = offset + iov_length(iov, nr_segs); | ||
332 | |||
333 | if (end > isize) | ||
334 | vmtruncate(inode, isize); | ||
335 | } | ||
336 | |||
337 | return ret; | ||
323 | } | 338 | } |
324 | 339 | ||
325 | const struct address_space_operations jfs_aops = { | 340 | const struct address_space_operations jfs_aops = { |
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 39e038ac8fcb..1dd9e6a7d787 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c | |||
@@ -237,6 +237,19 @@ nilfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, | |||
237 | /* Needs synchronization with the cleaner */ | 237 | /* Needs synchronization with the cleaner */ |
238 | size = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, | 238 | size = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, |
239 | offset, nr_segs, nilfs_get_block, NULL); | 239 | offset, nr_segs, nilfs_get_block, NULL); |
240 | |||
241 | /* | ||
242 | * In case of error extending write may have instantiated a few | ||
243 | * blocks outside i_size. Trim these off again. | ||
244 | */ | ||
245 | if (unlikely((rw & WRITE) && size < 0)) { | ||
246 | loff_t isize = i_size_read(inode); | ||
247 | loff_t end = offset + iov_length(iov, nr_segs); | ||
248 | |||
249 | if (end > isize) | ||
250 | vmtruncate(inode, isize); | ||
251 | } | ||
252 | |||
240 | return size; | 253 | return size; |
241 | } | 254 | } |
242 | 255 | ||
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 96337a4fbbdf..0de69c9a08be 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -643,11 +643,10 @@ static ssize_t ocfs2_direct_IO(int rw, | |||
643 | if (i_size_read(inode) <= offset) | 643 | if (i_size_read(inode) <= offset) |
644 | return 0; | 644 | return 0; |
645 | 645 | ||
646 | ret = blockdev_direct_IO_no_locking(rw, iocb, inode, | 646 | ret = __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, |
647 | inode->i_sb->s_bdev, iov, offset, | 647 | iov, offset, nr_segs, |
648 | nr_segs, | 648 | ocfs2_direct_IO_get_blocks, |
649 | ocfs2_direct_IO_get_blocks, | 649 | ocfs2_dio_end_io, NULL, 0); |
650 | ocfs2_dio_end_io); | ||
651 | 650 | ||
652 | mlog_exit(ret); | 651 | mlog_exit(ret); |
653 | return ret; | 652 | return ret; |
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 6edac85c2b93..4c1fb548ab64 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
@@ -3057,10 +3057,25 @@ static ssize_t reiserfs_direct_IO(int rw, struct kiocb *iocb, | |||
3057 | { | 3057 | { |
3058 | struct file *file = iocb->ki_filp; | 3058 | struct file *file = iocb->ki_filp; |
3059 | struct inode *inode = file->f_mapping->host; | 3059 | struct inode *inode = file->f_mapping->host; |
3060 | ssize_t ret; | ||
3060 | 3061 | ||
3061 | return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, | 3062 | ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, |
3062 | offset, nr_segs, | 3063 | offset, nr_segs, |
3063 | reiserfs_get_blocks_direct_io, NULL); | 3064 | reiserfs_get_blocks_direct_io, NULL); |
3065 | |||
3066 | /* | ||
3067 | * In case of error extending write may have instantiated a few | ||
3068 | * blocks outside i_size. Trim these off again. | ||
3069 | */ | ||
3070 | if (unlikely((rw & WRITE) && ret < 0)) { | ||
3071 | loff_t isize = i_size_read(inode); | ||
3072 | loff_t end = offset + iov_length(iov, nr_segs); | ||
3073 | |||
3074 | if (end > isize) | ||
3075 | vmtruncate(inode, isize); | ||
3076 | } | ||
3077 | |||
3078 | return ret; | ||
3064 | } | 3079 | } |
3065 | 3080 | ||
3066 | int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) | 3081 | int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) |
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index d24e78f32f3e..7968d41e27ad 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
@@ -1478,17 +1478,17 @@ xfs_vm_direct_IO( | |||
1478 | if (rw & WRITE) { | 1478 | if (rw & WRITE) { |
1479 | iocb->private = xfs_alloc_ioend(inode, IO_NEW); | 1479 | iocb->private = xfs_alloc_ioend(inode, IO_NEW); |
1480 | 1480 | ||
1481 | ret = blockdev_direct_IO_no_locking(rw, iocb, inode, bdev, iov, | 1481 | ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iov, |
1482 | offset, nr_segs, | 1482 | offset, nr_segs, |
1483 | xfs_get_blocks_direct, | 1483 | xfs_get_blocks_direct, |
1484 | xfs_end_io_direct_write); | 1484 | xfs_end_io_direct_write, NULL, 0); |
1485 | if (ret != -EIOCBQUEUED && iocb->private) | 1485 | if (ret != -EIOCBQUEUED && iocb->private) |
1486 | xfs_destroy_ioend(iocb->private); | 1486 | xfs_destroy_ioend(iocb->private); |
1487 | } else { | 1487 | } else { |
1488 | ret = blockdev_direct_IO_no_locking(rw, iocb, inode, bdev, iov, | 1488 | ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iov, |
1489 | offset, nr_segs, | 1489 | offset, nr_segs, |
1490 | xfs_get_blocks_direct, | 1490 | xfs_get_blocks_direct, |
1491 | NULL); | 1491 | NULL, NULL, 0); |
1492 | } | 1492 | } |
1493 | 1493 | ||
1494 | return ret; | 1494 | return ret; |
diff --git a/include/linux/fs.h b/include/linux/fs.h index f91affb7d530..b347b2d5666f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2269,16 +2269,6 @@ static inline int xip_truncate_page(struct address_space *mapping, loff_t from) | |||
2269 | struct bio; | 2269 | struct bio; |
2270 | typedef void (dio_submit_t)(int rw, struct bio *bio, struct inode *inode, | 2270 | typedef void (dio_submit_t)(int rw, struct bio *bio, struct inode *inode, |
2271 | loff_t file_offset); | 2271 | loff_t file_offset); |
2272 | void dio_end_io(struct bio *bio, int error); | ||
2273 | |||
2274 | ssize_t __blockdev_direct_IO_newtrunc(int rw, struct kiocb *iocb, struct inode *inode, | ||
2275 | struct block_device *bdev, const struct iovec *iov, loff_t offset, | ||
2276 | unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io, | ||
2277 | dio_submit_t submit_io, int lock_type); | ||
2278 | ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, | ||
2279 | struct block_device *bdev, const struct iovec *iov, loff_t offset, | ||
2280 | unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io, | ||
2281 | dio_submit_t submit_io, int lock_type); | ||
2282 | 2272 | ||
2283 | enum { | 2273 | enum { |
2284 | /* need locking between buffered and direct access */ | 2274 | /* need locking between buffered and direct access */ |
@@ -2288,24 +2278,13 @@ enum { | |||
2288 | DIO_SKIP_HOLES = 0x02, | 2278 | DIO_SKIP_HOLES = 0x02, |
2289 | }; | 2279 | }; |
2290 | 2280 | ||
2291 | static inline ssize_t blockdev_direct_IO_newtrunc(int rw, struct kiocb *iocb, | 2281 | void dio_end_io(struct bio *bio, int error); |
2292 | struct inode *inode, struct block_device *bdev, const struct iovec *iov, | 2282 | |
2293 | loff_t offset, unsigned long nr_segs, get_block_t get_block, | 2283 | ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, |
2294 | dio_iodone_t end_io) | 2284 | struct block_device *bdev, const struct iovec *iov, loff_t offset, |
2295 | { | 2285 | unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io, |
2296 | return __blockdev_direct_IO_newtrunc(rw, iocb, inode, bdev, iov, offset, | 2286 | dio_submit_t submit_io, int flags); |
2297 | nr_segs, get_block, end_io, NULL, | ||
2298 | DIO_LOCKING | DIO_SKIP_HOLES); | ||
2299 | } | ||
2300 | 2287 | ||
2301 | static inline ssize_t blockdev_direct_IO_no_locking_newtrunc(int rw, struct kiocb *iocb, | ||
2302 | struct inode *inode, struct block_device *bdev, const struct iovec *iov, | ||
2303 | loff_t offset, unsigned long nr_segs, get_block_t get_block, | ||
2304 | dio_iodone_t end_io) | ||
2305 | { | ||
2306 | return __blockdev_direct_IO_newtrunc(rw, iocb, inode, bdev, iov, offset, | ||
2307 | nr_segs, get_block, end_io, NULL, 0); | ||
2308 | } | ||
2309 | static inline ssize_t blockdev_direct_IO(int rw, struct kiocb *iocb, | 2288 | static inline ssize_t blockdev_direct_IO(int rw, struct kiocb *iocb, |
2310 | struct inode *inode, struct block_device *bdev, const struct iovec *iov, | 2289 | struct inode *inode, struct block_device *bdev, const struct iovec *iov, |
2311 | loff_t offset, unsigned long nr_segs, get_block_t get_block, | 2290 | loff_t offset, unsigned long nr_segs, get_block_t get_block, |
@@ -2315,15 +2294,6 @@ static inline ssize_t blockdev_direct_IO(int rw, struct kiocb *iocb, | |||
2315 | nr_segs, get_block, end_io, NULL, | 2294 | nr_segs, get_block, end_io, NULL, |
2316 | DIO_LOCKING | DIO_SKIP_HOLES); | 2295 | DIO_LOCKING | DIO_SKIP_HOLES); |
2317 | } | 2296 | } |
2318 | |||
2319 | static inline ssize_t blockdev_direct_IO_no_locking(int rw, struct kiocb *iocb, | ||
2320 | struct inode *inode, struct block_device *bdev, const struct iovec *iov, | ||
2321 | loff_t offset, unsigned long nr_segs, get_block_t get_block, | ||
2322 | dio_iodone_t end_io) | ||
2323 | { | ||
2324 | return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset, | ||
2325 | nr_segs, get_block, end_io, NULL, 0); | ||
2326 | } | ||
2327 | #endif | 2297 | #endif |
2328 | 2298 | ||
2329 | extern const struct file_operations generic_ro_fops; | 2299 | extern const struct file_operations generic_ro_fops; |