From 9092146be7c38c4c5f92484a330077ffe90da184 Mon Sep 17 00:00:00 2001 From: Philip Homburg Date: Fri, 5 Jan 2007 16:36:55 +0000 Subject: [PATCH] VFS cleanup (mostly open). --- include/minix/vfsif.h | 21 +-- servers/mfs/inode.c | 74 ++++++++++- servers/mfs/main.c | 2 +- servers/mfs/open.c | 88 +++++++++--- servers/mfs/path.c | 42 +++++- servers/mfs/proto.h | 4 +- servers/mfs/stadir.c | 123 ++--------------- servers/mfs/table.c | 9 +- servers/vfs/device.c | 7 +- servers/vfs/exec.c | 120 ++++++++--------- servers/vfs/link.c | 30 ++++- servers/vfs/main.c | 26 +++- servers/vfs/misc.c | 3 +- servers/vfs/mount.c | 55 +++++--- servers/vfs/open.c | 220 +++++++++++++++++++++++++++--- servers/vfs/path.c | 303 +++++++++++++++++++++++++++++++++++++++++- servers/vfs/pipe.c | 5 +- servers/vfs/protect.c | 73 ++++++++++ servers/vfs/proto.h | 26 +++- servers/vfs/read.c | 7 + servers/vfs/request.c | 190 ++++++++++++++++---------- servers/vfs/request.h | 22 +-- servers/vfs/stadir.c | 106 +++------------ servers/vfs/vnode.c | 245 +++++++++++++++++++++++++++++----- servers/vfs/vnode.h | 11 +- 25 files changed, 1301 insertions(+), 511 deletions(-) diff --git a/include/minix/vfsif.h b/include/minix/vfsif.h index 5409f0d30..b3a52d1aa 100644 --- a/include/minix/vfsif.h +++ b/include/minix/vfsif.h @@ -10,9 +10,11 @@ #define REQ_FLAGS m6_l3 #define REQ_DEV m6_l3 #define REQ_WHO_E m6_l3 +#define REQ_GRANT m6_l3 #define REQ_USER_ADDR m6_p2 #define REQ_LENGTH m6_l3 #define REQ_SYMLOOP m6_c2 +#define REQ_COUNT m6_l2 #define REQ_NEW_UID m6_s3 #define REQ_NEW_GID m6_c2 @@ -75,7 +77,6 @@ #define RES_MODE m6_s1 #define RES_FILE_SIZE m6_l2 #define RES_DEV m6_l3 -#define RES_POS m6_l3 #define RES_INODE_INDEX m6_s2 #define RES_NLINKS m6_s3 #define RES_SYMLOOP m6_c1 @@ -110,7 +111,6 @@ #define REQ_WRITE 6 #define REQ_CLONE_OPCL 7 #define REQ_FTRUNC 8 - #define REQ_CHOWN 9 #define REQ_CHMOD 10 #define REQ_ACCESS 11 @@ -118,13 +118,14 @@ #define REQ_MKDIR 13 #define REQ_INHIBREAD 14 #define REQ_STAT 15 -#define REQ_FSTAT 16 + +#define REQ_CREATE 16 + #define REQ_UNLINK 17 #define REQ_RMDIR 18 #define REQ_UTIME 19 -#define REQ_FSTATFS 20 -#define REQ_LSTAT 21 /* NO POINT !!! */ -#define REQ_GETDIR 22 + +#define REQ_FSTATFS 21 #define REQ_LINK 25 @@ -156,11 +157,3 @@ #define ELEAVEMOUNT 302 #define ESYMLINK 303 - - - - - - - - diff --git a/servers/mfs/inode.c b/servers/mfs/inode.c index a98fc9671..a18ffbe74 100644 --- a/servers/mfs/inode.c +++ b/servers/mfs/inode.c @@ -27,6 +27,7 @@ FORWARD _PROTOTYPE( void old_icopy, (struct inode *rip, d1_inode *dip, int direction, int norm)); FORWARD _PROTOTYPE( void new_icopy, (struct inode *rip, d2_inode *dip, int direction, int norm)); +FORWARD _PROTOTYPE( void put_inode2, (struct inode *rip, int count)); /*===========================================================================* @@ -37,6 +38,7 @@ PUBLIC int fs_putnode() /* Find the inode specified by the request message and decrease its counter. */ struct inode *rip; + int count; /* Sanity check for the direct index */ if (fs_m_in.REQ_INODE_INDEX >= 0 && @@ -50,10 +52,27 @@ PUBLIC int fs_putnode() } if (!rip) + { printf("FSput_inode: inode #%d dev: %d couldn't be put, req_nr: %d\n", fs_m_in.REQ_INODE_NR, fs_dev, req_nr); + panic(__FILE__, "fs_putnode failed", NO_NUM); + } + + count= fs_m_in.REQ_COUNT; + if (count <= 0) + { + printf("put_inode: bad value for count: %d\n", count); + panic(__FILE__, "fs_putnode failed", NO_NUM); + return EINVAL; + } + if (count > rip->i_count) + { + printf("put_inode: count too high: %d > %d\n", count, rip->i_count); + panic(__FILE__, "fs_putnode failed", NO_NUM); + return EINVAL; + } - put_inode(rip); + put_inode2(rip, count); return OK; } @@ -80,6 +99,8 @@ PUBLIC int fs_getnode() fs_m_out.RES_MODE = rip->i_mode; fs_m_out.RES_FILE_SIZE = rip->i_size; fs_m_out.RES_DEV = (Dev_t) rip->i_zone[0]; + fs_m_out.RES_UID = rip->i_uid; + fs_m_out.RES_GID = rip->i_gid; return OK; } @@ -183,6 +204,10 @@ int numb; /* inode number (ANSI: may not be unshort) */ rip->i_count = 1; if (dev != NO_DEV) rw_inode(rip, READING); /* get inode from disk */ rip->i_update = 0; /* all the times are initially up-to-date */ + if ((rip->i_mode & I_TYPE) == I_NAMED_PIPE) + rip->i_pipe = I_PIPE; + else + rip->i_pipe = NO_PIPE; /* Add to hash */ addhash_inode(rip); @@ -240,7 +265,52 @@ register struct inode *rip; /* pointer to inode to be released */ if (rip->i_pipe == I_PIPE) truncate_inode(rip, 0); } rip->i_mount = NO_MOUNT; - rip->i_pipe = NO_PIPE; /* should always be cleared */ + if (rip->i_dirt == DIRTY) rw_inode(rip, WRITING); + + if (rip->i_nlinks == 0) { + /* free, put at the front of the LRU list */ + unhash_inode(rip); + rip->i_num = 0; + TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused); + } + else { + /* unused, put at the back of the LRU (cache it) */ + TAILQ_INSERT_TAIL(&unused_inodes, rip, i_unused); + } + } +} + + +/*===========================================================================* + * put_inode2 * + *===========================================================================*/ +PRIVATE void put_inode2(rip, count) +register struct inode *rip; /* pointer to inode to be released */ +int count; +{ +/* The caller is no longer using this inode. If no one else is using it either + * write it back to the disk immediately. If it has no links, truncate it and + * return it to the pool of available inodes. + */ + + if (rip == NIL_INODE) return; /* checking here is easier than in caller */ + + if (rip->i_count < count) + panic(__FILE__, "put_inode2: bad value for count", count); + rip->i_count -= count; + if (rip->i_count == 0) { /* i_count == 0 means no one is using it now */ + if (rip->i_nlinks == 0) { + /* i_nlinks == 0 means free the inode. */ + truncate_inode(rip, 0); /* return all the disk blocks */ + rip->i_mode = I_NOT_ALLOC; /* clear I_TYPE field */ + rip->i_dirt = DIRTY; + free_inode(rip->i_dev, rip->i_num); + } + else { + if (rip->i_pipe == I_PIPE) + truncate_inode(rip, 0); + } + rip->i_mount = NO_MOUNT; if (rip->i_dirt == DIRTY) rw_inode(rip, WRITING); if (rip->i_nlinks == 0) { diff --git a/servers/mfs/main.c b/servers/mfs/main.c index 9a61e637a..7fdcab630 100644 --- a/servers/mfs/main.c +++ b/servers/mfs/main.c @@ -180,7 +180,7 @@ PRIVATE void cch_check(void) for (i = 0; i < NR_INODES; ++i) { if (inode[i].i_count != cch[i] && req_nr != REQ_OPEN && req_nr != REQ_GETNODE && - req_nr != REQ_PUTNODE && req_nr != REQ_GETDIR && + req_nr != REQ_PUTNODE && req_nr != REQ_CLONE_OPCL && req_nr != REQ_READSUPER && req_nr != REQ_MOUNTPOINT && req_nr != REQ_UNMOUNT && req_nr != REQ_PIPE && req_nr != REQ_SYNC && diff --git a/servers/mfs/open.c b/servers/mfs/open.c index 9e040c1ee..77e92c3f9 100644 --- a/servers/mfs/open.c +++ b/servers/mfs/open.c @@ -15,7 +15,7 @@ PRIVATE char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0}; FORWARD _PROTOTYPE( struct inode *new_node, (struct inode *ldirp, - char *string, mode_t bits, zone_t z0, int opaque, char *parsed)); + char *string, mode_t bits, zone_t z0)); /*===========================================================================* @@ -61,7 +61,7 @@ printf("MFS(%d) get_inode for parent dir by creat() failed\n", SELF_E); } /* Create a new inode by calling new_node(). */ - rip = new_node(ldirp, lastc, omode, NO_ZONE, oflags&O_EXCL, NULL); + rip = new_node(ldirp, lastc, omode, NO_ZONE); r = err_code; if (r == OK) exist = FALSE; /* we just created the file */ else if (r != EEXIST) { @@ -113,11 +113,6 @@ printf("MFS(%d) get_inode by open() failed\n", SELF_E); case I_NAMED_PIPE: rip->i_pipe = I_PIPE; - b = (bits & R_BIT ? R_BIT : W_BIT); - if (b == R_BIT) - fs_m_out.RES_POS = rip->i_zone[V2_NR_DZONES+0]; - else - fs_m_out.RES_POS = rip->i_zone[V2_NR_DZONES+1]; break; } } @@ -148,6 +143,66 @@ printf("MFS(%d) get_inode by open() failed\n", SELF_E); return OK; } +/*===========================================================================* + * fs_create * + *===========================================================================*/ +PUBLIC int fs_create() +{ + int r, b; + struct inode *ldirp; + struct inode *rip; + mode_t omode; + char lastc[NAME_MAX]; + + /* Read request message */ + omode = fs_m_in.REQ_MODE; + + caller_uid = fs_m_in.REQ_UID; + caller_gid = fs_m_in.REQ_GID; + + /* Try to make the file. */ + + /* Copy the last component */ + err_code = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH, + SELF, (vir_bytes) lastc, (phys_bytes) fs_m_in.REQ_PATH_LEN); + + if (err_code != OK) return err_code; + + /* Get last directory inode */ + if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { +printf("MFS(%d) get_inode for parent dir by creat() failed\n", SELF_E); + return ENOENT; + } + + /* Create a new inode by calling new_node(). */ + rip = new_node(ldirp, lastc, omode, NO_ZONE); + r = err_code; + + /* If error, release inode. */ + if (r != OK) { + put_inode(ldirp); + put_inode(rip); + return(r); + } + + /* Reply message */ + fs_m_out.m_source = rip->i_dev; /* filled with FS endpoint by the system */ + fs_m_out.RES_INODE_NR = rip->i_num; + fs_m_out.RES_MODE = rip->i_mode; + fs_m_out.RES_FILE_SIZE = rip->i_size; + fs_m_out.RES_INODE_INDEX = (rip - &inode[0]) / sizeof(struct inode); + + /* This values are needed for the execution */ + fs_m_out.RES_UID = rip->i_uid; + fs_m_out.RES_GID = rip->i_gid; + if ((rip->i_mode & I_TYPE) == I_REGULAR) fs_m_out.RES_CTIME = rip->i_ctime; + + /* Drop parent dir */ + put_inode(ldirp); + + return OK; +} + /*===========================================================================* * fs_mknod * *===========================================================================*/ @@ -172,8 +227,7 @@ printf("MFS(%d) get_inode for parent dir by mknod() failed\n", SELF_E); } /* Try to create the new node */ - ip = new_node(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) fs_m_in.REQ_DEV, - TRUE, NULL); + ip = new_node(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) fs_m_in.REQ_DEV); put_inode(ip); put_inode(ldirp); @@ -208,7 +262,7 @@ printf("MFS(%d) get_inode for parent dir by mkdir() failed\n", SELF_E); } /* Next make the inode. If that fails, return error code. */ - rip = new_node(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) 0, TRUE, NULL); + rip = new_node(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) 0); if (rip == NIL_INODE || err_code == EEXIST) { put_inode(rip); /* can't make dir: it already exists */ @@ -275,7 +329,7 @@ PUBLIC int fs_slink() /* Create the inode for the symlink. */ sip = new_node(ldirp, string, (mode_t) (I_SYMBOLIC_LINK | RWX_MODES), - (zone_t) 0, TRUE, NULL); + (zone_t) 0); /* Allocate a disk block for the contents of the symlink. * Copy contents of symlink (the name pointed to) into first disk block. @@ -325,7 +379,7 @@ PUBLIC int fs_slink() * new_node * *===========================================================================*/ PRIVATE struct inode *new_node(struct inode *ldirp, - char *string, mode_t bits, zone_t z0, int opaque, char *parsed) + char *string, mode_t bits, zone_t z0) { /* New_node() is called by fs_open(), fs_mknod(), and fs_mkdir(). * In all cases it allocates a new inode, makes a directory entry for it in @@ -341,11 +395,6 @@ PRIVATE struct inode *new_node(struct inode *ldirp, register struct inode *rip; register int r; - /* - *ldirp = parse_path(path, string, opaque ? LAST_DIR : LAST_DIR_EATSYM); - if (*ldirp == NIL_INODE) return(NIL_INODE); - */ - /* Get final component of the path. */ rip = advance(&ldirp, string); @@ -391,11 +440,6 @@ PRIVATE struct inode *new_node(struct inode *ldirp, r = err_code; } - if(parsed) { /* Give the caller the parsed string if requested. */ - strncpy(parsed, string, NAME_MAX-1); - parsed[NAME_MAX-1] = '\0'; - } - /* The caller has to return the directory inode (*ldirp). */ err_code = r; return(rip); diff --git a/servers/mfs/path.c b/servers/mfs/path.c index ab0b80cef..5c6f37e37 100644 --- a/servers/mfs/path.c +++ b/servers/mfs/path.c @@ -36,7 +36,7 @@ PUBLIC int lookup() { char string[NAME_MAX]; struct inode *rip; - int s_error; + int s_error, flags; string[0] = '\0'; @@ -48,13 +48,16 @@ PUBLIC int lookup() caller_uid = fs_m_in.REQ_UID; caller_gid = fs_m_in.REQ_GID; + flags = fs_m_in.REQ_FLAGS; + + /* Clear RES_OFFSET for ENOENT */ + fs_m_out.RES_OFFSET= 0; /* Lookup inode */ - rip = parse_path(user_path, string, fs_m_in.REQ_FLAGS); + rip = parse_path(user_path, string, flags); /* Copy back the last name if it is required */ - if ((fs_m_in.REQ_FLAGS & LAST_DIR || fs_m_in.REQ_FLAGS & LAST_DIR_EATSYM) - && err_code != ENAMETOOLONG) { + if (err_code != OK || (flags & PATH_PENULTIMATE)) { s_error = sys_datacopy(SELF_E, (vir_bytes) string, FS_PROC_NR, (vir_bytes) fs_m_in.REQ_USER_ADDR, (phys_bytes) MIN(strlen(string)+1, NAME_MAX)); @@ -63,7 +66,11 @@ PUBLIC int lookup() /* Error or mount point encountered */ if (rip == NIL_INODE) - return err_code; + { + if (err_code != EENTERMOUNT) + fs_m_out.RES_INODE_NR = 0; /* signal no inode */ + return err_code; + } fs_m_out.RES_INODE_NR = rip->i_num; fs_m_out.RES_MODE = rip->i_mode; @@ -77,7 +84,7 @@ PUBLIC int lookup() /* Drop inode (path parse increased the counter) */ put_inode(rip); - return OK; + return err_code; } @@ -107,6 +114,7 @@ int action; /* action on last part of path */ printf("FS: couldn't find starting inode req_nr: %d %s\n", req_nr, user_path); err_code = ENOENT; +printf("%s, %d\n", __FILE__, __LINE__); return NIL_INODE; } @@ -116,6 +124,7 @@ int action; /* action on last part of path */ == NIL_INODE) { printf("FS: couldn't find chroot inode\n"); err_code = ENOENT; +printf("%s, %d\n", __FILE__, __LINE__); return NIL_INODE; } } @@ -135,6 +144,7 @@ int action; /* action on last part of path */ /* Note: empty (start) path is checked in the VFS process */ if (rip->i_nlinks == 0/* || *path == '\0'*/) { err_code = ENOENT; +printf("%s, %d\n", __FILE__, __LINE__); return(NIL_INODE); } @@ -148,7 +158,11 @@ int action; /* action on last part of path */ if (rip->i_mount == I_MOUNT && rip->i_num != ROOT_INODE) { dir_ip = rip; rip = advance(&dir_ip, ".."); - if (rip == NIL_INODE) return rip; + if (rip == NIL_INODE) + { +printf("%s, %d\n", __FILE__, __LINE__); + return NIL_INODE; + } put_inode(rip); /* advance() increased the counter */ } @@ -166,8 +180,10 @@ int action; /* action on last part of path */ /* Scan the path component by component. */ while (TRUE) { /* Extract one component. */ + fs_m_out.RES_OFFSET = path_processed; /* For ENOENT */ if ( (new_name = get_name(path, string)) == (char*) 0) { put_inode(rip); /* bad path in user space */ +printf("%s, %d\n", __FILE__, __LINE__); return(NIL_INODE); } if (*new_name == '\0' && (action & PATH_PENULTIMATE)) { @@ -177,6 +193,7 @@ int action; /* action on last part of path */ /* last file of path prefix is not a directory */ put_inode(rip); err_code = ENOTDIR; +printf("%s, %d\n", __FILE__, __LINE__); return(NIL_INODE); } } @@ -194,9 +211,17 @@ int action; /* action on last part of path */ if (rip == NIL_INODE) { if (*new_name == '\0' && (action & PATH_NONSYMBOLIC) != 0) + { +printf("%s, %d\n", __FILE__, __LINE__); return(dir_ip); + } + else if (err_code == ENOENT) + { + return(dir_ip); + } else { put_inode(dir_ip); +printf("%s, %d\n", __FILE__, __LINE__); return(NIL_INODE); } } @@ -211,6 +236,7 @@ int action; /* action on last part of path */ if (ltraverse(rip, user_path, new_name) != OK) { put_inode(dir_ip); err_code = ENOENT; +printf("%s, %d\n", __FILE__, __LINE__); return NIL_INODE; } @@ -218,6 +244,7 @@ int action; /* action on last part of path */ if (++symloop > SYMLOOP) { put_inode(dir_ip); err_code = ELOOP; +printf("%s, %d\n", __FILE__, __LINE__); return NIL_INODE; } @@ -250,6 +277,7 @@ int action; /* action on last part of path */ /* Either last name reached or symbolic link is opaque */ if ((action & PATH_NONSYMBOLIC) != 0) { put_inode(rip); +printf("%s, %d\n", __FILE__, __LINE__); return(dir_ip); } else { put_inode(dir_ip); diff --git a/servers/mfs/proto.h b/servers/mfs/proto.h index e8aef47d9..54f071985 100644 --- a/servers/mfs/proto.h +++ b/servers/mfs/proto.h @@ -24,12 +24,10 @@ int fs_mknod(void); int fs_mkdir(void); int fs_inhibread(void); int fs_stat(void); -int fs_fstat(void); +int fs_create(void); int fs_unlink(void); int fs_utime(void); int fs_fstatfs(void); -int fs_lstat(void); -int fs_getdir(void); int fs_link(void); int fs_lookup_rn_old(void); int fs_lookup_rn_new(void); diff --git a/servers/mfs/stadir.c b/servers/mfs/stadir.c index 6b7d7cb1a..720ee0460 100644 --- a/servers/mfs/stadir.c +++ b/servers/mfs/stadir.c @@ -13,111 +13,17 @@ FORWARD _PROTOTYPE( int stat_inode, (struct inode *rip, int pipe_pos, - char *user_addr, int who_e) ); + int who_e, cp_grant_id_t gid) ); -/*===========================================================================* - * fs_getdir * - *===========================================================================*/ -PUBLIC int fs_getdir() -{ - register int r; - register struct inode *rip; - - struct inodelist *rlp; - - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; - - /* Try to open the new directory. */ - if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { -printf("MFS(%d) get_inode by fs_getdir() failed\n", SELF_E); - return(EINVAL); - } - - r = forbidden(rip, X_BIT); /* check if dir is searchable */ - - /* If error, return inode. */ - if (r != OK) { - put_inode(rip); - return(r); - } - - /* If OK send back inode details */ - fs_m_out.m_source = rip->i_dev; /* filled with FS endpoint by the system */ - fs_m_out.RES_INODE_NR = rip->i_num; - fs_m_out.RES_MODE = rip->i_mode; - fs_m_out.RES_FILE_SIZE = rip->i_size; - -/* -printf("MFS(%d): ", SELF_E); -for (rlp = &hash_inodes[0]; rlp < &hash_inodes[INODE_HASH_SIZE]; ++rlp) { - int elements = 0; - LIST_FOREACH(rip, rlp, i_hash) elements++; - printf("%d ", elements); -} -printf("\n"); -*/ - - return OK; -} - -/*===========================================================================* - * fs_stat * - *===========================================================================*/ -PUBLIC int fs_stat() -{ - register struct inode *rip; - register int r; - - /* Both stat() and fstat() use the same routine to do the real work. That - * routine expects an inode, so acquire it temporarily. - */ - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; - - if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { -printf("MFS(%d) get_inode by fs_stat() failed\n", SELF_E); - return(EINVAL); - } - - r = stat_inode(rip, 0, fs_m_in.REQ_USER_ADDR, fs_m_in.REQ_WHO_E); - put_inode(rip); /* release the inode */ - return(r); -} - - -/*===========================================================================* - * fs_fstat * - *===========================================================================*/ -PUBLIC int fs_fstat() -{ - int r; - struct inode *rip; - - /* Both stat() and fstat() use the same routine to do the real work. That - * routine expects an inode, so acquire it temporarily. - */ - if ((rip = find_inode(fs_dev, fs_m_in.REQ_FD_INODE_NR)) - == NIL_INODE) { - printf("FSfstat: couldn't find inode %d\n", fs_m_in.REQ_FD_INODE_NR); - return EINVAL; - } - - r = stat_inode(rip, fs_m_in.REQ_FD_POS, fs_m_in.REQ_FD_USER_ADDR, - fs_m_in.REQ_FD_WHO_E); - - return r; -} - /*===========================================================================* * stat_inode * *===========================================================================*/ -PRIVATE int stat_inode(rip, pipe_pos, user_addr, who_e) +PRIVATE int stat_inode(rip, pipe_pos, who_e, gid) register struct inode *rip; /* pointer to inode to stat */ int pipe_pos; /* position in a pipe, supplied by fstat() */ -char *user_addr; /* user space address where stat buf goes */ -int who_e; /* kernel endpoint of the caller */ +int who_e; /* Caller endpoint */ +cp_grant_id_t gid; /* grant for the stat buf */ { /* Common code for stat and fstat system calls. */ @@ -153,14 +59,13 @@ int who_e; /* kernel endpoint of the caller */ statbuf.st_ctime = rip->i_ctime; /* Copy the struct to user space. */ - r = sys_datacopy(SELF, (vir_bytes) &statbuf, - who_e, (vir_bytes) user_addr, (phys_bytes) sizeof(statbuf)); + r = sys_safecopyto(who_e, gid, 0, (vir_bytes) &statbuf, + (phys_bytes) sizeof(statbuf), D); return(r); } - /*===========================================================================* * fs_fstatfs * *===========================================================================*/ @@ -169,7 +74,7 @@ PUBLIC int fs_fstatfs() struct statfs st; struct inode *rip; int r; - + if ((rip = find_inode(fs_dev, fs_m_in.REQ_FD_INODE_NR)) == NIL_INODE) { printf("FSfstatfs: couldn't find inode %d\n", fs_m_in.REQ_FD_INODE_NR); @@ -179,28 +84,26 @@ PUBLIC int fs_fstatfs() st.f_bsize = rip->i_sp->s_block_size; /* Copy the struct to user space. */ - r = sys_datacopy(SELF, (vir_bytes) &st, fs_m_in.REQ_FD_WHO_E, - (vir_bytes) fs_m_in.REQ_FD_USER_ADDR, (phys_bytes) sizeof(st)); + r = sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT, 0, + (vir_bytes) &st, (phys_bytes) sizeof(st), D); return(r); } /*===========================================================================* - * fs_lstat * + * fs_stat * *===========================================================================*/ -PUBLIC int fs_lstat() +PUBLIC int fs_stat() { register int r; /* return value */ register struct inode *rip; /* target inode */ - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { -printf("MFS(%d) get_inode by fs_lstat() failed\n", SELF_E); +printf("MFS(%d) get_inode by fs_stat() failed\n", SELF_E); return(EINVAL); } - r = stat_inode(rip, 0, fs_m_in.REQ_USER_ADDR, fs_m_in.REQ_WHO_E); + r = stat_inode(rip, 0, fs_m_in.m_source, fs_m_in.REQ_GRANT); put_inode(rip); /* release the inode */ return(r); } diff --git a/servers/mfs/table.c b/servers/mfs/table.c index a86739fb9..9a5a8f243 100644 --- a/servers/mfs/table.c +++ b/servers/mfs/table.c @@ -31,14 +31,13 @@ PUBLIC _PROTOTYPE (int (*fs_call_vec[]), (void) ) = { fs_mkdir, /* 13 */ fs_inhibread, /* 14 */ /* for lseek() */ fs_stat, /* 15 */ - fs_fstat, /* 16 */ + fs_create, /* 16 */ fs_unlink, /* 17 */ /* unlink() */ fs_unlink, /* 18 */ /* rmdir() */ fs_utime, /* 19 */ - fs_fstatfs, /* 20 */ - fs_lstat, /* 21 */ - fs_getdir, /* 22 */ /* chdir(), chroot() */ - + no_sys, /* 20 */ + fs_fstatfs, /* 21 */ + no_sys, /* 22 */ no_sys, /* 23 */ no_sys, /* 24 */ fs_link, /* 25 */ diff --git a/servers/vfs/device.c b/servers/vfs/device.c index efe4441e6..51d31e168 100644 --- a/servers/vfs/device.c +++ b/servers/vfs/device.c @@ -654,7 +654,7 @@ PUBLIC int do_ioctl() && (vp->v_mode & I_TYPE) != I_BLOCK_SPECIAL) return(ENOTTY); dev = (dev_t) vp->v_sdev; - return(dev_io(DEV_IOCTL, dev, who_e, m_in.ADDRESS, cvu64(0), + return (dev_io(DEV_IOCTL, dev, who_e, m_in.ADDRESS, cvu64(0), m_in.REQUEST, f->filp_flags)); } @@ -837,7 +837,7 @@ int flags; /* mode bits and flags */ vp = fp->fp_filp[m_in.fd]->filp_vno; put_vnode(vp); - if ((vp = get_free_vnode()) == NIL_VNODE) { + if ((vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) { printf("VFSclone_opcl: failed to get a free vnode..\n"); vp = fp->fp_filp[m_in.fd]->filp_vno; } @@ -852,7 +852,8 @@ int flags; /* mode bits and flags */ vp->v_inode_nr = res.inode_nr; vp->v_mode = res.fmode; vp->v_sdev = dev; - vp->v_count = 1; + vp->v_fs_count = 1; + vp->v_ref_count = 1; fp->fp_filp[m_in.fd]->filp_vno = vp; } dev_mess.REP_STATUS = OK; diff --git a/servers/vfs/exec.c b/servers/vfs/exec.c index 0cfc72dc4..6c32cf6d2 100644 --- a/servers/vfs/exec.c +++ b/servers/vfs/exec.c @@ -79,20 +79,16 @@ vir_bytes frame_len; uid_t new_uid; gid_t new_gid; struct fproc *rfp; - struct vnode vn; - struct vmnt *vmp; + struct vnode *vp; time_t v_ctime; - uid_t v_uid; - gid_t v_gid; char *cp; + struct stat sb; char progname[PROC_NAME_LEN]; static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */ /* Request and response structures */ struct lookup_req lookup_req; - struct access_req access_req; - struct open_req open_req; - struct node_details res; + struct node_details Xres; okendpt(proc_e, &proc_s); rfp= fp= &fproc[proc_s]; @@ -105,6 +101,7 @@ vir_bytes frame_len; if (r != OK) { printf("pm_exec: fetch_name failed\n"); +printf("return at %s, %d\n", __FILE__, __LINE__); return(r); /* file name not in user data segment */ } @@ -112,6 +109,7 @@ vir_bytes frame_len; if (frame_len > ARG_MAX) { printf("pm_exec: bad frame_len\n"); +printf("return at %s, %d\n", __FILE__, __LINE__); return(ENOMEM); /* stack too big */ } r = sys_datacopy(proc_e, (vir_bytes) frame, @@ -120,6 +118,7 @@ vir_bytes frame_len; if (r != OK) { printf("pm_exec: sys_datacopy failed\n"); +printf("return at %s, %d\n", __FILE__, __LINE__); return(r); } @@ -142,70 +141,48 @@ vir_bytes frame_len; lookup_req.flags = EAT_PATH; /* Request lookup */ - if ((r = lookup(&lookup_req, &res)) != OK) return r; + if ((r = lookup_vp(&lookup_req, &vp)) != OK) + { + put_vnode(vp); + return r; + } - if ((res.fmode & I_TYPE) != I_REGULAR) { + if ((vp->v_mode & I_TYPE) != I_REGULAR) { +printf("put_vnode at %s, %d\n", __FILE__, __LINE__); + put_vnode(vp); +printf("return at %s, %d\n", __FILE__, __LINE__); return ENOEXEC; } - else { - /* Fill in request fields */ - access_req.fs_e = res.fs_e; - access_req.amode = X_BIT; - access_req.inode_nr = res.inode_nr; - access_req.uid = fp->fp_effuid; - access_req.gid = fp->fp_effgid; - - - /* Issue request */ - if ((r = req_access(&access_req)) != OK) { - printf("VFSexec: access failed for %s\n", progname); - return r; - } - } - /* Open request. */ - open_req.inode_nr = res.inode_nr; - open_req.fs_e = res.fs_e; - open_req.oflags = 0; - open_req.omode = 0; - open_req.lastc = NULL; - open_req.uid = 0; - open_req.gid = 0; - - /* Issue request */ - if ((r = req_open(&open_req, &res)) != OK) { - printf("VFSexec: open failed\n"); + /* Check access. */ + if ((r = forbidden(vp, X_BIT)) != OK) + { +printf("put_vnode at %s, %d\n", __FILE__, __LINE__); + put_vnode(vp); +printf("return at %s, %d\n", __FILE__, __LINE__); return r; } - /* Use the vnode to store file details */ - vn.v_inode_nr = res.inode_nr; - vn.v_mode = res.fmode; - vn.v_index = res.inode_index; - vn.v_size = res.fsize; - vn.v_fs_e = res.fs_e; - vn.v_count = 1; - if ( (vmp = find_vmnt(vn.v_fs_e)) == NIL_VMNT) - printf("VFS: vmnt not found by exec()"); - - vn.v_dev = vmp->m_dev; - vn.v_vmnt = vmp; - - v_ctime = res.ctime; - v_uid = res.uid; - v_gid = res.gid; + /* Get ctime */ + r= req_stat(vp->v_fs_e, vp->v_inode_nr, FS_PROC_NR, (char *)&sb, 0); + if (r != OK) + { + put_vnode(vp); + return r; + } + v_ctime = sb.st_ctime; if (round == 0) { /* Deal with setuid/setgid executables */ - if (vn.v_mode & I_SET_UID_BIT) - new_uid = v_uid; - if (vn.v_mode & I_SET_GID_BIT) - new_gid = v_gid; + if (vp->v_mode & I_SET_UID_BIT) + new_uid = vp->v_uid; + if (vp->v_mode & I_SET_GID_BIT) + new_gid = vp->v_gid; } /* Read the file header and extract the segment sizes. */ - r = read_header(&vn, &sep_id, &text_bytes, &data_bytes, &bss_bytes, + r = read_header(vp, &sep_id, &text_bytes, &data_bytes, &bss_bytes, &tot_bytes, &pc, &hdrlen); if (r != ESCRIPT || round != 0) break; @@ -215,14 +192,17 @@ vir_bytes frame_len; if (r != OK) { printf("pm_exec: 2nd fetch_name failed\n"); - put_vnode(&vn); +printf("put_vnode at %s, %d\n", __FILE__, __LINE__); + put_vnode(vp); +printf("return at %s, %d\n", __FILE__, __LINE__); return(r); /* strange */ } - r= patch_stack(&vn, mbuf, &frame_len); - put_vnode(&vn); + r= patch_stack(vp, mbuf, &frame_len); + put_vnode(vp); if (r != OK) { printf("pm_exec: patch stack\n"); +printf("return at %s, %d\n", __FILE__, __LINE__); return r; } } @@ -230,16 +210,20 @@ vir_bytes frame_len; if (r != OK) { printf("pm_exec: returning ENOEXEC, r = %d\n", r); + printf("pm_exec: progname = '%s'\n", progname); + put_vnode(vp); return ENOEXEC; } r= exec_newmem(proc_e, text_bytes, data_bytes, bss_bytes, tot_bytes, - frame_len, sep_id, vn.v_dev, vn.v_inode_nr, v_ctime, + frame_len, sep_id, vp->v_dev, vp->v_inode_nr, v_ctime, progname, new_uid, new_gid, &stack_top, &load_text, &allow_setuid); if (r != OK) { printf("pm_exec: exec_newmap failed: %d\n", r); - put_vnode(&vn); +printf("put_vnode at %s, %d\n", __FILE__, __LINE__); + put_vnode(vp); +printf("return at %s, %d\n", __FILE__, __LINE__); return r; } @@ -255,15 +239,19 @@ vir_bytes frame_len; /* Read in text and data segments. */ if (load_text) { - r= read_seg(&vn, off, proc_e, T, text_bytes); + r= read_seg(vp, off, proc_e, T, text_bytes); } off += text_bytes; if (r == OK) - r= read_seg(&vn, off, proc_e, D, data_bytes); + r= read_seg(vp, off, proc_e, D, data_bytes); - put_vnode(&vn); + put_vnode(vp); - if (r != OK) return r; + if (r != OK) + { +printf("return at %s, %d\n", __FILE__, __LINE__); + return r; + } clo_exec(rfp); diff --git a/servers/vfs/link.c b/servers/vfs/link.c index c61686970..69c471bdb 100644 --- a/servers/vfs/link.c +++ b/servers/vfs/link.c @@ -270,6 +270,8 @@ PUBLIC int do_truncate() struct lookup_req lookup_req; struct node_details res; int r; + + printf("in do_truncate\n"); if (fetch_name(m_in.m2_p1, m_in.m2_i1, M1) != OK) return err_code; @@ -309,25 +311,39 @@ PUBLIC int do_truncate() PUBLIC int do_ftruncate() { /* As with do_truncate(), truncate_inode() does the actual work. */ - int r; struct filp *rfilp; - struct ftrunc_req req; if ( (rfilp = get_filp(m_in.m2_i1)) == NIL_FILP) return err_code; - if ( (rfilp->filp_vno->v_mode & I_TYPE) != I_REGULAR) + return truncate_vn(rfilp->filp_vno, m_in.m2_l1); +} + + +/*===========================================================================* + * truncate_vn * + *===========================================================================*/ +PUBLIC int truncate_vn(vp, newsize) +struct vnode *vp; +off_t newsize; +{ + int r; + struct ftrunc_req req; + + if ( (vp->v_mode & I_TYPE) != I_REGULAR && + (vp->v_mode & I_TYPE) != I_NAMED_PIPE) { return EINVAL; + } /* Fill in FS request */ - req.fs_e = rfilp->filp_vno->v_fs_e; - req.inode_nr = rfilp->filp_vno->v_inode_nr; - req.start = m_in.m2_l1; + req.fs_e = vp->v_fs_e; + req.inode_nr = vp->v_inode_nr; + req.start = newsize; req.end = 0; /* Indicate trunc in fs_freesp_trunc */ /* Issue request */ if ((r = req_ftrunc(&req)) != OK) return r; - rfilp->filp_vno->v_size = m_in.m2_l1; + vp->v_size = newsize; return OK; } diff --git a/servers/vfs/main.c b/servers/vfs/main.c index f7dac46df..bfd62da0f 100644 --- a/servers/vfs/main.c +++ b/servers/vfs/main.c @@ -57,7 +57,6 @@ PUBLIC int main() fs_init(); - /* This is the main loop that gets work, processes it, and sends replies. */ while (TRUE) { get_work(); /* sets who and call_nr */ @@ -86,6 +85,14 @@ PUBLIC int main() /* Device notifies us of an event. */ dev_status(&m_in); } +#if 0 + if (!check_vrefs()) + { + printf("after call %d from %d/%d\n", + call_nr, who_p, who_e); + panic(__FILE__, "check_vrefs failed at line", __LINE__); + } +#endif continue; } @@ -119,6 +126,13 @@ PUBLIC int main() if (error != SUSPEND) { reply(who_e, error); } } +#if 0 + if (!check_vrefs()) + { + printf("after call %d from %d/%d\n", call_nr, who_p, who_e); + panic(__FILE__, "check_vrefs failed at line", __LINE__); + } +#endif } return(OK); /* shouldn't come here */ } @@ -261,8 +275,8 @@ PRIVATE void fs_init() FD_ZERO(&(rfp->fp_filp_inuse)); if (rfp->fp_pid != PID_FREE) { - rfp->fp_rd = get_vnode(ROOT_FS_E, ROOT_INODE); - rfp->fp_wd = get_vnode(ROOT_FS_E, ROOT_INODE); + rfp->fp_rd = get_vnode_x(ROOT_FS_E, ROOT_INODE); + rfp->fp_wd = get_vnode_x(ROOT_FS_E, ROOT_INODE); } else rfp->fp_endpoint = NONE; } @@ -308,7 +322,7 @@ PRIVATE void init_root() vmp = &vmnt[0]; /* We'll need a vnode for the root inode, check whether there is one */ - if ((root_node = get_free_vnode()) == NIL_VNODE) { + if ((root_node = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) { panic(__FILE__,"Cannot get free vnode", r); } @@ -344,7 +358,8 @@ PRIVATE void init_root() root_node->v_mode = sres.fmode; root_node->v_size = sres.fsize; root_node->v_sdev = NO_DEV; - root_node->v_count = 1; + root_node->v_fs_count = 0; /* Is this correct? */ + root_node->v_ref_count = 1; /* Fill in max file size and blocksize for the vmnt */ vmp->m_fs_e = sres.fs_e; @@ -360,6 +375,7 @@ PRIVATE void init_root() /* Root directory is mounted on itself */ vmp->m_mounted_on = root_node; + root_node->v_ref_count++; vmp->m_root_node = root_node; } diff --git a/servers/vfs/misc.c b/servers/vfs/misc.c index 87729f0ae..f839004d0 100644 --- a/servers/vfs/misc.c +++ b/servers/vfs/misc.c @@ -326,7 +326,8 @@ PUBLIC void pm_reboot() put_vnode(vmnt[0].m_mounted_on); vmnt[0].m_mounted_on = &vdummy; vmnt[0].m_root_node = &vdummy; - vdummy.v_count = 1; + vdummy.v_fs_count = 0; /* Is this right? */ + vdummy.v_ref_count = 1; /* Unmount all filesystems. File systems are mounted on other file systems, * so you have to pull off the loose bits repeatedly to get it all undone. diff --git a/servers/vfs/mount.c b/servers/vfs/mount.c index 8d26a958c..769926ea3 100644 --- a/servers/vfs/mount.c +++ b/servers/vfs/mount.c @@ -110,6 +110,7 @@ PRIVATE int mount_fs(endpoint_t fs_e) struct readsuper_req sreq; struct readsuper_res sres; struct lookup_req lookup_req; + node_req_t node_req; /* Only the super-user may do MOUNT. */ if (!super_user) return(EPERM); @@ -131,13 +132,13 @@ PRIVATE int mount_fs(endpoint_t fs_e) if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); /* Get free vnode for the mountpoint */ - if ((mounted_on = get_free_vnode()) == NIL_VNODE) { + if ((mounted_on = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) { printf("VFSmount: not free vnode available\n"); return ENFILE; } /* Mark it as used so that we won't find the same for the root_node */ - mounted_on->v_count = 1; + mounted_on->v_ref_count = 1; /* Convert name to device number */ if ((dev = name_to_dev()) == NO_DEV) return(err_code); @@ -145,7 +146,7 @@ PRIVATE int mount_fs(endpoint_t fs_e) /* Check whether there is a block special file open which uses the * same device (partition) */ for (bspec = &vnode[0]; bspec < &vnode[NR_VNODES]; ++bspec) { - if (bspec->v_count > 0 && bspec->v_sdev == dev) { + if (bspec->v_ref_count > 0 && bspec->v_sdev == dev) { /* Found, sync the buffer cache */ req_sync(bspec->v_fs_e); break; @@ -187,7 +188,7 @@ PRIVATE int mount_fs(endpoint_t fs_e) * vnodes are different or if the root of FS is equal two the * root of the filesystem we found, we found a filesystem that * is in use. */ - mounted_on->v_count = 0; + mounted_on->v_ref_count = 0; return EBUSY; /* already mounted */ } @@ -221,7 +222,8 @@ PRIVATE int mount_fs(endpoint_t fs_e) mounted_on->v_mode = res.fmode; mounted_on->v_size = res.fsize; mounted_on->v_sdev = NO_DEV; - mounted_on->v_count = 1; + mounted_on->v_fs_count = 1; + mounted_on->v_ref_count = 1; /* Find the vmnt for the vnode */ if ( (vmp2 = find_vmnt(mounted_on->v_fs_e)) == NIL_VMNT) @@ -257,13 +259,13 @@ PRIVATE int mount_fs(endpoint_t fs_e) } /* We'll need a vnode for the root inode, check whether there is one */ - if ((root_node = get_free_vnode()) == NIL_VNODE) { + if ((root_node = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) { printf("VFSmount: no free vnode available\n"); return ENFILE; } /* Set it back to zero so that if st goes wrong it won't be kept in use */ - mounted_on->v_count = 0; + mounted_on->v_ref_count = 0; /* Fetch the name of the mountpoint */ if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) { @@ -300,13 +302,28 @@ PRIVATE int mount_fs(endpoint_t fs_e) return r; } + /* Fill in request message fields.*/ + node_req.fs_e = sres.fs_e; + node_req.inode_nr = sres.inode_nr; + + /* Issue request */ + if ((r = req_getnode(&node_req, &res)) != OK) + { + printf("mount: req_getnode failed: %d\n", r); + dev_close(dev); + return r; + } + /* Fill in root node's fields */ - root_node->v_fs_e = sres.fs_e; - root_node->v_inode_nr = sres.inode_nr; - root_node->v_mode = sres.fmode; - root_node->v_size = sres.fsize; + root_node->v_fs_e = res.fs_e; + root_node->v_inode_nr = res.inode_nr; + root_node->v_mode = res.fmode; + root_node->v_uid = res.uid; + root_node->v_gid = res.gid; + root_node->v_size = res.fsize; root_node->v_sdev = NO_DEV; - root_node->v_count = 1; + root_node->v_fs_count = 2; + root_node->v_ref_count = 1; /* Fill in max file size and blocksize for the vmnt */ vmp->m_fs_e = sres.fs_e; @@ -326,6 +343,7 @@ PRIVATE int mount_fs(endpoint_t fs_e) /* Superblock and root node already read. * Nothing else can go wrong. Perform the mount. */ vmp->m_root_node = root_node; + root_node->v_ref_count++; vmp->m_mounted_on = root_node; root_dev = dev; ROOT_FS_E = fs_e; @@ -380,7 +398,8 @@ PRIVATE int mount_fs(endpoint_t fs_e) mounted_on->v_mode = res.fmode; mounted_on->v_size = res.fsize; mounted_on->v_sdev = NO_DEV; - mounted_on->v_count = 1; + mounted_on->v_fs_count = 1; + mounted_on->v_ref_count = 1; /* Find the vmnt for the vnode */ if ( (vmp2 = find_vmnt(mounted_on->v_fs_e)) == NIL_VMNT) @@ -464,8 +483,8 @@ Dev_t dev; */ count = 0; for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) { - if (vp->v_count > 0 && vp->v_dev == dev) { - count += vp->v_count; + if (vp->v_ref_count > 0 && vp->v_dev == dev) { + count += vp->v_ref_count; } } @@ -474,6 +493,8 @@ Dev_t dev; return(EBUSY); /* can't umount a busy file system */ } + vnode_clean_refs(vmp->m_root_node); + /* Request FS the unmount */ if ((r = req_unmount(vmp->m_fs_e)) != OK) return r; @@ -509,10 +530,10 @@ Dev_t dev; /* Root device is mounted on itself */ if (vmp->m_root_node != vmp->m_mounted_on) { put_vnode(vmp->m_mounted_on); - vmp->m_root_node->v_count = 0; + vmp->m_root_node->v_ref_count = 0; } else { - vmp->m_mounted_on->v_count--; + vmp->m_mounted_on->v_fs_count--; } fs_e = vmp->m_fs_e; diff --git a/servers/vfs/open.c b/servers/vfs/open.c index 1489e5c96..d05233c07 100644 --- a/servers/vfs/open.c +++ b/servers/vfs/open.c @@ -34,7 +34,8 @@ #define offset_lo m2_l1 #define offset_high m2_l2 - +FORWARD _PROTOTYPE( int x_open, (int bits, int oflags, int omode, + char *lastc, struct vnode **vpp) ); FORWARD _PROTOTYPE( int common_open, (int oflags, mode_t omode) ); FORWARD _PROTOTYPE( int pipe_open, (struct vnode *vp,mode_t bits,int oflags)); @@ -89,13 +90,13 @@ PRIVATE int common_open(register int oflags, mode_t omode) struct filp *fil_ptr, *filp2; struct vnode *vp, *vp2; struct vmnt *vmp; - char lastc[NAME_MAX]; + char Xlastc[NAME_MAX]; + char *pathrem; int m; /* Request and response structures */ - struct lookup_req lookup_req; - struct open_req req; - struct node_details res; + struct lookup_req Xlookup_req; + struct open_req Xreq; /* Remap the bottom two bits of oflags. */ m = oflags & O_ACCMODE; @@ -109,26 +110,74 @@ PRIVATE int common_open(register int oflags, mode_t omode) /* See if file descriptor and filp slots are available. */ if ((r = get_fd(0, bits, &m_in.fd, &fil_ptr)) != OK) return(r); - /* See if a free vnode is available */ - if ((vp = get_free_vnode()) == NIL_VNODE) { - printf("VFS: no vnode available!\n"); - return err_code; - } - /* If O_CREATE, set umask */ if (oflags & O_CREAT) { omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask); } + vp= NULL; + +#if 0 + printf("common_open: for '%s'\n", user_fullpath); +#endif + /* Fill in lookup request fields */ - lookup_req.path = user_fullpath; - lookup_req.lastc = lastc; - lookup_req.flags = oflags&O_CREAT ? (oflags&O_EXCL ? LAST_DIR : + Xlookup_req.path = user_fullpath; + Xlookup_req.lastc = Xlastc; + Xlookup_req.flags = oflags&O_CREAT ? (oflags&O_EXCL ? LAST_DIR : LAST_DIR_EATSYM) : EAT_PATH; + Xlookup_req.flags = ((oflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) ? + LAST_DIR : EAT_PATH; + Xlastc[0]= '\0'; /* Clear lastc, it will be filled with the part of the + * path that cannot be resolved. + */ /* Request lookup */ - if ((r = lookup(&lookup_req, &res)) != OK) return r; + r = Xlookup_vp(&Xlookup_req, &vp, &pathrem); + + if (r == OK && ((oflags & (O_CREAT|O_EXCL)) != (O_CREAT|O_EXCL))) + { + /* Clear lastc */ + Xlastc[0]= '\0'; + } + /* Hide ENOENT for O_CREAT */ + if (r == ENOENT && (oflags & O_CREAT)) + { + if (pathrem == NULL) + panic(__FILE__, "no pathrem", NO_NUM); + if (strchr(pathrem, '/') == 0) + r= OK; + else + { + printf("common_open: / in pathrem"); + } + } + + if (r != OK) + { + if (vp) + { + put_vnode(vp); + vp= NULL; + } + return r; + } + + if (!vp) panic(__FILE__, "common_open: no vp", NO_NUM); + + r= x_open(bits, oflags, omode, Xlastc, &vp); + if (r != OK) + { + if (vp) + { + put_vnode(vp); + vp= NULL; + } + return r; + } + +#if 0 /* Lookup was okay, fill in request fields for * the actual open request. */ req.inode_nr = res.inode_nr; @@ -145,8 +194,9 @@ PRIVATE int common_open(register int oflags, mode_t omode) /* Check whether the vnode is already in use */ if ((vp2 = find_vnode(res.fs_e, res.inode_nr)) != NIL_VNODE) { vp = vp2; - vp->v_size = res.fsize;; /* In case of trunc... */ - vp->v_count++; + vp->v_size = res.fsize; /* In case of trunc... */ + vp->v_ref_count++; + vp->v_fs_count++; } /* Otherwise use the free one */ else { @@ -157,12 +207,16 @@ PRIVATE int common_open(register int oflags, mode_t omode) vp->v_dev = vmp->m_dev; vp->v_inode_nr = res.inode_nr; vp->v_mode = res.fmode; + vp->v_uid = res.uid; + vp->v_gid = res.gid; vp->v_size = res.fsize; vp->v_sdev = res.dev; - vp->v_count = 1; + vp->v_fs_count = 1; + vp->v_ref_count = 1; vp->v_vmnt = vmp; vp->v_index = res.inode_index; } +#endif /* Claim the file descriptor and filp slot and fill them in. */ fp->fp_filp[m_in.fd] = fil_ptr; @@ -171,6 +225,7 @@ PRIVATE int common_open(register int oflags, mode_t omode) fil_ptr->filp_flags = oflags; fil_ptr->filp_vno = vp; + vp->v_isfifo= FALSE; switch (vp->v_mode & I_TYPE) { case I_CHAR_SPECIAL: /* Invoke the driver for special processing. */ @@ -180,6 +235,8 @@ PRIVATE int common_open(register int oflags, mode_t omode) case I_BLOCK_SPECIAL: /* Invoke the driver for special processing. */ r = dev_open(vp->v_sdev, who_e, bits | (oflags & ~O_ACCMODE)); + if (r != OK) + panic(__FILE__, "common_open: dev_open failed", r); /* Check whether the device is mounted or not */ found = 0; @@ -219,7 +276,10 @@ PRIVATE int common_open(register int oflags, mode_t omode) break; case I_NAMED_PIPE: + printf("common_open: setting I_PIPE, inode %d on dev 0x%x\n", + vp->v_inode_nr, vp->v_dev); vp->v_pipe = I_PIPE; + vp->v_isfifo= TRUE; oflags |= O_APPEND; /* force append mode */ fil_ptr->filp_flags = oflags; r = pipe_open(vp, bits, oflags); @@ -269,6 +329,126 @@ PRIVATE int common_open(register int oflags, mode_t omode) return(m_in.fd); } +/*===========================================================================* + * x_open * + *===========================================================================*/ +PRIVATE int x_open(bits, oflags, omode, lastc, vpp) +mode_t bits; +int oflags; +mode_t omode; +char *lastc; +struct vnode **vpp; +{ + int r, b, exist = TRUE; + struct vnode *vp, *dvp, *tmp_vp; + struct vmnt *vmp; + struct node_details res; + + /* If O_CREATE is set, try to make the file. */ + if ((oflags & O_CREAT) && lastc[0] != '\0') { + dvp= *vpp; /* Parent directory */ + + /* See if a free vnode is available */ + if ((vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) { + printf("VFS x_open: no free vnode available\n"); + return EINVAL; + } + + r= req_create(dvp->v_fs_e, dvp->v_inode_nr, omode, fp->fp_effuid, + fp->fp_effgid, lastc, &res); + if (r != OK) + return r; + exist = FALSE; + + /* Check whether vnode is already in use or not */ + if ((tmp_vp = find_vnode(res.fs_e, res.inode_nr)) != NIL_VNODE) { + vp= tmp_vp; + vp->v_ref_count++; + vp->v_fs_count++; + } + else + { + /* Fill in the free vnode's fields */ + vp->v_fs_e = res.fs_e; + vp->v_inode_nr = res.inode_nr; + vp->v_mode = res.fmode; + vp->v_size = res.fsize; + vp->v_uid = res.uid; + vp->v_gid = res.gid; + vp->v_sdev = res.dev; + + if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT) + panic(__FILE__, "lookup_vp: vmnt not found", NO_NUM); + + vp->v_vmnt = vmp; + vp->v_dev = vmp->m_dev; + vp->v_fs_count = 1; + vp->v_ref_count = 1; + } + + /* Release dvp */ + put_vnode(dvp); + + /* Update *vpp */ + *vpp= vp; + } + else { + vp= *vpp; + } + + /* Only do the normal open code if we didn't just create the file. */ + if (!exist) + return OK; + + /* Check protections. */ + if ((r = forbidden(vp, bits)) != OK) + return r; + + /* Opening reg. files directories and special files differ. */ + switch (vp->v_mode & I_TYPE) { + case I_REGULAR: + /* Truncate regular file if O_TRUNC. */ + if (oflags & O_TRUNC) { + if ((r = forbidden(vp, W_BIT)) !=OK) break; + truncate_vn(vp, 0); + } + break; + + case I_DIRECTORY: + /* Directories may be read but not written. */ + r = (bits & W_BIT ? EISDIR : OK); + break; + + case I_CHAR_SPECIAL: + case I_BLOCK_SPECIAL: + if (vp->v_sdev == (dev_t)-1) + panic(__FILE__, "x_open: bad special", NO_NUM); + break; + + case I_NAMED_PIPE: + printf("x_open (fifo): reference count %d, fd %d\n", + vp->v_ref_count, vp->v_fs_count); + if (vp->v_ref_count == 1) + { + printf("x_open (fifo): first reference, size %u\n", + vp->v_size); + if (vp->v_size != 0) + { + printf("x_open (fifo): clearing\n"); + r= truncate_vn(vp, 0); + if (r != OK) + { + printf( + "x_open (fifo): truncate_vn failed: %d\n", + r); + } + } + } + break; + } + + return(r); +} /*===========================================================================* @@ -283,6 +463,8 @@ PRIVATE int pipe_open(register struct vnode *vp, register mode_t bits, * processes hanging on the pipe. */ + printf("pipe_open: setting I_PIPE, inode %d on dev 0x%x\n", + vp->v_inode_nr, vp->v_dev); vp->v_pipe = I_PIPE; if((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) { @@ -551,7 +733,7 @@ int fd_nr; /* If a write has been done, the inode is already marked as DIRTY. */ if (--rfilp->filp_count == 0) { - if (vp->v_pipe == I_PIPE && vp->v_count > 1) { + if (vp->v_pipe == I_PIPE && vp->v_ref_count > 1) { /* Save the file position in the v-node in case needed later. * The read and write positions are saved separately. */ diff --git a/servers/vfs/path.c b/servers/vfs/path.c index 86e060829..fa6051f97 100644 --- a/servers/vfs/path.c +++ b/servers/vfs/path.c @@ -21,6 +21,8 @@ #include "vnode.h" #include "param.h" +FORWARD _PROTOTYPE( int Xlookup, (lookup_req_t *lookup_req, + node_details_t *node, char **pathrem) ); /*===========================================================================* * lookup * @@ -104,6 +106,8 @@ node_details_t *node; } if (!start_node) { printf("VFSlookup: mounted partition couldn't be found\n"); + printf("VFSlookup: res.inode_nr = %d, res.fs_e = %d\n", + res.inode_nr, res.fs_e); return ENOENT; } @@ -138,15 +142,300 @@ node_details_t *node; r = req_lookup(&req, &res); } - /* If success, fill in response fields */ - if (OK == r) { - node->inode_nr = res.inode_nr; - node->fmode = res.fmode; - node->fsize = res.fsize; - node->dev = res.dev; - node->fs_e = res.fs_e; + /* Fill in response fields */ + node->inode_nr = res.inode_nr; + node->fmode = res.fmode; + node->fsize = res.fsize; + node->dev = res.dev; + node->fs_e = res.fs_e; + node->uid = res.uid; + node->gid = res.gid; + + return r; +} + + +/*===========================================================================* + * Xlookup * + *===========================================================================*/ +PRIVATE int Xlookup(lookup_req, node, pathrem) +lookup_req_t *lookup_req; +node_details_t *node; +char **pathrem; +{ + struct vmnt *vmp; + struct vnode *start_node; + struct lookup_res res; + int r, symloop = 0; + int cum_path_processed = 0; + + /* Make a copy of the request so that the original values will be kept */ + struct lookup_req req = *lookup_req; + char *fullpath = lookup_req->path; + + /* Clear pathrem */ + *pathrem= NULL; + + /* Empty (start) path? */ + if (fullpath[0] == '\0') { + return ENOENT; + } + + /* Set user and group ids according to the system call */ + req.uid = (call_nr == ACCESS ? fp->fp_realuid : fp->fp_effuid); + req.gid = (call_nr == ACCESS ? fp->fp_realgid : fp->fp_effgid); + + /* Set the starting directories inode number and FS endpoint */ + start_node = (fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd); + req.start_dir = start_node->v_inode_nr; + req.fs_e = start_node->v_fs_e; + + /* Is the process' root directory on the same partition?, + * if so, set the chroot directory too. */ + if (fp->fp_rd->v_dev == fp->fp_wd->v_dev) + req.root_dir = fp->fp_rd->v_inode_nr; + else + req.root_dir = 0; + + req.symloop = symloop; + + /* Issue the request */ + r = req_lookup(&req, &res); + + /* While the response is related to mount control set the + * new requests respectively */ + while (r == EENTERMOUNT || r == ELEAVEMOUNT || r == ESYMLINK) { + + /* If a symlink was encountered during the lookup the + * new path has been copied back and the number of characters + * processed has been started over. */ + if (r == ESYMLINK || res.symloop > symloop) { + /* The link's content is copied back to the user_fullpath + * array. Use it as the path argument from now on... */ + fullpath = user_fullpath; + cum_path_processed = res.char_processed; + } + else { + /* Otherwise, cumulate the characters already processsed from + * the path */ + cum_path_processed += res.char_processed; + } + + /* Remember the current value of the symloop counter */ + symloop = res.symloop; + + /* Symlink encountered with absolute path */ + if (r == ESYMLINK) { + start_node = fp->fp_rd; + } + /* Entering a new partition */ + else if (r == EENTERMOUNT) { + start_node = 0; + /* Start node is now the mounted partition's root node */ + for (vmp = &vmnt[0]; vmp != &vmnt[NR_MNTS]; ++vmp) { + if (vmp->m_mounted_on->v_inode_nr == res.inode_nr + && vmp->m_mounted_on->v_fs_e == res.fs_e) { + start_node = vmp->m_root_node; + break; + } + } + if (!start_node) { + printf("VFSlookup: mounted partition couldn't be found\n"); + printf("VFSlookup: res.inode_nr = %d, res.fs_e = %d\n", + res.inode_nr, res.fs_e); + return ENOENT; + } + + } + /* Climbing up mount */ + else { + /* Find the vmnt that represents the partition on + * which we "climb up". */ + if ((vmp = find_vmnt(res.fs_e)) == NIL_VMNT) { + printf("VFS: couldn't find vmnt during the climbup!\n"); + return ENOENT; + } + /* Start node is the vnode on which the partition is + * mounted */ + start_node = vmp->m_mounted_on; + } + /* Fill in the request fields */ + req.start_dir = start_node->v_inode_nr; + req.fs_e = start_node->v_fs_e; + + /* Is the process' root directory on the same partition?*/ + if (start_node->v_dev == fp->fp_rd->v_dev) + req.root_dir = fp->fp_rd->v_inode_nr; + else + req.root_dir = 0; + + /* Fill in the current path name */ + req.path = &fullpath[cum_path_processed]; + req.symloop = symloop; + + /* Issue the request */ + r = req_lookup(&req, &res); } + + if (r == ENOENT) + { + cum_path_processed += res.char_processed; + *pathrem= &fullpath[cum_path_processed]; + } + + /* Fill in response fields */ + node->inode_nr = res.inode_nr; + node->fmode = res.fmode; + node->fsize = res.fsize; + node->dev = res.dev; + node->fs_e = res.fs_e; + node->uid = res.uid; + node->gid = res.gid; return r; } + +/*===========================================================================* + * lookup_vp * + *===========================================================================*/ +PUBLIC int lookup_vp(lookup_req, vpp) +lookup_req_t *lookup_req; +struct vnode **vpp; +{ + int r, lookup_res; + struct vnode *vp; + struct vmnt *vmp; + node_req_t node_req; + struct node_details res; + + lookup_res = lookup(lookup_req, &res); + + if (res.inode_nr == 0) + { + printf("lookup_vp: lookup returned no inode\n"); + printf("lookup_res = %d, last = '%s'\n", + lookup_res, lookup_req->lastc); + *vpp= NULL; + return lookup_res; + } + + /* Check whether vnode is already in use or not */ + if ((vp = find_vnode(res.fs_e, res.inode_nr)) != NIL_VNODE) { + vp->v_ref_count++; + *vpp= vp; + return lookup_res; + } + + /* See if free vnode is available */ + if ((vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) { + printf("VFS lookup_vp: no free vnode available\n"); + *vpp= NULL; + return EINVAL; + } + + /* Fill in request message fields.*/ + node_req.fs_e = res.fs_e; + node_req.inode_nr = res.inode_nr; + + /* Issue request */ + if ((r = req_getnode(&node_req, &res)) != OK) + { + printf("lookup_vp: req_getnode failed: %d\n", r); + *vpp= NULL; + return r; + } + + /* Fill in the free vnode's fields */ + vp->v_fs_e = res.fs_e; + vp->v_inode_nr = res.inode_nr; + vp->v_mode = res.fmode; + vp->v_size = res.fsize; + vp->v_uid = res.uid; + vp->v_gid = res.gid; + vp->v_sdev = res.dev; + + if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT) + panic(__FILE__, "lookup_vp: vmnt not found", NO_NUM); + + vp->v_vmnt = vmp; + vp->v_dev = vmp->m_dev; + vp->v_fs_count = 1; + vp->v_ref_count = 1; + + *vpp= vp; + return lookup_res; +} + +/*===========================================================================* + * Xlookup_vp * + *===========================================================================*/ +PUBLIC int Xlookup_vp(lookup_req, vpp, pathrem) +lookup_req_t *lookup_req; +struct vnode **vpp; +char **pathrem; +{ + int r, lookup_res; + struct vnode *vp; + struct vmnt *vmp; + node_req_t node_req; + struct node_details res; + + lookup_res = Xlookup(lookup_req, &res, pathrem); + + if (res.inode_nr == 0) + { + printf("Xlookup_vp: lookup returned no inode\n"); + printf("lookup_res = %d, last = '%s'\n", + lookup_res, lookup_req->lastc); + *vpp= NULL; + return lookup_res; + } + + /* Check whether vnode is already in use or not */ + if ((vp = find_vnode(res.fs_e, res.inode_nr)) != NIL_VNODE) { + vp->v_ref_count++; + *vpp= vp; + return lookup_res; + } + + /* See if free vnode is available */ + if ((vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) { + printf("VFS Xlookup_vp: no free vnode available\n"); + *vpp= NULL; + return EINVAL; + } + + /* Fill in request message fields.*/ + node_req.fs_e = res.fs_e; + node_req.inode_nr = res.inode_nr; + + /* Issue request */ + if ((r = req_getnode(&node_req, &res)) != OK) + { + printf("Xlookup_vp: req_getnode failed: %d\n", r); + *vpp= NULL; + return r; + } + + /* Fill in the free vnode's fields */ + vp->v_fs_e = res.fs_e; + vp->v_inode_nr = res.inode_nr; + vp->v_mode = res.fmode; + vp->v_size = res.fsize; + vp->v_uid = res.uid; + vp->v_gid = res.gid; + vp->v_sdev = res.dev; + + if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT) + panic(__FILE__, "Xlookup_vp: vmnt not found", NO_NUM); + + vp->v_vmnt = vmp; + vp->v_dev = vmp->m_dev; + vp->v_fs_count = 1; + vp->v_ref_count = 1; + + *vpp= vp; + return lookup_res; +} + diff --git a/servers/vfs/pipe.c b/servers/vfs/pipe.c index af327dc51..0dddab50b 100644 --- a/servers/vfs/pipe.c +++ b/servers/vfs/pipe.c @@ -59,7 +59,7 @@ PUBLIC int do_pipe() struct node_details res; /* See if a free vnode is available */ - if ( (vp = get_free_vnode()) == NIL_VNODE) { + if ( (vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) { printf("VFS: no vnode available!\n"); return err_code; } @@ -105,7 +105,8 @@ PUBLIC int do_pipe() vp->v_mode = res.fmode; vp->v_index = res.inode_index; vp->v_pipe = I_PIPE; - vp->v_count = 2; /* Double usage */ + vp->v_fs_count = 2; /* Double usage */ + vp->v_ref_count = 2; /* Double usage */ vp->v_size = 0; if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT) { diff --git a/servers/vfs/protect.c b/servers/vfs/protect.c index 35173a7ad..093bc2200 100644 --- a/servers/vfs/protect.c +++ b/servers/vfs/protect.c @@ -163,3 +163,76 @@ PUBLIC int do_access() return req_access(&req); } + +/*===========================================================================* + * forbidden * + *===========================================================================*/ +PUBLIC int forbidden(struct vnode *vp, mode_t access_desired) +{ +/* Given a pointer to an inode, 'rip', and the access desired, determine + * if the access is allowed, and if not why not. The routine looks up the + * caller's uid in the 'fproc' table. If access is allowed, OK is returned + * if it is forbidden, EACCES is returned. + */ + + register struct super_block *sp; + register mode_t bits, perm_bits; + int r, shift, type; + + if (vp->v_uid == (uid_t)-1 || vp->v_gid == (gid_t)-1) + { + printf("forbidden: bad uid/gid in vnode\n"); + printf("forbidden: last allocated at %s, %d\n", vp->v_file, vp->v_line); + return EACCES; + } + + /* Isolate the relevant rwx bits from the mode. */ + bits = vp->v_mode; + if (fp->fp_effuid == SU_UID) { + /* Grant read and write permission. Grant search permission for + * directories. Grant execute permission (for non-directories) if + * and only if one of the 'X' bits is set. + */ + if ( (bits & I_TYPE) == I_DIRECTORY || + bits & ((X_BIT << 6) | (X_BIT << 3) | X_BIT)) + perm_bits = R_BIT | W_BIT | X_BIT; + else + perm_bits = R_BIT | W_BIT; + } else { + if (fp->fp_effuid == vp->v_uid) shift = 6; /* owner */ + else if (fp->fp_effgid == vp->v_gid ) shift = 3; /* group */ + else shift = 0; /* other */ + perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT); + } + + /* If access desired is not a subset of what is allowed, it is refused. */ + r = OK; + if ((perm_bits | access_desired) != perm_bits) r = EACCES; + + /* Check to see if someone is trying to write on a file system that is + * mounted read-only. + */ + if (r == OK) + if (access_desired & W_BIT) + r = read_only(vp); + + return(r); +} + + +/*===========================================================================* + * read_only * + *===========================================================================*/ +PUBLIC int read_only(vp) +struct vnode *vp; /* ptr to inode whose file sys is to be cked */ +{ +/* Check to see if the file system on which the inode 'ip' resides is mounted + * read only. If so, return EROFS, else return OK. + */ + register struct vmnt *mp; + + mp = vp->v_vmnt; + return(mp->m_flags ? EROFS : OK); +} + + diff --git a/servers/vfs/proto.h b/servers/vfs/proto.h index c886cea90..67aaf73ac 100644 --- a/servers/vfs/proto.h +++ b/servers/vfs/proto.h @@ -58,6 +58,7 @@ _PROTOTYPE( int do_unlink, (void) ); _PROTOTYPE( int do_rename, (void) ); _PROTOTYPE( int do_truncate, (void) ); _PROTOTYPE( int do_ftruncate, (void) ); +_PROTOTYPE( int truncate_vn, (struct vnode *vp, off_t newsize) ); /* lock.c */ _PROTOTYPE( int lock_op, (struct filp *f, int req) ); @@ -100,6 +101,9 @@ _PROTOTYPE( int do_slink, (void) ); /* path.c */ _PROTOTYPE( int lookup, (lookup_req_t *request, node_details_t *node) ); +_PROTOTYPE( int lookup_vp, (lookup_req_t *request, struct vnode **vpp) ); +_PROTOTYPE( int Xlookup_vp, (lookup_req_t *request, struct vnode **vpp, + char **pathrem) ); /* pipe.c */ _PROTOTYPE( int do_pipe, (void) ); @@ -120,6 +124,8 @@ _PROTOTYPE( int do_access, (void) ); _PROTOTYPE( int do_chmod, (void) ); _PROTOTYPE( int do_chown, (void) ); _PROTOTYPE( int do_umask, (void) ); +_PROTOTYPE( int forbidden, (struct vnode *vp, mode_t access_desired) ); +_PROTOTYPE( int read_only, (struct vnode *vp) ); /* read.c */ _PROTOTYPE( int do_read, (void) ); @@ -129,8 +135,10 @@ _PROTOTYPE( int read_write, (int rw_flag) ); /* request.c */ _PROTOTYPE( int fs_sendrec, (endpoint_t fs_e, message *reqm) ); _PROTOTYPE( int req_getnode, (node_req_t *req, node_details_t *res) ); -_PROTOTYPE( int req_putnode, (node_req_t *req) ); +_PROTOTYPE( int req_putnode, (int fs_e, ino_t inode_nr, int count) ); _PROTOTYPE( int req_open, (open_req_t *req, node_details_t *res) ); +_PROTOTYPE( int req_create, (int fs_e, ino_t inode_nr, int omode, + int uid, int gid, char *path, node_details_t *res) ); _PROTOTYPE( int req_readwrite, (readwrite_req_t *req, readwrite_res_t *res) ); _PROTOTYPE( int req_pipe, (pipe_req_t *req, node_details_t *res) ); @@ -143,15 +151,15 @@ _PROTOTYPE( int req_access, (access_req_t *req) ); _PROTOTYPE( int req_mknod, (mknod_req_t *req) ); _PROTOTYPE( int req_mkdir, (mkdir_req_t *req) ); _PROTOTYPE( int req_inhibread, (node_req_t *req) ); -_PROTOTYPE( int req_stat, (stat_req_t *req) ); -_PROTOTYPE( int req_fstat, (stat_req_t *req) ); -_PROTOTYPE( int req_fstatfs, (stat_req_t *req) ); +_PROTOTYPE( int req_stat, (int fs_e, ino_t inode_nr, int who_e, + char *buf, int pos) ); +_PROTOTYPE( int req_fstatfs, (int fs_e, ino_t inode_nr, int who_e, + char *buf) ); _PROTOTYPE( int req_unlink, (unlink_req_t *req) ); _PROTOTYPE( int req_rmdir, (unlink_req_t *req) ); _PROTOTYPE( int req_utime, (utime_req_t *req) ); _PROTOTYPE( int req_stime, (endpoint_t fs_e, time_t boottime) ); _PROTOTYPE( int req_sync, (endpoint_t fs_e) ); -_PROTOTYPE( int req_getdir, (getdir_req_t *req, node_details_t *res) ); _PROTOTYPE( int req_link, (link_req_t *req) ); _PROTOTYPE( int req_slink, (slink_req_t *req) ); _PROTOTYPE( int req_rdlink, (rdlink_req_t *req) ); @@ -202,11 +210,17 @@ _PROTOTYPE( struct vmnt *get_free_vmnt, (short *index) ); _PROTOTYPE( struct vmnt *find_vmnt, (int fs_e) ); /* vnode.c */ -_PROTOTYPE( struct vnode *get_free_vnode, (void) ); +_PROTOTYPE( struct vnode *get_free_vnode, (char *file, int line) ); _PROTOTYPE( struct vnode *find_vnode, (int fs_e, int numb) ); _PROTOTYPE( void dup_vnode, (struct vnode *vp) ); _PROTOTYPE( void put_vnode, (struct vnode *vp) ); +_PROTOTYPE( void vnode_clean_refs, (struct vnode *vp) ); _PROTOTYPE( struct vnode *get_vnode, (int fs_e, int inode_nr) ); +_PROTOTYPE( struct vnode *get_vnode_x, (int fs_e, int inode_nr) ); +#if 0 +_PROTOTYPE( void mark_vn, (struct vnode *vp, char *file, int line) ); +_PROTOTYPE( int check_vrefs, (void) ); +#endif /* write.c */ _PROTOTYPE( int do_write, (void) ); diff --git a/servers/vfs/read.c b/servers/vfs/read.c index 3f755cfeb..d142d33dd 100644 --- a/servers/vfs/read.c +++ b/servers/vfs/read.c @@ -192,6 +192,13 @@ int rw_flag; /* READING or WRITING */ req.user_addr = m_in.buffer; req.inode_index = vp->v_index; + if (vp->v_isfifo) + { + printf("read_write: %s for FIFO @ %u size %u\n", + (rw_flag == READING) ? "read" : "write", + ex64lo(position), m_in.nbytes); + } + /* Issue request */ r = req_readwrite(&req, &res); diff --git a/servers/vfs/request.c b/servers/vfs/request.c index 28d850f11..b41ea8746 100644 --- a/servers/vfs/request.c +++ b/servers/vfs/request.c @@ -12,6 +12,8 @@ #include "fs.h" #include +#include +#include #include #include #include @@ -50,6 +52,8 @@ node_details_t *res; res->fmode = m.RES_MODE; res->fsize = m.RES_FILE_SIZE; res->dev = m.RES_DEV; + res->uid = m.RES_UID; + res->gid = m.RES_GID; return OK; } @@ -58,17 +62,20 @@ node_details_t *res; /*===========================================================================* * req_putnode * *===========================================================================*/ -PUBLIC int req_putnode(req) -node_req_t *req; +PUBLIC int req_putnode(fs_e, inode_nr, count) +int fs_e; +ino_t inode_nr; +int count; { message m; /* Fill in request message */ m.m_type = REQ_PUTNODE; - m.REQ_INODE_NR = req->inode_nr; + m.REQ_INODE_NR = inode_nr; + m.REQ_COUNT = count; /* Send/rec request */ - return fs_sendrec(req->fs_e, &m); + return fs_sendrec(fs_e, &m); } /*===========================================================================* @@ -110,6 +117,49 @@ node_details_t *res; } +/*===========================================================================* + * req_create * + *===========================================================================*/ +int req_create(fs_e, inode_nr, omode, uid, gid, path, res) +int fs_e; +ino_t inode_nr; +int omode; +uid_t uid; +gid_t gid; +char *path; +node_details_t *res; +{ + int r; + message m; + + /* Fill in request message */ + m.m_type = REQ_CREATE; + m.REQ_INODE_NR = inode_nr; + m.REQ_MODE = omode; + m.REQ_UID = uid; + m.REQ_GID = gid; + m.REQ_PATH = path; + m.REQ_PATH_LEN = strlen(path) + 1; + + /* Send/rec request */ + if ((r = fs_sendrec(fs_e, &m)) != OK) return r; + + /* Fill in response structure */ + res->fs_e = m.m_source; + res->inode_nr = m.RES_INODE_NR; + res->fmode = m.RES_MODE; + res->fsize = m.RES_FILE_SIZE; + res->dev = m.RES_DEV; + res->inode_index = m.RES_INODE_INDEX; + /* For exec */ + res->uid = m.RES_UID; + res->gid = m.RES_GID; + res->ctime = m.RES_CTIME; + + return OK; +} + + /*===========================================================================* * req_readwrite * *===========================================================================*/ @@ -351,60 +401,81 @@ node_req_t *req; /*===========================================================================* * req_stat * *===========================================================================*/ -PUBLIC int req_stat(req) -stat_req_t *req; +PUBLIC int req_stat(fs_e, inode_nr, who_e, buf, pos) +int fs_e; +ino_t inode_nr; +int who_e; +char *buf; +int pos; { - message m; + cp_grant_id_t gid; + int r; + message m; + struct stat sb; + + if (pos != 0) + { + gid= cpf_grant_direct(fs_e, (vir_bytes)&sb, sizeof(struct stat), + CPF_WRITE); + } + else + { + gid= cpf_grant_magic(fs_e, who_e, (vir_bytes)buf, sizeof(struct stat), + CPF_WRITE); + } + if (gid < 0) + return gid; - /* Fill in request message */ - m.m_type = REQ_STAT; - m.REQ_INODE_NR = req->inode_nr; - m.REQ_UID = req->uid; - m.REQ_GID = req->gid; - m.REQ_WHO_E = req->who_e; - m.REQ_USER_ADDR = req->buf; + /* Fill in request message */ + m.m_type = REQ_STAT; + m.REQ_INODE_NR = inode_nr; + m.REQ_GRANT = gid; - /* Send/rec request */ - return fs_sendrec(req->fs_e, &m); -} + /* Send/rec request */ + r= fs_sendrec(fs_e, &m); + cpf_revoke(gid); -/*===========================================================================* - * req_fstat * - *===========================================================================*/ -PUBLIC int req_fstat(req) -stat_req_t *req; -{ - message m; - - /* Fill in request message */ - m.m_type = REQ_FSTAT; - m.REQ_FD_INODE_NR = req->inode_nr; - m.REQ_FD_WHO_E = req->who_e; - m.REQ_FD_USER_ADDR = req->buf; - m.REQ_FD_POS = req->pos; + if (r == OK && pos != 0) + { + sb.st_size -= pos; + r= sys_vircopy(SELF, D, (vir_bytes)&sb, who_e, D, (vir_bytes)buf, + sizeof(struct stat)); + } - /* Send/rec request */ - return fs_sendrec(req->fs_e, &m); + return r; } /*===========================================================================* * req_fstatfs * *===========================================================================*/ -PUBLIC int req_fstatfs(req) -stat_req_t *req; +PUBLIC int req_fstatfs(fs_e, inode_nr, who_e, buf) +int fs_e; +ino_t inode_nr; +int who_e; +char *buf; { - message m; + int r; + cp_grant_id_t gid; + message m; - /* Fill in request message */ - m.m_type = REQ_FSTATFS; - m.REQ_FD_INODE_NR = req->inode_nr; - m.REQ_FD_WHO_E = req->who_e; - m.REQ_FD_USER_ADDR = req->buf; + gid= cpf_grant_magic(fs_e, who_e, (vir_bytes)buf, sizeof(struct statfs), + CPF_WRITE); + if (gid < 0) + return gid; - /* Send/rec request */ - return fs_sendrec(req->fs_e, &m); + /* Fill in request message */ + m.m_type = REQ_FSTATFS; + m.REQ_INODE_NR = inode_nr; + m.REQ_GRANT = gid; + + /* Send/rec request */ + r= fs_sendrec(fs_e, &m); + + cpf_revoke(gid); + + return r; } @@ -505,35 +576,6 @@ endpoint_t fs_e; } -/*===========================================================================* - * req_getdir * - *===========================================================================*/ -PUBLIC int req_getdir(req, res) -getdir_req_t *req; -node_details_t *res; -{ - int r; - message m; - - /* Fill in request message */ - m.m_type = REQ_GETDIR; - m.REQ_INODE_NR = req->inode_nr; - m.REQ_UID = req->uid; - m.REQ_GID = req->gid; - - /* Send/rec request */ - if ((r = fs_sendrec(req->fs_e, &m)) != OK) return r; - - /* Fill in response structure */ - res->fs_e = m.m_source; - res->inode_nr = m.RES_INODE_NR; - res->fmode = m.RES_MODE; - res->fsize = m.RES_FILE_SIZE; - - return OK; -} - - /*===========================================================================* * req_link * *===========================================================================*/ @@ -787,10 +829,14 @@ lookup_res_t *res; res->fs_e = m.m_source; switch (r) { case OK: + default: res->inode_nr = m.RES_INODE_NR; res->fmode = m.RES_MODE; res->fsize = m.RES_FILE_SIZE; res->dev = m.RES_DEV; + res->uid= m.RES_UID; + res->gid= m.RES_GID; + res->char_processed = m.RES_OFFSET; /* For ENOENT */ break; case EENTERMOUNT: res->inode_nr = m.RES_INODE_NR; diff --git a/servers/vfs/request.h b/servers/vfs/request.h index a41a278f5..ca65ac016 100644 --- a/servers/vfs/request.h +++ b/servers/vfs/request.h @@ -142,17 +142,6 @@ typedef struct mkdir_req { } mkdir_req_t; -/* Structure for REQ_STAT, REQ_FSTAT, REQ_FSTATFS requests */ -typedef struct stat_req { - int fs_e; - ino_t inode_nr; - uid_t uid; - gid_t gid; - int who_e; - char *buf; - int pos; -} stat_req_t; - /* Structure for REQ_UNLINK request */ typedef struct unlink_req { int fs_e; @@ -174,15 +163,6 @@ typedef struct utime_req { } utime_req_t; -/* Structure for REQ_GETDIR request */ -typedef struct getdir_req { - endpoint_t fs_e; - ino_t inode_nr; - uid_t uid; - gid_t gid; -} getdir_req_t; - - /* Structure for REQ_LINK request */ typedef struct link_req { endpoint_t fs_e; @@ -294,6 +274,8 @@ typedef struct lookup_res { ino_t inode_nr; mode_t fmode; off_t fsize; + uid_t uid; + gid_t gid; /* For char/block special files */ dev_t dev; diff --git a/servers/vfs/stadir.c b/servers/vfs/stadir.c index 40889a3bf..2b90d2a81 100644 --- a/servers/vfs/stadir.c +++ b/servers/vfs/stadir.c @@ -37,8 +37,6 @@ PUBLIC int do_fchdir() { /* Change directory on already-opened fd. */ struct filp *rfilp; - struct getdir_req req; - struct node_details res; int r; /* Is the file descriptor valid? */ @@ -48,17 +46,11 @@ PUBLIC int do_fchdir() if ((rfilp->filp_vno->v_mode & I_TYPE) != I_DIRECTORY) return ENOTDIR; - /* Fill in request message fields.*/ - req.fs_e = rfilp->filp_vno->v_fs_e; - req.inode_nr = rfilp->filp_vno->v_inode_nr; - req.uid = fp->fp_effuid; - req.gid = fp->fp_effgid; - /* Issue request and handle error */ - if ((r = req_getdir(&req, &res)) != OK) return r; + r = forbidden(rfilp->filp_vno, X_BIT); + if (r != OK) return r; - /* GETDIR increased the counter in the FS proc */ - rfilp->filp_vno->v_count++; + rfilp->filp_vno->v_ref_count++; /* change_into expects a reference */ return change_into(&fp->fp_wd, rfilp->filp_vno); } @@ -129,63 +121,27 @@ char *name_ptr; /* pointer to the directory name to change to */ int len; /* length of the directory name string */ { /* Do the actual work for chdir() and chroot(). */ - struct vnode *vp, *vp2; - struct vmnt *vmp; - struct getdir_req req; - struct node_details res; + struct vnode *vp; struct lookup_req lookup_req; int r; if (fetch_name(name_ptr, len, M3) != OK) return(err_code); - /* See if free vnode is available */ - if ((vp = get_free_vnode()) == NIL_VNODE) { - printf("VFSchange: no free vnode available\n"); - return EINVAL; - } - /* Fill in lookup request fields */ lookup_req.path = user_fullpath; lookup_req.lastc = NULL; lookup_req.flags = EAT_PATH; /* Request lookup */ - if ((r = lookup(&lookup_req, &res)) != OK) return r; + if ((r = lookup_vp(&lookup_req, &vp)) != OK) return r; /* Is it a dir? */ - if ((res.fmode & I_TYPE) != I_DIRECTORY) + if ((vp->v_mode & I_TYPE) != I_DIRECTORY) + { + put_vnode(vp); return ENOTDIR; - - /* Fill in request message fields.*/ - req.fs_e = res.fs_e; - req.inode_nr = res.inode_nr; - req.uid = fp->fp_effuid; - req.gid = fp->fp_effgid; - - /* Issue request */ - if ((r = req_getdir(&req, &res)) != OK) return r; - - /* Check whether vnode is already in use or not */ - if ((vp2 = find_vnode(res.fs_e, res.inode_nr)) - != NIL_VNODE) { - vp2->v_count++; - vp = vp2; - } - else { - /* Fill in the free vnode's fields */ - vp->v_fs_e = res.fs_e; - vp->v_inode_nr = res.inode_nr; - vp->v_mode = res.fmode; - vp->v_size = res.fsize; - - if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT) - printf("VFSchange: vmnt not found"); - - vp->v_vmnt = vmp; - vp->v_dev = vmp->m_dev; - vp->v_count = 1; } - + return change_into(iip, vp); } @@ -211,7 +167,6 @@ struct vnode *vp; /* this is what the inode has to become */ PUBLIC int do_stat() { /* Perform the stat(name, buf) system call. */ - struct stat_req req; struct node_details res; struct lookup_req lookup_req; int r; @@ -226,16 +181,8 @@ PUBLIC int do_stat() /* Request lookup */ if ((r = lookup(&lookup_req, &res)) != OK) return r; - /* Fill in request message fields.*/ - req.fs_e = res.fs_e; - req.who_e = who_e; - req.buf = m_in.name2; - req.inode_nr = res.inode_nr; - req.uid = fp->fp_effuid; - req.gid = fp->fp_effgid; - /* Issue request */ - return req_stat(&req); + return req_stat(res.fs_e, res.inode_nr, who_e, m_in.name2, 0); } @@ -248,7 +195,6 @@ PUBLIC int do_fstat() /* Perform the fstat(fd, buf) system call. */ register struct filp *rfilp; int pipe_pos = 0; - struct stat_req req; /* Is the file descriptor valid? */ if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) { @@ -256,6 +202,7 @@ PUBLIC int do_fstat() } /* If we read from a pipe, send position too */ + pipe_pos= 0; if (rfilp->filp_vno->v_pipe == I_PIPE) { if (rfilp->filp_mode & R_BIT) if (ex64hi(rfilp->filp_pos) != 0) @@ -266,15 +213,9 @@ PUBLIC int do_fstat() pipe_pos = ex64lo(rfilp->filp_pos); } - /* Fill in request message */ - req.fs_e = rfilp->filp_vno->v_fs_e; - req.inode_nr = rfilp->filp_vno->v_inode_nr; - req.pos = pipe_pos; - req.who_e = who_e; - req.buf = m_in.buffer; - /* Issue request */ - return req_fstat(&req); + return req_stat(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr, + who_e, m_in.buffer, pipe_pos); } @@ -286,19 +227,13 @@ PUBLIC int do_fstatfs() { /* Perform the fstatfs(fd, buf) system call. */ register struct filp *rfilp; - struct stat_req req; /* Is the file descriptor valid? */ if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code); - /* Send FS request */ - req.fs_e = rfilp->filp_vno->v_fs_e; - req.inode_nr = rfilp->filp_vno->v_inode_nr; - req.who_e = who_e; - req.buf = m_in.buffer; - /* Issue request */ - return req_fstatfs(&req); + return req_fstatfs(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr, + who_e, m_in.buffer); } @@ -309,7 +244,6 @@ PUBLIC int do_fstatfs() PUBLIC int do_lstat() { /* Perform the lstat(name, buf) system call. */ - struct stat_req req; struct node_details res; struct lookup_req lookup_req; int r; @@ -324,16 +258,8 @@ PUBLIC int do_lstat() /* Request lookup */ if ((r = lookup(&lookup_req, &res)) != OK) return r; - /* Fill in request message fields.*/ - req.fs_e = res.fs_e; - req.who_e = who_e; - req.buf = m_in.name2; - req.inode_nr = res.inode_nr; - req.uid = fp->fp_effuid; - req.gid = fp->fp_effgid; - /* Issue request */ - return req_stat(&req); + return req_stat(res.fs_e, res.inode_nr, who_e, m_in.name2, 0); } diff --git a/servers/vfs/vnode.c b/servers/vfs/vnode.c index 0646bc4c7..a283d4c41 100644 --- a/servers/vfs/vnode.c +++ b/servers/vfs/vnode.c @@ -14,6 +14,9 @@ #include "vnode.h" #include "vmnt.h" +#include "fproc.h" +#include "file.h" + #include /*===========================================================================* @@ -30,9 +33,13 @@ PUBLIC struct vnode *get_vnode(int fs_e, int inode_nr) /* Request & response structures */ struct node_req req; struct node_details res; + + /* XXX remove this when debugging is complete */ + if (find_vnode(fs_e, inode_nr) != NULL) + panic(__FILE__, "get_vnode: vnode already present", NO_NUM); /* Check whether a free vnode is avaliable */ - if ((vp = get_free_vnode()) == NIL_VNODE) { + if ((vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) { printf("VFSget_vnode: no vnode available\n"); return NIL_VNODE; } @@ -60,22 +67,61 @@ PUBLIC struct vnode *get_vnode(int fs_e, int inode_nr) vp->v_vmnt = vmp; vp->v_dev = vmp->m_dev; - vp->v_count = 1; + vp->v_fs_count = 1; + vp->v_ref_count = 1; return vp; } +/*===========================================================================* + * get_vnode * + *===========================================================================*/ +PUBLIC struct vnode *get_vnode_x(int fs_e, int inode_nr) +{ +/* get_vnode() is called to get the details of the specified inode. + * Note that inode's usage counter in the FS is supposed to be incremented. + */ + struct vnode *vp, *vp2; + struct vmnt *vmp; + + /* Request & response structures */ + struct node_req req; + struct node_details res; + + vp= find_vnode(fs_e, inode_nr); + if (vp) + { + vp->v_ref_count++; + return vp; + } + + return get_vnode(fs_e, inode_nr); +} + + /*===========================================================================* * get_free_vnode * *===========================================================================*/ -PUBLIC struct vnode *get_free_vnode() +PUBLIC struct vnode *get_free_vnode(file, line) +char *file; +int line; { /* Find a free vnode slot in the vnode table */ struct vnode *vp; for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp) - if (vp->v_count == 0) return vp; + if (vp->v_ref_count == 0) + { + vp->v_pipe= NO_PIPE; + vp->v_uid= -1; + vp->v_gid= -1; + vp->v_sdev= -1; + vp->v_file= file; + vp->v_line= line; + return vp; + } + err_code = ENFILE; return NIL_VNODE; @@ -91,7 +137,7 @@ PUBLIC struct vnode *find_vnode(int fs_e, int numb) struct vnode *vp; for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp) - if (vp->v_count > 0 && vp->v_inode_nr == numb + if (vp->v_ref_count > 0 && vp->v_inode_nr == numb && vp->v_fs_e == fs_e) return vp; return NIL_VNODE; @@ -106,23 +152,12 @@ PUBLIC void dup_vnode(struct vnode *vp) /* dup_vnode() is called to increment the vnode and therefore the * referred inode's counter. */ - struct node_req req; - struct node_details res; - if (vp == NIL_VNODE) { printf("VFSdup_vnode NIL_VNODE\n"); return; } - /* Fill req struct */ - req.inode_nr = vp->v_inode_nr; - req.fs_e = vp->v_fs_e; - - /* Send request to FS */ - if (req_getnode(&req, &res) != OK) - printf("VFSdup_vnode Warning: inode doesn't exist\n"); - else - vp->v_count++; + vp->v_ref_count++; } @@ -134,28 +169,176 @@ PUBLIC void put_vnode(struct vnode *vp) /* Decrease vnode's usage counter and decrease inode's usage counter in the * corresponding FS process. */ - struct node_req req; - if (vp == NIL_VNODE) { /*printf("VFSput_vnode NIL_VNODE\n");*/ return; } - /* Fill in request fields */ - req.fs_e = vp->v_fs_e; - req.inode_nr = vp->v_inode_nr; + if (vp < &vnode[0] || vp >= &vnode[NR_VNODES]) + { + printf("put_vnode: &vnode[0] = %p, &vnode[NR_VNODES] = %p, vp = %p\n", + &vnode[0], &vnode[NR_VNODES], vp); + panic(__FILE__, "put_vnode: bad vnode pointer", NO_NUM); + } - /* Send request */ - if (req_putnode(&req) == OK) { - /* Decrease counter */ - if (--vp->v_count == 0) { - vp->v_pipe = NO_PIPE; - vp->v_sdev = NO_DEV; - vp->v_index = 0; - } + if (vp->v_ref_count > 1) + { + /* Decrease counter */ + vp->v_ref_count--; + if (vp->v_fs_count > 256) + vnode_clean_refs(vp); + return; + } + + if (vp->v_ref_count <= 0) + { + printf("put_vnode: bad v_ref_count %d\n", vp->v_ref_count); + panic(__FILE__, "put_vnode failed", NO_NUM); + } + if (vp->v_fs_count <= 0) + { + printf("put_vnode: bad v_fs_count %d\n", vp->v_fs_count); + panic(__FILE__, "put_vnode failed", NO_NUM); } - else + + /* Send request */ + if (req_putnode(vp->v_fs_e, vp->v_inode_nr, vp->v_fs_count) != OK) printf("VFSput_vnode Warning: inode doesn't exist\n"); + + vp->v_fs_count= 0; + vp->v_ref_count= 0; + vp->v_pipe = NO_PIPE; + vp->v_sdev = NO_DEV; + vp->v_index = 0; } +/*===========================================================================* + * vnode_clean_refs * + *===========================================================================*/ +PUBLIC void vnode_clean_refs(struct vnode *vp) +{ +/* Tell the underlying FS to drop all reference but one. */ + if (vp == NIL_VNODE) { + return; + } + + if (vp->v_fs_count <= 1) + return; /* Nothing to do */ + printf("vnode_clean_refs: dropping some references at FS\n"); + if (req_putnode(vp->v_fs_e, vp->v_inode_nr, vp->v_fs_count-1) != OK) + printf("vnode_clean_refs: req_putnode failed\n"); + vp->v_fs_count= 1; +} + + +#if 0 +/*===========================================================================* + * mark_vn * + *===========================================================================*/ +PUBLIC void mark_vn(vp, file, line) +struct vnode *vp; +char *file; +int line; +{ + if (!vp) + return; + vp->v_file= file; + vp->v_line= line; +} + + +/*===========================================================================* + * check_vrefs * + *===========================================================================*/ +PUBLIC int check_vrefs() +{ + int i, bad; + int ispipe_flag, ispipe_mode; + struct vnode *vp; + struct vmnt *vmp; + struct fproc *rfp; + struct filp *f; + + /* Clear v_ref_check */ + for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp) + vp->v_ref_check= 0; + + /* Count reference for processes */ + for (rfp=&fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { + if (rfp->fp_pid == PID_FREE) + continue; + vp= rfp->fp_rd; + if (vp < &vnode[0] || vp >= &vnode[NR_VNODES]) + panic(__FILE__, "check_vrefs: bad vnode", NO_NUM); + vp->v_ref_check++; + + vp= rfp->fp_wd; + if (vp < &vnode[0] || vp >= &vnode[NR_VNODES]) + panic(__FILE__, "check_vrefs: bad vnode", NO_NUM); + vp->v_ref_check++; + + } + + /* Count references from filedescriptors */ + for (f = &filp[0]; f < &filp[NR_FILPS]; f++) + { + if (f->filp_count == 0) + continue; + vp= f->filp_vno; + if (vp < &vnode[0] || vp >= &vnode[NR_VNODES]) + panic(__FILE__, "check_vrefs: bad vnode", NO_NUM); + vp->v_ref_check++; + } + + /* Count references to mount points */ + for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) + { + if (vmp->m_dev == NO_DEV) + continue; + vp= vmp->m_mounted_on; + if (vp < &vnode[0] || vp >= &vnode[NR_VNODES]) + panic(__FILE__, "check_vrefs: bad vnode", NO_NUM); + vp->v_ref_check++; + + vp= vmp->m_root_node; + if (vp < &vnode[0] || vp >= &vnode[NR_VNODES]) + panic(__FILE__, "check_vrefs: bad vnode", NO_NUM); + vp->v_ref_check++; + } + + /* Check references */ + bad= 0; + for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp) + { + if (vp->v_ref_count != vp->v_ref_check) + { + printf( +"Bad reference count for inode %d on device 0x%x: found %d, listed %d\n", + vp->v_inode_nr, vp->v_dev, vp->v_ref_check, + vp->v_ref_count); + printf("last marked at %s, %d\n", + vp->v_file, vp->v_line); + bad= 1; + } + + /* Also check v_pipe */ + if (vp->v_ref_count != 0) + { + ispipe_flag= (vp->v_pipe == I_PIPE); + ispipe_mode= ((vp->v_mode & I_TYPE) == I_NAMED_PIPE); + if (ispipe_flag != ispipe_mode) + { + printf( +"Bad v_pipe for inode %d on device 0x%x: found %d, mode 0%o\n", + vp->v_inode_nr, vp->v_dev, vp->v_pipe, + vp->v_mode); + printf("last marked at %s, %d\n", + vp->v_file, vp->v_line); + bad= 1; + } + } + } + return !bad; +} +#endif diff --git a/servers/vfs/vnode.h b/servers/vfs/vnode.h index afd8565fb..6cc1eec0c 100644 --- a/servers/vfs/vnode.h +++ b/servers/vfs/vnode.h @@ -4,8 +4,12 @@ EXTERN struct vnode { endpoint_t v_fs_e; /* FS process' endpoint number */ ino_t v_inode_nr; /* inode number on its (minor) device */ mode_t v_mode; /* file type, protection, etc. */ + uid_t v_uid; + gid_t v_gid; off_t v_size; /* current file size in bytes */ - int v_count; /* # times vnode used; 0 means slot is free */ + int v_ref_count; /* # times vnode used; 0 means slot is free */ + int v_fs_count; /* # reference at the underlying FS */ + int v_ref_check; /* for consistency checks */ char v_pipe; /* set to I_PIPE if pipe */ off_t v_pipe_rd_pos; off_t v_pipe_wr_pos; @@ -19,6 +23,11 @@ EXTERN struct vnode { int v_blocksize; /* block size of the filesys */ unsigned short v_index; /* inode's index in the FS inode table */ struct vmnt *v_vmnt; /* vmnt object of the partition */ + + /* For debugging */ + char *v_file; + int v_line; + int v_isfifo; } vnode[NR_VNODES]; #define NIL_VNODE (struct vnode *) 0 /* indicates absence of vnode slot */ -- 2.44.0