aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Coddington <bcodding@redhat.com>2018-10-18 15:01:48 -0400
committerTrond Myklebust <trond.myklebust@hammerspace.com>2018-10-18 17:20:57 -0400
commitfdbd1a2e4a71adcb1ae219fcfd964930d77a7f84 (patch)
tree728f68714faa6fddc69ea60e8ff8a9f61d3ed09c
parente732f4485a150492b286f3efc06f9b34dd6b9995 (diff)
nfs: Fix a missed page unlock after pg_doio()
We must check pg_error and call error_cleanup after any call to pg_doio. Currently, we are skipping the unlock of a page if we encounter an error in nfs_pageio_complete() before handing off the work to the RPC layer. Signed-off-by: Benjamin Coddington <bcodding@redhat.com> Cc: stable@vger.kernel.org Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
-rw-r--r--fs/nfs/pagelist.c40
1 files changed, 21 insertions, 19 deletions
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index f97c455f5734..3b50edf6f883 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -1110,6 +1110,20 @@ static int nfs_pageio_add_request_mirror(struct nfs_pageio_descriptor *desc,
1110 return ret; 1110 return ret;
1111} 1111}
1112 1112
1113static void nfs_pageio_error_cleanup(struct nfs_pageio_descriptor *desc)
1114{
1115 u32 midx;
1116 struct nfs_pgio_mirror *mirror;
1117
1118 if (!desc->pg_error)
1119 return;
1120
1121 for (midx = 0; midx < desc->pg_mirror_count; midx++) {
1122 mirror = &desc->pg_mirrors[midx];
1123 desc->pg_completion_ops->error_cleanup(&mirror->pg_list);
1124 }
1125}
1126
1113int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, 1127int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
1114 struct nfs_page *req) 1128 struct nfs_page *req)
1115{ 1129{
@@ -1160,25 +1174,11 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
1160 return 1; 1174 return 1;
1161 1175
1162out_failed: 1176out_failed:
1163 /* 1177 /* remember fatal errors */
1164 * We might have failed before sending any reqs over wire. 1178 if (nfs_error_is_fatal(desc->pg_error))
1165 * Clean up rest of the reqs in mirror pg_list. 1179 nfs_context_set_write_error(req->wb_context,
1166 */ 1180 desc->pg_error);
1167 if (desc->pg_error) { 1181 nfs_pageio_error_cleanup(desc);
1168 struct nfs_pgio_mirror *mirror;
1169 void (*func)(struct list_head *);
1170
1171 /* remember fatal errors */
1172 if (nfs_error_is_fatal(desc->pg_error))
1173 nfs_context_set_write_error(req->wb_context,
1174 desc->pg_error);
1175
1176 func = desc->pg_completion_ops->error_cleanup;
1177 for (midx = 0; midx < desc->pg_mirror_count; midx++) {
1178 mirror = &desc->pg_mirrors[midx];
1179 func(&mirror->pg_list);
1180 }
1181 }
1182 return 0; 1182 return 0;
1183} 1183}
1184 1184
@@ -1250,6 +1250,8 @@ void nfs_pageio_complete(struct nfs_pageio_descriptor *desc)
1250 for (midx = 0; midx < desc->pg_mirror_count; midx++) 1250 for (midx = 0; midx < desc->pg_mirror_count; midx++)
1251 nfs_pageio_complete_mirror(desc, midx); 1251 nfs_pageio_complete_mirror(desc, midx);
1252 1252
1253 if (desc->pg_error < 0)
1254 nfs_pageio_error_cleanup(desc);
1253 if (desc->pg_ops->pg_cleanup) 1255 if (desc->pg_ops->pg_cleanup)
1254 desc->pg_ops->pg_cleanup(desc); 1256 desc->pg_ops->pg_cleanup(desc);
1255 nfs_pageio_cleanup_mirroring(desc); 1257 nfs_pageio_cleanup_mirroring(desc);