Revert "NFS: More O_DIRECT accounting fixes for error paths"
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 12 Oct 2023 17:41:40 +0000 (19:41 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 15 Oct 2023 16:32:41 +0000 (18:32 +0200)
This reverts commit 1f49386d67792424028acfe781d466b010f8fa3f which is
commit 8982f7aff39fb526aba4441fff2525fcedd5e1a3 upstream.

There are reported NFS problems in the 6.1.56 release, so revert a set
of NFS patches to hopefully resolve the issue.

Reported-by: poester <poester@internetbrands.com>
Link: https://lore.kernel.org/r/20231012165439.137237-2-kernel@linuxace.com
Reported-by: Daniel Díaz <daniel.diaz@linaro.org>
Link: https://lore.kernel.org/r/2023100755-livestock-barcode-fe41@gregkh
Cc: Trond Myklebust <trond.myklebust@hammerspace.com>
Cc: Anna Schumaker <Anna.Schumaker@Netapp.com>
Cc: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/nfs/direct.c

index d879c32..449d248 100644 (file)
@@ -93,10 +93,12 @@ nfs_direct_handle_truncated(struct nfs_direct_req *dreq,
                dreq->max_count = dreq_len;
                if (dreq->count > dreq_len)
                        dreq->count = dreq_len;
-       }
 
-       if (test_bit(NFS_IOHDR_ERROR, &hdr->flags) && !dreq->error)
-               dreq->error = hdr->error;
+               if (test_bit(NFS_IOHDR_ERROR, &hdr->flags))
+                       dreq->error = hdr->error;
+               else /* Clear outstanding error if this is EOF */
+                       dreq->error = 0;
+       }
 }
 
 static void
@@ -118,18 +120,6 @@ nfs_direct_count_bytes(struct nfs_direct_req *dreq,
                dreq->count = dreq_len;
 }
 
-static void nfs_direct_truncate_request(struct nfs_direct_req *dreq,
-                                       struct nfs_page *req)
-{
-       loff_t offs = req_offset(req);
-       size_t req_start = (size_t)(offs - dreq->io_start);
-
-       if (req_start < dreq->max_count)
-               dreq->max_count = req_start;
-       if (req_start < dreq->count)
-               dreq->count = req_start;
-}
-
 /**
  * nfs_swap_rw - NFS address space operation for swap I/O
  * @iocb: target I/O control block
@@ -549,6 +539,10 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
 
        nfs_direct_join_group(&reqs, dreq->inode);
 
+       dreq->count = 0;
+       dreq->max_count = 0;
+       list_for_each_entry(req, &reqs, wb_list)
+               dreq->max_count += req->wb_bytes;
        nfs_clear_pnfs_ds_commit_verifiers(&dreq->ds_cinfo);
        get_dreq(dreq);
 
@@ -582,14 +576,10 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
                req = nfs_list_entry(reqs.next);
                nfs_list_remove_request(req);
                nfs_unlock_and_release_request(req);
-               if (desc.pg_error == -EAGAIN) {
+               if (desc.pg_error == -EAGAIN)
                        nfs_mark_request_commit(req, NULL, &cinfo, 0);
-               } else {
-                       spin_lock(&dreq->lock);
-                       nfs_direct_truncate_request(dreq, req);
-                       spin_unlock(&dreq->lock);
+               else
                        nfs_release_request(req);
-               }
        }
 
        if (put_dreq(dreq))
@@ -609,6 +599,8 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
        if (status < 0) {
                /* Errors in commit are fatal */
                dreq->error = status;
+               dreq->max_count = 0;
+               dreq->count = 0;
                dreq->flags = NFS_ODIRECT_DONE;
        } else {
                status = dreq->error;
@@ -619,12 +611,7 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
        while (!list_empty(&data->pages)) {
                req = nfs_list_entry(data->pages.next);
                nfs_list_remove_request(req);
-               if (status < 0) {
-                       spin_lock(&dreq->lock);
-                       nfs_direct_truncate_request(dreq, req);
-                       spin_unlock(&dreq->lock);
-                       nfs_release_request(req);
-               } else if (!nfs_write_match_verf(verf, req)) {
+               if (status >= 0 && !nfs_write_match_verf(verf, req)) {
                        dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
                        /*
                         * Despite the reboot, the write was successful,
@@ -632,7 +619,7 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
                         */
                        req->wb_nio = 0;
                        nfs_mark_request_commit(req, NULL, &cinfo, 0);
-               } else
+               } else /* Error or match */
                        nfs_release_request(req);
                nfs_unlock_and_release_request(req);
        }
@@ -685,7 +672,6 @@ static void nfs_direct_write_clear_reqs(struct nfs_direct_req *dreq)
        while (!list_empty(&reqs)) {
                req = nfs_list_entry(reqs.next);
                nfs_list_remove_request(req);
-               nfs_direct_truncate_request(dreq, req);
                nfs_release_request(req);
                nfs_unlock_and_release_request(req);
        }
@@ -735,8 +721,7 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
        }
 
        nfs_direct_count_bytes(dreq, hdr);
-       if (test_bit(NFS_IOHDR_UNSTABLE_WRITES, &hdr->flags) &&
-           !test_bit(NFS_IOHDR_ERROR, &hdr->flags)) {
+       if (test_bit(NFS_IOHDR_UNSTABLE_WRITES, &hdr->flags)) {
                if (!dreq->flags)
                        dreq->flags = NFS_ODIRECT_DO_COMMIT;
                flags = dreq->flags;