mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
NFS Client Bugfixes for Linux 6.12-rc
Localio Bugfixes: * Remove duplicated include in localio.c * Fix race in NFS calls to nfsd_file_put_local() and nfsd_serv_put() * Fix Kconfig for NFS_COMMON_LOCALIO_SUPPORT * Fix nfsd_file tracepoints to handle NULL rqstp pointers Other Bugfixes: * Fix program selection loop in svc_process_common * Fix integer overflow in decode_rc_list() * Prevent NULL-pointer dereference in nfs42_complete_copies() * Fix CB_RECALL performance issues when using a large number of delegations -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEnZ5MQTpR7cLU7KEp18tUv7ClQOsFAmcJjjQACgkQ18tUv7Cl QOvgJw/6A33s+pjyBVLIKT6oMCPkUJeQ4Rhg9Je0Qw/ji0eFkT4Eyd65kRz3T9M/ qRrCfWaUd2dTYcbKQyhuGTlEfICZa9R4I0/Ztk9yvf9xcd1xFXKzTkFekGUVeHQA OcngDu9psFxhvyzKI8nAHs1ephX/T7TywvTKANMRbeRCYYvVkytAt9YeVMigYZa5 dnchoUdGUdL6B6RXCU/Qhf0A1uYyA4hkk/FTBCPgv+kYx5pnjFq0y/yIIHDzCR3I +yE1ss3EpVTQgt2Ca/cmDyYXsa7G8G51U7cS5AeIoXfsf1EGtTujowWcBY4oqFEC ixx58fQe48AqwsP5XDZn8gnsuYH9snnw5rIB0IVqq55/a+XLMupHayyf/iziMV3s JWgT4gKDyFca2pT+bJ8iWweU+ecRYxKGnh2NydyBiqowogsHZm4uKh0vELvqqkBd RIjCyIiQVhYBII2jqpjRnxrqhGUT5XO99NQdQIGV0bUjCEP4YAjY4ChfEVcWXhnB ppyBP+r8N5O77NcVqsVQS26U0/jb9K30LyYl9VT43ank3d+VVtHA5ZqnUflWtwuc 2XiGDvXW9mIvbVraWIZXUNVy39bzRclDf5bx4jeYLnKCMym81rkEIBOvBKQKZTrl v+1Nhaj+fSw+rFSUm0KPqms0UDiT0Ol7ltu84ifadYqubbSEbqU= =QBvR -----END PGP SIGNATURE----- Merge tag 'nfs-for-6.12-2' of git://git.linux-nfs.org/projects/anna/linux-nfs Pull NFS client fixes from Anna Schumaker: "Localio Bugfixes: - remove duplicated include in localio.c - fix race in NFS calls to nfsd_file_put_local() and nfsd_serv_put() - fix Kconfig for NFS_COMMON_LOCALIO_SUPPORT - fix nfsd_file tracepoints to handle NULL rqstp pointers Other Bugfixes: - fix program selection loop in svc_process_common - fix integer overflow in decode_rc_list() - prevent NULL-pointer dereference in nfs42_complete_copies() - fix CB_RECALL performance issues when using a large number of delegations" * tag 'nfs-for-6.12-2' of git://git.linux-nfs.org/projects/anna/linux-nfs: NFS: remove revoked delegation from server's delegation list nfsd/localio: fix nfsd_file tracepoints to handle NULL rqstp nfs_common: fix Kconfig for NFS_COMMON_LOCALIO_SUPPORT nfs_common: fix race in NFS calls to nfsd_file_put_local() and nfsd_serv_put() NFSv4: Prevent NULL-pointer dereference in nfs42_complete_copies() SUNRPC: Fix integer overflow in decode_rc_list() sunrpc: fix prog selection loop in svc_process_common nfs: Remove duplicated include in localio.c
This commit is contained in:
commit
6254d53727
@ -388,7 +388,7 @@ config NFS_COMMON
|
||||
|
||||
config NFS_COMMON_LOCALIO_SUPPORT
|
||||
tristate
|
||||
default n
|
||||
depends on NFS_LOCALIO
|
||||
default y if NFSD=y || NFS_FS=y
|
||||
default m if NFSD=m && NFS_FS=m
|
||||
select SUNRPC
|
||||
|
@ -375,6 +375,8 @@ static __be32 decode_rc_list(struct xdr_stream *xdr,
|
||||
|
||||
rc_list->rcl_nrefcalls = ntohl(*p++);
|
||||
if (rc_list->rcl_nrefcalls) {
|
||||
if (unlikely(rc_list->rcl_nrefcalls > xdr->buf->len))
|
||||
goto out;
|
||||
p = xdr_inline_decode(xdr,
|
||||
rc_list->rcl_nrefcalls * 2 * sizeof(uint32_t));
|
||||
if (unlikely(p == NULL))
|
||||
|
@ -996,6 +996,7 @@ struct nfs_server *nfs_alloc_server(void)
|
||||
INIT_LIST_HEAD(&server->layouts);
|
||||
INIT_LIST_HEAD(&server->state_owners_lru);
|
||||
INIT_LIST_HEAD(&server->ss_copies);
|
||||
INIT_LIST_HEAD(&server->ss_src_copies);
|
||||
|
||||
atomic_set(&server->active, 0);
|
||||
|
||||
|
@ -1001,6 +1001,11 @@ void nfs_delegation_mark_returned(struct inode *inode,
|
||||
}
|
||||
|
||||
nfs_mark_delegation_revoked(delegation);
|
||||
clear_bit(NFS_DELEGATION_RETURNING, &delegation->flags);
|
||||
spin_unlock(&delegation->lock);
|
||||
if (nfs_detach_delegation(NFS_I(inode), delegation, NFS_SERVER(inode)))
|
||||
nfs_put_delegation(delegation);
|
||||
goto out_rcu_unlock;
|
||||
|
||||
out_clear_returning:
|
||||
clear_bit(NFS_DELEGATION_RETURNING, &delegation->flags);
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include <net/addrconf.h>
|
||||
#include <linux/nfs_common.h>
|
||||
#include <linux/nfslocalio.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/bvec.h>
|
||||
|
||||
#include <linux/nfs.h>
|
||||
@ -341,7 +340,7 @@ nfs_local_pgio_release(struct nfs_local_kiocb *iocb)
|
||||
{
|
||||
struct nfs_pgio_header *hdr = iocb->hdr;
|
||||
|
||||
nfs_to->nfsd_file_put_local(iocb->localio);
|
||||
nfs_to_nfsd_file_put_local(iocb->localio);
|
||||
nfs_local_iocb_free(iocb);
|
||||
nfs_local_hdr_release(hdr, hdr->task.tk_ops);
|
||||
}
|
||||
@ -622,7 +621,7 @@ int nfs_local_doio(struct nfs_client *clp, struct nfsd_file *localio,
|
||||
}
|
||||
out:
|
||||
if (status != 0) {
|
||||
nfs_to->nfsd_file_put_local(localio);
|
||||
nfs_to_nfsd_file_put_local(localio);
|
||||
hdr->task.tk_status = status;
|
||||
nfs_local_hdr_release(hdr, call_ops);
|
||||
}
|
||||
@ -673,7 +672,7 @@ nfs_local_release_commit_data(struct nfsd_file *localio,
|
||||
struct nfs_commit_data *data,
|
||||
const struct rpc_call_ops *call_ops)
|
||||
{
|
||||
nfs_to->nfsd_file_put_local(localio);
|
||||
nfs_to_nfsd_file_put_local(localio);
|
||||
call_ops->rpc_call_done(&data->task, data);
|
||||
call_ops->rpc_release(data);
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ static int handle_async_copy(struct nfs42_copy_res *res,
|
||||
|
||||
if (dst_server != src_server) {
|
||||
spin_lock(&src_server->nfs_client->cl_lock);
|
||||
list_add_tail(©->src_copies, &src_server->ss_copies);
|
||||
list_add_tail(©->src_copies, &src_server->ss_src_copies);
|
||||
spin_unlock(&src_server->nfs_client->cl_lock);
|
||||
}
|
||||
|
||||
|
@ -1585,7 +1585,7 @@ static void nfs42_complete_copies(struct nfs4_state_owner *sp, struct nfs4_state
|
||||
complete(©->completion);
|
||||
}
|
||||
}
|
||||
list_for_each_entry(copy, &sp->so_server->ss_copies, src_copies) {
|
||||
list_for_each_entry(copy, &sp->so_server->ss_src_copies, src_copies) {
|
||||
if ((test_bit(NFS_CLNT_SRC_SSC_COPY_STATE, &state->flags) &&
|
||||
!nfs4_stateid_match_other(&state->stateid,
|
||||
©->parent_src_state->stateid)))
|
||||
|
@ -142,8 +142,11 @@ struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *uuid,
|
||||
/* We have an implied reference to net thanks to nfsd_serv_try_get */
|
||||
localio = nfs_to->nfsd_open_local_fh(net, uuid->dom, rpc_clnt,
|
||||
cred, nfs_fh, fmode);
|
||||
if (IS_ERR(localio))
|
||||
if (IS_ERR(localio)) {
|
||||
rcu_read_lock();
|
||||
nfs_to->nfsd_serv_put(net);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
return localio;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_open_local_fh);
|
||||
|
@ -398,7 +398,7 @@ nfsd_file_put(struct nfsd_file *nf)
|
||||
* reference to the associated nn->nfsd_serv.
|
||||
*/
|
||||
void
|
||||
nfsd_file_put_local(struct nfsd_file *nf)
|
||||
nfsd_file_put_local(struct nfsd_file *nf) __must_hold(rcu)
|
||||
{
|
||||
struct net *net = nf->nf_net;
|
||||
|
||||
|
@ -53,7 +53,7 @@ void nfsd_localio_ops_init(void)
|
||||
*
|
||||
* On successful return, returned nfsd_file will have its nf_net member
|
||||
* set. Caller (NFS client) is responsible for calling nfsd_serv_put and
|
||||
* nfsd_file_put (via nfs_to->nfsd_file_put_local).
|
||||
* nfsd_file_put (via nfs_to_nfsd_file_put_local).
|
||||
*/
|
||||
struct nfsd_file *
|
||||
nfsd_open_local_fh(struct net *net, struct auth_domain *dom,
|
||||
|
@ -214,14 +214,14 @@ int nfsd_minorversion(struct nfsd_net *nn, u32 minorversion, enum vers_op change
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool nfsd_serv_try_get(struct net *net)
|
||||
bool nfsd_serv_try_get(struct net *net) __must_hold(rcu)
|
||||
{
|
||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||
|
||||
return (nn && percpu_ref_tryget_live(&nn->nfsd_serv_ref));
|
||||
}
|
||||
|
||||
void nfsd_serv_put(struct net *net)
|
||||
void nfsd_serv_put(struct net *net) __must_hold(rcu)
|
||||
{
|
||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||
|
||||
|
@ -1113,7 +1113,7 @@ TRACE_EVENT(nfsd_file_acquire,
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->xid = be32_to_cpu(rqstp->rq_xid);
|
||||
__entry->xid = rqstp ? be32_to_cpu(rqstp->rq_xid) : 0;
|
||||
__entry->inode = inode;
|
||||
__entry->may_flags = may_flags;
|
||||
__entry->nf_ref = nf ? refcount_read(&nf->nf_ref) : 0;
|
||||
@ -1147,7 +1147,7 @@ TRACE_EVENT(nfsd_file_insert_err,
|
||||
__field(long, error)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->xid = be32_to_cpu(rqstp->rq_xid);
|
||||
__entry->xid = rqstp ? be32_to_cpu(rqstp->rq_xid) : 0;
|
||||
__entry->inode = inode;
|
||||
__entry->may_flags = may_flags;
|
||||
__entry->error = error;
|
||||
@ -1177,7 +1177,7 @@ TRACE_EVENT(nfsd_file_cons_err,
|
||||
__field(const void *, nf_file)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->xid = be32_to_cpu(rqstp->rq_xid);
|
||||
__entry->xid = rqstp ? be32_to_cpu(rqstp->rq_xid) : 0;
|
||||
__entry->inode = inode;
|
||||
__entry->may_flags = may_flags;
|
||||
__entry->nf_ref = refcount_read(&nf->nf_ref);
|
||||
|
@ -249,6 +249,7 @@ struct nfs_server {
|
||||
struct list_head layouts;
|
||||
struct list_head delegations;
|
||||
struct list_head ss_copies;
|
||||
struct list_head ss_src_copies;
|
||||
|
||||
unsigned long delegation_gen;
|
||||
unsigned long mig_gen;
|
||||
|
@ -65,10 +65,25 @@ struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *,
|
||||
struct rpc_clnt *, const struct cred *,
|
||||
const struct nfs_fh *, const fmode_t);
|
||||
|
||||
static inline void nfs_to_nfsd_file_put_local(struct nfsd_file *localio)
|
||||
{
|
||||
/*
|
||||
* Once reference to nfsd_serv is dropped, NFSD could be
|
||||
* unloaded, so ensure safe return from nfsd_file_put_local()
|
||||
* by always taking RCU.
|
||||
*/
|
||||
rcu_read_lock();
|
||||
nfs_to->nfsd_file_put_local(localio);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
#else /* CONFIG_NFS_LOCALIO */
|
||||
static inline void nfsd_localio_ops_init(void)
|
||||
{
|
||||
}
|
||||
static inline void nfs_to_nfsd_file_put_local(struct nfsd_file *localio)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_NFS_LOCALIO */
|
||||
|
||||
#endif /* __LINUX_NFSLOCALIO_H */
|
||||
|
@ -1321,7 +1321,7 @@ static int
|
||||
svc_process_common(struct svc_rqst *rqstp)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct svc_program *progp;
|
||||
struct svc_program *progp = NULL;
|
||||
const struct svc_procedure *procp = NULL;
|
||||
struct svc_serv *serv = rqstp->rq_server;
|
||||
struct svc_process_info process;
|
||||
@ -1351,13 +1351,10 @@ svc_process_common(struct svc_rqst *rqstp)
|
||||
rqstp->rq_vers = be32_to_cpup(p++);
|
||||
rqstp->rq_proc = be32_to_cpup(p);
|
||||
|
||||
for (pr = 0; pr < serv->sv_nprogs; pr++) {
|
||||
for (pr = 0; pr < serv->sv_nprogs; pr++)
|
||||
if (rqstp->rq_prog == serv->sv_programs[pr].pg_prog)
|
||||
progp = &serv->sv_programs[pr];
|
||||
|
||||
if (rqstp->rq_prog == progp->pg_prog)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode auth data, and add verifier to reply buffer.
|
||||
* We do this before anything else in order to get a decent
|
||||
|
Loading…
Reference in New Issue
Block a user