Summary
Add an umount shell command that properly unmounts a filesystem: flushes dirty data, closes the filesystem, and removes the mount point. Also add an unmount() method to FileSystemService to complement the existing mount().
Motivation
There is currently no way to unmount a filesystem from the shell. FileSystemService has mount() but no unmount(). FileSystemAPIImpl has a TODO at line 463: // TODO handle removal (+ add unmount. Without unmount, users cannot safely remove removable media, and the flush-on-close path in AbstractFileSystem.close() is never triggered from the shell.
Implementation
1. Add unmount() to FileSystemService
// FileSystemService.java — add method:
/**
* Unmount the filesystem at the given path.
* Flushes the filesystem, closes it, and removes the mount point.
*
* @param fullPath the mount point path
* @throws IOException if flush or close fails
* @throws IllegalArgumentException if path is not a mount point
*/
public void unmount(String fullPath) throws IOException;
2. Implement in FileSystemAPIImpl
public void unmount(String fullPath) throws IOException {
FileSystem<?> fs = mountPoints.remove(fullPath);
if (fs == null) {
throw new IllegalArgumentException("Not a mount point: " + fullPath);
}
try {
if (!fs.isReadOnly()) {
fs.flush();
}
fs.close();
} catch (IOException ex) {
// Re-add on failure so state stays consistent
mountPoints.put(fullPath, fs);
throw ex;
}
}
3. Shell command
package org.jnode.fs.command;
public class UnmountCommand extends AbstractCommand {
private final FileArgument argDir =
new FileArgument("directory", Argument.MANDATORY,
"the mount point to unmount");
public UnmountCommand() {
super("Unmount a filesystem");
registerArguments(argDir);
}
public static void main(String[] args) throws Exception {
new UnmountCommand().execute(args);
}
@Override
public void execute() throws Exception {
FileSystemService fss = InitialNaming.lookup(FileSystemService.NAME);
PrintWriter out = getOutput().getPrintWriter();
PrintWriter err = getError().getPrintWriter();
String path = argDir.getValue().getCanonicalPath();
if (!fss.isMount(path)) {
err.println("Not a mount point: " + path);
err.println("Use 'mount' to list mounted filesystems.");
exit(1);
}
try {
fss.unmount(path);
out.println("Unmounted " + path);
} catch (IOException ex) {
err.println("Failed to unmount " + path + ": " + ex.getMessage());
exit(1);
}
}
}
4. Plugin XML
Add to fs/descriptors/org.jnode.fs.command.xml:
<extension point="org.jnode.shell.aliases">
<alias name="umount" class="org.jnode.fs.command.UnmountCommand"/>
</extension>
<extension point="org.jnode.shell.syntaxes">
<syntax alias="umount">
<sequence description="Unmount the filesystem at the given path">
<argument argLabel="directory"/>
</sequence>
</syntax>
</extension>
Files to create/modify
- Modify:
fs/src/fs/org/jnode/fs/service/FileSystemService.java — add unmount() method
- Modify:
fs/src/fs/org/jnode/fs/service/def/FileSystemAPIImpl.java — implement unmount(), resolve TODO
- Create:
fs/src/commands/org/jnode/fs/command/UnmountCommand.java
- Modify:
fs/descriptors/org.jnode.fs.command.xml — add alias and syntax
Testing / Validation
Test 1: Basic unmount
- Mount:
mount /dev/ide0-auto /mnt
- Write:
echo test > /mnt/test.txt
- Unmount:
umount /mnt
- Expected:
Unmounted /mnt
- Verify flush + close in serial log
- Remount, verify file persists
Test 2: Unmount non-existent path
- Run
umount /nonexistent
- Expected:
Not a mount point: /nonexistent, exit code 1
Test 3: Unmount already unmounted
- Mount, unmount
- Run
umount /mnt again
- Expected: error, exit code 1
Test 4: Unmount read-only filesystem
- Mount ISO9660:
mount /dev/cdrom0 /cdrom
- Run
umount /cdrom
- Expected:
Unmounted /cdrom (flush skipped for read-only)
Test 5: Flush failure during unmount
- Write data to mounted FAT filesystem
- Unmount — should flush before close
- Verify in serial log: FLUSH CACHE command issued before close
Test 6: Unmount with open file handles
- Open a file on the mounted filesystem (via another process or background)
- Try to unmount
- Expected behavior: should either fail or close handles — document the chosen behavior
Test 7: Integration with sync
- Mount, write data
sync /mnt
umount /mnt
- Verify clean unmount, no data loss on reboot
Acceptance Criteria
Summary
Add an
umountshell command that properly unmounts a filesystem: flushes dirty data, closes the filesystem, and removes the mount point. Also add anunmount()method toFileSystemServiceto complement the existingmount().Motivation
There is currently no way to unmount a filesystem from the shell.
FileSystemServicehasmount()but nounmount().FileSystemAPIImplhas a TODO at line 463:// TODO handle removal (+ add unmount. Without unmount, users cannot safely remove removable media, and the flush-on-close path inAbstractFileSystem.close()is never triggered from the shell.Implementation
1. Add
unmount()toFileSystemService2. Implement in
FileSystemAPIImpl3. Shell command
4. Plugin XML
Add to
fs/descriptors/org.jnode.fs.command.xml:Files to create/modify
fs/src/fs/org/jnode/fs/service/FileSystemService.java— addunmount()methodfs/src/fs/org/jnode/fs/service/def/FileSystemAPIImpl.java— implementunmount(), resolve TODOfs/src/commands/org/jnode/fs/command/UnmountCommand.javafs/descriptors/org.jnode.fs.command.xml— add alias and syntaxTesting / Validation
Test 1: Basic unmount
mount /dev/ide0-auto /mntecho test > /mnt/test.txtumount /mntUnmounted /mntTest 2: Unmount non-existent path
umount /nonexistentNot a mount point: /nonexistent, exit code 1Test 3: Unmount already unmounted
umount /mntagainTest 4: Unmount read-only filesystem
mount /dev/cdrom0 /cdromumount /cdromUnmounted /cdrom(flush skipped for read-only)Test 5: Flush failure during unmount
Test 6: Unmount with open file handles
Test 7: Integration with sync
sync /mntumount /mntAcceptance Criteria
umount /pathflushes, closes, and removes the mount pointFileSystemService.unmount()is implemented and documentedFileSystemAPIImplTODO for mount removal is resolvedmountoutput after unmount no longer lists the removed mount