commit d1366147e6a15c115e8c654fd1dd354e6fa82b42
parent c953c01492a7be3bb1887f8e4ad94ddbc55eb2d8
Author: Bor Grošelj Simić <bor.groseljsimic@telemach.net>
Date: Thu, 28 Oct 2021 00:15:33 +0200
fs::mem: further improvements
Improve inode search algorithm and rewrite some of the functions with
match instead of tedious ifs on types.
Signed-off-by: Bor Grošelj Simić <bor.groseljsimic@telemach.net>
Diffstat:
3 files changed, 50 insertions(+), 44 deletions(-)
diff --git a/fs/mem/+test.ha b/fs/mem/+test.ha
@@ -93,10 +93,16 @@ use strconv;
fs::subdir(memfs, filename) as fs::error as fs::wrongtype: void;
let sub = mksubdir(memfs, "dir") as *fs::fs;
+ let subsub = mksubdir(memfs, "dir/dir2") as *fs::fs;
let f = fs::create(sub, "file", 0, fs::flags::WRONLY)!;
io::write(f, [42])!;
io::close(f);
+ let f = fs::create(subsub, "file", 0, fs::flags::WRONLY)!;
+ io::write(f, [42])!;
+ fs::remove(subsub, "file")!;
+ io::close(f);
+ fs::close(subsub);
let sub2 = fs::subdir(memfs, "dir") as *fs::fs;
assert(sub2 == sub);
diff --git a/fs/mem/mem.ha b/fs/mem/mem.ha
@@ -57,6 +57,7 @@ export fn memopen() *fs::fs = alloc(inode {
data = empty_dir(),
name = "",
+ hash = hash_of(""),
opencount = 1,
parent = null,
});
@@ -91,20 +92,15 @@ fn create(
) (io::handle | fs::error) = {
let t = file_flags(flags...)?;
let mode = t.0, appnd = t.1;
-
- let parent = fs: *inode;
- match (inode_find(parent, path)) {
+ let parent = inode_find(fs: *inode, path::dirname(path))?;
+ let name = path::basename(path);
+ match (inode_find(parent, name)) {
case errors::noentry => void;
case =>
return errors::exists;
};
- if (path::dirname(path) != ".") {
- parent = inode_find(parent, path::dirname(path))?;
- };
-
- let name = strings::dup(path::basename(path));
let ino = alloc(inode {
- name = name,
+ name = strings::dup(name),
hash = hash_of(name),
data = []: []u8,
parent = parent,
@@ -121,10 +117,12 @@ fn open(
let t = file_flags(flags...)?;
let mode = t.0, appnd = t.1;
let ino = inode_find(fs: *inode, path)?;
- if (ino.data is directory) {
+ match (ino.data) {
+ case directory =>
return fs::wrongtype;
+ case file =>
+ return stream_open(ino, mode, appnd)?;
};
- return stream_open(ino, mode, appnd)?;
};
fn stat(fs: *fs::fs, path: str) (fs::filestat | fs::error) = {
@@ -143,20 +141,16 @@ fn stat(fs: *fs::fs, path: str) (fs::filestat | fs::error) = {
fn mkdir(fs: *fs::fs, path: str) (void | fs::error) = {
let ino = mksubdir(fs, path)?: *inode;
ino.opencount = 0;
- return void;
};
fn mksubdir(fs: *fs::fs, path: str) (*fs::fs | fs::error) = {
- let parent = fs: *inode;
- match (inode_find(parent, path)) {
+ let parent = inode_find(fs: *inode, path::dirname(path))?;
+ let name = path::basename(path);
+ match (inode_find(parent, name)) {
case errors::noentry => void;
case =>
return errors::exists;
};
- if (path::dirname(path) != ".") {
- parent = inode_find(parent, path::dirname(path))?;
- };
- let name = strings::dup(path::basename(path));
let ino = alloc(inode {
close = &close,
create = &create,
@@ -170,7 +164,7 @@ fn mksubdir(fs: *fs::fs, path: str) (*fs::fs | fs::error) = {
subdir = &subdir,
data = empty_dir(),
- name = name,
+ name = strings::dup(name),
hash = hash_of(name),
opencount = 1,
parent = parent,
@@ -181,25 +175,28 @@ fn mksubdir(fs: *fs::fs, path: str) (*fs::fs | fs::error) = {
fn subdir(fs: *fs::fs, path: str) (*fs::fs | fs::error) = {
let ino = inode_find(fs: *inode, path)?;
- if (!(ino.data is directory)) {
+ match (ino.data) {
+ case directory =>
+ ino.opencount += 1;
+ return ino;
+ case file =>
return fs::wrongtype;
};
- ino.opencount += 1;
- return ino;
};
fn iter(fs: *fs::fs, path: str) (*fs::iterator | fs::error) = {
let ino = inode_find(fs: *inode, path)?;
- if (!(ino.data is directory)) {
+ match (ino.data) {
+ case d: directory =>
+ return alloc(iterator {
+ next = &next,
+ parent = ino,
+ idx = 0,
+ curr = d.ents[0],
+ });
+ case file =>
return fs::wrongtype;
};
- let p = ino.data: directory;
- return alloc(iterator {
- next = &next,
- parent = ino,
- idx = 0,
- curr = p.ents[0],
- });
};
fn next(iter: *fs::iterator) (fs::dirent | void) = {
@@ -223,7 +220,7 @@ fn _next(it: *fs::iterator) nullable *inode = {
iter.curr = ino.next;
return ino;
};
- let p = iter.parent.data as directory;
+ let p = iter.parent.data: directory;
iter.idx += 1;
for (iter.idx < len(p.ents)) match (p.ents[iter.idx]) {
case null =>
@@ -240,26 +237,29 @@ fn rmdir(fs: *fs::fs, path: str) (void | fs::error) = {
if (fs: *inode == ino) {
return errors::invalid;
};
- if (!(ino.data is directory)) {
+ match (ino.data) {
+ case d: directory =>
+ if (ino.opencount != 0 || d.sz != 0) {
+ return errors::busy;
+ };
+ unlink(ino.parent: *inode, ino);
+ inode_free(ino);
+ case file =>
return fs::wrongtype;
};
- let p = ino.data as directory;
- if (ino.opencount != 0 || p.sz != 0) {
- return errors::busy;
- };
- unlink(ino.parent: *inode, ino);
- inode_free(ino);
};
fn remove(fs: *fs::fs, path: str) (void | fs::error) = {
let ino = inode_find(fs: *inode, path)?;
- if (!(ino.data is file)) {
+ match (ino.data) {
+ case file =>
+ unlink(ino.parent: *inode, ino);
+ if (ino.opencount == 0) {
+ inode_free(ino);
+ };
+ case directory =>
return fs::wrongtype;
};
- unlink(ino.parent: *inode, ino);
- if (ino.opencount == 0) {
- inode_free(ino);
- };
};
fn close(fs: *fs::fs) void = {
diff --git a/fs/mem/util.ha b/fs/mem/util.ha
@@ -89,7 +89,7 @@ fn inode_free(ino: *inode) void = {
};
fn inode_find(dir: *inode, path: str) (*inode | fs::error) = {
- if (path == "") {
+ if (path == "" || path == ".") {
return dir;
};
let it = path::iter(path);