aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/quota/netlink.c17
-rw-r--r--include/uapi/linux/genetlink.h1
-rw-r--r--net/netlink/genetlink.c10
3 files changed, 24 insertions, 4 deletions
diff --git a/fs/quota/netlink.c b/fs/quota/netlink.c
index 16e8abb7709b..aa22fe03b76c 100644
--- a/fs/quota/netlink.c
+++ b/fs/quota/netlink.c
@@ -11,13 +11,23 @@
11 11
12/* Netlink family structure for quota */ 12/* Netlink family structure for quota */
13static struct genl_family quota_genl_family = { 13static struct genl_family quota_genl_family = {
14 .id = GENL_ID_GENERATE, 14 /*
15 * Needed due to multicast group ID abuse - old code assumed
16 * the family ID was also a valid multicast group ID (which
17 * isn't true) and userspace might thus rely on it. Assign a
18 * static ID for this group to make dealing with that easier.
19 */
20 .id = GENL_ID_VFS_DQUOT,
15 .hdrsize = 0, 21 .hdrsize = 0,
16 .name = "VFS_DQUOT", 22 .name = "VFS_DQUOT",
17 .version = 1, 23 .version = 1,
18 .maxattr = QUOTA_NL_A_MAX, 24 .maxattr = QUOTA_NL_A_MAX,
19}; 25};
20 26
27static struct genl_multicast_group quota_mcgrp = {
28 .name = "events",
29};
30
21/** 31/**
22 * quota_send_warning - Send warning to userspace about exceeded quota 32 * quota_send_warning - Send warning to userspace about exceeded quota
23 * @type: The quota type: USRQQUOTA, GRPQUOTA,... 33 * @type: The quota type: USRQQUOTA, GRPQUOTA,...
@@ -78,7 +88,7 @@ void quota_send_warning(struct kqid qid, dev_t dev,
78 goto attr_err_out; 88 goto attr_err_out;
79 genlmsg_end(skb, msg_head); 89 genlmsg_end(skb, msg_head);
80 90
81 genlmsg_multicast(skb, 0, quota_genl_family.id, GFP_NOFS); 91 genlmsg_multicast(skb, 0, quota_mcgrp.id, GFP_NOFS);
82 return; 92 return;
83attr_err_out: 93attr_err_out:
84 printk(KERN_ERR "VFS: Not enough space to compose quota message!\n"); 94 printk(KERN_ERR "VFS: Not enough space to compose quota message!\n");
@@ -92,6 +102,9 @@ static int __init quota_init(void)
92 if (genl_register_family(&quota_genl_family) != 0) 102 if (genl_register_family(&quota_genl_family) != 0)
93 printk(KERN_ERR 103 printk(KERN_ERR
94 "VFS: Failed to create quota netlink interface.\n"); 104 "VFS: Failed to create quota netlink interface.\n");
105 if (genl_register_mc_group(&quota_genl_family, &quota_mcgrp))
106 printk(KERN_ERR
107 "VFS: Failed to register quota mcast group.\n");
95 return 0; 108 return 0;
96}; 109};
97 110
diff --git a/include/uapi/linux/genetlink.h b/include/uapi/linux/genetlink.h
index c880a417d8a9..1af72d8228e0 100644
--- a/include/uapi/linux/genetlink.h
+++ b/include/uapi/linux/genetlink.h
@@ -27,6 +27,7 @@ struct genlmsghdr {
27 */ 27 */
28#define GENL_ID_GENERATE 0 28#define GENL_ID_GENERATE 0
29#define GENL_ID_CTRL NLMSG_MIN_TYPE 29#define GENL_ID_CTRL NLMSG_MIN_TYPE
30#define GENL_ID_VFS_DQUOT (NLMSG_MIN_TYPE + 1)
30 31
31/************************************************************************** 32/**************************************************************************
32 * Controller 33 * Controller
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 353909d46dda..bee91a7527a5 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -69,8 +69,11 @@ static struct list_head family_ht[GENL_FAM_TAB_SIZE];
69 * abuses the API and thinks it can statically use group 1. 69 * abuses the API and thinks it can statically use group 1.
70 * That group will typically conflict with other groups that 70 * That group will typically conflict with other groups that
71 * any proper users use. 71 * any proper users use.
72 * Bit 17 is marked as already used since the VFS quota code
73 * also abused this API and relied on family == group ID, we
74 * cater to that by giving it a static family and group ID.
72 */ 75 */
73static unsigned long mc_group_start = 0x3; 76static unsigned long mc_group_start = 0x3 | BIT(GENL_ID_VFS_DQUOT);
74static unsigned long *mc_groups = &mc_group_start; 77static unsigned long *mc_groups = &mc_group_start;
75static unsigned long mc_groups_longs = 1; 78static unsigned long mc_groups_longs = 1;
76 79
@@ -130,7 +133,8 @@ static u16 genl_generate_id(void)
130 int i; 133 int i;
131 134
132 for (i = 0; i <= GENL_MAX_ID - GENL_MIN_ID; i++) { 135 for (i = 0; i <= GENL_MAX_ID - GENL_MIN_ID; i++) {
133 if (!genl_family_find_byid(id_gen_idx)) 136 if (id_gen_idx != GENL_ID_VFS_DQUOT &&
137 !genl_family_find_byid(id_gen_idx))
134 return id_gen_idx; 138 return id_gen_idx;
135 if (++id_gen_idx > GENL_MAX_ID) 139 if (++id_gen_idx > GENL_MAX_ID)
136 id_gen_idx = GENL_MIN_ID; 140 id_gen_idx = GENL_MIN_ID;
@@ -169,6 +173,8 @@ int genl_register_mc_group(struct genl_family *family,
169 id = GENL_ID_CTRL; 173 id = GENL_ID_CTRL;
170 else if (strcmp(family->name, "NET_DM") == 0) 174 else if (strcmp(family->name, "NET_DM") == 0)
171 id = 1; 175 id = 1;
176 else if (strcmp(family->name, "VFS_DQUOT") == 0)
177 id = GENL_ID_VFS_DQUOT;
172 else 178 else
173 id = find_first_zero_bit(mc_groups, 179 id = find_first_zero_bit(mc_groups,
174 mc_groups_longs * BITS_PER_LONG); 180 mc_groups_longs * BITS_PER_LONG);