mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
NFSD: Add NFSD_CMD_UNLOCK_IP netlink command
The existing write_unlock_ip procfs interface releases NLM file locks held by a specific client IP address, but procfs provides no structured way to extend that operation to other scopes such as revoking NFSv4 state. Add NFSD_CMD_UNLOCK_IP as a dedicated netlink command for releasing NLM locks by client address. The command accepts a binary sockaddr_in or sockaddr_in6 in its address attribute. The handler validates the address family and length, then calls nlmsvc_unlock_all_by_ip() to release matching NLM locks. Because lockd is a single global instance, that call operates across all network namespaces regardless of which namespace the caller inhabits. A separate netlink command for filesystem-scoped unlock is added in a subsequent commit. The nfsd_ctl_unlock_ip tracepoint is updated from string-based address logging to __sockaddr, which stores the binary sockaddr and formats it with %pISpc. This affects both the new netlink path and the existing procfs write_unlock_ip path, giving consistent structured output in both cases. Reviewed-by: Jeff Layton <jlayton@kernel.org> Tested-by: Dai Ngo <dai.ngo@oracle.com> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
parent
0a7c2aa584
commit
978cda83de
|
|
@ -301,6 +301,15 @@ attribute-sets:
|
|||
type: u32
|
||||
enum: cache-type
|
||||
enum-as-flags: true
|
||||
-
|
||||
name: unlock-ip
|
||||
attributes:
|
||||
-
|
||||
name: address
|
||||
type: binary
|
||||
doc: struct sockaddr_in or struct sockaddr_in6.
|
||||
checks:
|
||||
min-len: 16
|
||||
|
||||
operations:
|
||||
list:
|
||||
|
|
@ -455,6 +464,15 @@ operations:
|
|||
request:
|
||||
attributes:
|
||||
- mask
|
||||
-
|
||||
name: unlock-ip
|
||||
doc: release NLM locks held by an IP address
|
||||
attribute-set: unlock-ip
|
||||
flags: [admin-perm]
|
||||
do:
|
||||
request:
|
||||
attributes:
|
||||
- address
|
||||
|
||||
mcast-groups:
|
||||
list:
|
||||
|
|
|
|||
|
|
@ -103,6 +103,11 @@ static const struct nla_policy nfsd_cache_flush_nl_policy[NFSD_A_CACHE_FLUSH_MAS
|
|||
[NFSD_A_CACHE_FLUSH_MASK] = NLA_POLICY_MASK(NLA_U32, 0x3),
|
||||
};
|
||||
|
||||
/* NFSD_CMD_UNLOCK_IP - do */
|
||||
static const struct nla_policy nfsd_unlock_ip_nl_policy[NFSD_A_UNLOCK_IP_ADDRESS + 1] = {
|
||||
[NFSD_A_UNLOCK_IP_ADDRESS] = NLA_POLICY_MIN_LEN(16),
|
||||
};
|
||||
|
||||
/* Ops table for nfsd */
|
||||
static const struct genl_split_ops nfsd_nl_ops[] = {
|
||||
{
|
||||
|
|
@ -189,6 +194,13 @@ static const struct genl_split_ops nfsd_nl_ops[] = {
|
|||
.maxattr = NFSD_A_CACHE_FLUSH_MASK,
|
||||
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
|
||||
},
|
||||
{
|
||||
.cmd = NFSD_CMD_UNLOCK_IP,
|
||||
.doit = nfsd_nl_unlock_ip_doit,
|
||||
.policy = nfsd_unlock_ip_nl_policy,
|
||||
.maxattr = NFSD_A_UNLOCK_IP_ADDRESS,
|
||||
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct genl_multicast_group nfsd_nl_mcgrps[] = {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ int nfsd_nl_expkey_get_reqs_dumpit(struct sk_buff *skb,
|
|||
struct netlink_callback *cb);
|
||||
int nfsd_nl_expkey_set_reqs_doit(struct sk_buff *skb, struct genl_info *info);
|
||||
int nfsd_nl_cache_flush_doit(struct sk_buff *skb, struct genl_info *info);
|
||||
int nfsd_nl_unlock_ip_doit(struct sk_buff *skb, struct genl_info *info);
|
||||
|
||||
enum {
|
||||
NFSD_NLGRP_NONE,
|
||||
|
|
|
|||
|
|
@ -247,7 +247,7 @@ static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
|
|||
if (rpc_pton(net, fo_path, size, sap, salen) == 0)
|
||||
return -EINVAL;
|
||||
|
||||
trace_nfsd_ctl_unlock_ip(net, buf);
|
||||
trace_nfsd_ctl_unlock_ip(net, sap, svc_addr_len(sap));
|
||||
return nlmsvc_unlock_all_by_ip(sap);
|
||||
}
|
||||
|
||||
|
|
@ -2276,6 +2276,44 @@ int nfsd_cache_notify(struct cache_detail *cd, struct cache_head *h, u32 cache_t
|
|||
NFSD_NLGRP_EXPORTD, GFP_KERNEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* nfsd_nl_unlock_ip_doit - release NLM locks held by an IP address
|
||||
* @skb: reply buffer
|
||||
* @info: netlink metadata and command arguments
|
||||
*
|
||||
* Return: 0 on success or a negative errno.
|
||||
*/
|
||||
int nfsd_nl_unlock_ip_doit(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct sockaddr *sap;
|
||||
|
||||
if (GENL_REQ_ATTR_CHECK(info, NFSD_A_UNLOCK_IP_ADDRESS))
|
||||
return -EINVAL;
|
||||
sap = nla_data(info->attrs[NFSD_A_UNLOCK_IP_ADDRESS]);
|
||||
switch (sap->sa_family) {
|
||||
case AF_INET:
|
||||
if (nla_len(info->attrs[NFSD_A_UNLOCK_IP_ADDRESS]) <
|
||||
sizeof(struct sockaddr_in))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (nla_len(info->attrs[NFSD_A_UNLOCK_IP_ADDRESS]) <
|
||||
sizeof(struct sockaddr_in6))
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
/*
|
||||
* nlmsvc_unlock_all_by_ip() releases matching locks
|
||||
* across all network namespaces because lockd operates
|
||||
* a single global instance.
|
||||
*/
|
||||
trace_nfsd_ctl_unlock_ip(genl_info_net(info), sap,
|
||||
svc_addr_len(sap));
|
||||
return nlmsvc_unlock_all_by_ip(sap);
|
||||
}
|
||||
|
||||
/**
|
||||
* nfsd_net_init - Prepare the nfsd_net portion of a new net namespace
|
||||
* @net: a freshly-created network namespace
|
||||
|
|
|
|||
|
|
@ -1985,19 +1985,20 @@ TRACE_EVENT(nfsd_cb_recall_any_done,
|
|||
TRACE_EVENT(nfsd_ctl_unlock_ip,
|
||||
TP_PROTO(
|
||||
const struct net *net,
|
||||
const char *address
|
||||
const struct sockaddr *addr,
|
||||
const unsigned int addrlen
|
||||
),
|
||||
TP_ARGS(net, address),
|
||||
TP_ARGS(net, addr, addrlen),
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, netns_ino)
|
||||
__string(address, address)
|
||||
__sockaddr(addr, addrlen)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->netns_ino = net->ns.inum;
|
||||
__assign_str(address);
|
||||
__assign_sockaddr(addr, addr, addrlen);
|
||||
),
|
||||
TP_printk("address=%s",
|
||||
__get_str(address)
|
||||
TP_printk("addr=%pISpc",
|
||||
__get_sockaddr(addr)
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -204,6 +204,13 @@ enum {
|
|||
NFSD_A_CACHE_FLUSH_MAX = (__NFSD_A_CACHE_FLUSH_MAX - 1)
|
||||
};
|
||||
|
||||
enum {
|
||||
NFSD_A_UNLOCK_IP_ADDRESS = 1,
|
||||
|
||||
__NFSD_A_UNLOCK_IP_MAX,
|
||||
NFSD_A_UNLOCK_IP_MAX = (__NFSD_A_UNLOCK_IP_MAX - 1)
|
||||
};
|
||||
|
||||
enum {
|
||||
NFSD_CMD_RPC_STATUS_GET = 1,
|
||||
NFSD_CMD_THREADS_SET,
|
||||
|
|
@ -220,6 +227,7 @@ enum {
|
|||
NFSD_CMD_EXPKEY_GET_REQS,
|
||||
NFSD_CMD_EXPKEY_SET_REQS,
|
||||
NFSD_CMD_CACHE_FLUSH,
|
||||
NFSD_CMD_UNLOCK_IP,
|
||||
|
||||
__NFSD_CMD_MAX,
|
||||
NFSD_CMD_MAX = (__NFSD_CMD_MAX - 1)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user