diff options
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 853d6d1cc822..755584684f6c 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -2043,7 +2043,8 @@ retry: | |||
2043 | } | 2043 | } |
2044 | wdata->pid = wdata->cfile->pid; | 2044 | wdata->pid = wdata->cfile->pid; |
2045 | server = tlink_tcon(wdata->cfile->tlink)->ses->server; | 2045 | server = tlink_tcon(wdata->cfile->tlink)->ses->server; |
2046 | rc = server->ops->async_writev(wdata); | 2046 | rc = server->ops->async_writev(wdata, |
2047 | cifs_writedata_release); | ||
2047 | } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN); | 2048 | } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN); |
2048 | 2049 | ||
2049 | for (i = 0; i < nr_pages; ++i) | 2050 | for (i = 0; i < nr_pages; ++i) |
@@ -2331,9 +2332,20 @@ size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len) | |||
2331 | } | 2332 | } |
2332 | 2333 | ||
2333 | static void | 2334 | static void |
2334 | cifs_uncached_writev_complete(struct work_struct *work) | 2335 | cifs_uncached_writedata_release(struct kref *refcount) |
2335 | { | 2336 | { |
2336 | int i; | 2337 | int i; |
2338 | struct cifs_writedata *wdata = container_of(refcount, | ||
2339 | struct cifs_writedata, refcount); | ||
2340 | |||
2341 | for (i = 0; i < wdata->nr_pages; i++) | ||
2342 | put_page(wdata->pages[i]); | ||
2343 | cifs_writedata_release(refcount); | ||
2344 | } | ||
2345 | |||
2346 | static void | ||
2347 | cifs_uncached_writev_complete(struct work_struct *work) | ||
2348 | { | ||
2337 | struct cifs_writedata *wdata = container_of(work, | 2349 | struct cifs_writedata *wdata = container_of(work, |
2338 | struct cifs_writedata, work); | 2350 | struct cifs_writedata, work); |
2339 | struct inode *inode = wdata->cfile->dentry->d_inode; | 2351 | struct inode *inode = wdata->cfile->dentry->d_inode; |
@@ -2347,12 +2359,7 @@ cifs_uncached_writev_complete(struct work_struct *work) | |||
2347 | 2359 | ||
2348 | complete(&wdata->done); | 2360 | complete(&wdata->done); |
2349 | 2361 | ||
2350 | if (wdata->result != -EAGAIN) { | 2362 | kref_put(&wdata->refcount, cifs_uncached_writedata_release); |
2351 | for (i = 0; i < wdata->nr_pages; i++) | ||
2352 | put_page(wdata->pages[i]); | ||
2353 | } | ||
2354 | |||
2355 | kref_put(&wdata->refcount, cifs_writedata_release); | ||
2356 | } | 2363 | } |
2357 | 2364 | ||
2358 | /* attempt to send write to server, retry on any -EAGAIN errors */ | 2365 | /* attempt to send write to server, retry on any -EAGAIN errors */ |
@@ -2370,7 +2377,8 @@ cifs_uncached_retry_writev(struct cifs_writedata *wdata) | |||
2370 | if (rc != 0) | 2377 | if (rc != 0) |
2371 | continue; | 2378 | continue; |
2372 | } | 2379 | } |
2373 | rc = server->ops->async_writev(wdata); | 2380 | rc = server->ops->async_writev(wdata, |
2381 | cifs_uncached_writedata_release); | ||
2374 | } while (rc == -EAGAIN); | 2382 | } while (rc == -EAGAIN); |
2375 | 2383 | ||
2376 | return rc; | 2384 | return rc; |
@@ -2454,7 +2462,8 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, | |||
2454 | wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE); | 2462 | wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE); |
2455 | rc = cifs_uncached_retry_writev(wdata); | 2463 | rc = cifs_uncached_retry_writev(wdata); |
2456 | if (rc) { | 2464 | if (rc) { |
2457 | kref_put(&wdata->refcount, cifs_writedata_release); | 2465 | kref_put(&wdata->refcount, |
2466 | cifs_uncached_writedata_release); | ||
2458 | break; | 2467 | break; |
2459 | } | 2468 | } |
2460 | 2469 | ||
@@ -2496,7 +2505,7 @@ restart_loop: | |||
2496 | } | 2505 | } |
2497 | } | 2506 | } |
2498 | list_del_init(&wdata->list); | 2507 | list_del_init(&wdata->list); |
2499 | kref_put(&wdata->refcount, cifs_writedata_release); | 2508 | kref_put(&wdata->refcount, cifs_uncached_writedata_release); |
2500 | } | 2509 | } |
2501 | 2510 | ||
2502 | if (total_written > 0) | 2511 | if (total_written > 0) |
@@ -2559,8 +2568,8 @@ cifs_writev(struct kiocb *iocb, const struct iovec *iov, | |||
2559 | if (rc > 0) { | 2568 | if (rc > 0) { |
2560 | ssize_t err; | 2569 | ssize_t err; |
2561 | 2570 | ||
2562 | err = generic_write_sync(file, pos, rc); | 2571 | err = generic_write_sync(file, iocb->ki_pos - rc, rc); |
2563 | if (err < 0 && rc > 0) | 2572 | if (err < 0) |
2564 | rc = err; | 2573 | rc = err; |
2565 | } | 2574 | } |
2566 | 2575 | ||