From 0dc5c83ec21a452bf3849334883f9bd63bed8027 Mon Sep 17 00:00:00 2001 From: David van Moolenbroek Date: Sun, 24 Aug 2014 09:55:05 +0000 Subject: [PATCH] libvtreefs: use libfsdriver Change-Id: I0e6446bd0ccc3b89edc237be441ebfd92585f352 --- minix/drivers/system/gpio/Makefile | 4 +- minix/fs/procfs/Makefile | 4 +- minix/fs/procfs/main.c | 2 +- minix/lib/libvtreefs/Makefile | 9 +- minix/lib/libvtreefs/glo.h | 7 +- minix/lib/libvtreefs/inc.h | 29 +-- minix/lib/libvtreefs/inode.c | 16 +- minix/lib/libvtreefs/inode.h | 2 +- minix/lib/libvtreefs/link.c | 16 +- minix/lib/libvtreefs/mount.c | 32 ++- minix/lib/libvtreefs/path.c | 324 ++++------------------------- minix/lib/libvtreefs/proto.h | 29 +-- minix/lib/libvtreefs/read.c | 112 +++------- minix/lib/libvtreefs/stadir.c | 51 ++--- minix/lib/libvtreefs/table.c | 50 +---- minix/lib/libvtreefs/utility.c | 29 --- minix/lib/libvtreefs/vtreefs.c | 139 ++++--------- minix/servers/devman/Makefile | 4 +- 18 files changed, 192 insertions(+), 667 deletions(-) delete mode 100644 minix/lib/libvtreefs/utility.c diff --git a/minix/drivers/system/gpio/Makefile b/minix/drivers/system/gpio/Makefile index 6ebe80070..ef195ea06 100644 --- a/minix/drivers/system/gpio/Makefile +++ b/minix/drivers/system/gpio/Makefile @@ -2,8 +2,8 @@ PROG= gpio SRCS= gpio.c -DPADD+= ${LIBBLOCKDRIVER} ${LIBSYS} ${LIBGPIO} ${LIBCLKCONF} -LDADD+= -lvtreefs -lsys -lgpio -lclkconf +DPADD+= ${LIBVTREEFS} ${LIBFSDRIVER} ${LIBSYS} ${LIBGPIO} ${LIBCLKCONF} +LDADD+= -lvtreefs -lfsdriver -lsys -lgpio -lclkconf # This is a system driver. CPPFLAGS+= -D_SYSTEM=1 diff --git a/minix/fs/procfs/Makefile b/minix/fs/procfs/Makefile index 04b619601..51c87dc4e 100644 --- a/minix/fs/procfs/Makefile +++ b/minix/fs/procfs/Makefile @@ -8,7 +8,7 @@ CPPFLAGS+= -I${NETBSDSRCDIR}/minix CPPFLAGS+= -I${NETBSDSRCDIR}/minix/fs CPPFLAGS+= -I${NETBSDSRCDIR}/minix/servers -DPADD+= ${LIBVTREEFS} ${LIBMINIXFS} -LDADD+= -lvtreefs -lminixfs +DPADD+= ${LIBVTREEFS} ${LIBFSDRIVER} +LDADD+= -lvtreefs -lfsdriver .include diff --git a/minix/fs/procfs/main.c b/minix/fs/procfs/main.c index 6a99bdc89..180543aa2 100644 --- a/minix/fs/procfs/main.c +++ b/minix/fs/procfs/main.c @@ -89,7 +89,7 @@ int main(void) stat.size = 0; stat.dev = NO_DEV; - /* Start VTreeFS. This call does not return. */ + /* Start VTreeFS. */ start_vtreefs(&hooks, NR_INODES, &stat, NR_PROCS + NR_TASKS); return 0; diff --git a/minix/lib/libvtreefs/Makefile b/minix/lib/libvtreefs/Makefile index 35f091728..379d9b3cb 100644 --- a/minix/lib/libvtreefs/Makefile +++ b/minix/lib/libvtreefs/Makefile @@ -1,9 +1,9 @@ -NOGCCERROR=yes -NOCLANGERROR=yes -CPPFLAGS+= -D_MINIX_SYSTEM - # Makefile for libvtreefs +NOGCCERROR=yes + +CPPFLAGS+= -D_MINIX_SYSTEM + LIB= vtreefs CPPFLAGS+= -I${NETBSDSRCDIR}/include @@ -17,7 +17,6 @@ SRCS= \ sdbm.c \ stadir.c \ table.c \ - utility.c \ vtreefs.c .include diff --git a/minix/lib/libvtreefs/glo.h b/minix/lib/libvtreefs/glo.h index c770ae5d0..0e5fd1a59 100644 --- a/minix/lib/libvtreefs/glo.h +++ b/minix/lib/libvtreefs/glo.h @@ -8,13 +8,8 @@ EXTERN struct fs_hooks *vtreefs_hooks; -EXTERN message fs_m_in; -EXTERN message fs_m_out; - EXTERN dev_t fs_dev; -EXTERN int fs_mounted; - -extern int(*fs_call_vec[]) (void); +extern struct fsdriver vtreefs_table; #endif /* _VTREEFS_GLO_H */ diff --git a/minix/lib/libvtreefs/inc.h b/minix/lib/libvtreefs/inc.h index 15249f1d8..acef05f17 100644 --- a/minix/lib/libvtreefs/inc.h +++ b/minix/lib/libvtreefs/inc.h @@ -1,29 +1,8 @@ -#define _SYSTEM 1 /* tell headers that this is the kernel */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include +#include + +#include #include "glo.h" #include "proto.h" diff --git a/minix/lib/libvtreefs/inode.c b/minix/lib/libvtreefs/inode.c index c7fdda1b5..9aaef3233 100644 --- a/minix/lib/libvtreefs/inode.c +++ b/minix/lib/libvtreefs/inode.c @@ -33,7 +33,7 @@ void init_inodes(unsigned int inodes, struct inode_stat *stat, /* Initialize the inode-related state. */ struct inode *node; - int i; + unsigned int i; assert(inodes > 0); assert(nr_indexed_entries >= 0); @@ -134,7 +134,7 @@ static int parent_index_hash(struct inode *parent, index_t index) /*===========================================================================* * purge_inode * *===========================================================================*/ -void purge_inode(struct inode *parent) +static void purge_inode(struct inode *parent) { /* Delete a deletable inode to make room for a new inode. */ @@ -149,7 +149,7 @@ void purge_inode(struct inode *parent) */ static int last_checked = 0; struct inode *node; - int count; + unsigned int count; assert(TAILQ_EMPTY(&unused_inodes)); @@ -484,7 +484,6 @@ void ref_inode(struct inode *node) */ CHECK_INODE(node); - assert(node->i_count >= 0); node->i_count++; } @@ -581,7 +580,7 @@ int is_inode_deleted(struct inode *node) /*===========================================================================* * fs_putnode * *===========================================================================*/ -int fs_putnode(void) +int fs_putnode(ino_t ino_nr, unsigned int count) { /* Find the inode specified by the request message, and decrease its * reference count. @@ -589,14 +588,13 @@ int fs_putnode(void) struct inode *node; /* Get the inode specified by its number. */ - if ((node = find_inode(fs_m_in.m_vfs_fs_putnode.inode)) == NULL) + if ((node = find_inode(ino_nr)) == NULL) return EINVAL; /* Decrease the reference count. */ - node->i_count -= fs_m_in.m_vfs_fs_putnode.count - 1; - - assert(node->i_count > 0); + assert(node->i_count >= count); + node->i_count -= count - 1; put_inode(node); return OK; diff --git a/minix/lib/libvtreefs/inode.h b/minix/lib/libvtreefs/inode.h index a20445bf7..6160ac771 100644 --- a/minix/lib/libvtreefs/inode.h +++ b/minix/lib/libvtreefs/inode.h @@ -18,7 +18,7 @@ struct inode { /* Inode metadata */ struct inode_stat i_stat; /* POSIX attributes */ char i_name[PNAME_MAX + 1]; /* name of the inode in the parent */ - int i_count; /* reference count */ + unsigned int i_count; /* reference count */ index_t i_index; /* index number in parent / NO_INDEX */ int i_indexed; /* number of indexed entries */ cbdata_t i_cbdata; /* callback data */ diff --git a/minix/lib/libvtreefs/link.c b/minix/lib/libvtreefs/link.c index a1d4d9908..61711b228 100644 --- a/minix/lib/libvtreefs/link.c +++ b/minix/lib/libvtreefs/link.c @@ -5,7 +5,7 @@ /*===========================================================================* * fs_rdlink * *===========================================================================*/ -int fs_rdlink(void) +ssize_t fs_rdlink(ino_t ino_nr, struct fsdriver_data *data, size_t bytes) { /* Retrieve symbolic link target. */ @@ -14,7 +14,7 @@ int fs_rdlink(void) size_t len; int r; - if ((node = find_inode(fs_m_in.m_vfs_fs_rdlink.inode)) == NULL) + if ((node = find_inode(ino_nr)) == NULL) return EINVAL; /* Call the rdlink hook. */ @@ -28,14 +28,12 @@ int fs_rdlink(void) len = strlen(path); assert(len > 0 && len < sizeof(path)); - if (len > fs_m_in.m_vfs_fs_rdlink.mem_size) - len = fs_m_in.m_vfs_fs_rdlink.mem_size; + if (len > bytes) + len = bytes; /* Copy out the result. */ - r = sys_safecopyto(fs_m_in.m_source, fs_m_in.m_vfs_fs_rdlink.grant, 0, - (vir_bytes) path, len); - if (r != OK) return r; + if ((r = fsdriver_copyout(data, 0, path, len)) != OK) + return r; - fs_m_out.m_fs_vfs_rdlink.nbytes = len; - return OK; + return len; } diff --git a/minix/lib/libvtreefs/mount.c b/minix/lib/libvtreefs/mount.c index ee18941f0..e9bfeaf6d 100644 --- a/minix/lib/libvtreefs/mount.c +++ b/minix/lib/libvtreefs/mount.c @@ -1,21 +1,23 @@ /* VTreeFS - mount.c - by Alen Stojanov and David van Moolenbroek */ #include "inc.h" +#include /*===========================================================================* - * fs_readsuper * + * fs_mount * *===========================================================================*/ -int fs_readsuper(void) +int fs_mount(dev_t dev, unsigned int flags, struct fsdriver_node *root_node, + unsigned int *res_flags) { /* This function gets the root inode and sends back its details. */ struct inode *root; /* Get the device number, for stat requests. */ - fs_dev = fs_m_in.m_vfs_fs_readsuper.device; + fs_dev = dev; /* The VTreeFS must not be mounted as a root file system. */ - if (fs_m_in.m_vfs_fs_readsuper.flags & REQ_ISROOT) + if (flags & REQ_ISROOT) return EINVAL; /* Get the root inode and increase its reference count. */ @@ -27,15 +29,14 @@ int fs_readsuper(void) vtreefs_hooks->init_hook(); /* Return the root inode's properties. */ - fs_m_out.m_fs_vfs_readsuper.inode = get_inode_number(root); - fs_m_out.m_fs_vfs_readsuper.mode = root->i_stat.mode; - fs_m_out.m_fs_vfs_readsuper.file_size = root->i_stat.size; - fs_m_out.m_fs_vfs_readsuper.uid = root->i_stat.uid; - fs_m_out.m_fs_vfs_readsuper.gid = root->i_stat.gid; - fs_m_out.m_fs_vfs_readsuper.device = NO_DEV; - fs_m_out.m_fs_vfs_readsuper.flags = RES_NOFLAGS; + root_node->fn_ino_nr = get_inode_number(root); + root_node->fn_mode = root->i_stat.mode; + root_node->fn_size = root->i_stat.size; + root_node->fn_uid = root->i_stat.uid; + root_node->fn_gid = root->i_stat.gid; + root_node->fn_dev = NO_DEV; - fs_mounted = TRUE; + *res_flags = RES_NOFLAGS; return OK; } @@ -43,7 +44,7 @@ int fs_readsuper(void) /*===========================================================================* * fs_unmount * *===========================================================================*/ -int fs_unmount(void) +void fs_unmount(void) { /* Unmount the file system. */ @@ -57,9 +58,4 @@ int fs_unmount(void) /* The system is unmounted. Call the cleanup hook. */ if (vtreefs_hooks->cleanup_hook != NULL) vtreefs_hooks->cleanup_hook(); - - /* We can now be shut down safely. */ - fs_mounted = FALSE; - - return OK; } diff --git a/minix/lib/libvtreefs/path.c b/minix/lib/libvtreefs/path.c index a06c9709c..686a79e3a 100644 --- a/minix/lib/libvtreefs/path.c +++ b/minix/lib/libvtreefs/path.c @@ -2,313 +2,59 @@ #include "inc.h" -/*===========================================================================* - * access_as_dir * - *===========================================================================*/ -static int access_as_dir(struct inode *node, vfs_ucred_t *ucred) -{ - /* Check whether the given inode may be accessed as directory. - * Return OK or an appropriate error code. - */ - mode_t mask; - int i; - - /* The inode must be a directory to begin with. */ - if (!S_ISDIR(node->i_stat.mode)) return ENOTDIR; - - /* The caller must have search access to the directory. - * Root always does. - */ - if (ucred->vu_uid == SUPER_USER) return OK; - - if (ucred->vu_uid == node->i_stat.uid) mask = S_IXUSR; - else if (ucred->vu_gid == node->i_stat.gid) mask = S_IXGRP; - else { - mask = S_IXOTH; - - for (i = 0; i < ucred->vu_ngroups; i++) { - if (ucred->vu_sgroups[i] == node->i_stat.gid) { - mask = S_IXGRP; - - break; - } - } - } - - return (node->i_stat.mode & mask) ? OK : EACCES; -} - -/*===========================================================================* - * next_name * - *===========================================================================*/ -static int next_name(char **ptr, char **start, char name[PNAME_MAX+1]) -{ - /* Get the next path component from a path. - */ - char *p; - int i; - - for (p = *ptr; *p == '/'; p++); - - *start = p; - - if (*p) { - for (i = 0; *p && *p != '/' && i <= PNAME_MAX; p++, i++) - name[i] = *p; - - if (i > PNAME_MAX) - return ENAMETOOLONG; - - name[i] = 0; - } else { - strcpy(name, "."); - } - - *ptr = p; - return OK; -} - -/*===========================================================================* - * go_up * - *===========================================================================*/ -static int go_up(struct inode *node, struct inode **parent) -{ - /* Given a directory inode, progress into the parent directory. - */ - - *parent = get_parent_inode(node); - - /* Trapped in a deleted directory? Should not be possible. */ - if (*parent == NULL) - return ENOENT; - - ref_inode(*parent); - - return OK; -} - -/*===========================================================================* - * go_down * - *===========================================================================*/ -static int go_down(struct inode *parent, char *name, struct inode **child) -{ - /* Given a directory inode and a name, progress into a directory entry. - */ - int r; - - /* Call the lookup hook, if present, before doing the actual lookup. */ - if (!is_inode_deleted(parent) && vtreefs_hooks->lookup_hook != NULL) { - r = vtreefs_hooks->lookup_hook(parent, name, - get_inode_cbdata(parent)); - if (r != OK) return r; - } - - if ((*child = get_inode_by_name(parent, name)) == NULL) - return ENOENT; - - ref_inode(*child); - - return OK; -} - -/*===========================================================================* - * resolve_link * - *===========================================================================*/ -static int resolve_link(struct inode *node, char pptr[PATH_MAX], char *tail) -{ - /* Given a symbolic link, resolve and return the contents of the link. - */ - char path[PATH_MAX]; - size_t len; - int r; - - assert(vtreefs_hooks->rdlink_hook != NULL); - assert(!is_inode_deleted(node)); - - r = vtreefs_hooks->rdlink_hook(node, path, sizeof(path), - get_inode_cbdata(node)); - if (r != OK) return r; - - len = strlen(path); - assert(len > 0 && len < sizeof(path)); - - if (len + strlen(tail) >= sizeof(path)) - return ENAMETOOLONG; - - strlcat(path, tail, sizeof(path)); - - strlcpy(pptr, path, PATH_MAX); - - return OK; -} - /*===========================================================================* * fs_lookup * *===========================================================================*/ -int fs_lookup(void) +int fs_lookup(ino_t dir_nr, char *name, struct fsdriver_node *node_details, + int *is_mountpt) { /* Resolve a path string to an inode. */ - ino_t dir_ino_nr, root_ino_nr; - struct inode *cur_ino, *next_ino, *root_ino; - char path[PATH_MAX], name[PNAME_MAX+1]; - char *ptr, *last; - vfs_ucred_t ucred; - size_t len; - int r, r2, symloop; + struct inode *node, *child; + int r; - dir_ino_nr = fs_m_in.m_vfs_fs_lookup.dir_ino; - root_ino_nr = fs_m_in.m_vfs_fs_lookup.root_ino; - len = fs_m_in.m_vfs_fs_lookup.path_len; - - /* Fetch the path name. */ - if (len < 1 || len > PATH_MAX) + if ((node = find_inode(dir_nr)) == NULL) return EINVAL; - r = sys_safecopyfrom(fs_m_in.m_source, - fs_m_in.m_vfs_fs_lookup.grant_path, 0, (vir_bytes) path, - (phys_bytes) len); - if (r != OK) return r; + if (!S_ISDIR(node->i_stat.mode)) + return ENOTDIR; - if (path[len-1] != 0) return EINVAL; + if (strlen(name) > PNAME_MAX) + return ENAMETOOLONG; - /* Fetch the caller's credentials. */ - if (fs_m_in.m_vfs_fs_lookup.flags & PATH_GET_UCRED) { - assert(fs_m_in.m_vfs_fs_lookup.ucred_size == sizeof(ucred)); - - r = sys_safecopyfrom(fs_m_in.m_source, - fs_m_in.m_vfs_fs_lookup.grant_ucred, 0, - (vir_bytes) &ucred, fs_m_in.m_vfs_fs_lookup.ucred_size); - - if (r != OK) - return r; - } - else { - ucred.vu_uid = fs_m_in.m_vfs_fs_lookup.uid; - ucred.vu_gid = fs_m_in.m_vfs_fs_lookup.gid; - ucred.vu_ngroups = 0; - } - - /* Start the actual lookup. */ - if ((cur_ino = get_inode(dir_ino_nr)) == NULL) - return EINVAL; - - /* Chroot'ed environment? */ - if (root_ino_nr > 0) - root_ino = find_inode(root_ino_nr); - else - root_ino = NULL; - - symloop = 0; - - for (ptr = last = path; ptr[0] != 0; ) { - /* There is more path to process. That means that the current - * file is now being accessed as a directory. Check type and - * permissions. + if (!strcmp(name, ".")) { + /* Stay in the given directory. */ + child = node; + } else if (!strcmp(name, "..")) { + /* Progress into the parent directory. */ + if ((child = get_parent_inode(node)) == NULL) + return ENOENT; /* deleted? should not be possible */ + } else { + /* Progress into a directory entry. Call the lookup hook, if + * present, before doing the actual lookup. */ - if ((r = access_as_dir(cur_ino, &ucred)) != OK) - break; - - /* Get the next path component. The result is a non-empty - * string. - */ - if ((r = next_name(&ptr, &last, name)) != OK) - break; - - if (!strcmp(name, ".") || - (cur_ino == root_ino && !strcmp(name, ".."))) - continue; - - if (!strcmp(name, "..")) { - if (cur_ino == get_root_inode()) - r = ELEAVEMOUNT; - else - r = go_up(cur_ino, &next_ino); - } else { - r = go_down(cur_ino, name, &next_ino); - - /* Perform symlink resolution if we have to. */ - if (r == OK && S_ISLNK(next_ino->i_stat.mode) && - (ptr[0] != '\0' || - !(fs_m_in.m_vfs_fs_lookup.flags & PATH_RET_SYMLINK))) { - - if (++symloop == _POSIX_SYMLOOP_MAX) { - put_inode(next_ino); - - r = ELOOP; - - break; - } - - /* Resolve the symlink, and append the - * remaining unresolved part of the path. - */ - r = resolve_link(next_ino, path, ptr); - - put_inode(next_ino); - - if (r != OK) - break; - - /* If the symlink is absolute, return it to - * VFS. - */ - if (path[0] == '/') { - r = ESYMLINK; - last = path; - - break; - } - - ptr = path; - continue; - } + if (!is_inode_deleted(node) && + vtreefs_hooks->lookup_hook != NULL) { + r = vtreefs_hooks->lookup_hook(node, name, + get_inode_cbdata(node)); + if (r != OK) return r; } - if (r != OK) - break; - - /* We have found a new file. Continue from this file. */ - assert(next_ino != NULL); - - put_inode(cur_ino); - - cur_ino = next_ino; + if ((child = get_inode_by_name(node, name)) == NULL) + return ENOENT; } - /* If an error occurred, close the file and return error information. - */ - if (r != OK) { - put_inode(cur_ino); + /* On success, open the resulting file and return its details. */ + ref_inode(child); - /* We'd need support for this here. */ - assert(r != EENTERMOUNT); + node_details->fn_ino_nr = get_inode_number(child); + node_details->fn_mode = child->i_stat.mode; + node_details->fn_size = child->i_stat.size; + node_details->fn_uid = child->i_stat.uid; + node_details->fn_gid = child->i_stat.gid; + node_details->fn_dev = child->i_stat.dev; - /* Copy back the path if we resolved at least one symlink. */ - if (symloop > 0 && (r == ELEAVEMOUNT || r == ESYMLINK)) { - r2 = sys_safecopyto(fs_m_in.m_source, - fs_m_in.m_vfs_fs_lookup.grant_path, 0, - (vir_bytes) path, strlen(path) + 1); - - if (r2 != OK) - r = r2; - } - - if (r == ELEAVEMOUNT || r == ESYMLINK) { - fs_m_out.m_fs_vfs_lookup.offset = (int) (last - path); - fs_m_out.m_fs_vfs_lookup.symloop = symloop; - } - - return r; - } - - /* On success, leave the resulting file open and return its details. */ - fs_m_out.m_fs_vfs_lookup.inode = get_inode_number(cur_ino); - fs_m_out.m_fs_vfs_lookup.mode = cur_ino->i_stat.mode; - fs_m_out.m_fs_vfs_lookup.file_size = cur_ino->i_stat.size; - fs_m_out.m_fs_vfs_lookup.uid = cur_ino->i_stat.uid; - fs_m_out.m_fs_vfs_lookup.gid = cur_ino->i_stat.gid; - fs_m_out.m_fs_vfs_lookup.device = cur_ino->i_stat.dev; + *is_mountpt = FALSE; return OK; } diff --git a/minix/lib/libvtreefs/proto.h b/minix/lib/libvtreefs/proto.h index 6c558da73..6bc5083b1 100644 --- a/minix/lib/libvtreefs/proto.h +++ b/minix/lib/libvtreefs/proto.h @@ -11,31 +11,34 @@ void put_inode(struct inode *node); void ref_inode(struct inode *node); int get_inode_number(struct inode *node); int is_inode_deleted(struct inode *node); -int fs_putnode(void); +int fs_putnode(ino_t ino_nr, unsigned int count); /* link.c */ -int fs_rdlink(void); +ssize_t fs_rdlink(ino_t ino_nr, struct fsdriver_data *data, size_t bytes); /* mount.c */ -int fs_readsuper(void); -int fs_unmount(void); +int fs_mount(dev_t dev, unsigned int flags, struct fsdriver_node *root_node, + unsigned int *res_flags); +void fs_unmount(void); + +/* main.c */ +void fs_other(const message *m_ptr, int ipc_status); /* path.c */ -int fs_lookup(void); +int fs_lookup(ino_t dir_nr, char *name, struct fsdriver_node *node, + int *is_mountpt); /* read.c */ -int fs_read(void); -int fs_getdents(void); +ssize_t fs_read(ino_t ino_nr, struct fsdriver_data *data, size_t bytes, + off_t pos, int call); +ssize_t fs_getdents(ino_t ino_nr, struct fsdriver_data *data, size_t bytes, + off_t *pos); /* sdbm.c */ long sdbm_hash(char *str, int len); /* stadir.c */ -int fs_stat(void); -int fs_statvfs(void); - -/* utility.c */ -int no_sys(void); -int do_noop(void); +int fs_stat(ino_t ino_nr, struct stat *buf); +int fs_statvfs(struct statvfs *buf); #endif /* _VTREEFS_PROTO_H */ diff --git a/minix/lib/libvtreefs/read.c b/minix/lib/libvtreefs/read.c index ad3d6c202..85b99262c 100644 --- a/minix/lib/libvtreefs/read.c +++ b/minix/lib/libvtreefs/read.c @@ -2,40 +2,33 @@ #include "inc.h" #include -#include #define GETDENTS_BUFSIZ 4096 -#define DWORD_ALIGN(len) (((len) + sizeof(long) - 1) & ~(sizeof(long) - 1)) /*===========================================================================* * fs_read * *===========================================================================*/ -int fs_read(void) +ssize_t fs_read(ino_t ino_nr, struct fsdriver_data *data, size_t bytes, + off_t pos, int __unused call) { /* Read from a file. */ - cp_grant_id_t gid; struct inode *node; - off_t pos; size_t len; char *ptr; int r; - /* Try to get inode by to its inode number. */ - if ((node = find_inode(fs_m_in.m_vfs_fs_readwrite.inode)) == NULL) + /* Try to get inode by its inode number. */ + if ((node = find_inode(ino_nr)) == NULL) return EINVAL; /* Check whether the node is a regular file. */ if (!S_ISREG(node->i_stat.mode)) return EINVAL; - /* Get the values from the request message. */ - gid = fs_m_in.m_vfs_fs_readwrite.grant; - pos = fs_m_in.m_vfs_fs_readwrite.seek_pos; - /* Call the read hook, if any. */ if (!is_inode_deleted(node) && vtreefs_hooks->read_hook != NULL) { - len = fs_m_in.m_vfs_fs_readwrite.nbytes; + len = bytes; /* On success, the read hook provides us with a pointer to the * resulting data. This avoids copying overhead. @@ -43,51 +36,41 @@ int fs_read(void) r = vtreefs_hooks->read_hook(node, pos, &ptr, &len, get_inode_cbdata(node)); - assert(len <= fs_m_in.m_vfs_fs_readwrite.nbytes); + assert(len <= bytes); /* Copy the resulting data to user space. */ - if (r == OK && len > 0) { - r = sys_safecopyto(fs_m_in.m_source, fs_m_in.m_vfs_fs_readwrite.grant, - 0, (vir_bytes) ptr, len); - } + if (r == OK && len > 0) + r = fsdriver_copyout(data, 0, ptr, len); } else { /* Feign an empty file. */ r = OK; len = 0; } - if (r == OK) { - fs_m_out.m_fs_vfs_readwrite.seek_pos = pos + len; - fs_m_out.m_fs_vfs_readwrite.nbytes = len; - } - - return r; + return (r != OK) ? r : len; } /*===========================================================================* * fs_getdents * *===========================================================================*/ -int fs_getdents(void) +ssize_t fs_getdents(ino_t ino_nr, struct fsdriver_data *data, size_t bytes, + off_t *posp) { /* Retrieve directory entries. */ - struct inode *node, *child = NULL; - struct dirent *dent; - char *name; - size_t len, off, user_off, user_left; + struct fsdriver_dentry fsdentry; + struct inode *node, *child; + const char *name; off_t pos; int r, skip, get_next, indexed; static char buf[GETDENTS_BUFSIZ]; - if (fs_m_in.m_vfs_fs_getdents.seek_pos >= ULONG_MAX) + if (*posp >= ULONG_MAX) return EIO; - if ((node = find_inode(fs_m_in.m_vfs_fs_getdents.inode)) == NULL) + if ((node = find_inode(ino_nr)) == NULL) return EINVAL; - off = 0; - user_off = 0; - user_left = fs_m_in.m_vfs_fs_getdents.mem_size; indexed = node->i_indexed; get_next = FALSE; child = NULL; @@ -98,8 +81,12 @@ int fs_getdents(void) if (r != OK) return r; } - for (pos = fs_m_in.m_vfs_fs_getdents.seek_pos; ; pos++) { + fsdriver_dentry_init(&fsdentry, data, bytes, buf, sizeof(buf)); + + do { /* Determine which inode and name to use for this entry. */ + pos = (*posp)++; + if (pos == 0) { /* The "." entry. */ child = node; @@ -158,56 +145,13 @@ int fs_getdents(void) name = child->i_name; } - /* record length incl. alignment. */ - len = _DIRENT_RECLEN(dent, strlen(name)); - - /* Is the user buffer too small to store another record? */ - if (user_off + off + len > user_left) { - /* Is the user buffer too small for even a single - * record? - */ - if (user_off == 0 && off == 0) - return EINVAL; - - break; - } - - /* If our own buffer cannot contain the new record, copy out - * first. - */ - if (off + len > sizeof(buf)) { - r = sys_safecopyto(fs_m_in.m_source, fs_m_in.m_vfs_fs_getdents.grant, - user_off, (vir_bytes) buf, off); - if (r != OK) return r; - - user_off += off; - user_left -= off; - off = 0; - } - - /* Fill in the actual directory entry. */ - dent = (struct dirent *) &buf[off]; - dent->d_ino = (ino_t) get_inode_number(child); - dent->d_reclen = len; - dent->d_type = fs_mode_to_type(child->i_stat.mode); - dent->d_namlen = strlen(name); - strcpy(dent->d_name, name); - - off += len; - } - - /* If there is anything left in our own buffer, copy that out now. */ - if (off > 0) { - r = sys_safecopyto(fs_m_in.m_source, fs_m_in.m_vfs_fs_getdents.grant, - user_off, (vir_bytes) buf, off); - if (r != OK) + /* Add the directory entry to the output. */ + r = fsdriver_dentry_add(&fsdentry, + (ino_t) get_inode_number(child), name, strlen(name), + IFTODT(child->i_stat.mode)); + if (r < 0) return r; + } while (r > 0); - user_off += off; - } - - fs_m_out.m_fs_vfs_getdents.seek_pos = pos; - fs_m_out.m_fs_vfs_getdents.nbytes = user_off; - - return OK; + return fsdriver_dentry_finish(&fsdentry); } diff --git a/minix/lib/libvtreefs/stadir.c b/minix/lib/libvtreefs/stadir.c index 615d886fb..f29e3e6d1 100644 --- a/minix/lib/libvtreefs/stadir.c +++ b/minix/lib/libvtreefs/stadir.c @@ -2,37 +2,30 @@ #include "inc.h" -#include -#include -#include - /*===========================================================================* * fs_stat * *===========================================================================*/ -int fs_stat(void) +int fs_stat(ino_t ino_nr, struct stat *buf) { /* Retrieve file status. */ char path[PATH_MAX]; - struct stat statbuf; time_t cur_time; struct inode *node; int r; - if ((node = find_inode(fs_m_in.m_vfs_fs_stat.inode)) == NULL) + if ((node = find_inode(ino_nr)) == NULL) return EINVAL; - memset(&statbuf, 0, sizeof(struct stat)); - /* Fill in the basic info. */ - statbuf.st_dev = fs_dev; - statbuf.st_ino = get_inode_number(node); - statbuf.st_mode = node->i_stat.mode; - statbuf.st_nlink = !is_inode_deleted(node); - statbuf.st_uid = node->i_stat.uid; - statbuf.st_gid = node->i_stat.gid; - statbuf.st_rdev = (dev_t) node->i_stat.dev; - statbuf.st_size = node->i_stat.size; + buf->st_dev = fs_dev; + buf->st_ino = get_inode_number(node); + buf->st_mode = node->i_stat.mode; + buf->st_nlink = !is_inode_deleted(node); + buf->st_uid = node->i_stat.uid; + buf->st_gid = node->i_stat.gid; + buf->st_rdev = (dev_t) node->i_stat.dev; + buf->st_size = node->i_stat.size; /* If it is a symbolic link, return the size of the link target. */ if (S_ISLNK(node->i_stat.mode) && vtreefs_hooks->rdlink_hook != NULL) { @@ -40,34 +33,28 @@ int fs_stat(void) get_inode_cbdata(node)); if (r == OK) - statbuf.st_size = strlen(path); + buf->st_size = strlen(path); } /* Take the current time as file time for all files. */ cur_time = time(NULL); - statbuf.st_atime = cur_time; - statbuf.st_mtime = cur_time; - statbuf.st_ctime = cur_time; + buf->st_atime = cur_time; + buf->st_mtime = cur_time; + buf->st_ctime = cur_time; - /* Copy the struct to user space. */ - return sys_safecopyto(fs_m_in.m_source, fs_m_in.m_vfs_fs_stat.grant, 0, - (vir_bytes) &statbuf, (phys_bytes) sizeof(statbuf)); + return OK; } /*===========================================================================* * fs_statvfs * *===========================================================================*/ -int fs_statvfs(void) +int fs_statvfs(struct statvfs *buf) { /* Retrieve file system statistics. */ - struct statvfs statvfs; - memset(&statvfs, 0, sizeof(statvfs)); + buf->f_flag = ST_NOTRUNC; + buf->f_namemax = PNAME_MAX; - statvfs.f_flag = ST_NOTRUNC; - statvfs.f_namemax = PNAME_MAX; - - return sys_safecopyto(fs_m_in.m_source, fs_m_in.m_vfs_fs_statvfs.grant, - 0, (vir_bytes) &statvfs, sizeof(statvfs)); + return OK; } diff --git a/minix/lib/libvtreefs/table.c b/minix/lib/libvtreefs/table.c index 468dccba7..193d89660 100644 --- a/minix/lib/libvtreefs/table.c +++ b/minix/lib/libvtreefs/table.c @@ -3,43 +3,15 @@ #define _TABLE #include "inc.h" -int (*fs_call_vec[])(void) = { - no_sys, /* 0 */ - no_sys, /* 1 getnode */ - fs_putnode, /* 2 putnode */ - no_sys, /* 3 slink */ - no_sys, /* 4 ftrunc */ - no_sys, /* 5 chown */ - no_sys, /* 6 chmod */ - do_noop, /* 7 inhibread */ - fs_stat, /* 8 stat */ - no_sys, /* 9 utime */ - fs_statvfs, /* 10 statvfs */ - no_sys, /* 11 bread */ - no_sys, /* 12 bwrite */ - no_sys, /* 13 unlink */ - no_sys, /* 14 rmdir */ - fs_unmount, /* 15 unmount */ - do_noop, /* 16 sync */ - do_noop, /* 17 new_driver */ - no_sys, /* 18 flush */ - fs_read, /* 19 read */ - no_sys, /* 20 write */ - no_sys, /* 21 mknod */ - no_sys, /* 22 mkdir */ - no_sys, /* 23 create */ - no_sys, /* 24 link */ - no_sys, /* 25 rename */ - fs_lookup, /* 26 lookup */ - no_sys, /* 27 mountpoint */ - fs_readsuper, /* 28 readsuper */ - no_sys, /* 29 newnode */ - fs_rdlink, /* 30 rdlink */ - fs_getdents, /* 31 getdents */ - no_sys, /* 32 peek */ - no_sys, /* 33 bpeek */ +struct fsdriver vtreefs_table = { + .fdr_mount = fs_mount, + .fdr_unmount = fs_unmount, + .fdr_lookup = fs_lookup, + .fdr_putnode = fs_putnode, + .fdr_read = fs_read, + .fdr_getdents = fs_getdents, + .fdr_rdlink = fs_rdlink, + .fdr_stat = fs_stat, + .fdr_statvfs = fs_statvfs, + .fdr_other = fs_other }; - -/* This should not fail with "array size is negative": */ -extern int - dummy[sizeof(fs_call_vec) == NREQS * sizeof(fs_call_vec[0]) ? 1 : -1]; diff --git a/minix/lib/libvtreefs/utility.c b/minix/lib/libvtreefs/utility.c deleted file mode 100644 index d4b0e86e6..000000000 --- a/minix/lib/libvtreefs/utility.c +++ /dev/null @@ -1,29 +0,0 @@ -/* VTreeFS - utility.c - by Alen Stojanov and David van Moolenbroek */ - -#include "inc.h" - -/*===========================================================================* - * no_sys * - *===========================================================================*/ -int no_sys(void) -{ - /* This call is not recognized by VTreeFS. If a message hook is - * defined, let it handle the call; otherwise return ENOSYS. - */ - - if (vtreefs_hooks->message_hook != NULL) - return vtreefs_hooks->message_hook(&fs_m_in); - - return ENOSYS; -} - -/*===========================================================================* - * do_noop * - *===========================================================================*/ -int do_noop(void) -{ - /* This call has no effect. - */ - - return OK; -} diff --git a/minix/lib/libvtreefs/vtreefs.c b/minix/lib/libvtreefs/vtreefs.c index 1cc59ed9e..ebdd0e9d2 100644 --- a/minix/lib/libvtreefs/vtreefs.c +++ b/minix/lib/libvtreefs/vtreefs.c @@ -2,10 +2,6 @@ #include "inc.h" -static int get_work(void); -static void send_reply(int err, int transid); -static void got_signal(int signal); - static unsigned int inodes; static struct inode_stat *root_stat; static index_t root_entries; @@ -21,12 +17,23 @@ static int init_server(int UNUSED(type), sef_init_info_t *UNUSED(info)) /* Initialize the virtual tree. */ init_inodes(inodes, root_stat, root_entries); - /* Do not yet allow any requests except REQ_READSUPER. */ - fs_mounted = FALSE; - return OK; } +/*===========================================================================* + * got_signal * + *===========================================================================*/ +static void got_signal(int signal) +{ + /* We received a signal. + */ + + if (signal != SIGTERM) + return; + + fsdriver_terminate(); +} + /*===========================================================================* * sef_local_startup * *===========================================================================*/ @@ -42,18 +49,36 @@ static void sef_local_startup(void) sef_startup(); } +/*===========================================================================* + * fs_other * + *===========================================================================*/ +void fs_other(const message *m_ptr, int __unused ipc_status) +{ + /* We received a message that is not among the recognized file system + * requests. Call the message hook, if there is one. + */ + message msg; + + if (vtreefs_hooks->message_hook != NULL) { + /* Not all of vtreefs's users play nice with the message, so + * make a copy to allow it to be modified. + */ + msg = *m_ptr; + + vtreefs_hooks->message_hook(&msg); + } +} + /*===========================================================================* * start_vtreefs * *===========================================================================*/ void start_vtreefs(struct fs_hooks *hooks, unsigned int nr_inodes, struct inode_stat *stat, index_t nr_indexed_entries) { - /* This is the main routine of this service. The main loop consists of - * three major activities: getting new work, processing the work, and - * sending the reply. The loop exits when the process is signaled to - * exit; due to limitations of SEF, it can not return to the caller. + /* This is the main routine of this service. It uses the main loop as + * provided by the fsdriver library. The routine returns once the file + * system has been unmounted and the process is signaled to exit. */ - int call_nr, err, transid; /* Use global variables to work around the inability to pass parameters * through SEF to the initialization function.. @@ -65,95 +90,7 @@ void start_vtreefs(struct fs_hooks *hooks, unsigned int nr_inodes, sef_local_startup(); - for (;;) { - get_work(); - - transid = TRNS_GET_ID(fs_m_in.m_type); - fs_m_in.m_type = TRNS_DEL_ID(fs_m_in.m_type); - if (fs_m_in.m_type == 0) { - assert(!IS_VFS_FS_TRANSID(transid)); - fs_m_in.m_type = transid; /* Backwards compat. */ - transid = 0; - } else - assert(IS_VFS_FS_TRANSID(transid)); - - call_nr = fs_m_in.m_type; - - if (fs_m_in.m_source != VFS_PROC_NR) { - if (vtreefs_hooks->message_hook != NULL) { - /* If the request is not among the recognized - * requests, call the message hook. - */ - vtreefs_hooks->message_hook(&fs_m_in); - } - - continue; - } - - if (fs_mounted || call_nr == REQ_READSUPER) { - call_nr -= FS_BASE; - - if (call_nr >= 0 && call_nr < NREQS) { - err = (*fs_call_vec[call_nr])(); - } else { - err = ENOSYS; - } - } - else err = EINVAL; - - send_reply(err, transid); - } -} - -/*===========================================================================* - * get_work * - *===========================================================================*/ -static int get_work(void) -{ - /* Retrieve work. Return the call number. - */ - int r; - - if ((r = sef_receive(ANY, &fs_m_in)) != OK) - panic("receive failed: %d", r); - - return fs_m_in.m_type; -} - -/*===========================================================================* - * send_reply * - *===========================================================================*/ -static void send_reply(int err, int transid) -{ - /* Send a reply to the caller. - */ - int r; - - fs_m_out.m_type = err; - if (IS_VFS_FS_TRANSID(transid)) { - fs_m_out.m_type = TRNS_ADD_ID(fs_m_out.m_type, transid); - } - - if ((r = ipc_send(fs_m_in.m_source, &fs_m_out)) != OK) - panic("unable to send reply: %d", r); -} - -/*===========================================================================* - * got_signal * - *===========================================================================*/ -static void got_signal(int signal) -{ - /* We received a signal. If it is a termination signal, and the file - * system has already been unmounted, clean up and exit. - */ - - if (signal != SIGTERM) - return; - - if (fs_mounted) - return; + fsdriver_task(&vtreefs_table); cleanup_inodes(); - - exit(0); } diff --git a/minix/servers/devman/Makefile b/minix/servers/devman/Makefile index 84d67e654..770cf575d 100644 --- a/minix/servers/devman/Makefile +++ b/minix/servers/devman/Makefile @@ -1,7 +1,7 @@ PROG = devman SRCS = main.c device.c buf.c bind.c -DPADD+= ${LIBSYS} -LDADD = -lvtreefs -lsys +DPADD+= ${LIBVTREEFS} ${LIBFSDRIVER} ${LIBSYS} +LDADD+= -lvtreefs -lfsdriver -lsys .include