Commit d600ad1f authored by Peng Tao's avatar Peng Tao Committed by Trond Myklebust

NFS41: pop some layoutget errors to application

For ERESTARTSYS/EIO/EROFS/ENOSPC/E2BIG in layoutget, we
should just bail out instead of hiding the error and
retrying inband IO.

Change all the call sites to pop the error all the way up.
Signed-off-by: default avatarPeng Tao <tao.peng@primarydata.com>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent d0379a5d
...@@ -670,6 +670,10 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) ...@@ -670,6 +670,10 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
req = nfs_list_entry(reqs.next); req = nfs_list_entry(reqs.next);
nfs_direct_setup_mirroring(dreq, &desc, req); nfs_direct_setup_mirroring(dreq, &desc, req);
if (desc.pg_error < 0) {
list_splice_init(&reqs, &failed);
goto out_failed;
}
list_for_each_entry_safe(req, tmp, &reqs, wb_list) { list_for_each_entry_safe(req, tmp, &reqs, wb_list) {
if (!nfs_pageio_add_request(&desc, req)) { if (!nfs_pageio_add_request(&desc, req)) {
...@@ -677,13 +681,17 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) ...@@ -677,13 +681,17 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
nfs_list_add_request(req, &failed); nfs_list_add_request(req, &failed);
spin_lock(cinfo.lock); spin_lock(cinfo.lock);
dreq->flags = 0; dreq->flags = 0;
dreq->error = -EIO; if (desc.pg_error < 0)
dreq->error = desc.pg_error;
else
dreq->error = -EIO;
spin_unlock(cinfo.lock); spin_unlock(cinfo.lock);
} }
nfs_release_request(req); nfs_release_request(req);
} }
nfs_pageio_complete(&desc); nfs_pageio_complete(&desc);
out_failed:
while (!list_empty(&failed)) { while (!list_empty(&failed)) {
req = nfs_list_entry(failed.next); req = nfs_list_entry(failed.next);
nfs_list_remove_request(req); nfs_list_remove_request(req);
...@@ -900,6 +908,11 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, ...@@ -900,6 +908,11 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
} }
nfs_direct_setup_mirroring(dreq, &desc, req); nfs_direct_setup_mirroring(dreq, &desc, req);
if (desc.pg_error < 0) {
nfs_free_request(req);
result = desc.pg_error;
break;
}
nfs_lock_request(req); nfs_lock_request(req);
req->wb_index = pos >> PAGE_SHIFT; req->wb_index = pos >> PAGE_SHIFT;
......
...@@ -883,13 +883,19 @@ static void ...@@ -883,13 +883,19 @@ static void
filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio, filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio,
struct nfs_page *req) struct nfs_page *req)
{ {
if (!pgio->pg_lseg) if (!pgio->pg_lseg) {
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
req->wb_context, req->wb_context,
0, 0,
NFS4_MAX_UINT64, NFS4_MAX_UINT64,
IOMODE_READ, IOMODE_READ,
GFP_KERNEL); GFP_KERNEL);
if (IS_ERR(pgio->pg_lseg)) {
pgio->pg_error = PTR_ERR(pgio->pg_lseg);
pgio->pg_lseg = NULL;
return;
}
}
/* If no lseg, fall back to read through mds */ /* If no lseg, fall back to read through mds */
if (pgio->pg_lseg == NULL) if (pgio->pg_lseg == NULL)
nfs_pageio_reset_read_mds(pgio); nfs_pageio_reset_read_mds(pgio);
...@@ -902,13 +908,20 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio, ...@@ -902,13 +908,20 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio,
struct nfs_commit_info cinfo; struct nfs_commit_info cinfo;
int status; int status;
if (!pgio->pg_lseg) if (!pgio->pg_lseg) {
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
req->wb_context, req->wb_context,
0, 0,
NFS4_MAX_UINT64, NFS4_MAX_UINT64,
IOMODE_RW, IOMODE_RW,
GFP_NOFS); GFP_NOFS);
if (IS_ERR(pgio->pg_lseg)) {
pgio->pg_error = PTR_ERR(pgio->pg_lseg);
pgio->pg_lseg = NULL;
return;
}
}
/* If no lseg, fall back to write through mds */ /* If no lseg, fall back to write through mds */
if (pgio->pg_lseg == NULL) if (pgio->pg_lseg == NULL)
goto out_mds; goto out_mds;
......
...@@ -795,13 +795,19 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio, ...@@ -795,13 +795,19 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
int ds_idx; int ds_idx;
/* Use full layout for now */ /* Use full layout for now */
if (!pgio->pg_lseg) if (!pgio->pg_lseg) {
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
req->wb_context, req->wb_context,
0, 0,
NFS4_MAX_UINT64, NFS4_MAX_UINT64,
IOMODE_READ, IOMODE_READ,
GFP_KERNEL); GFP_KERNEL);
if (IS_ERR(pgio->pg_lseg)) {
pgio->pg_error = PTR_ERR(pgio->pg_lseg);
pgio->pg_lseg = NULL;
return;
}
}
/* If no lseg, fall back to read through mds */ /* If no lseg, fall back to read through mds */
if (pgio->pg_lseg == NULL) if (pgio->pg_lseg == NULL)
goto out_mds; goto out_mds;
...@@ -835,13 +841,19 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio, ...@@ -835,13 +841,19 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio,
int i; int i;
int status; int status;
if (!pgio->pg_lseg) if (!pgio->pg_lseg) {
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
req->wb_context, req->wb_context,
0, 0,
NFS4_MAX_UINT64, NFS4_MAX_UINT64,
IOMODE_RW, IOMODE_RW,
GFP_NOFS); GFP_NOFS);
if (IS_ERR(pgio->pg_lseg)) {
pgio->pg_error = PTR_ERR(pgio->pg_lseg);
pgio->pg_lseg = NULL;
return;
}
}
/* If no lseg, fall back to write through mds */ /* If no lseg, fall back to write through mds */
if (pgio->pg_lseg == NULL) if (pgio->pg_lseg == NULL)
goto out_mds; goto out_mds;
...@@ -877,18 +889,25 @@ static unsigned int ...@@ -877,18 +889,25 @@ static unsigned int
ff_layout_pg_get_mirror_count_write(struct nfs_pageio_descriptor *pgio, ff_layout_pg_get_mirror_count_write(struct nfs_pageio_descriptor *pgio,
struct nfs_page *req) struct nfs_page *req)
{ {
if (!pgio->pg_lseg) if (!pgio->pg_lseg) {
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
req->wb_context, req->wb_context,
0, 0,
NFS4_MAX_UINT64, NFS4_MAX_UINT64,
IOMODE_RW, IOMODE_RW,
GFP_NOFS); GFP_NOFS);
if (IS_ERR(pgio->pg_lseg)) {
pgio->pg_error = PTR_ERR(pgio->pg_lseg);
pgio->pg_lseg = NULL;
goto out;
}
}
if (pgio->pg_lseg) if (pgio->pg_lseg)
return FF_LAYOUT_MIRROR_COUNT(pgio->pg_lseg); return FF_LAYOUT_MIRROR_COUNT(pgio->pg_lseg);
/* no lseg means that pnfs is not in use, so no mirroring here */ /* no lseg means that pnfs is not in use, so no mirroring here */
nfs_pageio_reset_write_mds(pgio); nfs_pageio_reset_write_mds(pgio);
out:
return 1; return 1;
} }
......
...@@ -874,6 +874,9 @@ static int nfs_pageio_setup_mirroring(struct nfs_pageio_descriptor *pgio, ...@@ -874,6 +874,9 @@ static int nfs_pageio_setup_mirroring(struct nfs_pageio_descriptor *pgio,
mirror_count = pgio->pg_ops->pg_get_mirror_count(pgio, req); mirror_count = pgio->pg_ops->pg_get_mirror_count(pgio, req);
if (pgio->pg_error < 0)
return pgio->pg_error;
if (!mirror_count || mirror_count > NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX) if (!mirror_count || mirror_count > NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX)
return -EINVAL; return -EINVAL;
...@@ -982,6 +985,8 @@ static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc, ...@@ -982,6 +985,8 @@ static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc,
} else { } else {
if (desc->pg_ops->pg_init) if (desc->pg_ops->pg_init)
desc->pg_ops->pg_init(desc, req); desc->pg_ops->pg_init(desc, req);
if (desc->pg_error < 0)
return 0;
mirror->pg_base = req->wb_pgbase; mirror->pg_base = req->wb_pgbase;
} }
if (!nfs_can_coalesce_requests(prev, req, desc)) if (!nfs_can_coalesce_requests(prev, req, desc))
...@@ -1147,6 +1152,8 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, ...@@ -1147,6 +1152,8 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
bytes = req->wb_bytes; bytes = req->wb_bytes;
nfs_pageio_setup_mirroring(desc, req); nfs_pageio_setup_mirroring(desc, req);
if (desc->pg_error < 0)
return 0;
for (midx = 0; midx < desc->pg_mirror_count; midx++) { for (midx = 0; midx < desc->pg_mirror_count; midx++) {
if (midx) { if (midx) {
...@@ -1232,7 +1239,7 @@ int nfs_pageio_resend(struct nfs_pageio_descriptor *desc, ...@@ -1232,7 +1239,7 @@ int nfs_pageio_resend(struct nfs_pageio_descriptor *desc,
nfs_pageio_complete(desc); nfs_pageio_complete(desc);
if (!list_empty(&failed)) { if (!list_empty(&failed)) {
list_move(&failed, &hdr->pages); list_move(&failed, &hdr->pages);
return -EIO; return desc->pg_error < 0 ? desc->pg_error : -EIO;
} }
return 0; return 0;
} }
......
...@@ -906,14 +906,15 @@ send_layoutget(struct pnfs_layout_hdr *lo, ...@@ -906,14 +906,15 @@ send_layoutget(struct pnfs_layout_hdr *lo,
if (IS_ERR(lseg)) { if (IS_ERR(lseg)) {
switch (PTR_ERR(lseg)) { switch (PTR_ERR(lseg)) {
case -ENOMEM:
case -ERESTARTSYS: case -ERESTARTSYS:
case -EIO:
case -ENOSPC:
case -EROFS:
case -E2BIG:
break; break;
default: default:
/* remember that LAYOUTGET failed and suspend trying */ return NULL;
pnfs_layout_io_set_failed(lo, range->iomode);
} }
return NULL;
} else } else
pnfs_layout_clear_fail_bit(lo, pnfs_layout_clear_fail_bit(lo,
pnfs_iomode_to_fail_bit(range->iomode)); pnfs_iomode_to_fail_bit(range->iomode));
...@@ -1649,7 +1650,7 @@ pnfs_update_layout(struct inode *ino, ...@@ -1649,7 +1650,7 @@ pnfs_update_layout(struct inode *ino,
"(%s, offset: %llu, length: %llu)\n", "(%s, offset: %llu, length: %llu)\n",
__func__, ino->i_sb->s_id, __func__, ino->i_sb->s_id,
(unsigned long long)NFS_FILEID(ino), (unsigned long long)NFS_FILEID(ino),
lseg == NULL ? "not found" : "found", IS_ERR_OR_NULL(lseg) ? "not found" : "found",
iomode==IOMODE_RW ? "read/write" : "read-only", iomode==IOMODE_RW ? "read/write" : "read-only",
(unsigned long long)pos, (unsigned long long)pos,
(unsigned long long)count); (unsigned long long)count);
...@@ -1828,6 +1829,11 @@ pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *r ...@@ -1828,6 +1829,11 @@ pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *r
rd_size, rd_size,
IOMODE_READ, IOMODE_READ,
GFP_KERNEL); GFP_KERNEL);
if (IS_ERR(pgio->pg_lseg)) {
pgio->pg_error = PTR_ERR(pgio->pg_lseg);
pgio->pg_lseg = NULL;
return;
}
} }
/* If no lseg, fall back to read through mds */ /* If no lseg, fall back to read through mds */
if (pgio->pg_lseg == NULL) if (pgio->pg_lseg == NULL)
...@@ -1840,13 +1846,19 @@ void ...@@ -1840,13 +1846,19 @@ void
pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio,
struct nfs_page *req, u64 wb_size) struct nfs_page *req, u64 wb_size)
{ {
if (pgio->pg_lseg == NULL) if (pgio->pg_lseg == NULL) {
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
req->wb_context, req->wb_context,
req_offset(req), req_offset(req),
wb_size, wb_size,
IOMODE_RW, IOMODE_RW,
GFP_NOFS); GFP_NOFS);
if (IS_ERR(pgio->pg_lseg)) {
pgio->pg_error = PTR_ERR(pgio->pg_lseg);
pgio->pg_lseg = NULL;
return;
}
}
/* If no lseg, fall back to write through mds */ /* If no lseg, fall back to write through mds */
if (pgio->pg_lseg == NULL) if (pgio->pg_lseg == NULL)
nfs_pageio_reset_write_mds(pgio); nfs_pageio_reset_write_mds(pgio);
......
...@@ -115,7 +115,7 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, ...@@ -115,7 +115,7 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
pgm = &pgio.pg_mirrors[0]; pgm = &pgio.pg_mirrors[0];
NFS_I(inode)->read_io += pgm->pg_bytes_written; NFS_I(inode)->read_io += pgm->pg_bytes_written;
return 0; return pgio.pg_error < 0 ? pgio.pg_error : 0;
} }
static void nfs_readpage_release(struct nfs_page *req) static void nfs_readpage_release(struct nfs_page *req)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment