All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lorenzo Bianconi <lorenzo@kernel.org>
To: Jeff Layton <jlayton@kernel.org>
Cc: linux-nfs@vger.kernel.org, lorenzo.bianconi@redhat.com,
	neilb@suse.de, kuba@kernel.org, chuck.lever@oracle.com,
	horms@kernel.org, netdev@vger.kernel.org
Subject: Re: [PATCH v6 3/3] NFSD: add write_ports to netlink command
Date: Mon, 22 Jan 2024 16:59:59 +0100	[thread overview]
Message-ID: <Za6Q_2pNve5BrrhM@lore-desk> (raw)
In-Reply-To: <307cd36ead20741667418fae6bf921ce44f891ea.camel@kernel.org>

[-- Attachment #1: Type: text/plain, Size: 16836 bytes --]

[...]
> > > 
> > > I'm not sure this is safe. Can anything else modify sv_permsocks while
> > > you're not holding the lock? Maybe not since you're holding the
> > > nfsd_mutex, but it's still probably best to restart the list walk if you
> > > have to drop the lock here.
> > > 
> > > You're typically only going to have a few sockets here anyway -- usually
> > > just one each for TCP, UDP and maybe RDMA.
> > 
> > what about beeing a bit proactive and set XPT_CLOSE bit before releasing the
> > spinlock (as we already do in svc_xprt_close)?
> > 
> 
> That does sound better, actually. You might have to open-code parts of
> svc_xprt_close, but it's not that big anyway.

or even just set XPT_CLOSE before releasing the spinlock since svc_xprt_close()
will not be affected anyway and we are not in the hotpath.

Regards,
Lorenzo

> 
> 
> > > 
> > > 
> > > > +			spin_lock_bh(&serv->sv_lock);
> > > > +		}
> > > > +	}
> > > > +	spin_unlock_bh(&serv->sv_lock);
> > > > +
> > > > +	if (!serv->sv_nrthreads && list_empty(&nn->nfsd_serv->sv_permsocks))
> > > > +		nfsd_destroy_serv(net);
> > > > +
> > > > +	mutex_unlock(&nfsd_mutex);
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +/**
> > > > + * nfsd_nl_listener_get_doit - get the nfs running listeners
> > > > + * @skb: reply buffer
> > > > + * @info: netlink metadata and command arguments
> > > > + *
> > > > + * Return 0 on success or a negative errno.
> > > > + */
> > > > +int nfsd_nl_listener_get_doit(struct sk_buff *skb, struct genl_info *info)
> > > > +{
> > > > +	struct svc_xprt *xprt;
> > > > +	struct svc_serv *serv;
> > > > +	struct nfsd_net *nn;
> > > > +	void *hdr;
> > > > +	int err;
> > > > +
> > > > +	skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
> > > > +	if (!skb)
> > > > +		return -ENOMEM;
> > > > +
> > > > +	hdr = genlmsg_iput(skb, info);
> > > > +	if (!hdr) {
> > > > +		err = -EMSGSIZE;
> > > > +		goto err_free_msg;
> > > > +	}
> > > > +
> > > > +	mutex_lock(&nfsd_mutex);
> > > > +	nn = net_generic(genl_info_net(info), nfsd_net_id);
> > > > +	if (!nn->nfsd_serv) {
> > > > +		err = -EINVAL;
> > > > +		goto err_nfsd_unlock;
> > > > +	}
> > > > +
> > > > +	serv = nn->nfsd_serv;
> > > > +	spin_lock_bh(&serv->sv_lock);
> > > > +	list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) {
> > > > +		struct nlattr *attr;
> > > > +
> > > > +		attr = nla_nest_start_noflag(skb,
> > > > +					     NFSD_A_SERVER_LISTENER_INSTANCE);
> > > > +		if (!attr) {
> > > > +			err = -EINVAL;
> > > > +			goto err_serv_unlock;
> > > > +		}
> > > > +
> > > > +		if (nla_put_string(skb, NFSD_A_SERVER_INSTANCE_TRANSPORT_NAME,
> > > > +				   xprt->xpt_class->xcl_name) ||
> > > > +		    nla_put_u32(skb, NFSD_A_SERVER_INSTANCE_PORT,
> > > > +				svc_xprt_local_port(xprt)) ||
> > > > +		    nla_put_u16(skb, NFSD_A_SERVER_INSTANCE_INET_PROTO,
> > > > +				xprt->xpt_local.ss_family)) {
> > > > +			err = -EINVAL;
> > > > +			goto err_serv_unlock;
> > > > +		}
> > > > +
> > > > +		nla_nest_end(skb, attr);
> > > > +	}
> > > > +	spin_unlock_bh(&serv->sv_lock);
> > > > +	mutex_unlock(&nfsd_mutex);
> > > > +
> > > > +	genlmsg_end(skb, hdr);
> > > > +
> > > > +	return genlmsg_reply(skb, info);
> > > > +
> > > > +err_serv_unlock:
> > > > +	spin_unlock_bh(&serv->sv_lock);
> > > > +err_nfsd_unlock:
> > > > +	mutex_unlock(&nfsd_mutex);
> > > > +err_free_msg:
> > > > +	nlmsg_free(skb);
> > > > +
> > > > +	return err;
> > > > +}
> > > > +
> > > >  /**
> > > >   * nfsd_net_init - Prepare the nfsd_net portion of a new net namespace
> > > >   * @net: a freshly-created network namespace
> > > > diff --git a/include/uapi/linux/nfsd_netlink.h b/include/uapi/linux/nfsd_netlink.h
> > > > index 2a06f9fe6fe9..659ab76b8840 100644
> > > > --- a/include/uapi/linux/nfsd_netlink.h
> > > > +++ b/include/uapi/linux/nfsd_netlink.h
> > > > @@ -51,12 +51,30 @@ enum {
> > > >  	NFSD_A_SERVER_PROTO_MAX = (__NFSD_A_SERVER_PROTO_MAX - 1)
> > > >  };
> > > >  
> > > > 
> > > > +enum {
> > > > +	NFSD_A_SERVER_INSTANCE_TRANSPORT_NAME = 1,
> > > > +	NFSD_A_SERVER_INSTANCE_PORT,
> > > > +	NFSD_A_SERVER_INSTANCE_INET_PROTO,
> > > > +
> > > > +	__NFSD_A_SERVER_INSTANCE_MAX,
> > > > +	NFSD_A_SERVER_INSTANCE_MAX = (__NFSD_A_SERVER_INSTANCE_MAX - 1)
> > > > +};
> > > > +
> > > > +enum {
> > > > +	NFSD_A_SERVER_LISTENER_INSTANCE = 1,
> > > > +
> > > > +	__NFSD_A_SERVER_LISTENER_MAX,
> > > > +	NFSD_A_SERVER_LISTENER_MAX = (__NFSD_A_SERVER_LISTENER_MAX - 1)
> > > > +};
> > > > +
> > > >  enum {
> > > >  	NFSD_CMD_RPC_STATUS_GET = 1,
> > > >  	NFSD_CMD_THREADS_SET,
> > > >  	NFSD_CMD_THREADS_GET,
> > > >  	NFSD_CMD_VERSION_SET,
> > > >  	NFSD_CMD_VERSION_GET,
> > > > +	NFSD_CMD_LISTENER_SET,
> > > > +	NFSD_CMD_LISTENER_GET,
> > > >  
> > > > 
> > > >  	__NFSD_CMD_MAX,
> > > >  	NFSD_CMD_MAX = (__NFSD_CMD_MAX - 1)
> > > > diff --git a/tools/net/ynl/generated/nfsd-user.c b/tools/net/ynl/generated/nfsd-user.c
> > > > index ad498543f464..d52f392c7f59 100644
> > > > --- a/tools/net/ynl/generated/nfsd-user.c
> > > > +++ b/tools/net/ynl/generated/nfsd-user.c
> > > > @@ -19,6 +19,8 @@ static const char * const nfsd_op_strmap[] = {
> > > >  	[NFSD_CMD_THREADS_GET] = "threads-get",
> > > >  	[NFSD_CMD_VERSION_SET] = "version-set",
> > > >  	[NFSD_CMD_VERSION_GET] = "version-get",
> > > > +	[NFSD_CMD_LISTENER_SET] = "listener-set",
> > > > +	[NFSD_CMD_LISTENER_GET] = "listener-get",
> > > >  };
> > > >  
> > > > 
> > > >  const char *nfsd_op_str(int op)
> > > > @@ -39,6 +41,17 @@ struct ynl_policy_nest nfsd_nfs_version_nest = {
> > > >  	.table = nfsd_nfs_version_policy,
> > > >  };
> > > >  
> > > > 
> > > > +struct ynl_policy_attr nfsd_server_instance_policy[NFSD_A_SERVER_INSTANCE_MAX + 1] = {
> > > > +	[NFSD_A_SERVER_INSTANCE_TRANSPORT_NAME] = { .name = "transport-name", .type = YNL_PT_NUL_STR, },
> > > > +	[NFSD_A_SERVER_INSTANCE_PORT] = { .name = "port", .type = YNL_PT_U32, },
> > > > +	[NFSD_A_SERVER_INSTANCE_INET_PROTO] = { .name = "inet-proto", .type = YNL_PT_U16, },
> > > > +};
> > > > +
> > > > +struct ynl_policy_nest nfsd_server_instance_nest = {
> > > > +	.max_attr = NFSD_A_SERVER_INSTANCE_MAX,
> > > > +	.table = nfsd_server_instance_policy,
> > > > +};
> > > > +
> > > >  struct ynl_policy_attr nfsd_rpc_status_policy[NFSD_A_RPC_STATUS_MAX + 1] = {
> > > >  	[NFSD_A_RPC_STATUS_XID] = { .name = "xid", .type = YNL_PT_U32, },
> > > >  	[NFSD_A_RPC_STATUS_FLAGS] = { .name = "flags", .type = YNL_PT_U32, },
> > > > @@ -79,6 +92,15 @@ struct ynl_policy_nest nfsd_server_proto_nest = {
> > > >  	.table = nfsd_server_proto_policy,
> > > >  };
> > > >  
> > > > 
> > > > +struct ynl_policy_attr nfsd_server_listener_policy[NFSD_A_SERVER_LISTENER_MAX + 1] = {
> > > > +	[NFSD_A_SERVER_LISTENER_INSTANCE] = { .name = "instance", .type = YNL_PT_NEST, .nest = &nfsd_server_instance_nest, },
> > > > +};
> > > > +
> > > > +struct ynl_policy_nest nfsd_server_listener_nest = {
> > > > +	.max_attr = NFSD_A_SERVER_LISTENER_MAX,
> > > > +	.table = nfsd_server_listener_policy,
> > > > +};
> > > > +
> > > >  /* Common nested types */
> > > >  void nfsd_nfs_version_free(struct nfsd_nfs_version *obj)
> > > >  {
> > > > @@ -124,6 +146,64 @@ int nfsd_nfs_version_parse(struct ynl_parse_arg *yarg,
> > > >  	return 0;
> > > >  }
> > > >  
> > > > 
> > > > +void nfsd_server_instance_free(struct nfsd_server_instance *obj)
> > > > +{
> > > > +	free(obj->transport_name);
> > > > +}
> > > > +
> > > > +int nfsd_server_instance_put(struct nlmsghdr *nlh, unsigned int attr_type,
> > > > +			     struct nfsd_server_instance *obj)
> > > > +{
> > > > +	struct nlattr *nest;
> > > > +
> > > > +	nest = mnl_attr_nest_start(nlh, attr_type);
> > > > +	if (obj->_present.transport_name_len)
> > > > +		mnl_attr_put_strz(nlh, NFSD_A_SERVER_INSTANCE_TRANSPORT_NAME, obj->transport_name);
> > > > +	if (obj->_present.port)
> > > > +		mnl_attr_put_u32(nlh, NFSD_A_SERVER_INSTANCE_PORT, obj->port);
> > > > +	if (obj->_present.inet_proto)
> > > > +		mnl_attr_put_u16(nlh, NFSD_A_SERVER_INSTANCE_INET_PROTO, obj->inet_proto);
> > > > +	mnl_attr_nest_end(nlh, nest);
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +int nfsd_server_instance_parse(struct ynl_parse_arg *yarg,
> > > > +			       const struct nlattr *nested)
> > > > +{
> > > > +	struct nfsd_server_instance *dst = yarg->data;
> > > > +	const struct nlattr *attr;
> > > > +
> > > > +	mnl_attr_for_each_nested(attr, nested) {
> > > > +		unsigned int type = mnl_attr_get_type(attr);
> > > > +
> > > > +		if (type == NFSD_A_SERVER_INSTANCE_TRANSPORT_NAME) {
> > > > +			unsigned int len;
> > > > +
> > > > +			if (ynl_attr_validate(yarg, attr))
> > > > +				return MNL_CB_ERROR;
> > > > +
> > > > +			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
> > > > +			dst->_present.transport_name_len = len;
> > > > +			dst->transport_name = malloc(len + 1);
> > > > +			memcpy(dst->transport_name, mnl_attr_get_str(attr), len);
> > > > +			dst->transport_name[len] = 0;
> > > > +		} else if (type == NFSD_A_SERVER_INSTANCE_PORT) {
> > > > +			if (ynl_attr_validate(yarg, attr))
> > > > +				return MNL_CB_ERROR;
> > > > +			dst->_present.port = 1;
> > > > +			dst->port = mnl_attr_get_u32(attr);
> > > > +		} else if (type == NFSD_A_SERVER_INSTANCE_INET_PROTO) {
> > > > +			if (ynl_attr_validate(yarg, attr))
> > > > +				return MNL_CB_ERROR;
> > > > +			dst->_present.inet_proto = 1;
> > > > +			dst->inet_proto = mnl_attr_get_u16(attr);
> > > > +		}
> > > > +	}
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > >  /* ============== NFSD_CMD_RPC_STATUS_GET ============== */
> > > >  /* NFSD_CMD_RPC_STATUS_GET - dump */
> > > >  int nfsd_rpc_status_get_rsp_dump_parse(const struct nlmsghdr *nlh, void *data)
> > > > @@ -467,6 +547,117 @@ struct nfsd_version_get_rsp *nfsd_version_get(struct ynl_sock *ys)
> > > >  	return NULL;
> > > >  }
> > > >  
> > > > 
> > > > +/* ============== NFSD_CMD_LISTENER_SET ============== */
> > > > +/* NFSD_CMD_LISTENER_SET - do */
> > > > +void nfsd_listener_set_req_free(struct nfsd_listener_set_req *req)
> > > > +{
> > > > +	unsigned int i;
> > > > +
> > > > +	for (i = 0; i < req->n_instance; i++)
> > > > +		nfsd_server_instance_free(&req->instance[i]);
> > > > +	free(req->instance);
> > > > +	free(req);
> > > > +}
> > > > +
> > > > +int nfsd_listener_set(struct ynl_sock *ys, struct nfsd_listener_set_req *req)
> > > > +{
> > > > +	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
> > > > +	struct nlmsghdr *nlh;
> > > > +	int err;
> > > > +
> > > > +	nlh = ynl_gemsg_start_req(ys, ys->family_id, NFSD_CMD_LISTENER_SET, 1);
> > > > +	ys->req_policy = &nfsd_server_listener_nest;
> > > > +
> > > > +	for (unsigned int i = 0; i < req->n_instance; i++)
> > > > +		nfsd_server_instance_put(nlh, NFSD_A_SERVER_LISTENER_INSTANCE, &req->instance[i]);
> > > > +
> > > > +	err = ynl_exec(ys, nlh, &yrs);
> > > > +	if (err < 0)
> > > > +		return -1;
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +/* ============== NFSD_CMD_LISTENER_GET ============== */
> > > > +/* NFSD_CMD_LISTENER_GET - do */
> > > > +void nfsd_listener_get_rsp_free(struct nfsd_listener_get_rsp *rsp)
> > > > +{
> > > > +	unsigned int i;
> > > > +
> > > > +	for (i = 0; i < rsp->n_instance; i++)
> > > > +		nfsd_server_instance_free(&rsp->instance[i]);
> > > > +	free(rsp->instance);
> > > > +	free(rsp);
> > > > +}
> > > > +
> > > > +int nfsd_listener_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
> > > > +{
> > > > +	struct nfsd_listener_get_rsp *dst;
> > > > +	struct ynl_parse_arg *yarg = data;
> > > > +	unsigned int n_instance = 0;
> > > > +	const struct nlattr *attr;
> > > > +	struct ynl_parse_arg parg;
> > > > +	int i;
> > > > +
> > > > +	dst = yarg->data;
> > > > +	parg.ys = yarg->ys;
> > > > +
> > > > +	if (dst->instance)
> > > > +		return ynl_error_parse(yarg, "attribute already present (server-listener.instance)");
> > > > +
> > > > +	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
> > > > +		unsigned int type = mnl_attr_get_type(attr);
> > > > +
> > > > +		if (type == NFSD_A_SERVER_LISTENER_INSTANCE) {
> > > > +			n_instance++;
> > > > +		}
> > > > +	}
> > > > +
> > > > +	if (n_instance) {
> > > > +		dst->instance = calloc(n_instance, sizeof(*dst->instance));
> > > > +		dst->n_instance = n_instance;
> > > > +		i = 0;
> > > > +		parg.rsp_policy = &nfsd_server_instance_nest;
> > > > +		mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
> > > > +			if (mnl_attr_get_type(attr) == NFSD_A_SERVER_LISTENER_INSTANCE) {
> > > > +				parg.data = &dst->instance[i];
> > > > +				if (nfsd_server_instance_parse(&parg, attr))
> > > > +					return MNL_CB_ERROR;
> > > > +				i++;
> > > > +			}
> > > > +		}
> > > > +	}
> > > > +
> > > > +	return MNL_CB_OK;
> > > > +}
> > > > +
> > > > +struct nfsd_listener_get_rsp *nfsd_listener_get(struct ynl_sock *ys)
> > > > +{
> > > > +	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
> > > > +	struct nfsd_listener_get_rsp *rsp;
> > > > +	struct nlmsghdr *nlh;
> > > > +	int err;
> > > > +
> > > > +	nlh = ynl_gemsg_start_req(ys, ys->family_id, NFSD_CMD_LISTENER_GET, 1);
> > > > +	ys->req_policy = &nfsd_server_listener_nest;
> > > > +	yrs.yarg.rsp_policy = &nfsd_server_listener_nest;
> > > > +
> > > > +	rsp = calloc(1, sizeof(*rsp));
> > > > +	yrs.yarg.data = rsp;
> > > > +	yrs.cb = nfsd_listener_get_rsp_parse;
> > > > +	yrs.rsp_cmd = NFSD_CMD_LISTENER_GET;
> > > > +
> > > > +	err = ynl_exec(ys, nlh, &yrs);
> > > > +	if (err < 0)
> > > > +		goto err_free;
> > > > +
> > > > +	return rsp;
> > > > +
> > > > +err_free:
> > > > +	nfsd_listener_get_rsp_free(rsp);
> > > > +	return NULL;
> > > > +}
> > > > +
> > > >  const struct ynl_family ynl_nfsd_family =  {
> > > >  	.name		= "nfsd",
> > > >  };
> > > > diff --git a/tools/net/ynl/generated/nfsd-user.h b/tools/net/ynl/generated/nfsd-user.h
> > > > index d062ee8fa8b6..5765fb6f2ef5 100644
> > > > --- a/tools/net/ynl/generated/nfsd-user.h
> > > > +++ b/tools/net/ynl/generated/nfsd-user.h
> > > > @@ -29,6 +29,18 @@ struct nfsd_nfs_version {
> > > >  	__u32 minor;
> > > >  };
> > > >  
> > > > 
> > > > +struct nfsd_server_instance {
> > > > +	struct {
> > > > +		__u32 transport_name_len;
> > > > +		__u32 port:1;
> > > > +		__u32 inet_proto:1;
> > > > +	} _present;
> > > > +
> > > > +	char *transport_name;
> > > > +	__u32 port;
> > > > +	__u16 inet_proto;
> > > > +};
> > > > +
> > > >  /* ============== NFSD_CMD_RPC_STATUS_GET ============== */
> > > >  /* NFSD_CMD_RPC_STATUS_GET - dump */
> > > >  struct nfsd_rpc_status_get_rsp_dump {
> > > > @@ -164,4 +176,47 @@ void nfsd_version_get_rsp_free(struct nfsd_version_get_rsp *rsp);
> > > >   */
> > > >  struct nfsd_version_get_rsp *nfsd_version_get(struct ynl_sock *ys);
> > > >  
> > > > 
> > > > +/* ============== NFSD_CMD_LISTENER_SET ============== */
> > > > +/* NFSD_CMD_LISTENER_SET - do */
> > > > +struct nfsd_listener_set_req {
> > > > +	unsigned int n_instance;
> > > > +	struct nfsd_server_instance *instance;
> > > > +};
> > > > +
> > > > +static inline struct nfsd_listener_set_req *nfsd_listener_set_req_alloc(void)
> > > > +{
> > > > +	return calloc(1, sizeof(struct nfsd_listener_set_req));
> > > > +}
> > > > +void nfsd_listener_set_req_free(struct nfsd_listener_set_req *req);
> > > > +
> > > > +static inline void
> > > > +__nfsd_listener_set_req_set_instance(struct nfsd_listener_set_req *req,
> > > > +				     struct nfsd_server_instance *instance,
> > > > +				     unsigned int n_instance)
> > > > +{
> > > > +	free(req->instance);
> > > > +	req->instance = instance;
> > > > +	req->n_instance = n_instance;
> > > > +}
> > > > +
> > > > +/*
> > > > + * set nfs running listeners
> > > > + */
> > > > +int nfsd_listener_set(struct ynl_sock *ys, struct nfsd_listener_set_req *req);
> > > > +
> > > > +/* ============== NFSD_CMD_LISTENER_GET ============== */
> > > > +/* NFSD_CMD_LISTENER_GET - do */
> > > > +
> > > > +struct nfsd_listener_get_rsp {
> > > > +	unsigned int n_instance;
> > > > +	struct nfsd_server_instance *instance;
> > > > +};
> > > > +
> > > > +void nfsd_listener_get_rsp_free(struct nfsd_listener_get_rsp *rsp);
> > > > +
> > > > +/*
> > > > + * get nfs running listeners
> > > > + */
> > > > +struct nfsd_listener_get_rsp *nfsd_listener_get(struct ynl_sock *ys);
> > > > +
> > > >  #endif /* _LINUX_NFSD_GEN_H */
> > > 
> > > -- 
> > > Jeff Layton <jlayton@kernel.org>
> > > 
> 
> -- 
> Jeff Layton <jlayton@kernel.org>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

  reply	other threads:[~2024-01-22 16:00 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-20 17:33 [PATCH v6 0/3] convert write_threads, write_version and write_ports to netlink commands Lorenzo Bianconi
2024-01-20 17:33 ` [PATCH v6 1/3] NFSD: convert write_threads to netlink command Lorenzo Bianconi
2024-01-20 17:33 ` [PATCH v6 2/3] NFSD: add write_version " Lorenzo Bianconi
2024-01-22 13:27   ` Jeff Layton
2024-01-20 17:33 ` [PATCH v6 3/3] NFSD: add write_ports " Lorenzo Bianconi
2024-01-22 13:41   ` Jeff Layton
2024-01-22 15:35     ` Lorenzo Bianconi
2024-01-22 15:50       ` Jeff Layton
2024-01-22 15:59         ` Lorenzo Bianconi [this message]
2024-01-22 21:35     ` NeilBrown
2024-01-22 21:37       ` Jeff Layton
2024-01-22 22:58       ` Chuck Lever
2024-01-23  9:59         ` Lorenzo Bianconi
2024-01-23 11:17           ` Jeff Layton
2024-01-23 13:21             ` Lorenzo Bianconi
2024-01-23 14:28               ` Jeff Layton
2024-01-24  9:52                 ` Lorenzo Bianconi
2024-01-24 11:24                   ` Jeff Layton
2024-01-24 13:55                     ` Chuck Lever III
2024-01-24 18:10                       ` Jeff Layton
2024-01-25 22:44                       ` NeilBrown
2024-01-26  2:38                         ` Chuck Lever III
2024-01-26  7:27                           ` NeilBrown
2024-01-26 13:58                         ` Chuck Lever III
2024-01-22 16:31   ` kernel test robot
2024-01-22 13:49 ` [PATCH v6 0/3] convert write_threads, write_version and write_ports to netlink commands Jeff Layton
2024-01-22 17:01   ` Lorenzo Bianconi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Za6Q_2pNve5BrrhM@lore-desk \
    --to=lorenzo@kernel.org \
    --cc=chuck.lever@oracle.com \
    --cc=horms@kernel.org \
    --cc=jlayton@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=lorenzo.bianconi@redhat.com \
    --cc=neilb@suse.de \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.