Revert "NFS: Fix error handling for O_DIRECT write scheduling"

This reverts commit f16fd0b11f which is
commit 954998b60c 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>
This commit is contained in:
Greg Kroah-Hartman 2023-10-12 19:41:42 +02:00
parent b0cee281c4
commit ff74bdc838
1 changed files with 18 additions and 48 deletions

View 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) static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
{ {
struct nfs_pageio_descriptor desc; struct nfs_pageio_descriptor desc;
struct nfs_page *req; struct nfs_page *req, *tmp;
LIST_HEAD(reqs); LIST_HEAD(reqs);
struct nfs_commit_info cinfo; struct nfs_commit_info cinfo;
LIST_HEAD(failed);
nfs_init_cinfo_from_dreq(&cinfo, dreq); nfs_init_cinfo_from_dreq(&cinfo, dreq);
nfs_direct_write_scan_commit_list(dreq->inode, &reqs, &cinfo); 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); &nfs_direct_write_completion_ops);
desc.pg_dreq = dreq; desc.pg_dreq = dreq;
while (!list_empty(&reqs)) { list_for_each_entry_safe(req, tmp, &reqs, wb_list) {
req = nfs_list_entry(reqs.next);
/* Bump the transmission count */ /* Bump the transmission count */
req->wb_nio++; req->wb_nio++;
if (!nfs_pageio_add_request(&desc, req)) { if (!nfs_pageio_add_request(&desc, req)) {
nfs_list_move_request(req, &failed);
spin_lock(&cinfo.inode->i_lock); spin_lock(&cinfo.inode->i_lock);
if (dreq->error < 0) {
desc.pg_error = dreq->error;
} else if (desc.pg_error != -EAGAIN) {
dreq->flags = 0; dreq->flags = 0;
if (!desc.pg_error) if (desc.pg_error < 0)
desc.pg_error = -EIO;
dreq->error = desc.pg_error; dreq->error = desc.pg_error;
} else else
dreq->flags = NFS_ODIRECT_RESCHED_WRITES; dreq->error = -EIO;
spin_unlock(&cinfo.inode->i_lock); spin_unlock(&cinfo.inode->i_lock);
break;
} }
nfs_release_request(req); nfs_release_request(req);
} }
nfs_pageio_complete(&desc); nfs_pageio_complete(&desc);
while (!list_empty(&reqs)) { while (!list_empty(&failed)) {
req = nfs_list_entry(reqs.next); req = nfs_list_entry(failed.next);
nfs_list_remove_request(req); nfs_list_remove_request(req);
nfs_unlock_and_release_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)) 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 nfs_pageio_descriptor desc;
struct inode *inode = dreq->inode; struct inode *inode = dreq->inode;
struct nfs_commit_info cinfo;
ssize_t result = 0; ssize_t result = 0;
size_t requested_bytes = 0; size_t requested_bytes = 0;
size_t wsize = max_t(size_t, NFS_SERVER(inode)->wsize, PAGE_SIZE); size_t wsize = max_t(size_t, NFS_SERVER(inode)->wsize, PAGE_SIZE);
bool defer = false;
trace_nfs_direct_write_schedule_iovec(dreq); 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; break;
} }
nfs_lock_request(req);
req->wb_index = pos >> PAGE_SHIFT;
req->wb_offset = pos & ~PAGE_MASK;
if (!nfs_pageio_add_request(&desc, req)) {
result = desc.pg_error;
nfs_unlock_and_release_request(req);
break;
}
pgbase = 0; pgbase = 0;
bytes -= req_len; bytes -= req_len;
requested_bytes += req_len; requested_bytes += req_len;
pos += req_len; pos += req_len;
dreq->bytes_left -= 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) {
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;
} }
nfs_direct_release_pages(pagevec, npages); nfs_direct_release_pages(pagevec, npages);
kvfree(pagevec); kvfree(pagevec);