kernel: Avoid calling umount whilst holding a spinlock.

This commit is contained in:
ShirkNeko
2025-11-07 14:23:58 +08:00
parent 03a164ebb7
commit 9ebddde0d5

View File

@@ -200,22 +200,19 @@ bool ksu_umount_path_is_busy(const char *path)
return check_path_busy(path); return check_path_busy(path);
} }
static void execute_umount_entry(struct umount_entry *entry, const struct cred *cred) static void try_umount_path(struct umount_entry *entry)
{ {
struct path kpath; struct path kpath;
int err; int err;
entry->ref_count++;
entry->state = UMOUNT_STATE_ACTIVE;
err = kern_path(entry->path, 0, &kpath); err = kern_path(entry->path, 0, &kpath);
if (err) { if (err) {
goto done; return;
} }
if (kpath.dentry != kpath.mnt->mnt_root) { if (kpath.dentry != kpath.mnt->mnt_root) {
path_put(&kpath); path_put(&kpath);
goto done; return;
} }
if (entry->check_mnt) { if (entry->check_mnt) {
@@ -223,7 +220,7 @@ static void execute_umount_entry(struct umount_entry *entry, const struct cred *
const char *fstype = kpath.mnt->mnt_sb->s_type->name; const char *fstype = kpath.mnt->mnt_sb->s_type->name;
if (strcmp(fstype, "overlay") != 0) { if (strcmp(fstype, "overlay") != 0) {
path_put(&kpath); path_put(&kpath);
goto done; return;
} }
} }
} }
@@ -234,10 +231,6 @@ static void execute_umount_entry(struct umount_entry *entry, const struct cred *
} }
path_put(&kpath); path_put(&kpath);
done:
entry->state = UMOUNT_STATE_IDLE;
entry->ref_count--;
} }
void ksu_umount_manager_execute_all(const struct cred *cred) void ksu_umount_manager_execute_all(const struct cred *cred)
@@ -249,7 +242,23 @@ void ksu_umount_manager_execute_all(const struct cred *cred)
list_for_each_entry(entry, &g_umount_mgr.entry_list, list) { list_for_each_entry(entry, &g_umount_mgr.entry_list, list) {
if (entry->state == UMOUNT_STATE_IDLE) { if (entry->state == UMOUNT_STATE_IDLE) {
execute_umount_entry(entry, cred); entry->ref_count++;
}
}
spin_unlock_irqrestore(&g_umount_mgr.lock, flags);
list_for_each_entry(entry, &g_umount_mgr.entry_list, list) {
if (entry->ref_count > 0 && entry->state == UMOUNT_STATE_IDLE) {
try_umount_path(entry);
}
}
spin_lock_irqsave(&g_umount_mgr.lock, flags);
list_for_each_entry(entry, &g_umount_mgr.entry_list, list) {
if (entry->ref_count > 0) {
entry->ref_count--;
} }
} }