mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 12:44:11 +08:00
NFS client fixes for 4.11 (part 2)
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 -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEnZ5MQTpR7cLU7KEp18tUv7ClQOsFAljeko0ACgkQ18tUv7Cl QOsZbw/+MXYEZCaILgaAjzoWO4qJhNuAzlblh2jSX2nitY6NAva2MORZoAnxqS/G 2qVWdYLvfQ2rKkIazInktaqBgsnl5Got9EbrD2hdV5LvM953U3KJkeXZD67ncvV7 YYmxaFipLfTfmLZDXlQ1h5wTKXXXw0VA2v2YL+sRZhAzVhcTyMyf1n89lT6H9Fqx UPitMuBbRskCPFMOZ6xP+T6MsOpeIGVHHOvYWSSydCT6IoujnTjNRaZ9+VFSm5iU rubL/qokg2VIJ60xbmv/toq61FkhI2xtJTtBFxHZo47En3RdwB53zOez/OmvTFLZ lKSCh/Xkk/DDhUQWrYDaydPyGE6mWR+E/18/BZh0tx0n+yvHPg0ax56CTSJwpvg7 f6pydxQo0RAH3S/IWb0JB3jyi++EKznWK2OokllOdmT3DrYyKD3LiTY4T2MO8Wlu +miFq6yk1iQHZR4R4JDkCWzpD7JeeR6lkg19kRZlBJm2Pv+8Rzg4qjBgqAo5OPxV RiQ0CuyKoR2rtMz/4pepBai4fM42S/Nc59QJI/45mTUJ40whyoygJEov7s3SdTZi H6cL7Ewe8m++MNW2aAsM2M0CVzoyv0D4mnPxgE8t8lNbkcT14bdi1WFwAHo/ICMd KpyhsDVltakqUbelD3WWJtTXbAPCgwlOzuPdfbqtBMQJNP1aONs= =1Xgv -----END PGP SIGNATURE----- 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:
commit
f9799ad21b
@ -2055,7 +2055,7 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
{
|
||||
struct inode *old_inode = d_inode(old_dentry);
|
||||
struct inode *new_inode = d_inode(new_dentry);
|
||||
struct dentry *dentry = NULL, *rehash = NULL;
|
||||
struct dentry *dentry = NULL;
|
||||
struct rpc_task *task;
|
||||
int error = -EBUSY;
|
||||
|
||||
@ -2078,10 +2078,8 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
* To prevent any new references to the target during the
|
||||
* rename, we unhash the dentry in advance.
|
||||
*/
|
||||
if (!d_unhashed(new_dentry)) {
|
||||
if (!d_unhashed(new_dentry))
|
||||
d_drop(new_dentry);
|
||||
rehash = new_dentry;
|
||||
}
|
||||
|
||||
if (d_count(new_dentry) > 2) {
|
||||
int err;
|
||||
@ -2098,7 +2096,6 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
goto out;
|
||||
|
||||
new_dentry = dentry;
|
||||
rehash = NULL;
|
||||
new_inode = NULL;
|
||||
}
|
||||
}
|
||||
@ -2119,8 +2116,6 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
error = task->tk_status;
|
||||
rpc_put_task(task);
|
||||
out:
|
||||
if (rehash)
|
||||
d_rehash(rehash);
|
||||
trace_nfs_rename_exit(old_dir, old_dentry,
|
||||
new_dir, new_dentry, error);
|
||||
/* new dentry created? */
|
||||
|
@ -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 {
|
||||
|
@ -208,6 +208,10 @@ static bool ff_layout_mirror_valid(struct pnfs_layout_segment *lseg,
|
||||
} else
|
||||
goto outerr;
|
||||
}
|
||||
|
||||
if (IS_ERR(mirror->mirror_ds))
|
||||
goto outerr;
|
||||
|
||||
if (mirror->mirror_ds->ds == NULL) {
|
||||
struct nfs4_deviceid_node *devid;
|
||||
devid = &mirror->mirror_ds->id_node;
|
||||
|
@ -2442,17 +2442,14 @@ static void nfs41_check_delegation_stateid(struct nfs4_state *state)
|
||||
}
|
||||
|
||||
nfs4_stateid_copy(&stateid, &delegation->stateid);
|
||||
if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) {
|
||||
if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags) ||
|
||||
!test_and_clear_bit(NFS_DELEGATION_TEST_EXPIRED,
|
||||
&delegation->flags)) {
|
||||
rcu_read_unlock();
|
||||
nfs_finish_clear_delegation_stateid(state, &stateid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!test_and_clear_bit(NFS_DELEGATION_TEST_EXPIRED, &delegation->flags)) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
cred = get_rpccred(delegation->cred);
|
||||
rcu_read_unlock();
|
||||
status = nfs41_test_and_free_expired_stateid(server, &stateid, cred);
|
||||
|
Loading…
Reference in New Issue
Block a user