Add a new SUNRPC_CMD_CACHE_FLUSH generic netlink command that allows userspace to flush the sunrpc auth caches (ip_map and unix_gid) without writing to /proc/net/rpc/*/flush. An optional SUNRPC_A_CACHE_FLUSH_MASK u32 attribute selects which caches to flush (bit 1 = ip_map, bit 2 = unix_gid). If the attribute is omitted, all sunrpc 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.
Unified · Split
| @@ -76,6 +76,14 @@ attribute-sets: · 75 unmodified lines | ||
| 76 | 76 | type: nest |
| 77 | 77 | nested-attributes: unix-gid |
| 78 | 78 | multi-attr: true |
| 79 | + - | |
| 80 | + name: cache-flush | |
| 81 | + attributes: | |
| 82 | + - | |
| 83 | + name: mask | |
| 84 | + type: u32 | |
| 85 | + enum: cache-type | |
| 86 | + enum-as-flags: true | |
| 79 | 87 | |
| 80 | 88 | operations: |
| 81 | 89 | list: |
| @@ -123,6 +131,15 @@ operations: · 41 unmodified lines | ||
| 123 | 131 | request: |
| 124 | 132 | attributes: |
| 125 | 133 | - requests |
| 134 | + - | |
| 135 | + name: cache-flush | |
| 136 | + doc: Flush sunrpc caches (ip_map and/or unix_gid) | |
| 137 | + attribute-set: cache-flush | |
| 138 | + flags: [admin-perm] | |
| 139 | + do: | |
| 140 | + request: | |
| 141 | + attributes: | |
| 142 | + - mask | |
| 126 | 143 | |
| 127 | 144 | mcast-groups: |
| 128 | 145 | list: |
| @@ -59,12 +59,20 @@ enum { · 58 unmodified lines | ||
| 59 | 59 | SUNRPC_A_UNIX_GID_REQS_MAX = (__SUNRPC_A_UNIX_GID_REQS_MAX - 1) |
| 60 | 60 | }; |
| 61 | 61 | |
| 62 | +enum { | |
| 63 | + SUNRPC_A_CACHE_FLUSH_MASK = 1, | |
| 64 | + | |
| 65 | + __SUNRPC_A_CACHE_FLUSH_MAX, | |
| 66 | + SUNRPC_A_CACHE_FLUSH_MAX = (__SUNRPC_A_CACHE_FLUSH_MAX - 1) | |
| 67 | +}; | |
| 68 | + | |
| 62 | 69 | enum { |
| 63 | 70 | SUNRPC_CMD_CACHE_NOTIFY = 1, |
| 64 | 71 | SUNRPC_CMD_IP_MAP_GET_REQS, |
| 65 | 72 | SUNRPC_CMD_IP_MAP_SET_REQS, |
| 66 | 73 | SUNRPC_CMD_UNIX_GID_GET_REQS, |
| 67 | 74 | SUNRPC_CMD_UNIX_GID_SET_REQS, |
| 75 | + SUNRPC_CMD_CACHE_FLUSH, | |
| 68 | 76 | |
| 69 | 77 | __SUNRPC_CMD_MAX, |
| 70 | 78 | SUNRPC_CMD_MAX = (__SUNRPC_CMD_MAX - 1) |
| @@ -49,6 +49,11 @@ static const struct nla_policy sunrpc_unix_gid_set_reqs_nl_policy[SUNRPC_A_UNIX_ · 48 unmodified lines | ||
| 49 | 49 | [SUNRPC_A_UNIX_GID_REQS_REQUESTS] = NLA_POLICY_NESTED(sunrpc_unix_gid_nl_policy), |
| 50 | 50 | }; |
| 51 | 51 | |
| 52 | +/* SUNRPC_CMD_CACHE_FLUSH - do */ | |
| 53 | +static const struct nla_policy sunrpc_cache_flush_nl_policy[SUNRPC_A_CACHE_FLUSH_MASK + 1] = { | |
| 54 | + [SUNRPC_A_CACHE_FLUSH_MASK] = NLA_POLICY_MASK(NLA_U32, 0x3), | |
| 55 | +}; | |
| 56 | + | |
| 52 | 57 | /* Ops table for sunrpc */ |
| 53 | 58 | static const struct genl_split_ops sunrpc_nl_ops[] = { |
| 54 | 59 | { |
| @@ -79,6 +84,13 @@ static const struct genl_split_ops sunrpc_nl_ops[] = { · 24 unmodified lines | ||
| 79 | 84 | .maxattr = SUNRPC_A_UNIX_GID_REQS_REQUESTS, |
| 80 | 85 | .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, |
| 81 | 86 | }, |
| 87 | + { | |
| 88 | + .cmd = SUNRPC_CMD_CACHE_FLUSH, | |
| 89 | + .doit = sunrpc_nl_cache_flush_doit, | |
| 90 | + .policy = sunrpc_cache_flush_nl_policy, | |
| 91 | + .maxattr = SUNRPC_A_CACHE_FLUSH_MASK, | |
| 92 | + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, | |
| 93 | + }, | |
| 82 | 94 | }; |
| 83 | 95 | |
| 84 | 96 | static const struct genl_multicast_group sunrpc_nl_mcgrps[] = { |
| @@ -23,6 +23,7 @@ int sunrpc_nl_unix_gid_get_reqs_dumpit(struct sk_buff *skb, · 22 unmodified lines | ||
| 23 | 23 | struct netlink_callback *cb); |
| 24 | 24 | int sunrpc_nl_unix_gid_set_reqs_doit(struct sk_buff *skb, |
| 25 | 25 | struct genl_info *info); |
| 26 | +int sunrpc_nl_cache_flush_doit(struct sk_buff *skb, struct genl_info *info); | |
| 26 | 27 | |
| 27 | 28 | enum { |
| 28 | 29 | SUNRPC_NLGRP_NONE, |
| @@ -818,6 +818,38 @@ int sunrpc_nl_unix_gid_set_reqs_doit(struct sk_buff *skb, · 817 unmodified lines | ||
| 818 | 818 | return ret; |
| 819 | 819 | } |
| 820 | 820 | |
| 821 | +/** | |
| 822 | + * sunrpc_nl_cache_flush_doit - flush sunrpc caches via netlink | |
| 823 | + * @skb: reply buffer | |
| 824 | + * @info: netlink metadata and command arguments | |
| 825 | + * | |
| 826 | + * Flush the ip_map and/or unix_gid caches. If SUNRPC_A_CACHE_FLUSH_MASK | |
| 827 | + * is provided, only flush the caches indicated by the bitmask (bit 1 = | |
| 828 | + * ip_map, bit 2 = unix_gid). If omitted, flush both. | |
| 829 | + * | |
| 830 | + * Return 0 on success or a negative errno. | |
| 831 | + */ | |
| 832 | +int sunrpc_nl_cache_flush_doit(struct sk_buff *skb, struct genl_info *info) | |
| 833 | +{ | |
| 834 | + struct sunrpc_net *sn; | |
| 835 | + u32 mask = ~0U; | |
| 836 | + | |
| 837 | + sn = net_generic(genl_info_net(info), sunrpc_net_id); | |
| 838 | + | |
| 839 | + if (info->attrs[SUNRPC_A_CACHE_FLUSH_MASK]) | |
| 840 | + mask = nla_get_u32(info->attrs[SUNRPC_A_CACHE_FLUSH_MASK]); | |
| 841 | + | |
| 842 | + if ((mask & SUNRPC_CACHE_TYPE_IP_MAP) && | |
| 843 | + sn->ip_map_cache) | |
| 844 | + cache_purge(sn->ip_map_cache); | |
| 845 | + | |
| 846 | + if ((mask & SUNRPC_CACHE_TYPE_UNIX_GID) && | |
| 847 | + sn->unix_gid_cache) | |
| 848 | + cache_purge(sn->unix_gid_cache); | |
| 849 | + | |
| 850 | + return 0; | |
| 851 | +} | |
| 852 | + | |
| 821 | 853 | static const struct cache_detail unix_gid_cache_template = { |
| 822 | 854 | .owner = THIS_MODULE, |
| 823 | 855 | .hash_size = GID_HASHMAX, |