The Uint8Array that stores the file data is usually larger than the file
size itself, to improve the amortized complexity of resizing the array.
When we previously switched over to using FileStorages, the method
fs#Write() was modified to retrieve only the subarray of the Uint8Array
that contains the file (i.e. excluding the unused padding at the end),
so appending to a file always tries to resize the array even though the
ArrayBuffer that backs it has enough space for the new data.
- Integrate new FileStorage interface with lib/filesystem.js
- Simplify the FileStorage interface with the intention that it only
serves read-only files.
While the original code would've worked for MemoryFileStorage, it will
not work for FileStorages that clone the data before saving (e.g.
IndexedDBFileStorage) as local changes won't be reflected onto the
storage class.
The "// jshint ignore:line" comments are pretty messy, so squint your eyes.
They're systematically placed, so we can regex it out when jshint's
new version finally arrives.
Using async/await instead of callbacks due to callback hell, and it also
helps minimising the diff)
Now that hard links aren't allowed across filesystems, it's ok to store
the relevant nlinks information within local inode.
For mountpoints (forwarder inodes that point to a root inode), it is
possible to bump the nlinks of the forwarder during link_under_dir and
unlink_from_dir so that this nlinks counter is modified independently
from the real inode's nlinks counter.
For divert(), it is actually ok to divert forwarder inodes that point to
hardlinked files, so I've relaxed the assertion predicate.
Although hardlinks across filesystems worked quite well in the current
implementation, we will run into problems when we try to implement
different backends for each sub-filesystem.
Note: EPERM is used instead of EXDEV since the mv command will silently
try to use copy-and-unlink when rename(2) fails with EXDEV.
The rules for linking has been reverted back:
- Before commit: Any inode, including forwarders, could be linked as
long as the parent is not a forwarder and is a directory.
- After commit: Only non-forwarders and root-forwarders are allowed to
be linked, and must be linked under a directory and not a forwarder.
The real_inode's status is supposedly set to STATUS_UNLINKED when there
are no more references to the inode from other directories. Previously,
this status was incorrectly applied to the forwarder and not the actual
real_inode.
Unfortunately, I didn't split this into multiple commits:
- Keeping track of nlinks is now all done by link_under_dir and
unlink_from_dir methods.
- Inodes are no longer associated with a name.
- Directory structure is now represented using a Map<name to idx>, so
the directory inode fully owns the directory entries instead a linked
list scattered across many inodes.
- The parameter order for FS#Link and FS#link_under_dir has been
modified to be consistent with 9p's: (dirid, fid, name)
- Allowed the movement of hardlinked files between filesystems
"vertically", as long as the target inode is reachable within the
filesystem and subfilesystems without ever having to traverse to the
parent filesystem.
- The methods FS#copy_inode and FS#divert does not put the filesystem in
an invalid state: FS#copy_inode does not modify inode.nlinks nor
inode.direntries, and FS#divert makes sure to delete the original nlinks
and direntries after it has been copied over to a new inode.
- Added extra assertions in FS#link_under_dir and FS#unlink_from_dir
- Forwarders should not be deleted upon unlink: the files are still
accessible.
- Non-root non-directory forwarders can now be linked under
non-forwarder directories for extra freedom for hardlinks. Now, the rule
for linking is: never link under a forwarder, and never link a directory
more than once.
Some tests and some 9p debug code is broken because they rely on
inode.name which no longer exists nor makes sense to exist.
Will fix in next commit.
If mountpoint already exists, then we're silently making its children
inaccessible which may not be what we expected/intended.
Create a new forwarder inode upon mounting.
Unresolved bug:
Calling fs.FillDirectory on a mountpoint gives incorrect information.
".." entry should describe parent of mountpoint, but currently describes
itself.