}
}
- /* Busy check: reject if any process has cwd or root in this mount */
+ /* Busy check: reject if any process has cwd in this mount */
extern struct process* ready_queue_head;
+ extern struct process* current_process;
extern spinlock_t sched_lock;
uintptr_t sched_fl = spin_lock_irqsave(&sched_lock);
+
+ /* Check current process first */
+ if (current_process && current_process->cwd[0] && path_is_mountpoint_prefix(mp, current_process->cwd)) {
+ spin_unlock_irqrestore(&sched_lock, sched_fl);
+ return -EBUSY;
+ }
+
+ /* Check all processes in ready queue */
struct process* p = ready_queue_head;
while (p) {
/* Check if cwd is within this mount */
spin_unlock_irqrestore(&sched_lock, sched_fl);
return -EBUSY;
}
- /* Check if root is within this mount (if different from cwd) */
- /* Note: root is not stored as a path in current process struct,
- * so we only check cwd for now. A full implementation would require
- * storing root as a path or implementing vfs_getpath. */
p = p->rq_next;
}
spin_unlock_irqrestore(&sched_lock, sched_fl);
{"mount replace rejection" "\\[test\\] mount replace rejection OK"}
{"ftruncate readonly" "\\[test\\] ftruncate readonly OK"}
{"mountpoint validation" "\\[test\\] mountpoint validation OK"}
+ {"umount cwd" "\\[test\\] umount cwd OK"}
{"sigqueue" "\\[test\\] sigqueue OK"}
{"clone" "\\[test\\] clone OK"}
{"inotify_init1" "\\[test\\] inotify_init1 OK"}
{"mount replace rejection" "\\[test\\] mount replace rejection OK"}
{"ftruncate readonly" "\\[test\\] ftruncate readonly OK"}
{"mountpoint validation" "\\[test\\] mountpoint validation OK"}
+ {"umount cwd" "\\[test\\] umount cwd OK"}
{"sigqueue" "\\[test\\] sigqueue OK"}
{"clone" "\\[test\\] clone OK"}
{"inotify_init1" "\\[test\\] inotify_init1 OK"}
(uint32_t)(sizeof("[test] mountpoint validation OK\n") - 1));
}
+ // I20: umount with active cwd — should fail with -EBUSY
+ {
+ (void)sys_mkdir("/tmp/mnt_cwd");
+ if (sys_mount("none", "/tmp/mnt_cwd", "tmpfs", 0) < 0) {
+ sys_write(1, "[test] umount cwd: mount failed\n",
+ (uint32_t)(sizeof("[test] umount cwd: mount failed\n") - 1));
+ sys_exit(1);
+ }
+ /* Change cwd into the mount */
+ if (sys_chdir("/tmp/mnt_cwd") < 0) {
+ sys_write(1, "[test] umount cwd: chdir failed\n",
+ (uint32_t)(sizeof("[test] umount cwd: chdir failed\n") - 1));
+ sys_exit(1);
+ }
+ /* umount should fail because cwd is in the mount */
+ int rc = sys_umount2("/tmp/mnt_cwd");
+ if (rc >= 0) {
+ sys_write(1, "[test] umount cwd: should fail with -EBUSY\n",
+ (uint32_t)(sizeof("[test] umount cwd: should fail with -EBUSY\n") - 1));
+ sys_exit(1);
+ }
+ /* Change cwd back to / */
+ if (sys_chdir("/") < 0) {
+ sys_write(1, "[test] umount cwd: chdir back failed\n",
+ (uint32_t)(sizeof("[test] umount cwd: chdir back failed\n") - 1));
+ sys_exit(1);
+ }
+ /* Now umount should succeed */
+ if (sys_umount2("/tmp/mnt_cwd") < 0) {
+ sys_write(1, "[test] umount cwd: umount failed\n",
+ (uint32_t)(sizeof("[test] umount cwd: umount failed\n") - 1));
+ sys_exit(1);
+ }
+ sys_write(1, "[test] umount cwd OK\n",
+ (uint32_t)(sizeof("[test] umount cwd OK\n") - 1));
+ }
+
+
// I13: clone — create a thread sharing address space
{
/* We use a simple clone with CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND