99#include <linux/init.h>
1010#include <linux/slab.h>
1111#include <linux/fs.h>
12+ #include <linux/stat.h>
1213#include <linux/namei.h>
1314#include <linux/mount.h>
1415#include <linux/path.h>
5051 DEEPIN_ERR_NOTIFY_ATTR_UID = 7 , /* User ID (u32) */
5152 DEEPIN_ERR_NOTIFY_ATTR_GID = 8 , /* Group ID (u32) */
5253 DEEPIN_ERR_NOTIFY_ATTR_STATUS = 9 , /* Enable/Disable Status (u8) */
53- DEEPIN_ERR_NOTIFY_ATTR_FUNC_NAME = 10 , /* Function Name (string) */
5454 __DEEPIN_ERR_NOTIFY_ATTR_MAX ,
5555};
5656
@@ -139,11 +139,56 @@ int deepin_err_notify_should_send(void)
139139 return __ratelimit (& deepin_err_notify_ratelimit );
140140}
141141
142+ /**
143+ * combine_path_and_last - Combine base path with last component
144+ * @buffer: Pre-allocated buffer to store the combined path (size PATH_MAX)
145+ * @path: The base path to combine
146+ * @last: The last component to append
147+ *
148+ * This function combines a base path with a last component, constructing
149+ * the full path: base_path + "/" + last. The result is stored in buffer.
150+ *
151+ * Returns: Pointer to the combined path string on success, NULL on failure
152+ */
142153static char * combine_path_and_last (char * buffer , const struct path * path ,
143154 const char * last )
144155{
145- /* TODO: Implement in next commit */
146- return NULL ;
156+ char * base_path ;
157+ size_t base_len , last_len , total_len ;
158+
159+ base_path = d_absolute_path (path , buffer , PATH_MAX );
160+ if (IS_ERR (base_path ))
161+ return NULL ;
162+
163+ /* Construct full path: base_path + "/" + last */
164+ base_len = strlen (base_path );
165+ last_len = strlen (last );
166+ total_len = base_len + 1 + last_len + 1 ;
167+
168+ if (total_len > PATH_MAX )
169+ return NULL ;
170+
171+ /*
172+ * Move base_path to start of buffer if needed.
173+ * d_absolute_path() may return a pointer to the middle of the buffer,
174+ * not the start. We need the path at the beginning so we can
175+ * append "/" + last to it.
176+ */
177+ if (base_path != buffer )
178+ memmove (buffer , base_path , base_len );
179+
180+ /* Avoid appending an extra "/" after root directory "/" which would
181+ * result in "//filename".
182+ */
183+ if (base_len > 0 && buffer [base_len - 1 ] != '/' ) {
184+ buffer [base_len ] = '/' ;
185+ memcpy (buffer + base_len + 1 , last , last_len + 1 );
186+ } else {
187+ /* base_path is already "/" or ends with "/" (rare case) */
188+ memcpy (buffer + base_len , last , last_len + 1 );
189+ }
190+
191+ return buffer ;
147192}
148193
149194/* Check if overlay filesystem is mounted on /usr and send read only error notification */
@@ -158,7 +203,7 @@ void deepin_check_and_notify_ro_fs_err(const struct deepin_path_last *path_last,
158203 ret = prepare_and_notify_fs_error (path_last , 1 );
159204
160205 if (ret < 0 ) {
161- pr_err (
206+ pr_debug (
162207 "deepin_err_notify: Failed to send notification to userspace: %d\n" ,
163208 ret );
164209 }
@@ -673,13 +718,26 @@ static int __init deepin_err_notify_init(void)
673718 * @new_path: path of new parent directory
674719 *
675720 * This function is called when a rename operation fails with EROFS error.
721+ * It attempts to look up the old and new paths and send error notification
722+ * if both paths are valid.
676723 */
677724void deepin_notify_rename_ro_fs_err (const struct qstr * old_last ,
678725 const struct qstr * new_last ,
679726 const struct path * old_path ,
680727 const struct path * new_path )
681728{
682- /* Simplified implementation - will be enhanced in next commit */
729+ const struct deepin_path_last path_lasts [2 ] = {
730+ { .path = * old_path , .last = old_last -> name },
731+ { .path = * new_path , .last = new_last -> name }
732+ };
733+ int ret ;
734+
735+ ret = prepare_and_notify_fs_error (path_lasts , 2 );
736+ if (ret < 0 ) {
737+ pr_debug (
738+ "deepin_err_notify: Failed to send notification to userspace: %d\n" ,
739+ ret );
740+ }
683741}
684742
685743/* Use fs_initcall to ensure initialization before file system operations */
0 commit comments