2727#include "internal.h"
2828#include "mount.h"
2929
30- /* Family name (max GENL_NAMSIZ characters, including null terminator) */
31- #define DEEPIN_ERR_NOTIFY_FAMILY_NAME "DEEPIN_ENOTIFY"
32-
33- /* Define netlink message types and attributes */
34- enum {
35- 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 */
40- __DEEPIN_ERR_NOTIFY_ATTR_MAX ,
41- };
42-
43- #define DEEPIN_ERR_NOTIFY_ATTR_MAX (__DEEPIN_ERR_NOTIFY_ATTR_MAX - 1)
44-
45- enum {
46- DEEPIN_ERR_NOTIFY_CMD_UNSPEC ,
47- DEEPIN_ERR_NOTIFY_CMD_NOTIFY , /* Error Notify Command */
48- __DEEPIN_ERR_NOTIFY_CMD_MAX ,
49- };
50-
51- #define DEEPIN_ERR_NOTIFY_CMD_MAX (__DEEPIN_ERR_NOTIFY_CMD_MAX - 1)
52-
5330/* Track deepin error notification initialization status */
5431static bool deepin_err_notify_initialized __read_mostly ;
5532
@@ -61,134 +38,112 @@ int deepin_err_notify_enabled(void)
6138 return deepin_err_notify_initialized && deepin_err_notify_enable ;
6239}
6340
41+ /* Rate limiting: allow 100 calls per 5 seconds */
42+ static DEFINE_RATELIMIT_STATE (deepin_ro_fs_err_ratelimit ,
43+ 5 * HZ , /* 5 seconds interval */
44+ 100 ); /* 100 calls per interval */
45+
6446/* Check if overlay filesystem is mounted on /usr and send read only error notification */
6547void deepin_check_and_notify_ro_fs_err (const struct path * path ,
6648 const char * func_name )
6749{
6850 char * path_buf = NULL ;
69- char * full_path = "" ;
70- /* Rate limiting: allow 100 calls per 5 seconds */
71- static DEFINE_RATELIMIT_STATE (deepin_ro_fs_err_ratelimit ,
72- 5 * HZ , /* 5 seconds interval */
73- 100 ); /* 100 calls per interval */
74-
75- /* Check rate limit before proceeding */
76- if (!__ratelimit (& deepin_ro_fs_err_ratelimit ))
77- return ;
51+ const char * filename = "" ;
7852
79- /* Early return if path or path->mnt is invalid */
80- if (!path || !path -> mnt || !path -> mnt -> mnt_sb )
53+ /* Early return if path is invalid or filesystem doesn't implement the callback */
54+ if (!path || !path -> mnt || !path -> mnt -> mnt_sb ||
55+ !path -> mnt -> mnt_sb -> s_op ||
56+ !path -> mnt -> mnt_sb -> s_op -> deepin_notify_error )
8157 return ;
8258
83- /* Use filesystem callback to decide if notification should be sent.
84- * If filesystem implements the callback, use it.
85- */
86- if (path -> mnt -> mnt_sb -> s_op &&
87- path -> mnt -> mnt_sb -> s_op -> deepin_should_notify_error ) {
88- if (!path -> mnt -> mnt_sb -> s_op -> deepin_should_notify_error (path -> mnt -> mnt_sb ))
89- return ;
90- } else {
91- /* If filesystem does not implement the callback, return immediately. */
59+ /* Check rate limit before proceeding */
60+ if (!__ratelimit (& deepin_ro_fs_err_ratelimit ))
9261 return ;
93- }
9462
95- /* Attempt to get the full path.
96- * Dynamic allocation is used to avoid excessive frame size.
97- */
63+ /* Convert path to filename string */
9864 if (path -> dentry ) {
9965 path_buf = kmalloc (PATH_MAX , GFP_KERNEL );
10066 if (path_buf ) {
101- char * p = NULL ;
102-
103- p = d_path (path , path_buf , PATH_MAX );
67+ char * p = d_path (path , path_buf , PATH_MAX );
10468 if (!IS_ERR (p ))
105- full_path = p ;
69+ filename = p ;
10670 }
10771 }
10872
109- deepin_send_ro_fs_err_notification (full_path , func_name );
110-
73+ /* Use filesystem callback to handle error notification */
74+ path -> mnt -> mnt_sb -> s_op -> deepin_notify_error (
75+ path -> mnt -> mnt_sb , & filename , 1 , func_name );
11176 kfree (path_buf );
11277}
11378
114- /* Define multicast group */
115- static const struct genl_multicast_group deepin_err_notify_nl_mcgrps [] = {
116- {
117- .name = "ro_fs_events" ,
118- },
119- };
120-
121- /* Define Generic Netlink family */
122- static struct genl_family deepin_err_notify_genl_family __ro_after_init = {
123- .module = THIS_MODULE ,
124- .hdrsize = 0 ,
125- .name = DEEPIN_ERR_NOTIFY_FAMILY_NAME ,
126- .version = 1 ,
127- .maxattr = DEEPIN_ERR_NOTIFY_ATTR_MAX ,
128- .mcgrps = deepin_err_notify_nl_mcgrps ,
129- .n_mcgrps = ARRAY_SIZE (deepin_err_notify_nl_mcgrps ),
130- };
131-
132- /* Send read only filesystem error notification */
133- void deepin_send_ro_fs_err_notification (const char * filename ,
134- const char * func_name )
79+ /* Check multiple paths and send read-only error notification */
80+ void deepin_check_and_notify_ro_fs_err_paths (const struct path * path ,
81+ const struct path * path_new ,
82+ const char * func_name )
13583{
136- pid_t pid = 0 ;
137- const char * comm = NULL ;
138- int msg_size ;
139- struct sk_buff * skb = NULL ;
140- void * msg_head = NULL ;
141- int error ;
142-
143- pid = current -> pid ;
144- comm = current -> comm ;
145-
146- msg_size = nla_total_size (strlen (filename ) + 1 ) +
147- nla_total_size (sizeof (u32 )) +
148- nla_total_size (strlen (comm ) + 1 ) +
149- nla_total_size (strlen (func_name ) + 1 );
150-
151- /* Use GFP_NOFS to avoid recursion in file system operations. */
152- skb = genlmsg_new (msg_size , GFP_NOFS );
153- if (!skb ) {
154- pr_err ("deepin_err_notify: Failed to allocate netlink message\n" );
155- return ;
156- }
84+ char * path_bufs [2 ] = { NULL , NULL };
85+ const char * filenames [2 ] = { "" , "" };
86+ int filename_count = 0 ;
87+ const struct super_operations * s_op = NULL ;
88+ struct super_block * sb = NULL ;
89+ const struct path * paths [2 ] = { path , path_new };
90+ int i ;
91+
92+ /* First pass: find a filesystem that implements deepin_notify_error
93+ * Check both paths and use the first one that has the callback
94+ */
95+ for (i = 0 ; i < 2 ; i ++ ) {
96+ if (!paths [i ] || !paths [i ]-> mnt || !paths [i ]-> mnt -> mnt_sb )
97+ continue ;
15798
158- msg_head = genlmsg_put (skb , 0 , 0 , & deepin_err_notify_genl_family , 0 ,
159- DEEPIN_ERR_NOTIFY_CMD_NOTIFY );
160- if (!msg_head ) {
161- pr_err ("deepin_err_notify: Failed to put netlink header\n" );
162- goto err_out ;
163- }
99+ sb = paths [i ]-> mnt -> mnt_sb ;
100+ s_op = sb -> s_op ;
164101
165- error = nla_put_string (skb , DEEPIN_ERR_NOTIFY_ATTR_FILENAME , filename );
166- if (error )
167- goto attr_err_out ;
102+ if (s_op && s_op -> deepin_notify_error ) {
103+ /* Found a filesystem with the callback */
104+ break ;
105+ }
168106
169- error = nla_put_u32 (skb , DEEPIN_ERR_NOTIFY_ATTR_PID , pid );
170- if (error )
171- goto attr_err_out ;
107+ /* Reset for next iteration */
108+ sb = NULL ;
109+ s_op = NULL ;
110+ }
172111
173- error = nla_put_string ( skb , DEEPIN_ERR_NOTIFY_ATTR_COMM , comm );
174- if (error )
175- goto attr_err_out ;
112+ /* Early return if no filesystem has the callback */
113+ if (! s_op || ! s_op -> deepin_notify_error )
114+ return ;
176115
177- error = nla_put_string (skb , DEEPIN_ERR_NOTIFY_ATTR_FUNC_NAME ,
178- func_name );
179- if (error )
180- goto attr_err_out ;
116+ /* Check rate limit before proceeding */
117+ if (!__ratelimit (& deepin_ro_fs_err_ratelimit ))
118+ return ;
181119
182- genlmsg_end (skb , msg_head );
120+ /* Second pass: collect all valid filenames from both paths
121+ * Only allocate memory now that we know we'll use it
122+ */
123+ for (i = 0 ; i < 2 ; i ++ ) {
124+ if (!paths [i ] || !paths [i ]-> mnt || !paths [i ]-> mnt -> mnt_sb )
125+ continue ;
126+
127+ if (!paths [i ]-> dentry )
128+ continue ;
129+
130+ path_bufs [i ] = kmalloc (PATH_MAX , GFP_KERNEL );
131+ if (path_bufs [i ]) {
132+ char * p = d_path (paths [i ], path_bufs [i ], PATH_MAX );
133+ if (!IS_ERR (p ))
134+ filenames [filename_count ++ ] = p ;
135+ }
136+ }
183137
184- /* Send multicast message. */
185- genlmsg_multicast (& deepin_err_notify_genl_family , skb , 0 , 0 , GFP_NOFS );
186- return ;
138+ /* Call the callback with collected filenames */
139+ if (filename_count == 2 ) {
140+ s_op -> deepin_notify_error (sb , filenames , filename_count ,
141+ func_name );
142+ }
187143
188- attr_err_out :
189- pr_err ("deepin_err_notify: Failed to add netlink attributes\n" );
190- err_out :
191- kfree_skb (skb );
144+ /* Free allocated buffers */
145+ for (i = 0 ; i < 2 ; i ++ )
146+ kfree (path_bufs [i ]);
192147}
193148
194149/* sysctl table and initialization */
@@ -216,27 +171,14 @@ static void __init deepin_err_notify_sysctl_init(void)
216171/* Deepin error notify initialization */
217172static int __init deepin_err_notify_init (void )
218173{
219- int error ;
220-
221- /* Compile-time check for family name length */
222- BUILD_BUG_ON (sizeof (DEEPIN_ERR_NOTIFY_FAMILY_NAME ) > GENL_NAMSIZ );
223-
224- error = genl_register_family (& deepin_err_notify_genl_family );
225- if (error ) {
226- pr_err ("deepin_err_notify: Failed to register Generic Netlink family: %d\n" ,
227- error );
228- return error ;
229- }
230-
231174 /* Set initialization success flag */
232175 deepin_err_notify_initialized = true;
233176
234177 /* Initialize sysctl interface */
235178 deepin_err_notify_sysctl_init ();
236-
237- pr_info ("deepin_err_notify: Generic Netlink family registered successfully\n" );
238179 return 0 ;
239180}
240181
241182/* Use fs_initcall to ensure initialization before file system operations */
242183fs_initcall (deepin_err_notify_init );
184+
0 commit comments