11// SPDX-License-Identifier: GPL-2.0
22/*
3- * fs/deepin_ro_fs_err_notify.c - Deepin read-only filesystem error notification
3+ * Deepin filesystem error notification
44 *
5- * This module provides notification functionality for read-only filesystem
6- * errors, specifically targeting overlay filesystems mounted on /usr .
5+ * This module provides notification functionality for filesystem errors,
6+ * especially for read-only filesystem errors .
77 */
88
99#include <linux/init.h>
3030/* Family name (max GENL_NAMSIZ characters, including null terminator) */
3131#define DEEPIN_ERR_NOTIFY_FAMILY_NAME "DEEPIN_ENOTIFY"
3232
33+ /* Multicast group name for error events (used in Netlink communication) */
34+ #define MULTICAST_GROUP_ERR_EVENTS "err_events"
35+
3336/* Define netlink message types and attributes */
3437enum {
3538 DEEPIN_ERR_NOTIFY_ATTR_UNSPEC ,
36- DEEPIN_ERR_NOTIFY_ATTR_FILENAME , /* Filename */
37- DEEPIN_ERR_NOTIFY_ATTR_PID , /* Process ID */
38- DEEPIN_ERR_NOTIFY_ATTR_COMM , /* Process Name */
39- DEEPIN_ERR_NOTIFY_ATTR_FUNC_NAME , /* Function Name */
39+ DEEPIN_ERR_NOTIFY_ATTR_FILENAME = 1 , /* Filename (string) */
40+ DEEPIN_ERR_NOTIFY_ATTR_INODE = 2 , /* Inode (u64) */
41+ DEEPIN_ERR_NOTIFY_ATTR_INODE_PARENT =
42+ 3 , /* Bool: inode from parent (u8) */
43+ DEEPIN_ERR_NOTIFY_ATTR_PID = 4 , /* Process ID (u32) */
44+ DEEPIN_ERR_NOTIFY_ATTR_PPID = 5 , /* Parent Process ID (u32) */
45+ DEEPIN_ERR_NOTIFY_ATTR_COMM =
46+ 6 , /* Process Short Name (string, 15 chars max) */
47+ DEEPIN_ERR_NOTIFY_ATTR_UID = 7 , /* User ID (u32) */
48+ DEEPIN_ERR_NOTIFY_ATTR_GID = 8 , /* Group ID (u32) */
49+ DEEPIN_ERR_NOTIFY_ATTR_STATUS = 9 , /* Enable/Disable Status (u8) */
50+ DEEPIN_ERR_NOTIFY_ATTR_FUNC_NAME = 10 , /* Function Name (string) */
4051 __DEEPIN_ERR_NOTIFY_ATTR_MAX ,
4152};
4253
4354#define DEEPIN_ERR_NOTIFY_ATTR_MAX (__DEEPIN_ERR_NOTIFY_ATTR_MAX - 1)
4455
4556enum {
4657 DEEPIN_ERR_NOTIFY_CMD_UNSPEC ,
47- DEEPIN_ERR_NOTIFY_CMD_NOTIFY , /* Error Notify Command */
58+ DEEPIN_ERR_NOTIFY_CMD_ERR_ROFS =
59+ 1 , /* Read Only Filesystem Error Notify Command */
60+ DEEPIN_ERR_NOTIFY_CMD_ENABLE = 2 , /* Enable error notification */
61+ DEEPIN_ERR_NOTIFY_CMD_DISABLE = 3 , /* Disable error notification */
62+ DEEPIN_ERR_NOTIFY_CMD_GET_STATUS = 4 , /* Get enable/disable status */
4863 __DEEPIN_ERR_NOTIFY_CMD_MAX ,
4964};
5065
@@ -56,7 +71,10 @@ static bool deepin_err_notify_initialized __read_mostly;
5671/* Runtime control variable for deepin error notification */
5772static int deepin_err_notify_enable __read_mostly = 0 ;
5873
59- int deepin_err_notify_enabled (void )
74+ /* Forward declaration of Generic Netlink family */
75+ static struct genl_family deepin_err_notify_genl_family ;
76+
77+ inline int deepin_err_notify_enabled (void )
6078{
6179 return deepin_err_notify_initialized && deepin_err_notify_enable ;
6280}
@@ -116,8 +134,116 @@ void deepin_check_and_notify_ro_fs_err(const struct deepin_path_last *path_last,
116134/* Define multicast group */
117135static const struct genl_multicast_group deepin_err_notify_nl_mcgrps [] = {
118136 {
119- .name = "ro_fs_events" ,
120- .flags = GENL_UNS_ADMIN_PERM ,
137+ .name = MULTICAST_GROUP_ERR_EVENTS ,
138+ .flags = GENL_UNS_ADMIN_PERM , /* Require CAP_NET_ADMIN */
139+ },
140+ };
141+
142+ /* Netlink attribute policy */
143+ static const struct nla_policy
144+ deepin_err_notify_genl_policy [DEEPIN_ERR_NOTIFY_ATTR_MAX + 1 ] = {
145+ [DEEPIN_ERR_NOTIFY_ATTR_FILENAME ] = { .type = NLA_STRING },
146+ [DEEPIN_ERR_NOTIFY_ATTR_INODE ] = { .type = NLA_U64 },
147+ [DEEPIN_ERR_NOTIFY_ATTR_INODE_PARENT ] = { .type = NLA_U8 },
148+ [DEEPIN_ERR_NOTIFY_ATTR_PID ] = { .type = NLA_U32 },
149+ [DEEPIN_ERR_NOTIFY_ATTR_PPID ] = { .type = NLA_U32 },
150+ [DEEPIN_ERR_NOTIFY_ATTR_COMM ] = { .type = NLA_STRING },
151+ [DEEPIN_ERR_NOTIFY_ATTR_UID ] = { .type = NLA_U32 },
152+ [DEEPIN_ERR_NOTIFY_ATTR_GID ] = { .type = NLA_U32 },
153+ [DEEPIN_ERR_NOTIFY_ATTR_STATUS ] = { .type = NLA_U8 },
154+ };
155+
156+ /**
157+ * deepin_err_notify_cmd_enable - Enable error notification via netlink
158+ * @skb: Socket buffer (unused)
159+ * @info: Generic netlink info structure
160+ *
161+ * Returns: 0 on success
162+ */
163+ static int deepin_err_notify_cmd_enable (struct sk_buff * skb ,
164+ struct genl_info * info )
165+ {
166+ deepin_err_notify_enable = 1 ;
167+ pr_debug ("deepin_err_notify: Error notification enabled via netlink\n" );
168+ return 0 ;
169+ }
170+
171+ /**
172+ * deepin_err_notify_cmd_disable - Disable error notification via netlink
173+ * @skb: Socket buffer (unused)
174+ * @info: Generic netlink info structure
175+ *
176+ * Returns: 0 on success
177+ */
178+ static int deepin_err_notify_cmd_disable (struct sk_buff * skb ,
179+ struct genl_info * info )
180+ {
181+ deepin_err_notify_enable = 0 ;
182+ pr_debug (
183+ "deepin_err_notify: Error notification disabled via netlink\n" );
184+ return 0 ;
185+ }
186+
187+ /**
188+ * deepin_err_notify_cmd_get_status - Get error notification status via netlink
189+ * @skb: Socket buffer (unused)
190+ * @info: Generic netlink info structure
191+ *
192+ * Returns: 0 on success, negative error code on failure
193+ */
194+ static int deepin_err_notify_cmd_get_status (struct sk_buff * skb ,
195+ struct genl_info * info )
196+ {
197+ struct sk_buff * msg ;
198+ void * hdr ;
199+ int ret ;
200+
201+ /* Allocate a new message */
202+ msg = nlmsg_new (NLMSG_DEFAULT_SIZE , GFP_KERNEL );
203+ if (!msg )
204+ return - ENOMEM ;
205+
206+ /* Add Generic Netlink header */
207+ hdr = genlmsg_put (msg , info -> snd_portid , info -> snd_seq ,
208+ & deepin_err_notify_genl_family , 0 ,
209+ DEEPIN_ERR_NOTIFY_CMD_GET_STATUS );
210+ if (!hdr ) {
211+ ret = - EMSGSIZE ;
212+ goto err_free_msg ;
213+ }
214+
215+ /* Add status attribute */
216+ ret = nla_put_u8 (msg , DEEPIN_ERR_NOTIFY_ATTR_STATUS ,
217+ deepin_err_notify_enable );
218+ if (ret < 0 )
219+ goto err_free_msg ;
220+
221+ genlmsg_end (msg , hdr );
222+
223+ /* Send unicast reply to the requester */
224+ return genlmsg_reply (msg , info );
225+
226+ err_free_msg :
227+ nlmsg_free (msg );
228+ return ret ;
229+ }
230+
231+ /* Define Generic Netlink operations */
232+ static const struct genl_ops deepin_err_notify_genl_ops [] = {
233+ {
234+ .cmd = DEEPIN_ERR_NOTIFY_CMD_ENABLE ,
235+ .doit = deepin_err_notify_cmd_enable ,
236+ .flags = GENL_ADMIN_PERM , /* Require CAP_NET_ADMIN */
237+ },
238+ {
239+ .cmd = DEEPIN_ERR_NOTIFY_CMD_DISABLE ,
240+ .doit = deepin_err_notify_cmd_disable ,
241+ .flags = GENL_ADMIN_PERM , /* Require CAP_NET_ADMIN */
242+ },
243+ {
244+ .cmd = DEEPIN_ERR_NOTIFY_CMD_GET_STATUS ,
245+ .doit = deepin_err_notify_cmd_get_status ,
246+ .flags = 0 , /* Allow any user to query status */
121247 },
122248};
123249
@@ -128,6 +254,9 @@ static struct genl_family deepin_err_notify_genl_family __ro_after_init = {
128254 .name = DEEPIN_ERR_NOTIFY_FAMILY_NAME ,
129255 .version = 1 ,
130256 .maxattr = DEEPIN_ERR_NOTIFY_ATTR_MAX ,
257+ .policy = deepin_err_notify_genl_policy ,
258+ .ops = deepin_err_notify_genl_ops ,
259+ .n_ops = ARRAY_SIZE (deepin_err_notify_genl_ops ),
131260 .mcgrps = deepin_err_notify_nl_mcgrps ,
132261 .n_mcgrps = ARRAY_SIZE (deepin_err_notify_nl_mcgrps ),
133262};
@@ -159,7 +288,7 @@ void deepin_send_ro_fs_err_notification(const char *filename,
159288 }
160289
161290 msg_head = genlmsg_put (skb , 0 , 0 , & deepin_err_notify_genl_family , 0 ,
162- DEEPIN_ERR_NOTIFY_CMD_NOTIFY );
291+ DEEPIN_ERR_NOTIFY_CMD_ERR_ROFS );
163292 if (!msg_head ) {
164293 pr_err ("deepin_err_notify: Failed to put netlink header\n" );
165294 goto err_out ;
@@ -210,28 +339,6 @@ void deepin_put_path_last(struct deepin_path_last *path_last)
210339 }
211340}
212341
213- /* sysctl table and initialization */
214- #ifdef CONFIG_SYSCTL
215- static struct ctl_table deepin_err_notify_sysctls [] = {
216- {
217- .procname = "deepin-err-notify-enable" ,
218- .data = & deepin_err_notify_enable ,
219- .maxlen = sizeof (int ),
220- .mode = 0644 ,
221- .proc_handler = proc_dointvec ,
222- },
223- };
224-
225- static void __init deepin_err_notify_sysctl_init (void )
226- {
227- register_sysctl_init ("fs" , deepin_err_notify_sysctls );
228- }
229- #else
230- static void __init deepin_err_notify_sysctl_init (void )
231- {
232- }
233- #endif /* CONFIG_SYSCTL */
234-
235342/* Deepin error notify initialization */
236343static int __init deepin_err_notify_init (void )
237344{
@@ -240,6 +347,7 @@ static int __init deepin_err_notify_init(void)
240347 /* Compile-time check for family name length */
241348 BUILD_BUG_ON (sizeof (DEEPIN_ERR_NOTIFY_FAMILY_NAME ) > GENL_NAMSIZ );
242349
350+ /* Register Generic Netlink family */
243351 error = genl_register_family (& deepin_err_notify_genl_family );
244352 if (error ) {
245353 pr_err ("deepin_err_notify: Failed to register Generic Netlink family: %d\n" ,
@@ -250,10 +358,9 @@ static int __init deepin_err_notify_init(void)
250358 /* Set initialization success flag */
251359 deepin_err_notify_initialized = true;
252360
253- /* Initialize sysctl interface */
254- deepin_err_notify_sysctl_init ();
255-
256- pr_info ("deepin_err_notify: Generic Netlink family registered successfully\n" );
361+ pr_debug (
362+ "deepin_err_notify: Generic Netlink family '%s' registered successfully\n" ,
363+ DEEPIN_ERR_NOTIFY_FAMILY_NAME );
257364 return 0 ;
258365}
259366
0 commit comments