PFS: use libfsdriver
In order to avoid creating libfsdriver exceptions, two changes to VFS are necessary: - the returned position field for reads/writes is no longer abused to return the new pipe size; VFS is perfectly capable of updating the size itself; - during system startup, PFS is now sent a mount request, just like all other file systems. In proper "two steps forward, one step back" fashion, the latter point has the consequence that PFS can no longer drop its privileges at startup. This is probably best resolved with a more general solution for all boot image system services. The upside is that PFS no longer needs to be linked with libc. Change-Id: I92e2410cdb0d93d0e6107bae10bc08efc2dbb8b3
This commit is contained in:
parent
2e89653e65
commit
f859061eaf
20 changed files with 213 additions and 404 deletions
|
@ -1,11 +1,9 @@
|
|||
# Makefile for Pipe File System (PFS)
|
||||
PROG= pfs
|
||||
SRCS= open.c table.c inode.c main.c super.c link.c \
|
||||
buffer.c read.c misc.c mount.c utility.c stadir.c
|
||||
buffer.c read.c misc.c mount.c stadir.c
|
||||
|
||||
DPADD+= ${LIBCHARDRIVER} ${LIBSYS}
|
||||
LDADD+= -lchardriver -lsys
|
||||
|
||||
LDADD+= -lc
|
||||
DPADD+= ${LIBFSDRIVER} ${LIBSYS}
|
||||
LDADD+= -lfsdriver -lsys
|
||||
|
||||
.include <minix.service.mk>
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
#include "fs.h"
|
||||
#include "buf.h"
|
||||
#include "inode.h"
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static struct buf *new_block(dev_t dev, ino_t inum);
|
||||
|
||||
|
|
|
@ -11,20 +11,23 @@
|
|||
#include <sys/types.h>
|
||||
#include <minix/const.h>
|
||||
#include <minix/type.h>
|
||||
#include <minix/dmap.h>
|
||||
|
||||
#include <minix/vfsif.h>
|
||||
#include <lib.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <minix/syslib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <minix/sysutil.h>
|
||||
|
||||
#include <minix/fsdriver.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "const.h"
|
||||
#include "proto.h"
|
||||
#include "glo.h"
|
||||
#include "buf.h"
|
||||
#include "inode.h"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,16 +7,12 @@
|
|||
#define EXTERN
|
||||
#endif
|
||||
|
||||
#include <minix/vfsif.h>
|
||||
|
||||
/* The following variables are used for returning results to the caller. */
|
||||
EXTERN int err_code; /* temporary storage for error number */
|
||||
|
||||
EXTERN int(*fs_call_vec[]) (message *fs_m_in, message *fs_m_out);
|
||||
extern struct fsdriver pfs_table;
|
||||
|
||||
EXTERN int exitsignaled;
|
||||
EXTERN int busy;
|
||||
EXTERN int unmountdone;
|
||||
|
||||
/* Inode map. */
|
||||
EXTERN bitchunk_t inodemap[FS_BITMAP_CHUNKS(PFS_NR_INODES)];
|
||||
|
|
|
@ -15,9 +15,6 @@
|
|||
*/
|
||||
|
||||
#include "fs.h"
|
||||
#include "buf.h"
|
||||
#include "inode.h"
|
||||
#include <minix/vfsif.h>
|
||||
|
||||
static void addhash_inode(struct inode * const node);
|
||||
static void unhash_inode(struct inode * const node);
|
||||
|
@ -26,29 +23,21 @@ static void unhash_inode(struct inode * const node);
|
|||
/*===========================================================================*
|
||||
* fs_putnode *
|
||||
*===========================================================================*/
|
||||
int fs_putnode(message *fs_m_in, message *fs_m_out)
|
||||
int fs_putnode(ino_t ino_nr, unsigned int count)
|
||||
{
|
||||
/* Find the inode specified by the request message and decrease its counter.*/
|
||||
|
||||
struct inode *rip;
|
||||
int count;
|
||||
dev_t dev;
|
||||
ino_t inum;
|
||||
|
||||
rip = find_inode(fs_m_in->m_vfs_fs_putnode.inode);
|
||||
rip = find_inode(ino_nr);
|
||||
|
||||
if(!rip) {
|
||||
printf("%s:%d put_inode: inode #%llu not found\n", __FILE__,
|
||||
__LINE__, fs_m_in->m_vfs_fs_putnode.inode);
|
||||
panic("fs_putnode failed");
|
||||
printf("%s:%d put_inode: inode #%llu not found\n", __FILE__,
|
||||
__LINE__, ino_nr);
|
||||
panic("fs_putnode failed");
|
||||
}
|
||||
|
||||
count = fs_m_in->m_vfs_fs_putnode.count;
|
||||
if (count <= 0) {
|
||||
printf("%s:%d put_inode: bad value for count: %d\n", __FILE__,
|
||||
__LINE__, count);
|
||||
panic("fs_putnode failed");
|
||||
} else if(count > rip->i_count) {
|
||||
if (count > rip->i_count) {
|
||||
printf("%s:%d put_inode: count too high: %d > %d\n", __FILE__,
|
||||
__LINE__, count, rip->i_count);
|
||||
panic("fs_putnode failed");
|
||||
|
@ -58,9 +47,8 @@ int fs_putnode(message *fs_m_in, message *fs_m_out)
|
|||
* put_inode(). */
|
||||
rip->i_count -= count - 1;
|
||||
dev = rip->i_dev;
|
||||
inum = rip->i_num;
|
||||
put_inode(rip);
|
||||
if (rip->i_count == 0) put_block(dev, inum);
|
||||
if (rip->i_count == 0) put_block(dev, ino_nr);
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,12 +11,11 @@ EXTERN struct inode {
|
|||
nlink_t i_nlinks; /* how many links to this file */
|
||||
uid_t i_uid; /* user id of the file's owner */
|
||||
gid_t i_gid; /* group number */
|
||||
off_t i_size; /* current file size in bytes */
|
||||
size_t i_size; /* current file size in bytes */
|
||||
time_t i_atime; /* time of last access (V2 only) */
|
||||
time_t i_mtime; /* when was file data last changed */
|
||||
time_t i_ctime; /* when was inode itself changed (V2 only)*/
|
||||
|
||||
/* The following items are not present on the disk. */
|
||||
dev_t i_dev; /* which device is the inode on */
|
||||
dev_t i_rdev; /* which special device is the inode on */
|
||||
ino_t i_num; /* inode number on its (minor) device */
|
||||
|
@ -35,5 +34,4 @@ EXTERN TAILQ_HEAD(unused_inodes_t, inode) unused_inodes;
|
|||
/* inode hashtable */
|
||||
EXTERN LIST_HEAD(inodelist, inode) hash_inodes[INODE_HASH_SIZE];
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,22 +1,15 @@
|
|||
#include "fs.h"
|
||||
#include "buf.h"
|
||||
#include "inode.h"
|
||||
#include <minix/vfsif.h>
|
||||
|
||||
/*===========================================================================*
|
||||
* fs_ftrunc *
|
||||
* fs_trunc *
|
||||
*===========================================================================*/
|
||||
int fs_ftrunc(message *fs_m_in, message *fs_m_out)
|
||||
int fs_trunc(ino_t ino_nr, off_t start, off_t end)
|
||||
{
|
||||
struct inode *rip;
|
||||
off_t start;
|
||||
ino_t inumb;
|
||||
|
||||
inumb = fs_m_in->m_vfs_fs_ftrunc.inode;
|
||||
if( (rip = find_inode(ino_nr)) == NULL) return(EINVAL);
|
||||
|
||||
if( (rip = find_inode(inumb)) == NULL) return(EINVAL);
|
||||
|
||||
start = fs_m_in->m_vfs_fs_ftrunc.trc_start;
|
||||
if (end != 0) return(EINVAL); /* creating holes is not supported */
|
||||
|
||||
return truncate_inode(rip, start);
|
||||
}
|
||||
|
|
|
@ -1,17 +1,4 @@
|
|||
#include "fs.h"
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
#include <minix/dmap.h>
|
||||
#include <minix/driver.h>
|
||||
#include <minix/endpoint.h>
|
||||
#include <minix/rs.h>
|
||||
#include <minix/vfsif.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include "buf.h"
|
||||
#include "inode.h"
|
||||
|
||||
static void get_work(message *m_in, int *status);
|
||||
|
||||
/* SEF functions and variables. */
|
||||
static void sef_local_startup(void);
|
||||
|
@ -23,54 +10,15 @@ static void sef_cb_signal_handler(int signo);
|
|||
*===========================================================================*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* 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 never terminates, unless a panic occurs.
|
||||
*/
|
||||
int ind, transid, req_nr, ipc_status;
|
||||
message pfs_m_in;
|
||||
message pfs_m_out;
|
||||
endpoint_t src;
|
||||
/* This is the main routine of this service. */
|
||||
|
||||
/* SEF local startup. */
|
||||
env_setargs(argc, argv);
|
||||
sef_local_startup();
|
||||
|
||||
while(!unmountdone || !exitsignaled) {
|
||||
/* Wait for request message. */
|
||||
get_work(&pfs_m_in, &ipc_status);
|
||||
/* The fsdriver library does the actual work here. */
|
||||
fsdriver_task(&pfs_table);
|
||||
|
||||
transid = TRNS_GET_ID(pfs_m_in.m_type);
|
||||
pfs_m_in.m_type = TRNS_DEL_ID(pfs_m_in.m_type);
|
||||
if (pfs_m_in.m_type == 0) {
|
||||
assert(!IS_VFS_FS_TRANSID(transid));
|
||||
pfs_m_in.m_type = transid;
|
||||
transid = 0;
|
||||
} else
|
||||
assert(IS_VFS_FS_TRANSID(transid) || transid == 0);
|
||||
|
||||
src = pfs_m_in.m_source;
|
||||
req_nr = pfs_m_in.m_type;
|
||||
|
||||
if (IS_FS_RQ(req_nr)) {
|
||||
ind = req_nr - FS_BASE;
|
||||
if (ind < 0 || ind >= FS_CALL_VEC_SIZE) {
|
||||
printf("pfs: bad FS request %d\n", req_nr);
|
||||
pfs_m_out.m_type = EINVAL;
|
||||
} else {
|
||||
pfs_m_out.m_type =
|
||||
(*fs_call_vec[ind])(&pfs_m_in, &pfs_m_out);
|
||||
}
|
||||
} else {
|
||||
printf("pfs: bad request %d\n", req_nr);
|
||||
pfs_m_out.m_type = EINVAL;
|
||||
}
|
||||
|
||||
if (IS_FS_RQ(req_nr) && IS_VFS_FS_TRANSID(transid)) {
|
||||
pfs_m_out.m_type = TRNS_ADD_ID(pfs_m_out.m_type, transid);
|
||||
}
|
||||
reply(src, &pfs_m_out);
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
@ -102,7 +50,6 @@ static int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
|||
struct passwd *pw;
|
||||
|
||||
/* Initialize main loop parameters. */
|
||||
exitsignaled = 0; /* No exit request seen yet. */
|
||||
busy = 0; /* Server is not 'busy' (i.e., inodes in use). */
|
||||
|
||||
/* Init inode table */
|
||||
|
@ -113,14 +60,6 @@ static int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
|||
init_inode_cache();
|
||||
buf_pool();
|
||||
|
||||
/* Drop root privileges */
|
||||
if ((pw = getpwnam(SERVICE_LOGIN)) == NULL) {
|
||||
printf("PFS: unable to retrieve uid of SERVICE_LOGIN, "
|
||||
"still running as root");
|
||||
} else if (setuid(pw->pw_uid) != 0) {
|
||||
panic("unable to drop privileges");
|
||||
}
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
@ -132,41 +71,5 @@ static void sef_cb_signal_handler(int signo)
|
|||
/* Only check for termination signal, ignore anything else. */
|
||||
if (signo != SIGTERM) return;
|
||||
|
||||
|
||||
exitsignaled = 1;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* get_work *
|
||||
*===========================================================================*/
|
||||
static void get_work(message * m_in, int *status)
|
||||
{
|
||||
int r, srcok = 0;
|
||||
endpoint_t src;
|
||||
|
||||
do {
|
||||
/* wait for a message */
|
||||
if ((r = sef_receive_status(ANY, m_in, status)) != OK)
|
||||
panic("sef_receive_status failed: %d", r);
|
||||
src = m_in->m_source;
|
||||
|
||||
if(src == VFS_PROC_NR) {
|
||||
srcok = 1; /* Normal FS request. */
|
||||
} else
|
||||
printf("PFS: unexpected source %d\n", src);
|
||||
} while(!srcok);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* reply *
|
||||
*===========================================================================*/
|
||||
void reply(who, m_out)
|
||||
endpoint_t who;
|
||||
message *m_out; /* report result */
|
||||
{
|
||||
int r;
|
||||
|
||||
if (OK != (r = ipc_send(who, m_out))) /* send the message */
|
||||
printf("PFS: unable to send reply: %d\n", r);
|
||||
fsdriver_terminate();
|
||||
}
|
||||
|
|
|
@ -1,28 +1,17 @@
|
|||
#include "fs.h"
|
||||
#include "inode.h"
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* fs_sync *
|
||||
*===========================================================================*/
|
||||
int fs_sync(message *fs_m_in, message *fs_m_out)
|
||||
{
|
||||
/* Perform the sync() system call. No-op on this FS. */
|
||||
|
||||
return(OK); /* sync() can't fail */
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* fs_chmod *
|
||||
*===========================================================================*/
|
||||
int fs_chmod(message *fs_m_in, message *fs_m_out)
|
||||
int fs_chmod(ino_t ino_nr, mode_t *mode)
|
||||
{
|
||||
struct inode *rip; /* target inode */
|
||||
mode_t mode = fs_m_in->m_vfs_fs_chmod.mode;
|
||||
|
||||
if( (rip = find_inode(fs_m_in->m_vfs_fs_chmod.inode)) == NULL) return(EINVAL);
|
||||
get_inode(rip->i_dev, rip->i_num); /* mark inode in use */
|
||||
rip->i_mode = (rip->i_mode & ~ALL_MODES) | (mode & ALL_MODES);
|
||||
put_inode(rip); /* release the inode */
|
||||
if( (rip = find_inode(ino_nr)) == NULL) return(EINVAL);
|
||||
|
||||
rip->i_mode = (rip->i_mode & ~ALL_MODES) | (*mode & ALL_MODES);
|
||||
|
||||
*mode = rip->i_mode; /* return new mode */
|
||||
return OK;
|
||||
}
|
||||
|
|
|
@ -3,16 +3,33 @@
|
|||
|
||||
|
||||
/*===========================================================================*
|
||||
* fs_unmount *
|
||||
* fs_mount *
|
||||
*===========================================================================*/
|
||||
int fs_unmount(message *fs_m_in, message *fs_m_out)
|
||||
int fs_mount(dev_t __unused dev, unsigned int __unused flags,
|
||||
struct fsdriver_node *node, unsigned int *res_flags)
|
||||
{
|
||||
/* Unmount Pipe File Server. */
|
||||
/* Mount Pipe File Server. */
|
||||
|
||||
if (busy) return(EBUSY); /* can't umount a busy file system */
|
||||
|
||||
/* Finish off the unmount. */
|
||||
unmountdone = TRUE;
|
||||
/* This function does not do much. PFS has no root node, and VFS will ignore
|
||||
* the returned node details anyway. The whole idea is to provide symmetry
|
||||
* with other file systems, thus keeping libfsdriver simple and free of
|
||||
* special cases. Everything else (e.g., mounting PFS in VFS) is already an
|
||||
* exception anyway.
|
||||
*/
|
||||
memset(node, 0, sizeof(*node));
|
||||
*res_flags = 0;
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* fs_unmount *
|
||||
*===========================================================================*/
|
||||
void fs_unmount(void)
|
||||
{
|
||||
/* Unmount Pipe File Server. */
|
||||
|
||||
if (busy)
|
||||
printf("PFS: unmounting while busy!\n"); /* nothing we can do anyway */
|
||||
}
|
||||
|
|
|
@ -1,31 +1,19 @@
|
|||
#include "fs.h"
|
||||
#include <sys/stat.h>
|
||||
#include "buf.h"
|
||||
#include "inode.h"
|
||||
#include <minix/vfsif.h>
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* fs_newnode *
|
||||
*===========================================================================*/
|
||||
int fs_newnode(message *fs_m_in, message *fs_m_out)
|
||||
int fs_newnode(mode_t mode, uid_t uid, gid_t gid, dev_t dev,
|
||||
struct fsdriver_node *node)
|
||||
{
|
||||
register int r = OK;
|
||||
mode_t bits;
|
||||
struct inode *rip;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
dev_t dev;
|
||||
|
||||
uid = fs_m_in->m_vfs_fs_newnode.uid;
|
||||
gid = fs_m_in->m_vfs_fs_newnode.gid;
|
||||
bits = fs_m_in->m_vfs_fs_newnode.mode;
|
||||
dev = fs_m_in->m_vfs_fs_newnode.device;
|
||||
|
||||
/* Try to allocate the inode */
|
||||
if( (rip = alloc_inode(dev, bits, uid, gid) ) == NULL) return(err_code);
|
||||
if( (rip = alloc_inode(dev, mode, uid, gid) ) == NULL) return(err_code);
|
||||
|
||||
switch (bits & S_IFMT) {
|
||||
switch (mode & S_IFMT) {
|
||||
case S_IFBLK:
|
||||
case S_IFCHR:
|
||||
rip->i_rdev = dev; /* Major/minor dev numbers */
|
||||
|
@ -42,12 +30,12 @@ int fs_newnode(message *fs_m_in, message *fs_m_out)
|
|||
free_inode(rip);
|
||||
} else {
|
||||
/* Fill in the fields of the response message */
|
||||
fs_m_out->m_fs_vfs_newnode.inode = rip->i_num;
|
||||
fs_m_out->m_fs_vfs_newnode.mode = rip->i_mode;
|
||||
fs_m_out->m_fs_vfs_newnode.file_size = rip->i_size;
|
||||
fs_m_out->m_fs_vfs_newnode.uid = rip->i_uid;
|
||||
fs_m_out->m_fs_vfs_newnode.gid = rip->i_gid;
|
||||
fs_m_out->m_fs_vfs_newnode.device = dev;
|
||||
node->fn_ino_nr = rip->i_num;
|
||||
node->fn_mode = rip->i_mode;
|
||||
node->fn_size = rip->i_size;
|
||||
node->fn_uid = rip->i_uid;
|
||||
node->fn_gid = rip->i_gid;
|
||||
node->fn_dev = dev;
|
||||
}
|
||||
|
||||
return(r);
|
||||
|
|
|
@ -10,8 +10,6 @@ struct inode;
|
|||
/* buffer.c */
|
||||
struct buf *get_block(dev_t dev, ino_t inum);
|
||||
void put_block(dev_t dev, ino_t inum);
|
||||
|
||||
/* cache.c */
|
||||
void buf_pool(void);
|
||||
|
||||
/* inode.c */
|
||||
|
@ -19,7 +17,7 @@ struct inode *alloc_inode(dev_t dev, mode_t mode, uid_t uid, gid_t gid);
|
|||
void dup_inode(struct inode *ip);
|
||||
struct inode *find_inode(ino_t numb);
|
||||
void free_inode(struct inode *rip);
|
||||
int fs_putnode(message *fs_m_in, message *fs_m_out);
|
||||
int fs_putnode(ino_t ino_nr, unsigned int count);
|
||||
void init_inode_cache(void);
|
||||
struct inode *get_inode(dev_t dev, ino_t numb);
|
||||
void put_inode(struct inode *rip);
|
||||
|
@ -27,30 +25,29 @@ void update_times(struct inode *rip);
|
|||
void wipe_inode(struct inode *rip);
|
||||
|
||||
/* link.c */
|
||||
int fs_ftrunc(message *fs_m_in, message *fs_m_out);
|
||||
int fs_trunc(ino_t ino_nr, off_t start, off_t end);
|
||||
int truncate_inode(struct inode *rip, off_t newsize);
|
||||
|
||||
/* main.c */
|
||||
void reply(endpoint_t who, message *m_out);
|
||||
|
||||
/* misc.c */
|
||||
int fs_sync(message *fs_m_in, message *fs_m_out);
|
||||
int fs_chmod(message *fs_m_in, message *fs_m_out);
|
||||
int fs_chmod(ino_t ino_nr, mode_t *mode);
|
||||
|
||||
/* mount.c */
|
||||
int fs_unmount(message *fs_m_in, message *fs_m_out);
|
||||
int fs_mount(dev_t dev, unsigned int flags, struct fsdriver_node *node,
|
||||
unsigned int *res_flags);
|
||||
void fs_unmount(void);
|
||||
|
||||
/* open.c */
|
||||
int fs_newnode(message *fs_m_in, message *fs_m_out);
|
||||
int fs_newnode(mode_t mode, uid_t uid, gid_t gid, dev_t dev,
|
||||
struct fsdriver_node *node);
|
||||
|
||||
/* read.c */
|
||||
int fs_readwrite(message *fs_m_in, message *fs_m_out);
|
||||
|
||||
/* utility.c */
|
||||
int no_sys(message *pfs_m_in, message *pfs_m_out);
|
||||
ssize_t fs_read(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
|
||||
off_t pos, int call);
|
||||
ssize_t fs_write(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
|
||||
off_t pos, int call);
|
||||
|
||||
/* stadir.c */
|
||||
int fs_stat(message *fs_m_in, message *fs_m_out);
|
||||
int fs_stat(ino_t ino_nr, struct stat *statbuf);
|
||||
|
||||
/* super.c */
|
||||
bit_t alloc_bit(void);
|
||||
|
|
|
@ -1,97 +1,85 @@
|
|||
#include "fs.h"
|
||||
#include "buf.h"
|
||||
#include "inode.h"
|
||||
#include <minix/com.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* fs_readwrite *
|
||||
* fs_read *
|
||||
*===========================================================================*/
|
||||
int fs_readwrite(message *fs_m_in, message *fs_m_out)
|
||||
ssize_t fs_read(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
|
||||
off_t __unused pos, int call)
|
||||
{
|
||||
int r, rw_flag;
|
||||
int r;
|
||||
struct buf *bp;
|
||||
cp_grant_id_t gid;
|
||||
off_t position, f_size;
|
||||
size_t nrbytes, cum_io;
|
||||
mode_t mode_word;
|
||||
struct inode *rip;
|
||||
ino_t inumb;
|
||||
|
||||
r = OK;
|
||||
cum_io = 0;
|
||||
inumb = fs_m_in->m_vfs_fs_readwrite.inode;
|
||||
|
||||
/* Find the inode referred */
|
||||
if ((rip = find_inode(inumb)) == NULL) return(EINVAL);
|
||||
if ((rip = find_inode(ino_nr)) == NULL) return(EINVAL);
|
||||
|
||||
mode_word = rip->i_mode & I_TYPE;
|
||||
if (mode_word != I_NAMED_PIPE) return(EIO);
|
||||
f_size = rip->i_size;
|
||||
if (!S_ISFIFO(rip->i_mode)) return(EIO);
|
||||
|
||||
/* Get the values from the request message */
|
||||
rw_flag = (fs_m_in->m_type == REQ_READ ? READING : WRITING);
|
||||
gid = fs_m_in->m_vfs_fs_readwrite.grant;
|
||||
nrbytes = fs_m_in->m_vfs_fs_readwrite.nbytes;
|
||||
/* We can't read or write beyond the max file position */
|
||||
if (bytes > PIPE_BUF) return(EFBIG);
|
||||
|
||||
/* We can't read beyond the max file position */
|
||||
if (nrbytes > PIPE_BUF) return(EFBIG);
|
||||
if (bytes > rip->i_size) {
|
||||
/* There aren't that many bytes to read */
|
||||
bytes = rip->i_size;
|
||||
}
|
||||
|
||||
/* Mark inode in use */
|
||||
if ((get_inode(rip->i_dev, rip->i_num)) == NULL) return(err_code);
|
||||
/* Copy a chunk from the block buffer to user space. */
|
||||
if ((bp = get_block(rip->i_dev, rip->i_num)) == NULL) return(err_code);
|
||||
|
||||
if (rw_flag == WRITING) {
|
||||
/* Check in advance to see if file will grow too big. */
|
||||
/* Casting nrbytes to signed is safe, because it's guaranteed not to
|
||||
* be beyond max signed value (i.e., MAX_FILE_POS).
|
||||
*/
|
||||
position = rip->i_size;
|
||||
if ((unsigned) position + nrbytes > PIPE_BUF) {
|
||||
put_inode(rip);
|
||||
put_block(rip->i_dev, rip->i_num);
|
||||
return(EFBIG);
|
||||
}
|
||||
} else {
|
||||
position = 0;
|
||||
if (nrbytes > rip->i_size) {
|
||||
/* There aren't that many bytes to read */
|
||||
nrbytes = rip->i_size;
|
||||
}
|
||||
r = fsdriver_copyout(data, 0, bp->b_data, bytes);
|
||||
|
||||
if (r == OK && rip->i_size > bytes) {
|
||||
/* Move any remaining data to the front of the buffer. */
|
||||
/* FIXME: see if this really is the optimal strategy. */
|
||||
memmove(bp->b_data, bp->b_data + bytes, rip->i_size - bytes);
|
||||
}
|
||||
|
||||
if (rw_flag == READING) {
|
||||
/* Copy a chunk from the block buffer to user space. */
|
||||
r = sys_safecopyto(fs_m_in->m_source, gid, (vir_bytes) 0,
|
||||
(vir_bytes) (bp->b_data+position), (size_t) nrbytes);
|
||||
} else {
|
||||
/* Copy a chunk from user space to the block buffer. */
|
||||
r = sys_safecopyfrom(fs_m_in->m_source, gid, (vir_bytes) 0,
|
||||
(vir_bytes) (bp->b_data+position), (size_t) nrbytes);
|
||||
}
|
||||
|
||||
if (r == OK) {
|
||||
position += (signed) nrbytes; /* Update position */
|
||||
cum_io += nrbytes;
|
||||
|
||||
/* On write, update file size and access time. */
|
||||
if (rw_flag == WRITING) {
|
||||
rip->i_size = position;
|
||||
} else {
|
||||
memmove(bp->b_data, bp->b_data+nrbytes, rip->i_size - nrbytes);
|
||||
rip->i_size -= nrbytes;
|
||||
}
|
||||
|
||||
if (rw_flag == READING) rip->i_update |= ATIME;
|
||||
if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME;
|
||||
}
|
||||
|
||||
fs_m_out->m_fs_vfs_readwrite.nbytes = cum_io;
|
||||
fs_m_out->m_fs_vfs_readwrite.seek_pos = rip->i_size;
|
||||
|
||||
put_inode(rip);
|
||||
put_block(rip->i_dev, rip->i_num);
|
||||
|
||||
return(r);
|
||||
if (r != OK)
|
||||
return r;
|
||||
|
||||
/* Update file size and access time. */
|
||||
rip->i_size -= bytes;
|
||||
rip->i_update |= ATIME;
|
||||
|
||||
return(bytes);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* fs_write *
|
||||
*===========================================================================*/
|
||||
ssize_t fs_write(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
|
||||
off_t __unused pos, int __unused call)
|
||||
{
|
||||
int r;
|
||||
struct buf *bp;
|
||||
struct inode *rip;
|
||||
|
||||
/* Find the inode referred */
|
||||
if ((rip = find_inode(ino_nr)) == NULL) return(EINVAL);
|
||||
|
||||
if (!S_ISFIFO(rip->i_mode)) return(EIO);
|
||||
|
||||
/* Check in advance to see if file will grow too big. */
|
||||
if (rip->i_size + bytes > PIPE_BUF)
|
||||
return(EFBIG);
|
||||
|
||||
/* Copy the data from user space to the block buffer. */
|
||||
if ((bp = get_block(rip->i_dev, rip->i_num)) == NULL) return(err_code);
|
||||
|
||||
r = fsdriver_copyin(data, 0, bp->b_data + rip->i_size, bytes);
|
||||
|
||||
put_block(rip->i_dev, rip->i_num);
|
||||
|
||||
if (r != OK)
|
||||
return r;
|
||||
|
||||
/* Update file size and file times. */
|
||||
rip->i_size += bytes;
|
||||
rip->i_update |= CTIME | MTIME;
|
||||
|
||||
return(bytes);
|
||||
}
|
||||
|
|
|
@ -1,23 +1,17 @@
|
|||
#include "fs.h"
|
||||
#include "inode.h"
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* stat_inode *
|
||||
* fs_stat *
|
||||
*===========================================================================*/
|
||||
static int stat_inode(
|
||||
register struct inode *rip, /* pointer to inode to stat */
|
||||
endpoint_t who_e, /* Caller endpoint */
|
||||
cp_grant_id_t gid /* grant for the stat buf */
|
||||
)
|
||||
int fs_stat(ino_t ino_nr, struct stat *statbuf)
|
||||
{
|
||||
/* Common code for stat and fstat system calls. */
|
||||
struct inode *rip;
|
||||
mode_t type;
|
||||
struct stat statbuf;
|
||||
u32_t blocks; /* The unit of this is 512 */
|
||||
int r, s;
|
||||
int s;
|
||||
|
||||
if ((rip = find_inode(ino_nr)) == NULL) return(EINVAL);
|
||||
|
||||
type = rip->i_mode & I_TYPE;
|
||||
s = (type == I_CHAR_SPECIAL || type == I_BLOCK_SPECIAL);
|
||||
|
@ -29,42 +23,20 @@ static int stat_inode(
|
|||
if (rip->i_size % S_BLKSIZE != 0)
|
||||
blocks += 1;
|
||||
|
||||
memset(&statbuf, 0, sizeof(struct stat));
|
||||
statbuf->st_dev = rip->i_dev;
|
||||
statbuf->st_ino = rip->i_num;
|
||||
statbuf->st_mode = rip->i_mode;
|
||||
statbuf->st_nlink = rip->i_nlinks;
|
||||
statbuf->st_uid = rip->i_uid;
|
||||
statbuf->st_gid = (short int) rip->i_gid;
|
||||
statbuf->st_rdev = (s ? rip->i_rdev : NO_DEV);
|
||||
statbuf->st_size = rip->i_size;
|
||||
if (!s) statbuf->st_mode &= ~I_REGULAR;/* wipe out I_REGULAR bit for pipes */
|
||||
statbuf->st_atime = rip->i_atime;
|
||||
statbuf->st_mtime = rip->i_mtime;
|
||||
statbuf->st_ctime = rip->i_ctime;
|
||||
statbuf->st_blksize = PIPE_BUF;
|
||||
statbuf->st_blocks = blocks;
|
||||
|
||||
statbuf.st_dev = rip->i_dev;
|
||||
statbuf.st_ino = rip->i_num;
|
||||
statbuf.st_mode = rip->i_mode;
|
||||
statbuf.st_nlink = rip->i_nlinks;
|
||||
statbuf.st_uid = rip->i_uid;
|
||||
statbuf.st_gid = (short int) rip->i_gid;
|
||||
statbuf.st_rdev = (s ? rip->i_rdev : NO_DEV);
|
||||
statbuf.st_size = rip->i_size;
|
||||
if (!s) statbuf.st_mode &= ~I_REGULAR;/* wipe out I_REGULAR bit for pipes */
|
||||
statbuf.st_atime = rip->i_atime;
|
||||
statbuf.st_mtime = rip->i_mtime;
|
||||
statbuf.st_ctime = rip->i_ctime;
|
||||
statbuf.st_blksize = PIPE_BUF;
|
||||
statbuf.st_blocks = blocks;
|
||||
|
||||
/* Copy the struct to user space. */
|
||||
r = sys_safecopyto(who_e, gid, (vir_bytes) 0, (vir_bytes) &statbuf,
|
||||
(size_t) sizeof(statbuf));
|
||||
|
||||
return(r);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* fs_stat *
|
||||
*===========================================================================*/
|
||||
int fs_stat(message *fs_m_in, message *fs_m_out)
|
||||
{
|
||||
register int r; /* return value */
|
||||
register struct inode *rip; /* target inode */
|
||||
|
||||
if( (rip = find_inode(fs_m_in->m_vfs_fs_stat.inode)) == NULL) return(EINVAL);
|
||||
get_inode(rip->i_dev, rip->i_num); /* mark inode in use */
|
||||
r = stat_inode(rip, fs_m_in->m_source, fs_m_in->m_vfs_fs_stat.grant);
|
||||
put_inode(rip); /* release the inode */
|
||||
return(r);
|
||||
return(OK);
|
||||
}
|
||||
|
|
|
@ -9,9 +9,6 @@
|
|||
*/
|
||||
|
||||
#include "fs.h"
|
||||
#include "buf.h"
|
||||
#include "inode.h"
|
||||
#include "const.h"
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
|
@ -6,42 +6,16 @@
|
|||
#define _TABLE
|
||||
|
||||
#include "fs.h"
|
||||
#include "inode.h"
|
||||
#include "buf.h"
|
||||
|
||||
/* File System Handlers (pfs) */
|
||||
int (*fs_call_vec[])(message *fs_m_in, message *fs_m_out) = {
|
||||
no_sys, /* 0 not used */
|
||||
no_sys, /* 1 */
|
||||
fs_putnode, /* 2 */
|
||||
no_sys, /* 3 */
|
||||
fs_ftrunc, /* 4 */
|
||||
no_sys, /* 5 */
|
||||
fs_chmod, /* 6 */
|
||||
no_sys, /* 7 */
|
||||
fs_stat, /* 8 */
|
||||
no_sys, /* 9 */
|
||||
no_sys, /* 10 */
|
||||
no_sys, /* 11 */
|
||||
no_sys, /* 12 */
|
||||
no_sys, /* 13 */
|
||||
no_sys, /* 14 */
|
||||
fs_unmount, /* 15 */
|
||||
fs_sync, /* 16 */
|
||||
no_sys, /* 17 */
|
||||
no_sys, /* 18 */
|
||||
fs_readwrite, /* 19 */
|
||||
fs_readwrite, /* 20 */
|
||||
no_sys, /* 21 */
|
||||
no_sys, /* 22 */
|
||||
no_sys, /* 23 */
|
||||
no_sys, /* 24 */
|
||||
no_sys, /* 25 */
|
||||
no_sys, /* 26 */
|
||||
no_sys, /* 27 */
|
||||
no_sys, /* 28 */
|
||||
fs_newnode, /* 29 */
|
||||
no_sys, /* 30 */
|
||||
no_sys, /* 31 */
|
||||
no_sys, /* 32 */
|
||||
struct fsdriver pfs_table = {
|
||||
.fdr_mount = fs_mount,
|
||||
.fdr_unmount = fs_unmount,
|
||||
.fdr_newnode = fs_newnode,
|
||||
.fdr_putnode = fs_putnode,
|
||||
.fdr_read = fs_read,
|
||||
.fdr_write = fs_write,
|
||||
.fdr_trunc = fs_trunc,
|
||||
.fdr_stat = fs_stat,
|
||||
.fdr_chmod = fs_chmod
|
||||
};
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
#include "fs.h"
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* no_sys *
|
||||
*===========================================================================*/
|
||||
int no_sys(message *pfs_m_in, message *pfs_m_out)
|
||||
{
|
||||
/* Somebody has used an illegal system call number */
|
||||
printf("no_sys: invalid call 0x%x to pfs\n", pfs_m_in->m_type);
|
||||
return(EINVAL);
|
||||
}
|
|
@ -289,7 +289,7 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *info)
|
|||
message mess;
|
||||
struct rprocpub rprocpub[NR_BOOT_PROCS];
|
||||
|
||||
receive_from = ANY;
|
||||
receive_from = NONE;
|
||||
self = NULL;
|
||||
verbose = 0;
|
||||
|
||||
|
@ -379,10 +379,8 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *info)
|
|||
init_vmnts(); /* init vmnt structures */
|
||||
init_select(); /* init select() structures */
|
||||
init_filps(); /* Init filp structures */
|
||||
mount_pfs(); /* mount Pipe File Server */
|
||||
|
||||
/* Mount initial ramdisk as file system root. */
|
||||
receive_from = MFS_PROC_NR;
|
||||
/* Mount PFS and initial file system root. */
|
||||
worker_start(fproc_addr(VFS_PROC_NR), do_init_root, &mess /*unused*/,
|
||||
FALSE /*use_spare*/);
|
||||
|
||||
|
@ -394,9 +392,19 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *info)
|
|||
*===========================================================================*/
|
||||
static void do_init_root(void)
|
||||
{
|
||||
char *mount_type, *mount_label;
|
||||
int r;
|
||||
char *mount_type = "mfs"; /* FIXME: use boot image process name instead */
|
||||
char *mount_label = "fs_imgrd"; /* FIXME: obtain this from RS */
|
||||
|
||||
/* Mount the pipe file server. */
|
||||
receive_from = PFS_PROC_NR;
|
||||
|
||||
mount_pfs();
|
||||
|
||||
/* Mount the root file system. */
|
||||
receive_from = MFS_PROC_NR;
|
||||
|
||||
mount_type = "mfs"; /* FIXME: use boot image process name instead */
|
||||
mount_label = "fs_imgrd"; /* FIXME: obtain this from RS */
|
||||
|
||||
r = mount_fs(DEV_IMGRD, "bootramdisk", "/", MFS_PROC_NR, 0, mount_type,
|
||||
mount_label);
|
||||
|
@ -485,6 +493,8 @@ static void get_work()
|
|||
}
|
||||
|
||||
for(;;) {
|
||||
assert(receive_from != NONE);
|
||||
|
||||
/* Normal case. No one to revive. Get a useful request. */
|
||||
if ((r = sef_receive(receive_from, &m_in)) != OK) {
|
||||
panic("VFS: sef_receive error: %d", r);
|
||||
|
|
|
@ -390,11 +390,16 @@ char mount_label[LABEL_MAX] )
|
|||
*===========================================================================*/
|
||||
void mount_pfs(void)
|
||||
{
|
||||
/* Mount the Pipe File Server. It's not really mounted onto the file system,
|
||||
but it's necessary it has a vmnt entry to make locking easier */
|
||||
|
||||
/* Mount the Pipe File Server. We treat it as a regular file system to a
|
||||
* certain extent, to prevent creating too many exceptions all over the place.
|
||||
* For example, it has a vmnt entry to make locking easier, and it gets sent
|
||||
* a mount request to keep the fsdriver library happy.
|
||||
*/
|
||||
dev_t dev;
|
||||
struct vmnt *vmp;
|
||||
struct node_details res;
|
||||
unsigned int fs_flags;
|
||||
int r;
|
||||
|
||||
if ((dev = find_free_nonedev()) == NO_DEV)
|
||||
panic("VFS: no nonedev to initialize PFS");
|
||||
|
@ -410,6 +415,13 @@ void mount_pfs(void)
|
|||
strlcpy(vmp->m_label, "pfs", LABEL_MAX);
|
||||
strlcpy(vmp->m_mount_path, "pipe", PATH_MAX);
|
||||
strlcpy(vmp->m_mount_dev, "none", PATH_MAX);
|
||||
|
||||
/* Ask PFS to acknowledge being mounted. Ignore the returned node details. */
|
||||
r = req_readsuper(vmp, "", dev, FALSE, FALSE, &res, &fs_flags);
|
||||
if (r != OK)
|
||||
printf("VFS: unable to mount PFS (%d)\n", r);
|
||||
else
|
||||
vmp->m_fs_flags = fs_flags;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
|
@ -355,7 +355,10 @@ size_t req_size;
|
|||
buf += cum_io_incr;
|
||||
req_size -= cum_io_incr;
|
||||
|
||||
vp->v_size = new_pos;
|
||||
if (rw_flag == READING)
|
||||
vp->v_size -= cum_io_incr;
|
||||
else
|
||||
vp->v_size += cum_io_incr;
|
||||
|
||||
if (partial_pipe) {
|
||||
/* partial write on pipe with */
|
||||
|
|
Loading…
Reference in a new issue