diff options
author | Jeff Layton <jlayton@redhat.com> | 2011-01-11 07:24:01 -0500 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2011-01-19 12:52:29 -0500 |
commit | 941b853d779de3298e39f1eb4e252984464eaea8 (patch) | |
tree | a1e41bb06debf22349f010a1c9427c9b89bb79b4 /fs/cifs/file.c | |
parent | 12fed00de963433128b5366a21a55808fab2f756 (diff) |
cifs: don't fail writepages on -EAGAIN errors
If CIFSSMBWrite2 returns -EAGAIN, then the error should be considered
temporary. CIFS should retry the write instead of setting an error on
the mapping and returning.
For WB_SYNC_ALL, just retry the write immediately. In the WB_SYNC_NONE
case, call redirty_page_for_writeback on all of the pages that didn't
get written out and then move on.
Also, fix up the handling of a short write with a successful return
code. MS-CIFS says that 0 bytes_written means ENOSPC or EFBIG. It
doesn't mention what a short, but non-zero write means, so for now
treat it as we would an -EAGAIN return.
Reviewed-by: Suresh Jayaraman <sjayaraman@suse.de>
Reviewed-by: Pavel Shilovsky <piastryyy@gmail.com>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 49 |
1 files changed, 37 insertions, 12 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index af371910f543..cfa2e5ebcafe 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -1377,6 +1377,7 @@ retry: | |||
1377 | break; | 1377 | break; |
1378 | } | 1378 | } |
1379 | if (n_iov) { | 1379 | if (n_iov) { |
1380 | retry_write: | ||
1380 | open_file = find_writable_file(CIFS_I(mapping->host), | 1381 | open_file = find_writable_file(CIFS_I(mapping->host), |
1381 | false); | 1382 | false); |
1382 | if (!open_file) { | 1383 | if (!open_file) { |
@@ -1389,31 +1390,55 @@ retry: | |||
1389 | &bytes_written, iov, n_iov, | 1390 | &bytes_written, iov, n_iov, |
1390 | long_op); | 1391 | long_op); |
1391 | cifsFileInfo_put(open_file); | 1392 | cifsFileInfo_put(open_file); |
1392 | cifs_update_eof(cifsi, offset, bytes_written); | ||
1393 | } | 1393 | } |
1394 | 1394 | ||
1395 | if (rc || bytes_written < bytes_to_write) { | 1395 | cFYI(1, "Write2 rc=%d, wrote=%u", rc, bytes_written); |
1396 | cERROR(1, "Write2 ret %d, wrote %d", | 1396 | |
1397 | rc, bytes_written); | 1397 | /* |
1398 | mapping_set_error(mapping, rc); | 1398 | * For now, treat a short write as if nothing got |
1399 | } else { | 1399 | * written. A zero length write however indicates |
1400 | * ENOSPC or EFBIG. We have no way to know which | ||
1401 | * though, so call it ENOSPC for now. EFBIG would | ||
1402 | * get translated to AS_EIO anyway. | ||
1403 | * | ||
1404 | * FIXME: make it take into account the data that did | ||
1405 | * get written | ||
1406 | */ | ||
1407 | if (rc == 0) { | ||
1408 | if (bytes_written == 0) | ||
1409 | rc = -ENOSPC; | ||
1410 | else if (bytes_written < bytes_to_write) | ||
1411 | rc = -EAGAIN; | ||
1412 | } | ||
1413 | |||
1414 | /* retry on data-integrity flush */ | ||
1415 | if (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN) | ||
1416 | goto retry_write; | ||
1417 | |||
1418 | /* fix the stats and EOF */ | ||
1419 | if (bytes_written > 0) { | ||
1400 | cifs_stats_bytes_written(tcon, bytes_written); | 1420 | cifs_stats_bytes_written(tcon, bytes_written); |
1421 | cifs_update_eof(cifsi, offset, bytes_written); | ||
1401 | } | 1422 | } |
1402 | 1423 | ||
1403 | for (i = 0; i < n_iov; i++) { | 1424 | for (i = 0; i < n_iov; i++) { |
1404 | page = pvec.pages[first + i]; | 1425 | page = pvec.pages[first + i]; |
1405 | /* Should we also set page error on | 1426 | /* on retryable write error, redirty page */ |
1406 | success rc but too little data written? */ | 1427 | if (rc == -EAGAIN) |
1407 | /* BB investigate retry logic on temporary | 1428 | redirty_page_for_writepage(wbc, page); |
1408 | server crash cases and how recovery works | 1429 | else if (rc != 0) |
1409 | when page marked as error */ | ||
1410 | if (rc) | ||
1411 | SetPageError(page); | 1430 | SetPageError(page); |
1412 | kunmap(page); | 1431 | kunmap(page); |
1413 | unlock_page(page); | 1432 | unlock_page(page); |
1414 | end_page_writeback(page); | 1433 | end_page_writeback(page); |
1415 | page_cache_release(page); | 1434 | page_cache_release(page); |
1416 | } | 1435 | } |
1436 | |||
1437 | if (rc != -EAGAIN) | ||
1438 | mapping_set_error(mapping, rc); | ||
1439 | else | ||
1440 | rc = 0; | ||
1441 | |||
1417 | if ((wbc->nr_to_write -= n_iov) <= 0) | 1442 | if ((wbc->nr_to_write -= n_iov) <= 0) |
1418 | done = 1; | 1443 | done = 1; |
1419 | index = next; | 1444 | index = next; |