Merge tag 'nfs-for-4.11-3' of git://git.linux-nfs.org/projects/anna/linux-nfs
Pull NFS client fixes from Anna Schumaker: "Here are a few more bugfixes that came in over the last couple of weeks. Most of these fix various hangs and loops that people found, but we also had a few error handling fixes. Stable Bugfixes: - fix infinite loop on BAD_STATEID error Other Bugfixes: - fix old dentry rehash after move - fix pnfs GETDEVINFO hangs - fix pnfs fallback to MDS on commit errors - fix flexfiles kernel oops" * tag 'nfs-for-4.11-3' of git://git.linux-nfs.org/projects/anna/linux-nfs: nfs: flexfiles: fix kernel OOPS if MDS returns unsupported DS type NFSv4.1 fix infinite loop on IO BAD_STATEID error PNFS fix fallback to MDS if got error on commit to DS NFS filelayout:call GETDEVICEINFO after pnfs_layout_process completes NFS store nfs4_deviceid in struct nfs4_filelayout_segment NFS cleanup struct nfs4_filelayout_segment NFS: Fix old dentry rehash after move
This commit is contained in:
@@ -202,10 +202,10 @@ static int filelayout_async_handle_error(struct rpc_task *task,
|
||||
task->tk_status);
|
||||
nfs4_mark_deviceid_unavailable(devid);
|
||||
pnfs_error_mark_layout_for_return(inode, lseg);
|
||||
pnfs_set_lo_fail(lseg);
|
||||
rpc_wake_up(&tbl->slot_tbl_waitq);
|
||||
/* fall through */
|
||||
default:
|
||||
pnfs_set_lo_fail(lseg);
|
||||
reset:
|
||||
dprintk("%s Retry through MDS. Error %d\n", __func__,
|
||||
task->tk_status);
|
||||
@@ -560,49 +560,17 @@ filelayout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
|
||||
return PNFS_ATTEMPTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* filelayout_check_layout()
|
||||
*
|
||||
* Make sure layout segment parameters are sane WRT the device.
|
||||
* At this point no generic layer initialization of the lseg has occurred,
|
||||
* and nothing has been added to the layout_hdr cache.
|
||||
*
|
||||
*/
|
||||
static int
|
||||
filelayout_check_layout(struct pnfs_layout_hdr *lo,
|
||||
struct nfs4_filelayout_segment *fl,
|
||||
struct nfs4_layoutget_res *lgr,
|
||||
struct nfs4_deviceid *id,
|
||||
gfp_t gfp_flags)
|
||||
filelayout_check_deviceid(struct pnfs_layout_hdr *lo,
|
||||
struct nfs4_filelayout_segment *fl,
|
||||
gfp_t gfp_flags)
|
||||
{
|
||||
struct nfs4_deviceid_node *d;
|
||||
struct nfs4_file_layout_dsaddr *dsaddr;
|
||||
int status = -EINVAL;
|
||||
|
||||
dprintk("--> %s\n", __func__);
|
||||
|
||||
/* FIXME: remove this check when layout segment support is added */
|
||||
if (lgr->range.offset != 0 ||
|
||||
lgr->range.length != NFS4_MAX_UINT64) {
|
||||
dprintk("%s Only whole file layouts supported. Use MDS i/o\n",
|
||||
__func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (fl->pattern_offset > lgr->range.offset) {
|
||||
dprintk("%s pattern_offset %lld too large\n",
|
||||
__func__, fl->pattern_offset);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!fl->stripe_unit) {
|
||||
dprintk("%s Invalid stripe unit (%u)\n",
|
||||
__func__, fl->stripe_unit);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* find and reference the deviceid */
|
||||
d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), id,
|
||||
d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), &fl->deviceid,
|
||||
lo->plh_lc_cred, gfp_flags);
|
||||
if (d == NULL)
|
||||
goto out;
|
||||
@@ -628,14 +596,56 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,
|
||||
__func__, fl->num_fh);
|
||||
goto out_put;
|
||||
}
|
||||
status = 0;
|
||||
out:
|
||||
return status;
|
||||
out_put:
|
||||
nfs4_fl_put_deviceid(dsaddr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* filelayout_check_layout()
|
||||
*
|
||||
* Make sure layout segment parameters are sane WRT the device.
|
||||
* At this point no generic layer initialization of the lseg has occurred,
|
||||
* and nothing has been added to the layout_hdr cache.
|
||||
*
|
||||
*/
|
||||
static int
|
||||
filelayout_check_layout(struct pnfs_layout_hdr *lo,
|
||||
struct nfs4_filelayout_segment *fl,
|
||||
struct nfs4_layoutget_res *lgr,
|
||||
gfp_t gfp_flags)
|
||||
{
|
||||
int status = -EINVAL;
|
||||
|
||||
dprintk("--> %s\n", __func__);
|
||||
|
||||
/* FIXME: remove this check when layout segment support is added */
|
||||
if (lgr->range.offset != 0 ||
|
||||
lgr->range.length != NFS4_MAX_UINT64) {
|
||||
dprintk("%s Only whole file layouts supported. Use MDS i/o\n",
|
||||
__func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (fl->pattern_offset > lgr->range.offset) {
|
||||
dprintk("%s pattern_offset %lld too large\n",
|
||||
__func__, fl->pattern_offset);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!fl->stripe_unit) {
|
||||
dprintk("%s Invalid stripe unit (%u)\n",
|
||||
__func__, fl->stripe_unit);
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = 0;
|
||||
out:
|
||||
dprintk("--> %s returns %d\n", __func__, status);
|
||||
return status;
|
||||
out_put:
|
||||
nfs4_fl_put_deviceid(dsaddr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
static void _filelayout_free_lseg(struct nfs4_filelayout_segment *fl)
|
||||
@@ -657,7 +667,6 @@ static int
|
||||
filelayout_decode_layout(struct pnfs_layout_hdr *flo,
|
||||
struct nfs4_filelayout_segment *fl,
|
||||
struct nfs4_layoutget_res *lgr,
|
||||
struct nfs4_deviceid *id,
|
||||
gfp_t gfp_flags)
|
||||
{
|
||||
struct xdr_stream stream;
|
||||
@@ -682,9 +691,9 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
|
||||
if (unlikely(!p))
|
||||
goto out_err;
|
||||
|
||||
memcpy(id, p, sizeof(*id));
|
||||
memcpy(&fl->deviceid, p, sizeof(fl->deviceid));
|
||||
p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE);
|
||||
nfs4_print_deviceid(id);
|
||||
nfs4_print_deviceid(&fl->deviceid);
|
||||
|
||||
nfl_util = be32_to_cpup(p++);
|
||||
if (nfl_util & NFL4_UFLG_COMMIT_THRU_MDS)
|
||||
@@ -831,15 +840,14 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid,
|
||||
{
|
||||
struct nfs4_filelayout_segment *fl;
|
||||
int rc;
|
||||
struct nfs4_deviceid id;
|
||||
|
||||
dprintk("--> %s\n", __func__);
|
||||
fl = kzalloc(sizeof(*fl), gfp_flags);
|
||||
if (!fl)
|
||||
return NULL;
|
||||
|
||||
rc = filelayout_decode_layout(layoutid, fl, lgr, &id, gfp_flags);
|
||||
if (rc != 0 || filelayout_check_layout(layoutid, fl, lgr, &id, gfp_flags)) {
|
||||
rc = filelayout_decode_layout(layoutid, fl, lgr, gfp_flags);
|
||||
if (rc != 0 || filelayout_check_layout(layoutid, fl, lgr, gfp_flags)) {
|
||||
_filelayout_free_lseg(fl);
|
||||
return NULL;
|
||||
}
|
||||
@@ -888,18 +896,51 @@ filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
|
||||
return min(stripe_unit - (unsigned int)stripe_offset, size);
|
||||
}
|
||||
|
||||
static struct pnfs_layout_segment *
|
||||
fl_pnfs_update_layout(struct inode *ino,
|
||||
struct nfs_open_context *ctx,
|
||||
loff_t pos,
|
||||
u64 count,
|
||||
enum pnfs_iomode iomode,
|
||||
bool strict_iomode,
|
||||
gfp_t gfp_flags)
|
||||
{
|
||||
struct pnfs_layout_segment *lseg = NULL;
|
||||
struct pnfs_layout_hdr *lo;
|
||||
struct nfs4_filelayout_segment *fl;
|
||||
int status;
|
||||
|
||||
lseg = pnfs_update_layout(ino, ctx, pos, count, iomode, strict_iomode,
|
||||
gfp_flags);
|
||||
if (!lseg)
|
||||
lseg = ERR_PTR(-ENOMEM);
|
||||
if (IS_ERR(lseg))
|
||||
goto out;
|
||||
|
||||
lo = NFS_I(ino)->layout;
|
||||
fl = FILELAYOUT_LSEG(lseg);
|
||||
|
||||
status = filelayout_check_deviceid(lo, fl, gfp_flags);
|
||||
if (status)
|
||||
lseg = ERR_PTR(status);
|
||||
out:
|
||||
if (IS_ERR(lseg))
|
||||
pnfs_put_lseg(lseg);
|
||||
return lseg;
|
||||
}
|
||||
|
||||
static void
|
||||
filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio,
|
||||
struct nfs_page *req)
|
||||
{
|
||||
if (!pgio->pg_lseg) {
|
||||
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
|
||||
req->wb_context,
|
||||
0,
|
||||
NFS4_MAX_UINT64,
|
||||
IOMODE_READ,
|
||||
false,
|
||||
GFP_KERNEL);
|
||||
pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode,
|
||||
req->wb_context,
|
||||
0,
|
||||
NFS4_MAX_UINT64,
|
||||
IOMODE_READ,
|
||||
false,
|
||||
GFP_KERNEL);
|
||||
if (IS_ERR(pgio->pg_lseg)) {
|
||||
pgio->pg_error = PTR_ERR(pgio->pg_lseg);
|
||||
pgio->pg_lseg = NULL;
|
||||
@@ -919,13 +960,13 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio,
|
||||
int status;
|
||||
|
||||
if (!pgio->pg_lseg) {
|
||||
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
|
||||
req->wb_context,
|
||||
0,
|
||||
NFS4_MAX_UINT64,
|
||||
IOMODE_RW,
|
||||
false,
|
||||
GFP_NOFS);
|
||||
pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode,
|
||||
req->wb_context,
|
||||
0,
|
||||
NFS4_MAX_UINT64,
|
||||
IOMODE_RW,
|
||||
false,
|
||||
GFP_NOFS);
|
||||
if (IS_ERR(pgio->pg_lseg)) {
|
||||
pgio->pg_error = PTR_ERR(pgio->pg_lseg);
|
||||
pgio->pg_lseg = NULL;
|
||||
|
@@ -55,15 +55,16 @@ struct nfs4_file_layout_dsaddr {
|
||||
};
|
||||
|
||||
struct nfs4_filelayout_segment {
|
||||
struct pnfs_layout_segment generic_hdr;
|
||||
u32 stripe_type;
|
||||
u32 commit_through_mds;
|
||||
u32 stripe_unit;
|
||||
u32 first_stripe_index;
|
||||
u64 pattern_offset;
|
||||
struct nfs4_file_layout_dsaddr *dsaddr; /* Point to GETDEVINFO data */
|
||||
unsigned int num_fh;
|
||||
struct nfs_fh **fh_array;
|
||||
struct pnfs_layout_segment generic_hdr;
|
||||
u32 stripe_type;
|
||||
u32 commit_through_mds;
|
||||
u32 stripe_unit;
|
||||
u32 first_stripe_index;
|
||||
u64 pattern_offset;
|
||||
struct nfs4_deviceid deviceid;
|
||||
struct nfs4_file_layout_dsaddr *dsaddr; /* Point to GETDEVINFO data */
|
||||
unsigned int num_fh;
|
||||
struct nfs_fh **fh_array;
|
||||
};
|
||||
|
||||
struct nfs4_filelayout {
|
||||
|
Reference in New Issue
Block a user