Revert "NFS: Fix error handling for O_DIRECT write scheduling"
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 12 Oct 2023 17:41:42 +0000 (19:41 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 15 Oct 2023 16:32:41 +0000 (18:32 +0200)
This reverts commit f16fd0b11f0f4d41846b5102b1656ea1fc9ac7a0 which is
commit 954998b60caa8f2a3bf3abe490de6f08d283687a 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 d71762f..3bb530d 100644 (file)
@@ -530,9 +530,10 @@ nfs_direct_write_scan_commit_list(struct inode *inode,
 static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
 {
        struct nfs_pageio_descriptor desc;
-       struct nfs_page *req;
+       struct nfs_page *req, *tmp;
        LIST_HEAD(reqs);
        struct nfs_commit_info cinfo;
+       LIST_HEAD(failed);
 
        nfs_init_cinfo_from_dreq(&cinfo, dreq);
        nfs_direct_write_scan_commit_list(dreq->inode, &reqs, &cinfo);
@@ -550,36 +551,27 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
                              &nfs_direct_write_completion_ops);
        desc.pg_dreq = dreq;
 
-       while (!list_empty(&reqs)) {
-               req = nfs_list_entry(reqs.next);
+       list_for_each_entry_safe(req, tmp, &reqs, wb_list) {
                /* Bump the transmission count */
                req->wb_nio++;
                if (!nfs_pageio_add_request(&desc, req)) {
+                       nfs_list_move_request(req, &failed);
                        spin_lock(&cinfo.inode->i_lock);
-                       if (dreq->error < 0) {
-                               desc.pg_error = dreq->error;
-                       } else if (desc.pg_error != -EAGAIN) {
-                               dreq->flags = 0;
-                               if (!desc.pg_error)
-                                       desc.pg_error = -EIO;
+                       dreq->flags = 0;
+                       if (desc.pg_error < 0)
                                dreq->error = desc.pg_error;
-                       else
-                               dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
+                       else
+                               dreq->error = -EIO;
                        spin_unlock(&cinfo.inode->i_lock);
-                       break;
                }
                nfs_release_request(req);
        }
        nfs_pageio_complete(&desc);
 
-       while (!list_empty(&reqs)) {
-               req = nfs_list_entry(reqs.next);
+       while (!list_empty(&failed)) {
+               req = nfs_list_entry(failed.next);
                nfs_list_remove_request(req);
                nfs_unlock_and_release_request(req);
-               if (desc.pg_error == -EAGAIN)
-                       nfs_mark_request_commit(req, NULL, &cinfo, 0);
-               else
-                       nfs_release_request(req);
        }
 
        if (put_dreq(dreq))
@@ -804,11 +796,9 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
 {
        struct nfs_pageio_descriptor desc;
        struct inode *inode = dreq->inode;
-       struct nfs_commit_info cinfo;
        ssize_t result = 0;
        size_t requested_bytes = 0;
        size_t wsize = max_t(size_t, NFS_SERVER(inode)->wsize, PAGE_SIZE);
-       bool defer = false;
 
        trace_nfs_direct_write_schedule_iovec(dreq);
 
@@ -849,39 +839,19 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
                                break;
                        }
 
-                       pgbase = 0;
-                       bytes -= req_len;
-                       requested_bytes += req_len;
-                       pos += req_len;
-                       dreq->bytes_left -= req_len;
-
-                       if (defer) {
-                               nfs_mark_request_commit(req, NULL, &cinfo, 0);
-                               continue;
-                       }
-
                        nfs_lock_request(req);
                        req->wb_index = pos >> PAGE_SHIFT;
                        req->wb_offset = pos & ~PAGE_MASK;
-                       if (nfs_pageio_add_request(&desc, req))
-                               continue;
-
-                       /* Exit on hard errors */
-                       if (desc.pg_error < 0 && desc.pg_error != -EAGAIN) {
+                       if (!nfs_pageio_add_request(&desc, req)) {
                                result = desc.pg_error;
                                nfs_unlock_and_release_request(req);
                                break;
                        }
-
-                       /* If the error is soft, defer remaining requests */
-                       nfs_init_cinfo_from_dreq(&cinfo, dreq);
-                       spin_lock(&cinfo.inode->i_lock);
-                       dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
-                       spin_unlock(&cinfo.inode->i_lock);
-                       nfs_unlock_request(req);
-                       nfs_mark_request_commit(req, NULL, &cinfo, 0);
-                       desc.pg_error = 0;
-                       defer = true;
+                       pgbase = 0;
+                       bytes -= req_len;
+                       requested_bytes += req_len;
+                       pos += req_len;
+                       dreq->bytes_left -= req_len;
                }
                nfs_direct_release_pages(pagevec, npages);
                kvfree(pagevec);