mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 03:27:30 -04:00
nfsd: add NFSD_CMD_CACHE_FLUSH netlink command
Add a new NFSD_CMD_CACHE_FLUSH generic netlink command that allows userspace to flush the nfsd export caches (svc_export and expkey) without writing to /proc/net/rpc/*/flush. An optional NFSD_A_CACHE_FLUSH_MASK u32 attribute selects which caches to flush (bit 1 = svc_export, bit 2 = expkey). If the attribute is omitted, all nfsd caches are flushed. This is used by exportfs to replace its /proc-based cache_flush() with a netlink equivalent, with /proc fallback for older kernels. Signed-off-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
@@ -293,6 +293,14 @@ attribute-sets:
|
||||
type: nest
|
||||
nested-attributes: expkey
|
||||
multi-attr: true
|
||||
-
|
||||
name: cache-flush
|
||||
attributes:
|
||||
-
|
||||
name: mask
|
||||
type: u32
|
||||
enum: cache-type
|
||||
enum-as-flags: true
|
||||
|
||||
operations:
|
||||
list:
|
||||
@@ -438,6 +446,15 @@ operations:
|
||||
request:
|
||||
attributes:
|
||||
- requests
|
||||
-
|
||||
name: cache-flush
|
||||
doc: Flush nfsd caches (svc_export and/or expkey)
|
||||
attribute-set: cache-flush
|
||||
flags: [admin-perm]
|
||||
do:
|
||||
request:
|
||||
attributes:
|
||||
- mask
|
||||
|
||||
mcast-groups:
|
||||
list:
|
||||
|
||||
@@ -108,6 +108,11 @@ static const struct nla_policy nfsd_expkey_set_reqs_nl_policy[NFSD_A_EXPKEY_REQS
|
||||
[NFSD_A_EXPKEY_REQS_REQUESTS] = NLA_POLICY_NESTED(nfsd_expkey_nl_policy),
|
||||
};
|
||||
|
||||
/* NFSD_CMD_CACHE_FLUSH - do */
|
||||
static const struct nla_policy nfsd_cache_flush_nl_policy[NFSD_A_CACHE_FLUSH_MASK + 1] = {
|
||||
[NFSD_A_CACHE_FLUSH_MASK] = NLA_POLICY_MASK(NLA_U32, 0x3),
|
||||
};
|
||||
|
||||
/* Ops table for nfsd */
|
||||
static const struct genl_split_ops nfsd_nl_ops[] = {
|
||||
{
|
||||
@@ -191,6 +196,13 @@ static const struct genl_split_ops nfsd_nl_ops[] = {
|
||||
.maxattr = NFSD_A_EXPKEY_REQS_REQUESTS,
|
||||
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
|
||||
},
|
||||
{
|
||||
.cmd = NFSD_CMD_CACHE_FLUSH,
|
||||
.doit = nfsd_nl_cache_flush_doit,
|
||||
.policy = nfsd_cache_flush_nl_policy,
|
||||
.maxattr = NFSD_A_CACHE_FLUSH_MASK,
|
||||
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct genl_multicast_group nfsd_nl_mcgrps[] = {
|
||||
|
||||
@@ -38,6 +38,7 @@ int nfsd_nl_svc_export_set_reqs_doit(struct sk_buff *skb,
|
||||
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);
|
||||
|
||||
enum {
|
||||
NFSD_NLGRP_NONE,
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/fs_context.h>
|
||||
|
||||
#include <linux/sunrpc/cache.h>
|
||||
#include <linux/sunrpc/svcsock.h>
|
||||
#include <linux/lockd/bind.h>
|
||||
#include <linux/sunrpc/addr.h>
|
||||
@@ -2212,6 +2213,41 @@ int nfsd_nl_pool_mode_get_doit(struct sk_buff *skb, struct genl_info *info)
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* nfsd_nl_cache_flush_doit - flush nfsd caches via netlink
|
||||
* @skb: reply buffer
|
||||
* @info: netlink metadata and command arguments
|
||||
*
|
||||
* Flush the svc_export and/or expkey caches. If NFSD_A_CACHE_FLUSH_MASK
|
||||
* is provided, only flush the caches indicated by the bitmask (bit 0 =
|
||||
* svc_export, bit 1 = expkey). If omitted, flush both.
|
||||
*
|
||||
* Return 0 on success or a negative errno.
|
||||
*/
|
||||
int nfsd_nl_cache_flush_doit(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct net *net = genl_info_net(info);
|
||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||
u32 mask = ~0U;
|
||||
|
||||
if (info->attrs[NFSD_A_CACHE_FLUSH_MASK])
|
||||
mask = nla_get_u32(info->attrs[NFSD_A_CACHE_FLUSH_MASK]);
|
||||
|
||||
mutex_lock(&nfsd_mutex);
|
||||
|
||||
if ((mask & NFSD_CACHE_TYPE_SVC_EXPORT) &&
|
||||
nn->svc_export_cache)
|
||||
cache_purge(nn->svc_export_cache);
|
||||
|
||||
if ((mask & NFSD_CACHE_TYPE_EXPKEY) &&
|
||||
nn->svc_expkey_cache)
|
||||
cache_purge(nn->svc_expkey_cache);
|
||||
|
||||
mutex_unlock(&nfsd_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfsd_cache_notify(struct cache_detail *cd, struct cache_head *h, u32 cache_type)
|
||||
{
|
||||
struct genlmsghdr *hdr;
|
||||
|
||||
@@ -197,6 +197,13 @@ enum {
|
||||
NFSD_A_EXPKEY_REQS_MAX = (__NFSD_A_EXPKEY_REQS_MAX - 1)
|
||||
};
|
||||
|
||||
enum {
|
||||
NFSD_A_CACHE_FLUSH_MASK = 1,
|
||||
|
||||
__NFSD_A_CACHE_FLUSH_MAX,
|
||||
NFSD_A_CACHE_FLUSH_MAX = (__NFSD_A_CACHE_FLUSH_MAX - 1)
|
||||
};
|
||||
|
||||
enum {
|
||||
NFSD_CMD_RPC_STATUS_GET = 1,
|
||||
NFSD_CMD_THREADS_SET,
|
||||
@@ -212,6 +219,7 @@ enum {
|
||||
NFSD_CMD_SVC_EXPORT_SET_REQS,
|
||||
NFSD_CMD_EXPKEY_GET_REQS,
|
||||
NFSD_CMD_EXPKEY_SET_REQS,
|
||||
NFSD_CMD_CACHE_FLUSH,
|
||||
|
||||
__NFSD_CMD_MAX,
|
||||
NFSD_CMD_MAX = (__NFSD_CMD_MAX - 1)
|
||||
|
||||
Reference in New Issue
Block a user