Skip to content

Commit d330f70

Browse files
committed
refactor(err_notify): Refactor read-only filesystem error
notification mechanism * Provide deepin_lookup_path_or_parent function to support path lookup and parent path retrieval * Change read-only filesystem error notification calls to be based on deepin_path_last structure * Add deepin_err_notify_should_send function to implement enablement and rate limiting checks for error notifications * Modify multiple file operation functions to use the new interface Signed-off-by: electricface <[email protected]>
1 parent 5315839 commit d330f70

File tree

8 files changed

+256
-187
lines changed

8 files changed

+256
-187
lines changed

fs/deepin_err_notify.c

Lines changed: 77 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -61,54 +61,56 @@ int deepin_err_notify_enabled(void)
6161
return deepin_err_notify_initialized && deepin_err_notify_enable;
6262
}
6363

64+
/**
65+
* deepin_err_notify_should_send - Check if error notification should be sent
66+
*
67+
* This function checks both the enable status and rate limiting to determine
68+
* whether an error notification should be sent.
69+
*
70+
* Return: 1 if notification should be sent, 0 otherwise
71+
*/
72+
int deepin_err_notify_should_send(void)
73+
{
74+
75+
/*
76+
* Rate limiting: Allow 20 calls per 5 seconds.
77+
* Rationale: Prevent excessive error notifications under high load,
78+
* which could overwhelm the monitoring system or cause log flooding.
79+
* 20 notifications per 5 seconds is sufficient to capture relevant
80+
* filesystem errors without missing critical events.
81+
*/
82+
static DEFINE_RATELIMIT_STATE(deepin_err_notify_ratelimit, 5 * HZ, 20);
83+
84+
if (!deepin_err_notify_enabled())
85+
return 0;
86+
87+
return __ratelimit(&deepin_err_notify_ratelimit);
88+
}
89+
90+
static int
91+
prepare_and_notify_fs_error(const struct deepin_path_last *path_lasts,
92+
int path_last_count)
93+
{
94+
/* TODO: Implement in next commit */
95+
return -EOPNOTSUPP;
96+
}
97+
6498
/* Check if overlay filesystem is mounted on /usr and send read only error notification */
65-
void deepin_check_and_notify_ro_fs_err(const struct path *path,
99+
void deepin_check_and_notify_ro_fs_err(const struct deepin_path_last *path_last,
66100
const char *func_name)
67101
{
68-
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;
78-
79-
/* Early return if path or path->mnt is invalid */
80-
if (!path || !path->mnt || !path->mnt->mnt_sb)
81-
return;
102+
int ret;
82103

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. */
104+
/* Early return if path_last is invalid */
105+
if (!path_last)
92106
return;
93-
}
107+
ret = prepare_and_notify_fs_error(path_last, 1);
94108

95-
/* Attempt to get the full path.
96-
* Dynamic allocation is used to avoid excessive frame size.
97-
*/
98-
if (path->dentry) {
99-
path_buf = kmalloc(PATH_MAX, GFP_KERNEL);
100-
if (path_buf) {
101-
char *p = NULL;
102-
103-
p = d_path(path, path_buf, PATH_MAX);
104-
if (!IS_ERR(p))
105-
full_path = p;
106-
}
109+
if (ret < 0) {
110+
pr_debug(
111+
"deepin_err_notify: Failed to send notification to userspace: %d\n",
112+
ret);
107113
}
108-
109-
deepin_send_ro_fs_err_notification(full_path, func_name);
110-
111-
kfree(path_buf);
112114
}
113115

114116
/* Define multicast group */
@@ -192,6 +194,22 @@ void deepin_send_ro_fs_err_notification(const char *filename,
192194
kfree_skb(skb);
193195
}
194196

197+
/**
198+
* deepin_put_path_last - Release resources held by deepin_path_last structure
199+
* @path_last: Pointer to the deepin_path_last structure to release
200+
*
201+
* This function releases the path reference and frees the allocated filename
202+
* string in the deepin_path_last structure.
203+
*/
204+
void deepin_put_path_last(struct deepin_path_last *path_last)
205+
{
206+
if (path_last) {
207+
path_put(&path_last->path);
208+
kfree(path_last->last);
209+
path_last->last = NULL;
210+
}
211+
}
212+
195213
/* sysctl table and initialization */
196214
#ifdef CONFIG_SYSCTL
197215
static struct ctl_table deepin_err_notify_sysctls[] = {
@@ -239,5 +257,23 @@ static int __init deepin_err_notify_init(void)
239257
return 0;
240258
}
241259

260+
/**
261+
* deepin_notify_rename_ro_fs_err - Notify read-only filesystem errors during rename
262+
* @old_last: qstr for old filename
263+
* @new_last: qstr for new filename
264+
* @old_path: path of old parent directory
265+
* @new_path: path of new parent directory
266+
*
267+
* This function is called when a rename operation fails with EROFS error.
268+
*/
269+
void deepin_notify_rename_ro_fs_err(const struct qstr *old_last,
270+
const struct qstr *new_last,
271+
const struct path *old_path,
272+
const struct path *new_path)
273+
{
274+
/* Simplified implementation - will be enhanced in next commit */
275+
pr_debug("deepin_err_notify: EROFS error in rename\n");
276+
}
277+
242278
/* Use fs_initcall to ensure initialization before file system operations */
243279
fs_initcall(deepin_err_notify_init);

fs/internal.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,33 @@ int deepin_get_path_for_err_notify(int dfd, struct filename *name, struct path *
6767
/*
6868
* deepin_err_notify.c
6969
*/
70+
struct deepin_path_last {
71+
struct path path;
72+
const char *last;
73+
};
74+
75+
int deepin_lookup_path_or_parent(int dfd, struct filename *name,
76+
unsigned int flags,
77+
struct deepin_path_last *result_path_last);
78+
7079
int deepin_err_notify_enabled(void);
71-
void deepin_check_and_notify_ro_fs_err(const struct path *path, const char *func_name);
80+
int deepin_err_notify_should_send(void);
81+
void deepin_check_and_notify_ro_fs_err(const struct deepin_path_last *path_last,
82+
const char *func_name);
83+
void deepin_notify_rename_ro_fs_err(const struct qstr *old_last,
84+
const struct qstr *new_last,
85+
const struct path *old_path,
86+
const struct path *new_path);
87+
void deepin_put_path_last(struct deepin_path_last *path_last);
7288
void deepin_send_ro_fs_err_notification(const char *filename, const char *func_name);
7389

90+
#ifdef CONFIG_DEEPIN_ERR_NOTIFY
91+
#define deepin_should_notify_ro_fs_err(error) \
92+
unlikely(((error) == -EROFS) && deepin_err_notify_should_send())
93+
#else
94+
#define deepin_should_notify_ro_fs_err(error) 0
95+
#endif
96+
7497
/*
7598
* namespace.c
7699
*/

fs/ioctl.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -903,10 +903,13 @@ SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
903903
if (error == -ENOIOCTLCMD)
904904
error = vfs_ioctl(f.file, cmd, arg);
905905

906-
#ifdef CONFIG_DEEPIN_ERR_NOTIFY
907-
if (unlikely((error == -EROFS) && deepin_err_notify_enabled()))
908-
deepin_check_and_notify_ro_fs_err(&f.file->f_path, "ioctl");
909-
#endif /* CONFIG_DEEPIN_ERR_NOTIFY */
906+
if (deepin_should_notify_ro_fs_err(error)) {
907+
struct deepin_path_last tmp_path_last = {
908+
.path = f.file->f_path,
909+
.last = NULL
910+
};
911+
deepin_check_and_notify_ro_fs_err(&tmp_path_last, "ioctl");
912+
}
910913

911914
out:
912915
fdput(f);

0 commit comments

Comments
 (0)