NFS client fixes for 4.11
Stable Bugfixes: - Fix decrementing nrequests in NFS v4.2 COPY to fix kernel warnings - Prevent a double free in async nfs4_exchange_id() - Squelch a kbuild sparse complaint for xprtrdma Other Bugfixes: - Fix a typo (NFS_ATTR_FATTR_GROUP_NAME) that causes a memory leak - Fix a reference leak that causes kernel warnings - Make nfs4_cb_sv_ops static to fix a sparse warning - Respect a server's max size in CREATE_SESSION - Handle errors from nfs4_pnfs_ds_connect - Flexfiles layout shouldn't mark devices as unavailable -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEnZ5MQTpR7cLU7KEp18tUv7ClQOsFAljMQsUACgkQ18tUv7Cl QOt0FA//eSieOojEm9uJIxfydrJY2VkPgqg0xmIxLhcMmXi/d4kO9GpS9YeJJZi4 r5oClq1afhXVR83JmNDCvIYUNwf5/lluckuzXZEYlC3qUbXjQt/Nn/FHfrqW8qXV HJy4PVwV+BHnfU6Y7p14zzucGPrMeWZQJO+7mRpboe1jcizHOMdcw+Aim7pr44y6 BI3QcLPtQGY4CnPOEkpDNuEWtO7iMME3bRJOJ2lOWz5smG0KAQo80OTHGXIe4OqR d+gHhoHZ2LbZwdbs+rsjAIMFsFrgXqZmXYbQCZ9SEsr4ysj3PesHPdGFrKXCZCSM 0MjlEcznGl6ooPDD9tO5Bi047Xhq2TlUWF+FIVYOdFur+7oIcJcnJB7epoYEQ2d2 6RMvddeKmEgW5Y77myIb3G6jTnk7S8dMq5aAGSyUmKoVhybfw0PGFMbZ2gDEpaTG HweeaPmR7J0e+MZBiShTBH2zulFcI1qG3kowu/oKccU9jGi/uA7vkXOSkaxkSzST +vS30JwArNOj7OFqhGZbi1YzoK0ixxxXLD4DaEDKKm4mOt7g1Zmb0QgVnGSx1V6X Or4Y4xTKn0vCt3e61O9dsBRApBCEVSBJMgYb9Z+LUSdQIKoUj+sQPMzY3iGTefcx r7qiUddBZerQ0CZCsRxXk/otJawGCO9XFuSY4CksvlReTeyl1Tc= =JY3W -----END PGP SIGNATURE----- Merge tag 'nfs-for-4.11-2' of git://git.linux-nfs.org/projects/anna/linux-nfs Pull NFS client fixes from Anna Schumaker: "We have a handful of stable fixes to fix kernel warnings and other bugs that have been around for a while. We've also found a few other reference counting bugs and memory leaks since the initial 4.11 pull. Stable Bugfixes: - Fix decrementing nrequests in NFS v4.2 COPY to fix kernel warnings - Prevent a double free in async nfs4_exchange_id() - Squelch a kbuild sparse complaint for xprtrdma Other Bugfixes: - Fix a typo (NFS_ATTR_FATTR_GROUP_NAME) that causes a memory leak - Fix a reference leak that causes kernel warnings - Make nfs4_cb_sv_ops static to fix a sparse warning - Respect a server's max size in CREATE_SESSION - Handle errors from nfs4_pnfs_ds_connect - Flexfiles layout shouldn't mark devices as unavailable" * tag 'nfs-for-4.11-2' of git://git.linux-nfs.org/projects/anna/linux-nfs: pNFS/flexfiles: never nfs4_mark_deviceid_unavailable pNFS: return status from nfs4_pnfs_ds_connect NFSv4.1 respect server's max size in CREATE_SESSION NFS prevent double free in async nfs4_exchange_id nfs: make nfs4_cb_sv_ops static xprtrdma: Squelch kbuild sparse complaint NFS: fix the fault nrequests decreasing for nfs_inode COPY NFSv4: fix a reference leak caused WARNING messages nfs4: fix a typo of NFS_ATTR_FATTR_GROUP_NAME
This commit is contained in:
Коммит
8841b5f0cd
|
@ -232,12 +232,12 @@ static struct svc_serv_ops nfs41_cb_sv_ops = {
|
|||
.svo_module = THIS_MODULE,
|
||||
};
|
||||
|
||||
struct svc_serv_ops *nfs4_cb_sv_ops[] = {
|
||||
static struct svc_serv_ops *nfs4_cb_sv_ops[] = {
|
||||
[0] = &nfs40_cb_sv_ops,
|
||||
[1] = &nfs41_cb_sv_ops,
|
||||
};
|
||||
#else
|
||||
struct svc_serv_ops *nfs4_cb_sv_ops[] = {
|
||||
static struct svc_serv_ops *nfs4_cb_sv_ops[] = {
|
||||
[0] = &nfs40_cb_sv_ops,
|
||||
[1] = NULL,
|
||||
};
|
||||
|
|
|
@ -325,10 +325,33 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static bool nfs_client_init_is_complete(const struct nfs_client *clp)
|
||||
/*
|
||||
* Return true if @clp is done initializing, false if still working on it.
|
||||
*
|
||||
* Use nfs_client_init_status to check if it was successful.
|
||||
*/
|
||||
bool nfs_client_init_is_complete(const struct nfs_client *clp)
|
||||
{
|
||||
return clp->cl_cons_state <= NFS_CS_READY;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_client_init_is_complete);
|
||||
|
||||
/*
|
||||
* Return 0 if @clp was successfully initialized, -errno otherwise.
|
||||
*
|
||||
* This must be called *after* nfs_client_init_is_complete() returns true,
|
||||
* otherwise it will pop WARN_ON_ONCE and return -EINVAL
|
||||
*/
|
||||
int nfs_client_init_status(const struct nfs_client *clp)
|
||||
{
|
||||
/* called without checking nfs_client_init_is_complete */
|
||||
if (clp->cl_cons_state > NFS_CS_READY) {
|
||||
WARN_ON_ONCE(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
return clp->cl_cons_state;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_client_init_status);
|
||||
|
||||
int nfs_wait_client_init_complete(const struct nfs_client *clp)
|
||||
{
|
||||
|
|
|
@ -266,6 +266,7 @@ nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
|
|||
struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg);
|
||||
struct nfs4_pnfs_ds *ret = ds;
|
||||
struct nfs_server *s = NFS_SERVER(lseg->pls_layout->plh_inode);
|
||||
int status;
|
||||
|
||||
if (ds == NULL) {
|
||||
printk(KERN_ERR "NFS: %s: No data server for offset index %d\n",
|
||||
|
@ -277,9 +278,14 @@ nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
|
|||
if (ds->ds_clp)
|
||||
goto out_test_devid;
|
||||
|
||||
nfs4_pnfs_ds_connect(s, ds, devid, dataserver_timeo,
|
||||
status = nfs4_pnfs_ds_connect(s, ds, devid, dataserver_timeo,
|
||||
dataserver_retrans, 4,
|
||||
s->nfs_client->cl_minorversion);
|
||||
if (status) {
|
||||
nfs4_mark_deviceid_unavailable(devid);
|
||||
ret = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out_test_devid:
|
||||
if (ret->ds_clp == NULL ||
|
||||
|
|
|
@ -175,7 +175,19 @@ ff_layout_no_read_on_rw(struct pnfs_layout_segment *lseg)
|
|||
static inline bool
|
||||
ff_layout_test_devid_unavailable(struct nfs4_deviceid_node *node)
|
||||
{
|
||||
return nfs4_test_deviceid_unavailable(node);
|
||||
/*
|
||||
* Flexfiles should never mark a DS unavailable, but if it does
|
||||
* print a (ratelimited) warning as this can affect performance.
|
||||
*/
|
||||
if (nfs4_test_deviceid_unavailable(node)) {
|
||||
u32 *p = (u32 *)node->deviceid.data;
|
||||
|
||||
pr_warn_ratelimited("NFS: flexfiles layout referencing an "
|
||||
"unavailable device [%x%x%x%x]\n",
|
||||
p[0], p[1], p[2], p[3]);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
|
|
@ -384,6 +384,7 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
|
|||
struct inode *ino = lseg->pls_layout->plh_inode;
|
||||
struct nfs_server *s = NFS_SERVER(ino);
|
||||
unsigned int max_payload;
|
||||
int status;
|
||||
|
||||
if (!ff_layout_mirror_valid(lseg, mirror, true)) {
|
||||
pr_err_ratelimited("NFS: %s: No data server for offset index %d\n",
|
||||
|
@ -404,7 +405,7 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
|
|||
/* FIXME: For now we assume the server sent only one version of NFS
|
||||
* to use for the DS.
|
||||
*/
|
||||
nfs4_pnfs_ds_connect(s, ds, devid, dataserver_timeo,
|
||||
status = nfs4_pnfs_ds_connect(s, ds, devid, dataserver_timeo,
|
||||
dataserver_retrans,
|
||||
mirror->mirror_ds->ds_versions[0].version,
|
||||
mirror->mirror_ds->ds_versions[0].minor_version);
|
||||
|
@ -420,11 +421,11 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
|
|||
mirror->mirror_ds->ds_versions[0].wsize = max_payload;
|
||||
goto out;
|
||||
}
|
||||
out_fail:
|
||||
ff_layout_track_ds_error(FF_LAYOUT_FROM_HDR(lseg->pls_layout),
|
||||
mirror, lseg->pls_range.offset,
|
||||
lseg->pls_range.length, NFS4ERR_NXIO,
|
||||
OP_ILLEGAL, GFP_NOIO);
|
||||
out_fail:
|
||||
if (fail_return || !ff_layout_has_available_ds(lseg))
|
||||
pnfs_error_mark_layout_for_return(ino, lseg);
|
||||
ds = NULL;
|
||||
|
|
|
@ -186,6 +186,8 @@ extern struct nfs_server *nfs_clone_server(struct nfs_server *,
|
|||
struct nfs_fh *,
|
||||
struct nfs_fattr *,
|
||||
rpc_authflavor_t);
|
||||
extern bool nfs_client_init_is_complete(const struct nfs_client *clp);
|
||||
extern int nfs_client_init_status(const struct nfs_client *clp);
|
||||
extern int nfs_wait_client_init_complete(const struct nfs_client *clp);
|
||||
extern void nfs_mark_client_ready(struct nfs_client *clp, int state);
|
||||
extern struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv,
|
||||
|
|
|
@ -1023,9 +1023,9 @@ static void nfs4_session_set_rwsize(struct nfs_server *server)
|
|||
server_resp_sz = sess->fc_attrs.max_resp_sz - nfs41_maxread_overhead;
|
||||
server_rqst_sz = sess->fc_attrs.max_rqst_sz - nfs41_maxwrite_overhead;
|
||||
|
||||
if (server->rsize > server_resp_sz)
|
||||
if (!server->rsize || server->rsize > server_resp_sz)
|
||||
server->rsize = server_resp_sz;
|
||||
if (server->wsize > server_rqst_sz)
|
||||
if (!server->wsize || server->wsize > server_rqst_sz)
|
||||
server->wsize = server_rqst_sz;
|
||||
#endif /* CONFIG_NFS_V4_1 */
|
||||
}
|
||||
|
|
|
@ -2258,8 +2258,6 @@ static int nfs4_opendata_access(struct rpc_cred *cred,
|
|||
if ((mask & ~cache.mask & (MAY_READ | MAY_EXEC)) == 0)
|
||||
return 0;
|
||||
|
||||
/* even though OPEN succeeded, access is denied. Close the file */
|
||||
nfs4_close_state(state, fmode);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
|
@ -7427,11 +7425,11 @@ static void nfs4_exchange_id_release(void *data)
|
|||
struct nfs41_exchange_id_data *cdata =
|
||||
(struct nfs41_exchange_id_data *)data;
|
||||
|
||||
nfs_put_client(cdata->args.client);
|
||||
if (cdata->xprt) {
|
||||
xprt_put(cdata->xprt);
|
||||
rpc_clnt_xprt_switch_put(cdata->args.client->cl_rpcclient);
|
||||
}
|
||||
nfs_put_client(cdata->args.client);
|
||||
kfree(cdata->res.impl_id);
|
||||
kfree(cdata->res.server_scope);
|
||||
kfree(cdata->res.server_owner);
|
||||
|
@ -7538,10 +7536,8 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
|
|||
task_setup_data.callback_data = calldata;
|
||||
|
||||
task = rpc_run_task(&task_setup_data);
|
||||
if (IS_ERR(task)) {
|
||||
status = PTR_ERR(task);
|
||||
goto out_impl_id;
|
||||
}
|
||||
if (IS_ERR(task))
|
||||
return PTR_ERR(task);
|
||||
|
||||
if (!xprt) {
|
||||
status = rpc_wait_for_completion_task(task);
|
||||
|
@ -7569,6 +7565,7 @@ out_server_owner:
|
|||
kfree(calldata->res.server_owner);
|
||||
out_calldata:
|
||||
kfree(calldata);
|
||||
nfs_put_client(clp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
|
@ -3942,7 +3942,7 @@ static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap,
|
|||
if (len <= 0)
|
||||
goto out;
|
||||
dprintk("%s: name=%s\n", __func__, group_name->data);
|
||||
return NFS_ATTR_FATTR_OWNER_NAME;
|
||||
return NFS_ATTR_FATTR_GROUP_NAME;
|
||||
} else {
|
||||
len = xdr_stream_decode_opaque_inline(xdr, (void **)&p,
|
||||
XDR_MAX_NETOBJ);
|
||||
|
|
|
@ -367,7 +367,7 @@ void nfs4_pnfs_ds_put(struct nfs4_pnfs_ds *ds);
|
|||
struct nfs4_pnfs_ds *nfs4_pnfs_ds_add(struct list_head *dsaddrs,
|
||||
gfp_t gfp_flags);
|
||||
void nfs4_pnfs_v3_ds_connect_unload(void);
|
||||
void nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,
|
||||
int nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,
|
||||
struct nfs4_deviceid_node *devid, unsigned int timeo,
|
||||
unsigned int retrans, u32 version, u32 minor_version);
|
||||
struct nfs4_pnfs_ds_addr *nfs4_decode_mp_ds_addr(struct net *net,
|
||||
|
|
|
@ -745,15 +745,17 @@ out:
|
|||
/*
|
||||
* Create an rpc connection to the nfs4_pnfs_ds data server.
|
||||
* Currently only supports IPv4 and IPv6 addresses.
|
||||
* If connection fails, make devid unavailable.
|
||||
* If connection fails, make devid unavailable and return a -errno.
|
||||
*/
|
||||
void nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,
|
||||
int nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,
|
||||
struct nfs4_deviceid_node *devid, unsigned int timeo,
|
||||
unsigned int retrans, u32 version, u32 minor_version)
|
||||
{
|
||||
if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) {
|
||||
int err = 0;
|
||||
int err;
|
||||
|
||||
again:
|
||||
err = 0;
|
||||
if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) {
|
||||
if (version == 3) {
|
||||
err = _nfs4_pnfs_v3_ds_connect(mds_srv, ds, timeo,
|
||||
retrans);
|
||||
|
@ -766,12 +768,29 @@ void nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,
|
|||
err = -EPROTONOSUPPORT;
|
||||
}
|
||||
|
||||
if (err)
|
||||
nfs4_mark_deviceid_unavailable(devid);
|
||||
nfs4_clear_ds_conn_bit(ds);
|
||||
} else {
|
||||
nfs4_wait_ds_connect(ds);
|
||||
|
||||
/* what was waited on didn't connect AND didn't mark unavail */
|
||||
if (!ds->ds_clp && !nfs4_test_deviceid_unavailable(devid))
|
||||
goto again;
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point the ds->ds_clp should be ready, but it might have
|
||||
* hit an error.
|
||||
*/
|
||||
if (!err) {
|
||||
if (!ds->ds_clp || !nfs_client_init_is_complete(ds->ds_clp)) {
|
||||
WARN_ON_ONCE(ds->ds_clp ||
|
||||
!nfs4_test_deviceid_unavailable(devid));
|
||||
return -EINVAL;
|
||||
}
|
||||
err = nfs_client_init_status(ds->ds_clp);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs4_pnfs_ds_connect);
|
||||
|
||||
|
|
|
@ -1784,7 +1784,8 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data)
|
|||
(long long)req_offset(req));
|
||||
if (status < 0) {
|
||||
nfs_context_set_write_error(req->wb_context, status);
|
||||
nfs_inode_remove_request(req);
|
||||
if (req->wb_page)
|
||||
nfs_inode_remove_request(req);
|
||||
dprintk_cont(", error = %d\n", status);
|
||||
goto next;
|
||||
}
|
||||
|
@ -1793,7 +1794,8 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data)
|
|||
* returned by the server against all stored verfs. */
|
||||
if (!nfs_write_verifier_cmp(&req->wb_verf, &data->verf.verifier)) {
|
||||
/* We have a match */
|
||||
nfs_inode_remove_request(req);
|
||||
if (req->wb_page)
|
||||
nfs_inode_remove_request(req);
|
||||
dprintk_cont(" OK\n");
|
||||
goto next;
|
||||
}
|
||||
|
|
|
@ -503,7 +503,8 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia,
|
|||
struct ib_cq *sendcq, *recvcq;
|
||||
int rc;
|
||||
|
||||
max_sge = min(ia->ri_device->attrs.max_sge, RPCRDMA_MAX_SEND_SGES);
|
||||
max_sge = min_t(unsigned int, ia->ri_device->attrs.max_sge,
|
||||
RPCRDMA_MAX_SEND_SGES);
|
||||
if (max_sge < RPCRDMA_MIN_SEND_SGES) {
|
||||
pr_warn("rpcrdma: HCA provides only %d send SGEs\n", max_sge);
|
||||
return -ENOMEM;
|
||||
|
|
Загрузка…
Ссылка в новой задаче