diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 1377ee20ecf91383e0239930a0cb60317a94726b..0fd811ac08b525d2a5962a168402557a1e01843b 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -428,7 +428,7 @@ static void nfs_direct_read_completion(struct nfs_pgio_header *hdr) hdr->release(hdr); } -static void nfs_read_sync_pgio_error(struct list_head *head) +static void nfs_read_sync_pgio_error(struct list_head *head, int error) { struct nfs_page *req; @@ -820,7 +820,7 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr) hdr->release(hdr); } -static void nfs_write_sync_pgio_error(struct list_head *head) +static void nfs_write_sync_pgio_error(struct list_head *head, int error) { struct nfs_page *req; diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 9cbd829b4ed5f4305035ac9c65bb4f623ea9a608..7f0b9409202ccabce81454ffab03e76fa34a0f2b 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -994,7 +994,7 @@ nfs_pageio_cleanup_request(struct nfs_pageio_descriptor *desc, LIST_HEAD(head); nfs_list_move_request(req, &head); - desc->pg_completion_ops->error_cleanup(&head); + desc->pg_completion_ops->error_cleanup(&head, desc->pg_error); } /** @@ -1130,7 +1130,8 @@ static void nfs_pageio_error_cleanup(struct nfs_pageio_descriptor *desc) for (midx = 0; midx < desc->pg_mirror_count; midx++) { mirror = &desc->pg_mirrors[midx]; - desc->pg_completion_ops->error_cleanup(&mirror->pg_list); + desc->pg_completion_ops->error_cleanup(&mirror->pg_list, + desc->pg_error); } } diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 48d7277c60a9793b3684e9587a69d26af410a8fb..09d5c282f50e92ef7c9735162e7cd9f63a922deb 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -205,7 +205,7 @@ static void nfs_initiate_read(struct nfs_pgio_header *hdr, } static void -nfs_async_read_error(struct list_head *head) +nfs_async_read_error(struct list_head *head, int error) { struct nfs_page *req; diff --git a/fs/nfs/write.c b/fs/nfs/write.c index d78d32027c710ce97dc00afcca7219820847b358..9dd11a720076ac957824063b4082c929473bcc74 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -1394,20 +1394,27 @@ static void nfs_redirty_request(struct nfs_page *req) nfs_release_request(req); } -static void nfs_async_write_error(struct list_head *head) +static void nfs_async_write_error(struct list_head *head, int error) { struct nfs_page *req; while (!list_empty(head)) { req = nfs_list_entry(head->next); nfs_list_remove_request(req); + if (nfs_error_is_fatal(error)) { + nfs_context_set_write_error(req->wb_context, error); + if (nfs_error_is_fatal_on_server(error)) { + nfs_write_error_remove_page(req); + continue; + } + } nfs_redirty_request(req); } } static void nfs_async_write_reschedule_io(struct nfs_pgio_header *hdr) { - nfs_async_write_error(&hdr->pages); + nfs_async_write_error(&hdr->pages, 0); filemap_fdatawrite_range(hdr->inode->i_mapping, hdr->args.offset, hdr->args.offset + hdr->args.count - 1); } diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index bd1c889a9ed956c14543117a8835eb4ae4474a9a..cab24a127feb34bab337102fcb69500ca18a1d54 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -1539,7 +1539,7 @@ struct nfs_commit_data { }; struct nfs_pgio_completion_ops { - void (*error_cleanup)(struct list_head *head); + void (*error_cleanup)(struct list_head *head, int); void (*init_hdr)(struct nfs_pgio_header *hdr); void (*completion)(struct nfs_pgio_header *hdr); void (*reschedule_io)(struct nfs_pgio_header *hdr);