diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2014-02-11 21:34:08 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-04-01 23:19:36 -0400 |
commit | 3b93f911d55cf8b3540f82fac4eeddfee7b5de0c (patch) | |
tree | 4c6f86393f929e02dd2385830bbcad064ba1cc2c /mm | |
parent | 5cb6c6c7eb1ed24744b41fad47d9a25b72207098 (diff) |
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.c | 37 |
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 | } |
2093 | EXPORT_SYMBOL(grab_cache_page_write_begin); | 2093 | EXPORT_SYMBOL(grab_cache_page_write_begin); |
2094 | 2094 | ||
2095 | static ssize_t generic_perform_write(struct file *file, | 2095 | ssize_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 | } |
2183 | EXPORT_SYMBOL(generic_perform_write); | ||
2183 | 2184 | ||
2184 | ssize_t | 2185 | ssize_t |
2185 | generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov, | 2186 | generic_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 | } |
2313 | out: | 2318 | out: |
2314 | current->backing_dev_info = NULL; | 2319 | current->backing_dev_info = NULL; |