diff options
author | Trond Myklebust <trond.myklebust@hammerspace.com> | 2019-08-12 18:04:36 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@hammerspace.com> | 2019-08-19 08:56:04 -0400 |
commit | eb2c50da9e256dbbb3ff27694440e4c1900cfef8 (patch) | |
tree | fb5c36bec2b2b8fdceeac4bc0e1fb74455b7e971 /fs/nfs/direct.c | |
parent | f4340e9314dbfadc48758945f85fc3b16612d06f (diff) |
NFS: Ensure O_DIRECT reports an error if the bytes read/written is 0
If the attempt to resend the I/O results in no bytes being read/written,
we must ensure that we report the error.
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Fixes: 0a00b77b331a ("nfs: mirroring support for direct io")
Cc: stable@vger.kernel.org # v3.20+
Diffstat (limited to 'fs/nfs/direct.c')
-rw-r--r-- | fs/nfs/direct.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 0cb442406168..222d7115db71 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -401,15 +401,21 @@ static void nfs_direct_read_completion(struct nfs_pgio_header *hdr) | |||
401 | unsigned long bytes = 0; | 401 | unsigned long bytes = 0; |
402 | struct nfs_direct_req *dreq = hdr->dreq; | 402 | struct nfs_direct_req *dreq = hdr->dreq; |
403 | 403 | ||
404 | if (test_bit(NFS_IOHDR_REDO, &hdr->flags)) | ||
405 | goto out_put; | ||
406 | |||
407 | spin_lock(&dreq->lock); | 404 | spin_lock(&dreq->lock); |
408 | if (test_bit(NFS_IOHDR_ERROR, &hdr->flags) && (hdr->good_bytes == 0)) | 405 | if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) |
409 | dreq->error = hdr->error; | 406 | dreq->error = hdr->error; |
410 | else | 407 | |
408 | if (test_bit(NFS_IOHDR_REDO, &hdr->flags)) { | ||
409 | spin_unlock(&dreq->lock); | ||
410 | goto out_put; | ||
411 | } | ||
412 | |||
413 | if (hdr->good_bytes != 0) | ||
411 | nfs_direct_good_bytes(dreq, hdr); | 414 | nfs_direct_good_bytes(dreq, hdr); |
412 | 415 | ||
416 | if (test_bit(NFS_IOHDR_EOF, &hdr->flags)) | ||
417 | dreq->error = 0; | ||
418 | |||
413 | spin_unlock(&dreq->lock); | 419 | spin_unlock(&dreq->lock); |
414 | 420 | ||
415 | while (!list_empty(&hdr->pages)) { | 421 | while (!list_empty(&hdr->pages)) { |
@@ -782,16 +788,19 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr) | |||
782 | bool request_commit = false; | 788 | bool request_commit = false; |
783 | struct nfs_page *req = nfs_list_entry(hdr->pages.next); | 789 | struct nfs_page *req = nfs_list_entry(hdr->pages.next); |
784 | 790 | ||
785 | if (test_bit(NFS_IOHDR_REDO, &hdr->flags)) | ||
786 | goto out_put; | ||
787 | |||
788 | nfs_init_cinfo_from_dreq(&cinfo, dreq); | 791 | nfs_init_cinfo_from_dreq(&cinfo, dreq); |
789 | 792 | ||
790 | spin_lock(&dreq->lock); | 793 | spin_lock(&dreq->lock); |
791 | 794 | ||
792 | if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) | 795 | if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) |
793 | dreq->error = hdr->error; | 796 | dreq->error = hdr->error; |
794 | if (dreq->error == 0) { | 797 | |
798 | if (test_bit(NFS_IOHDR_REDO, &hdr->flags)) { | ||
799 | spin_unlock(&dreq->lock); | ||
800 | goto out_put; | ||
801 | } | ||
802 | |||
803 | if (hdr->good_bytes != 0) { | ||
795 | nfs_direct_good_bytes(dreq, hdr); | 804 | nfs_direct_good_bytes(dreq, hdr); |
796 | if (nfs_write_need_commit(hdr)) { | 805 | if (nfs_write_need_commit(hdr)) { |
797 | if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES) | 806 | if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES) |