aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorAl Viro2014-02-11 20:34:08 -0600
committerAl Viro2014-04-01 22:19:36 -0500
commit3b93f911d55cf8b3540f82fac4eeddfee7b5de0c (patch)
tree4c6f86393f929e02dd2385830bbcad064ba1cc2c /mm
parent5cb6c6c7eb1ed24744b41fad47d9a25b72207098 (diff)
downloadlinux-phy-3b93f911d55cf8b3540f82fac4eeddfee7b5de0c.tar.gz
linux-phy-3b93f911d55cf8b3540f82fac4eeddfee7b5de0c.tar.xz
linux-phy-3b93f911d55cf8b3540f82fac4eeddfee7b5de0c.zip
export generic_perform_write(), start getting rid of generic_file_buffer_write()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'mm')
-rw-r--r--mm/filemap.c37
1 files changed, 21 insertions, 16 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index 93e9cf576452..09bfc9b3bb51 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2092,7 +2092,7 @@ found:
2092} 2092}
2093EXPORT_SYMBOL(grab_cache_page_write_begin); 2093EXPORT_SYMBOL(grab_cache_page_write_begin);
2094 2094
2095static ssize_t generic_perform_write(struct file *file, 2095ssize_t generic_perform_write(struct file *file,
2096 struct iov_iter *i, loff_t pos) 2096 struct iov_iter *i, loff_t pos)
2097{ 2097{
2098 struct address_space *mapping = file->f_mapping; 2098 struct address_space *mapping = file->f_mapping;
@@ -2180,6 +2180,7 @@ again:
2180 2180
2181 return written ? written : status; 2181 return written ? written : status;
2182} 2182}
2183EXPORT_SYMBOL(generic_perform_write);
2183 2184
2184ssize_t 2185ssize_t
2185generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov, 2186generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
@@ -2230,8 +2231,10 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
2230 size_t count; /* after file limit checks */ 2231 size_t count; /* after file limit checks */
2231 struct inode *inode = mapping->host; 2232 struct inode *inode = mapping->host;
2232 loff_t pos = iocb->ki_pos; 2233 loff_t pos = iocb->ki_pos;
2233 ssize_t written; 2234 ssize_t written = 0;
2234 ssize_t err; 2235 ssize_t err;
2236 ssize_t status;
2237 struct iov_iter from;
2235 2238
2236 ocount = 0; 2239 ocount = 0;
2237 err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ); 2240 err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ);
@@ -2242,8 +2245,6 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
2242 2245
2243 /* We can write back this queue in page reclaim */ 2246 /* We can write back this queue in page reclaim */
2244 current->backing_dev_info = mapping->backing_dev_info; 2247 current->backing_dev_info = mapping->backing_dev_info;
2245 written = 0;
2246
2247 err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); 2248 err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
2248 if (err) 2249 if (err)
2249 goto out; 2250 goto out;
@@ -2259,44 +2260,47 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
2259 if (err) 2260 if (err)
2260 goto out; 2261 goto out;
2261 2262
2263 iov_iter_init(&from, iov, nr_segs, count, 0);
2264
2262 /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */ 2265 /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
2263 if (unlikely(file->f_flags & O_DIRECT)) { 2266 if (unlikely(file->f_flags & O_DIRECT)) {
2264 loff_t endbyte; 2267 loff_t endbyte;
2265 ssize_t written_buffered;
2266 2268
2267 written = generic_file_direct_write(iocb, iov, &nr_segs, pos, 2269 written = generic_file_direct_write(iocb, iov, &from.nr_segs, pos,
2268 count, ocount); 2270 count, ocount);
2269 if (written < 0 || written == count) 2271 if (written < 0 || written == count)
2270 goto out; 2272 goto out;
2273 iov_iter_advance(&from, written);
2274
2271 /* 2275 /*
2272 * direct-io write to a hole: fall through to buffered I/O 2276 * direct-io write to a hole: fall through to buffered I/O
2273 * for completing the rest of the request. 2277 * for completing the rest of the request.
2274 */ 2278 */
2275 pos += written; 2279 pos += written;
2276 count -= written; 2280 count -= written;
2277 written_buffered = generic_file_buffered_write(iocb, iov, 2281
2278 nr_segs, pos, count, written); 2282 status = generic_perform_write(file, &from, pos);
2279 /* 2283 /*
2280 * If generic_file_buffered_write() retuned a synchronous error 2284 * If generic_perform_write() returned a synchronous error
2281 * then we want to return the number of bytes which were 2285 * then we want to return the number of bytes which were
2282 * direct-written, or the error code if that was zero. Note 2286 * direct-written, or the error code if that was zero. Note
2283 * that this differs from normal direct-io semantics, which 2287 * that this differs from normal direct-io semantics, which
2284 * will return -EFOO even if some bytes were written. 2288 * will return -EFOO even if some bytes were written.
2285 */ 2289 */
2286 if (written_buffered < 0) { 2290 if (unlikely(status < 0) && !written) {
2287 err = written_buffered; 2291 err = status;
2288 goto out; 2292 goto out;
2289 } 2293 }
2290 2294 iocb->ki_pos = pos + status;
2291 /* 2295 /*
2292 * We need to ensure that the page cache pages are written to 2296 * We need to ensure that the page cache pages are written to
2293 * disk and invalidated to preserve the expected O_DIRECT 2297 * disk and invalidated to preserve the expected O_DIRECT
2294 * semantics. 2298 * semantics.
2295 */ 2299 */
2296 endbyte = pos + written_buffered - written - 1; 2300 endbyte = pos + status - 1;
2297 err = filemap_write_and_wait_range(file->f_mapping, pos, endbyte); 2301 err = filemap_write_and_wait_range(file->f_mapping, pos, endbyte);
2298 if (err == 0) { 2302 if (err == 0) {
2299 written = written_buffered; 2303 written += status;
2300 invalidate_mapping_pages(mapping, 2304 invalidate_mapping_pages(mapping,
2301 pos >> PAGE_CACHE_SHIFT, 2305 pos >> PAGE_CACHE_SHIFT,
2302 endbyte >> PAGE_CACHE_SHIFT); 2306 endbyte >> PAGE_CACHE_SHIFT);
@@ -2307,8 +2311,9 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
2307 */ 2311 */
2308 } 2312 }
2309 } else { 2313 } else {
2310 written = generic_file_buffered_write(iocb, iov, nr_segs, 2314 written = generic_perform_write(file, &from, pos);
2311 pos, count, written); 2315 if (likely(written >= 0))
2316 iocb->ki_pos = pos + written;
2312 } 2317 }
2313out: 2318out:
2314 current->backing_dev_info = NULL; 2319 current->backing_dev_info = NULL;