VFS cleanup (mostly open).

This commit is contained in:
Philip Homburg 2007-01-05 16:36:55 +00:00
parent 753f7bebde
commit 9092146be7
25 changed files with 1301 additions and 511 deletions

View file

@ -10,9 +10,11 @@
#define REQ_FLAGS m6_l3 #define REQ_FLAGS m6_l3
#define REQ_DEV m6_l3 #define REQ_DEV m6_l3
#define REQ_WHO_E m6_l3 #define REQ_WHO_E m6_l3
#define REQ_GRANT m6_l3
#define REQ_USER_ADDR m6_p2 #define REQ_USER_ADDR m6_p2
#define REQ_LENGTH m6_l3 #define REQ_LENGTH m6_l3
#define REQ_SYMLOOP m6_c2 #define REQ_SYMLOOP m6_c2
#define REQ_COUNT m6_l2
#define REQ_NEW_UID m6_s3 #define REQ_NEW_UID m6_s3
#define REQ_NEW_GID m6_c2 #define REQ_NEW_GID m6_c2
@ -75,7 +77,6 @@
#define RES_MODE m6_s1 #define RES_MODE m6_s1
#define RES_FILE_SIZE m6_l2 #define RES_FILE_SIZE m6_l2
#define RES_DEV m6_l3 #define RES_DEV m6_l3
#define RES_POS m6_l3
#define RES_INODE_INDEX m6_s2 #define RES_INODE_INDEX m6_s2
#define RES_NLINKS m6_s3 #define RES_NLINKS m6_s3
#define RES_SYMLOOP m6_c1 #define RES_SYMLOOP m6_c1
@ -110,7 +111,6 @@
#define REQ_WRITE 6 #define REQ_WRITE 6
#define REQ_CLONE_OPCL 7 #define REQ_CLONE_OPCL 7
#define REQ_FTRUNC 8 #define REQ_FTRUNC 8
#define REQ_CHOWN 9 #define REQ_CHOWN 9
#define REQ_CHMOD 10 #define REQ_CHMOD 10
#define REQ_ACCESS 11 #define REQ_ACCESS 11
@ -118,13 +118,14 @@
#define REQ_MKDIR 13 #define REQ_MKDIR 13
#define REQ_INHIBREAD 14 #define REQ_INHIBREAD 14
#define REQ_STAT 15 #define REQ_STAT 15
#define REQ_FSTAT 16
#define REQ_CREATE 16
#define REQ_UNLINK 17 #define REQ_UNLINK 17
#define REQ_RMDIR 18 #define REQ_RMDIR 18
#define REQ_UTIME 19 #define REQ_UTIME 19
#define REQ_FSTATFS 20
#define REQ_LSTAT 21 /* NO POINT !!! */ #define REQ_FSTATFS 21
#define REQ_GETDIR 22
#define REQ_LINK 25 #define REQ_LINK 25
@ -156,11 +157,3 @@
#define ELEAVEMOUNT 302 #define ELEAVEMOUNT 302
#define ESYMLINK 303 #define ESYMLINK 303

View file

@ -27,6 +27,7 @@ FORWARD _PROTOTYPE( void old_icopy, (struct inode *rip, d1_inode *dip,
int direction, int norm)); int direction, int norm));
FORWARD _PROTOTYPE( void new_icopy, (struct inode *rip, d2_inode *dip, FORWARD _PROTOTYPE( void new_icopy, (struct inode *rip, d2_inode *dip,
int direction, int norm)); 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. /* Find the inode specified by the request message and decrease its counter.
*/ */
struct inode *rip; struct inode *rip;
int count;
/* Sanity check for the direct index */ /* Sanity check for the direct index */
if (fs_m_in.REQ_INODE_INDEX >= 0 && if (fs_m_in.REQ_INODE_INDEX >= 0 &&
@ -50,10 +52,27 @@ PUBLIC int fs_putnode()
} }
if (!rip) if (!rip)
{
printf("FSput_inode: inode #%d dev: %d couldn't be put, req_nr: %d\n", 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); fs_m_in.REQ_INODE_NR, fs_dev, req_nr);
panic(__FILE__, "fs_putnode failed", NO_NUM);
}
put_inode(rip); 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_inode2(rip, count);
return OK; return OK;
} }
@ -80,6 +99,8 @@ PUBLIC int fs_getnode()
fs_m_out.RES_MODE = rip->i_mode; fs_m_out.RES_MODE = rip->i_mode;
fs_m_out.RES_FILE_SIZE = rip->i_size; fs_m_out.RES_FILE_SIZE = rip->i_size;
fs_m_out.RES_DEV = (Dev_t) rip->i_zone[0]; 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; return OK;
} }
@ -183,6 +204,10 @@ int numb; /* inode number (ANSI: may not be unshort) */
rip->i_count = 1; rip->i_count = 1;
if (dev != NO_DEV) rw_inode(rip, READING); /* get inode from disk */ if (dev != NO_DEV) rw_inode(rip, READING); /* get inode from disk */
rip->i_update = 0; /* all the times are initially up-to-date */ 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 */ /* Add to hash */
addhash_inode(rip); 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); if (rip->i_pipe == I_PIPE) truncate_inode(rip, 0);
} }
rip->i_mount = NO_MOUNT; 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_dirt == DIRTY) rw_inode(rip, WRITING);
if (rip->i_nlinks == 0) { if (rip->i_nlinks == 0) {

View file

@ -180,7 +180,7 @@ PRIVATE void cch_check(void)
for (i = 0; i < NR_INODES; ++i) { for (i = 0; i < NR_INODES; ++i) {
if (inode[i].i_count != cch[i] && if (inode[i].i_count != cch[i] &&
req_nr != REQ_OPEN && req_nr != REQ_GETNODE && 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_CLONE_OPCL && req_nr != REQ_READSUPER &&
req_nr != REQ_MOUNTPOINT && req_nr != REQ_UNMOUNT && req_nr != REQ_MOUNTPOINT && req_nr != REQ_UNMOUNT &&
req_nr != REQ_PIPE && req_nr != REQ_SYNC && req_nr != REQ_PIPE && req_nr != REQ_SYNC &&

View file

@ -15,7 +15,7 @@
PRIVATE char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0}; PRIVATE char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0};
FORWARD _PROTOTYPE( struct inode *new_node, (struct inode *ldirp, 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(). */ /* 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; r = err_code;
if (r == OK) exist = FALSE; /* we just created the file */ if (r == OK) exist = FALSE; /* we just created the file */
else if (r != EEXIST) { else if (r != EEXIST) {
@ -113,11 +113,6 @@ printf("MFS(%d) get_inode by open() failed\n", SELF_E);
case I_NAMED_PIPE: case I_NAMED_PIPE:
rip->i_pipe = I_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; break;
} }
} }
@ -148,6 +143,66 @@ printf("MFS(%d) get_inode by open() failed\n", SELF_E);
return OK; 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 * * 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 */ /* Try to create the new node */
ip = new_node(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) fs_m_in.REQ_DEV, ip = new_node(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) fs_m_in.REQ_DEV);
TRUE, NULL);
put_inode(ip); put_inode(ip);
put_inode(ldirp); 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. */ /* 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) { if (rip == NIL_INODE || err_code == EEXIST) {
put_inode(rip); /* can't make dir: it already exists */ put_inode(rip); /* can't make dir: it already exists */
@ -275,7 +329,7 @@ PUBLIC int fs_slink()
/* Create the inode for the symlink. */ /* Create the inode for the symlink. */
sip = new_node(ldirp, string, (mode_t) (I_SYMBOLIC_LINK | RWX_MODES), 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. /* Allocate a disk block for the contents of the symlink.
* Copy contents of symlink (the name pointed to) into first disk block. * Copy contents of symlink (the name pointed to) into first disk block.
@ -325,7 +379,7 @@ PUBLIC int fs_slink()
* new_node * * new_node *
*===========================================================================*/ *===========================================================================*/
PRIVATE struct inode *new_node(struct inode *ldirp, 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(). /* 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 * 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 struct inode *rip;
register int r; 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. */ /* Get final component of the path. */
rip = advance(&ldirp, string); rip = advance(&ldirp, string);
@ -391,11 +440,6 @@ PRIVATE struct inode *new_node(struct inode *ldirp,
r = err_code; 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). */ /* The caller has to return the directory inode (*ldirp). */
err_code = r; err_code = r;
return(rip); return(rip);

View file

@ -36,7 +36,7 @@ PUBLIC int lookup()
{ {
char string[NAME_MAX]; char string[NAME_MAX];
struct inode *rip; struct inode *rip;
int s_error; int s_error, flags;
string[0] = '\0'; string[0] = '\0';
@ -48,13 +48,16 @@ PUBLIC int lookup()
caller_uid = fs_m_in.REQ_UID; caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID; 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 */ /* 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 */ /* 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) if (err_code != OK || (flags & PATH_PENULTIMATE)) {
&& err_code != ENAMETOOLONG) {
s_error = sys_datacopy(SELF_E, (vir_bytes) string, FS_PROC_NR, s_error = sys_datacopy(SELF_E, (vir_bytes) string, FS_PROC_NR,
(vir_bytes) fs_m_in.REQ_USER_ADDR, (phys_bytes) (vir_bytes) fs_m_in.REQ_USER_ADDR, (phys_bytes)
MIN(strlen(string)+1, NAME_MAX)); MIN(strlen(string)+1, NAME_MAX));
@ -63,7 +66,11 @@ PUBLIC int lookup()
/* Error or mount point encountered */ /* Error or mount point encountered */
if (rip == NIL_INODE) if (rip == NIL_INODE)
{
if (err_code != EENTERMOUNT)
fs_m_out.RES_INODE_NR = 0; /* signal no inode */
return err_code; return err_code;
}
fs_m_out.RES_INODE_NR = rip->i_num; fs_m_out.RES_INODE_NR = rip->i_num;
fs_m_out.RES_MODE = rip->i_mode; fs_m_out.RES_MODE = rip->i_mode;
@ -77,7 +84,7 @@ PUBLIC int lookup()
/* Drop inode (path parse increased the counter) */ /* Drop inode (path parse increased the counter) */
put_inode(rip); 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, printf("FS: couldn't find starting inode req_nr: %d %s\n", req_nr,
user_path); user_path);
err_code = ENOENT; err_code = ENOENT;
printf("%s, %d\n", __FILE__, __LINE__);
return NIL_INODE; return NIL_INODE;
} }
@ -116,6 +124,7 @@ int action; /* action on last part of path */
== NIL_INODE) { == NIL_INODE) {
printf("FS: couldn't find chroot inode\n"); printf("FS: couldn't find chroot inode\n");
err_code = ENOENT; err_code = ENOENT;
printf("%s, %d\n", __FILE__, __LINE__);
return NIL_INODE; 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 */ /* Note: empty (start) path is checked in the VFS process */
if (rip->i_nlinks == 0/* || *path == '\0'*/) { if (rip->i_nlinks == 0/* || *path == '\0'*/) {
err_code = ENOENT; err_code = ENOENT;
printf("%s, %d\n", __FILE__, __LINE__);
return(NIL_INODE); 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) { if (rip->i_mount == I_MOUNT && rip->i_num != ROOT_INODE) {
dir_ip = rip; dir_ip = rip;
rip = advance(&dir_ip, ".."); 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 */ 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. */ /* Scan the path component by component. */
while (TRUE) { while (TRUE) {
/* Extract one component. */ /* Extract one component. */
fs_m_out.RES_OFFSET = path_processed; /* For ENOENT */
if ( (new_name = get_name(path, string)) == (char*) 0) { if ( (new_name = get_name(path, string)) == (char*) 0) {
put_inode(rip); /* bad path in user space */ put_inode(rip); /* bad path in user space */
printf("%s, %d\n", __FILE__, __LINE__);
return(NIL_INODE); return(NIL_INODE);
} }
if (*new_name == '\0' && (action & PATH_PENULTIMATE)) { 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 */ /* last file of path prefix is not a directory */
put_inode(rip); put_inode(rip);
err_code = ENOTDIR; err_code = ENOTDIR;
printf("%s, %d\n", __FILE__, __LINE__);
return(NIL_INODE); return(NIL_INODE);
} }
} }
@ -194,9 +211,17 @@ int action; /* action on last part of path */
if (rip == NIL_INODE) { if (rip == NIL_INODE) {
if (*new_name == '\0' && (action & PATH_NONSYMBOLIC) != 0) if (*new_name == '\0' && (action & PATH_NONSYMBOLIC) != 0)
{
printf("%s, %d\n", __FILE__, __LINE__);
return(dir_ip); return(dir_ip);
}
else if (err_code == ENOENT)
{
return(dir_ip);
}
else { else {
put_inode(dir_ip); put_inode(dir_ip);
printf("%s, %d\n", __FILE__, __LINE__);
return(NIL_INODE); return(NIL_INODE);
} }
} }
@ -211,6 +236,7 @@ int action; /* action on last part of path */
if (ltraverse(rip, user_path, new_name) != OK) { if (ltraverse(rip, user_path, new_name) != OK) {
put_inode(dir_ip); put_inode(dir_ip);
err_code = ENOENT; err_code = ENOENT;
printf("%s, %d\n", __FILE__, __LINE__);
return NIL_INODE; return NIL_INODE;
} }
@ -218,6 +244,7 @@ int action; /* action on last part of path */
if (++symloop > SYMLOOP) { if (++symloop > SYMLOOP) {
put_inode(dir_ip); put_inode(dir_ip);
err_code = ELOOP; err_code = ELOOP;
printf("%s, %d\n", __FILE__, __LINE__);
return NIL_INODE; return NIL_INODE;
} }
@ -250,6 +277,7 @@ int action; /* action on last part of path */
/* Either last name reached or symbolic link is opaque */ /* Either last name reached or symbolic link is opaque */
if ((action & PATH_NONSYMBOLIC) != 0) { if ((action & PATH_NONSYMBOLIC) != 0) {
put_inode(rip); put_inode(rip);
printf("%s, %d\n", __FILE__, __LINE__);
return(dir_ip); return(dir_ip);
} else { } else {
put_inode(dir_ip); put_inode(dir_ip);

View file

@ -24,12 +24,10 @@ int fs_mknod(void);
int fs_mkdir(void); int fs_mkdir(void);
int fs_inhibread(void); int fs_inhibread(void);
int fs_stat(void); int fs_stat(void);
int fs_fstat(void); int fs_create(void);
int fs_unlink(void); int fs_unlink(void);
int fs_utime(void); int fs_utime(void);
int fs_fstatfs(void); int fs_fstatfs(void);
int fs_lstat(void);
int fs_getdir(void);
int fs_link(void); int fs_link(void);
int fs_lookup_rn_old(void); int fs_lookup_rn_old(void);
int fs_lookup_rn_new(void); int fs_lookup_rn_new(void);

View file

@ -13,111 +13,17 @@
FORWARD _PROTOTYPE( int stat_inode, (struct inode *rip, int pipe_pos, 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 * * 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 */ register struct inode *rip; /* pointer to inode to stat */
int pipe_pos; /* position in a pipe, supplied by fstat() */ int pipe_pos; /* position in a pipe, supplied by fstat() */
char *user_addr; /* user space address where stat buf goes */ int who_e; /* Caller endpoint */
int who_e; /* kernel endpoint of the caller */ cp_grant_id_t gid; /* grant for the stat buf */
{ {
/* Common code for stat and fstat system calls. */ /* 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; statbuf.st_ctime = rip->i_ctime;
/* Copy the struct to user space. */ /* Copy the struct to user space. */
r = sys_datacopy(SELF, (vir_bytes) &statbuf, r = sys_safecopyto(who_e, gid, 0, (vir_bytes) &statbuf,
who_e, (vir_bytes) user_addr, (phys_bytes) sizeof(statbuf)); (phys_bytes) sizeof(statbuf), D);
return(r); return(r);
} }
/*===========================================================================* /*===========================================================================*
* fs_fstatfs * * fs_fstatfs *
*===========================================================================*/ *===========================================================================*/
@ -179,28 +84,26 @@ PUBLIC int fs_fstatfs()
st.f_bsize = rip->i_sp->s_block_size; st.f_bsize = rip->i_sp->s_block_size;
/* Copy the struct to user space. */ /* Copy the struct to user space. */
r = sys_datacopy(SELF, (vir_bytes) &st, fs_m_in.REQ_FD_WHO_E, r = sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT, 0,
(vir_bytes) fs_m_in.REQ_FD_USER_ADDR, (phys_bytes) sizeof(st)); (vir_bytes) &st, (phys_bytes) sizeof(st), D);
return(r); return(r);
} }
/*===========================================================================* /*===========================================================================*
* fs_lstat * * fs_stat *
*===========================================================================*/ *===========================================================================*/
PUBLIC int fs_lstat() PUBLIC int fs_stat()
{ {
register int r; /* return value */ register int r; /* return value */
register struct inode *rip; /* target inode */ 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) { 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); 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 */ put_inode(rip); /* release the inode */
return(r); return(r);
} }

View file

@ -31,14 +31,13 @@ PUBLIC _PROTOTYPE (int (*fs_call_vec[]), (void) ) = {
fs_mkdir, /* 13 */ fs_mkdir, /* 13 */
fs_inhibread, /* 14 */ /* for lseek() */ fs_inhibread, /* 14 */ /* for lseek() */
fs_stat, /* 15 */ fs_stat, /* 15 */
fs_fstat, /* 16 */ fs_create, /* 16 */
fs_unlink, /* 17 */ /* unlink() */ fs_unlink, /* 17 */ /* unlink() */
fs_unlink, /* 18 */ /* rmdir() */ fs_unlink, /* 18 */ /* rmdir() */
fs_utime, /* 19 */ fs_utime, /* 19 */
fs_fstatfs, /* 20 */ no_sys, /* 20 */
fs_lstat, /* 21 */ fs_fstatfs, /* 21 */
fs_getdir, /* 22 */ /* chdir(), chroot() */ no_sys, /* 22 */
no_sys, /* 23 */ no_sys, /* 23 */
no_sys, /* 24 */ no_sys, /* 24 */
fs_link, /* 25 */ fs_link, /* 25 */

View file

@ -837,7 +837,7 @@ int flags; /* mode bits and flags */
vp = fp->fp_filp[m_in.fd]->filp_vno; vp = fp->fp_filp[m_in.fd]->filp_vno;
put_vnode(vp); 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"); printf("VFSclone_opcl: failed to get a free vnode..\n");
vp = fp->fp_filp[m_in.fd]->filp_vno; 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_inode_nr = res.inode_nr;
vp->v_mode = res.fmode; vp->v_mode = res.fmode;
vp->v_sdev = dev; 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; fp->fp_filp[m_in.fd]->filp_vno = vp;
} }
dev_mess.REP_STATUS = OK; dev_mess.REP_STATUS = OK;

View file

@ -79,20 +79,16 @@ vir_bytes frame_len;
uid_t new_uid; uid_t new_uid;
gid_t new_gid; gid_t new_gid;
struct fproc *rfp; struct fproc *rfp;
struct vnode vn; struct vnode *vp;
struct vmnt *vmp;
time_t v_ctime; time_t v_ctime;
uid_t v_uid;
gid_t v_gid;
char *cp; char *cp;
struct stat sb;
char progname[PROC_NAME_LEN]; char progname[PROC_NAME_LEN];
static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */ static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */
/* Request and response structures */ /* Request and response structures */
struct lookup_req lookup_req; struct lookup_req lookup_req;
struct access_req access_req; struct node_details Xres;
struct open_req open_req;
struct node_details res;
okendpt(proc_e, &proc_s); okendpt(proc_e, &proc_s);
rfp= fp= &fproc[proc_s]; rfp= fp= &fproc[proc_s];
@ -105,6 +101,7 @@ vir_bytes frame_len;
if (r != OK) if (r != OK)
{ {
printf("pm_exec: fetch_name failed\n"); printf("pm_exec: fetch_name failed\n");
printf("return at %s, %d\n", __FILE__, __LINE__);
return(r); /* file name not in user data segment */ return(r); /* file name not in user data segment */
} }
@ -112,6 +109,7 @@ vir_bytes frame_len;
if (frame_len > ARG_MAX) if (frame_len > ARG_MAX)
{ {
printf("pm_exec: bad frame_len\n"); printf("pm_exec: bad frame_len\n");
printf("return at %s, %d\n", __FILE__, __LINE__);
return(ENOMEM); /* stack too big */ return(ENOMEM); /* stack too big */
} }
r = sys_datacopy(proc_e, (vir_bytes) frame, r = sys_datacopy(proc_e, (vir_bytes) frame,
@ -120,6 +118,7 @@ vir_bytes frame_len;
if (r != OK) if (r != OK)
{ {
printf("pm_exec: sys_datacopy failed\n"); printf("pm_exec: sys_datacopy failed\n");
printf("return at %s, %d\n", __FILE__, __LINE__);
return(r); return(r);
} }
@ -142,70 +141,48 @@ vir_bytes frame_len;
lookup_req.flags = EAT_PATH; lookup_req.flags = EAT_PATH;
/* Request lookup */ /* 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; 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;
/* Check access. */
/* Issue request */ if ((r = forbidden(vp, X_BIT)) != OK)
if ((r = req_access(&access_req)) != OK) { {
printf("VFSexec: access failed for %s\n", progname); printf("put_vnode at %s, %d\n", __FILE__, __LINE__);
return r; put_vnode(vp);
} printf("return at %s, %d\n", __FILE__, __LINE__);
}
/* 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");
return r; return r;
} }
/* Use the vnode to store file details */ /* Get ctime */
vn.v_inode_nr = res.inode_nr; r= req_stat(vp->v_fs_e, vp->v_inode_nr, FS_PROC_NR, (char *)&sb, 0);
vn.v_mode = res.fmode; if (r != OK)
vn.v_index = res.inode_index; {
vn.v_size = res.fsize; put_vnode(vp);
vn.v_fs_e = res.fs_e; return r;
vn.v_count = 1; }
if ( (vmp = find_vmnt(vn.v_fs_e)) == NIL_VMNT) v_ctime = sb.st_ctime;
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;
if (round == 0) if (round == 0)
{ {
/* Deal with setuid/setgid executables */ /* Deal with setuid/setgid executables */
if (vn.v_mode & I_SET_UID_BIT) if (vp->v_mode & I_SET_UID_BIT)
new_uid = v_uid; new_uid = vp->v_uid;
if (vn.v_mode & I_SET_GID_BIT) if (vp->v_mode & I_SET_GID_BIT)
new_gid = v_gid; new_gid = vp->v_gid;
} }
/* Read the file header and extract the segment sizes. */ /* 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); &tot_bytes, &pc, &hdrlen);
if (r != ESCRIPT || round != 0) if (r != ESCRIPT || round != 0)
break; break;
@ -215,14 +192,17 @@ vir_bytes frame_len;
if (r != OK) if (r != OK)
{ {
printf("pm_exec: 2nd fetch_name failed\n"); 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 */ return(r); /* strange */
} }
r= patch_stack(&vn, mbuf, &frame_len); r= patch_stack(vp, mbuf, &frame_len);
put_vnode(&vn); put_vnode(vp);
if (r != OK) if (r != OK)
{ {
printf("pm_exec: patch stack\n"); printf("pm_exec: patch stack\n");
printf("return at %s, %d\n", __FILE__, __LINE__);
return r; return r;
} }
} }
@ -230,16 +210,20 @@ vir_bytes frame_len;
if (r != OK) if (r != OK)
{ {
printf("pm_exec: returning ENOEXEC, r = %d\n", r); printf("pm_exec: returning ENOEXEC, r = %d\n", r);
printf("pm_exec: progname = '%s'\n", progname);
put_vnode(vp);
return ENOEXEC; return ENOEXEC;
} }
r= exec_newmem(proc_e, text_bytes, data_bytes, bss_bytes, tot_bytes, 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); progname, new_uid, new_gid, &stack_top, &load_text, &allow_setuid);
if (r != OK) if (r != OK)
{ {
printf("pm_exec: exec_newmap failed: %d\n", r); 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; return r;
} }
@ -255,15 +239,19 @@ vir_bytes frame_len;
/* Read in text and data segments. */ /* Read in text and data segments. */
if (load_text) { 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; off += text_bytes;
if (r == OK) 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); clo_exec(rfp);

View file

@ -271,6 +271,8 @@ PUBLIC int do_truncate()
struct node_details res; struct node_details res;
int r; int r;
printf("in do_truncate\n");
if (fetch_name(m_in.m2_p1, m_in.m2_i1, M1) != OK) return err_code; if (fetch_name(m_in.m2_p1, m_in.m2_i1, M1) != OK) return err_code;
/* Fill in lookup request fields */ /* Fill in lookup request fields */
@ -309,25 +311,39 @@ PUBLIC int do_truncate()
PUBLIC int do_ftruncate() PUBLIC int do_ftruncate()
{ {
/* As with do_truncate(), truncate_inode() does the actual work. */ /* As with do_truncate(), truncate_inode() does the actual work. */
int r;
struct filp *rfilp; struct filp *rfilp;
struct ftrunc_req req;
if ( (rfilp = get_filp(m_in.m2_i1)) == NIL_FILP) if ( (rfilp = get_filp(m_in.m2_i1)) == NIL_FILP)
return err_code; 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; return EINVAL;
}
/* Fill in FS request */ /* Fill in FS request */
req.fs_e = rfilp->filp_vno->v_fs_e; req.fs_e = vp->v_fs_e;
req.inode_nr = rfilp->filp_vno->v_inode_nr; req.inode_nr = vp->v_inode_nr;
req.start = m_in.m2_l1; req.start = newsize;
req.end = 0; /* Indicate trunc in fs_freesp_trunc */ req.end = 0; /* Indicate trunc in fs_freesp_trunc */
/* Issue request */ /* Issue request */
if ((r = req_ftrunc(&req)) != OK) return r; if ((r = req_ftrunc(&req)) != OK) return r;
rfilp->filp_vno->v_size = m_in.m2_l1; vp->v_size = newsize;
return OK; return OK;
} }

View file

@ -57,7 +57,6 @@ PUBLIC int main()
fs_init(); fs_init();
/* This is the main loop that gets work, processes it, and sends replies. */ /* This is the main loop that gets work, processes it, and sends replies. */
while (TRUE) { while (TRUE) {
get_work(); /* sets who and call_nr */ get_work(); /* sets who and call_nr */
@ -86,6 +85,14 @@ PUBLIC int main()
/* Device notifies us of an event. */ /* Device notifies us of an event. */
dev_status(&m_in); 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; continue;
} }
@ -119,6 +126,13 @@ PUBLIC int main()
if (error != SUSPEND) { reply(who_e, error); } 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 */ return(OK); /* shouldn't come here */
} }
@ -261,8 +275,8 @@ PRIVATE void fs_init()
FD_ZERO(&(rfp->fp_filp_inuse)); FD_ZERO(&(rfp->fp_filp_inuse));
if (rfp->fp_pid != PID_FREE) { if (rfp->fp_pid != PID_FREE) {
rfp->fp_rd = get_vnode(ROOT_FS_E, ROOT_INODE); rfp->fp_rd = get_vnode_x(ROOT_FS_E, ROOT_INODE);
rfp->fp_wd = get_vnode(ROOT_FS_E, ROOT_INODE); rfp->fp_wd = get_vnode_x(ROOT_FS_E, ROOT_INODE);
} else rfp->fp_endpoint = NONE; } else rfp->fp_endpoint = NONE;
} }
@ -308,7 +322,7 @@ PRIVATE void init_root()
vmp = &vmnt[0]; vmp = &vmnt[0];
/* We'll need a vnode for the root inode, check whether there is one */ /* 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); panic(__FILE__,"Cannot get free vnode", r);
} }
@ -344,7 +358,8 @@ PRIVATE void init_root()
root_node->v_mode = sres.fmode; root_node->v_mode = sres.fmode;
root_node->v_size = sres.fsize; root_node->v_size = sres.fsize;
root_node->v_sdev = NO_DEV; 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 */ /* Fill in max file size and blocksize for the vmnt */
vmp->m_fs_e = sres.fs_e; vmp->m_fs_e = sres.fs_e;
@ -360,6 +375,7 @@ PRIVATE void init_root()
/* Root directory is mounted on itself */ /* Root directory is mounted on itself */
vmp->m_mounted_on = root_node; vmp->m_mounted_on = root_node;
root_node->v_ref_count++;
vmp->m_root_node = root_node; vmp->m_root_node = root_node;
} }

View file

@ -326,7 +326,8 @@ PUBLIC void pm_reboot()
put_vnode(vmnt[0].m_mounted_on); put_vnode(vmnt[0].m_mounted_on);
vmnt[0].m_mounted_on = &vdummy; vmnt[0].m_mounted_on = &vdummy;
vmnt[0].m_root_node = &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, /* 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. * so you have to pull off the loose bits repeatedly to get it all undone.

View file

@ -110,6 +110,7 @@ PRIVATE int mount_fs(endpoint_t fs_e)
struct readsuper_req sreq; struct readsuper_req sreq;
struct readsuper_res sres; struct readsuper_res sres;
struct lookup_req lookup_req; struct lookup_req lookup_req;
node_req_t node_req;
/* Only the super-user may do MOUNT. */ /* Only the super-user may do MOUNT. */
if (!super_user) return(EPERM); 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); if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
/* Get free vnode for the mountpoint */ /* 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"); printf("VFSmount: not free vnode available\n");
return ENFILE; return ENFILE;
} }
/* Mark it as used so that we won't find the same for the root_node */ /* 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 */ /* Convert name to device number */
if ((dev = name_to_dev()) == NO_DEV) return(err_code); 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 /* Check whether there is a block special file open which uses the
* same device (partition) */ * same device (partition) */
for (bspec = &vnode[0]; bspec < &vnode[NR_VNODES]; ++bspec) { 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 */ /* Found, sync the buffer cache */
req_sync(bspec->v_fs_e); req_sync(bspec->v_fs_e);
break; 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 * vnodes are different or if the root of FS is equal two the
* root of the filesystem we found, we found a filesystem that * root of the filesystem we found, we found a filesystem that
* is in use. */ * is in use. */
mounted_on->v_count = 0; mounted_on->v_ref_count = 0;
return EBUSY; /* already mounted */ 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_mode = res.fmode;
mounted_on->v_size = res.fsize; mounted_on->v_size = res.fsize;
mounted_on->v_sdev = NO_DEV; 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 */ /* Find the vmnt for the vnode */
if ( (vmp2 = find_vmnt(mounted_on->v_fs_e)) == NIL_VMNT) 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 */ /* 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"); printf("VFSmount: no free vnode available\n");
return ENFILE; return ENFILE;
} }
/* Set it back to zero so that if st goes wrong it won't be kept in use */ /* 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 */ /* Fetch the name of the mountpoint */
if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) { 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; 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 */ /* Fill in root node's fields */
root_node->v_fs_e = sres.fs_e; root_node->v_fs_e = res.fs_e;
root_node->v_inode_nr = sres.inode_nr; root_node->v_inode_nr = res.inode_nr;
root_node->v_mode = sres.fmode; root_node->v_mode = res.fmode;
root_node->v_size = sres.fsize; 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_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 */ /* Fill in max file size and blocksize for the vmnt */
vmp->m_fs_e = sres.fs_e; 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. /* Superblock and root node already read.
* Nothing else can go wrong. Perform the mount. */ * Nothing else can go wrong. Perform the mount. */
vmp->m_root_node = root_node; vmp->m_root_node = root_node;
root_node->v_ref_count++;
vmp->m_mounted_on = root_node; vmp->m_mounted_on = root_node;
root_dev = dev; root_dev = dev;
ROOT_FS_E = fs_e; 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_mode = res.fmode;
mounted_on->v_size = res.fsize; mounted_on->v_size = res.fsize;
mounted_on->v_sdev = NO_DEV; 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 */ /* Find the vmnt for the vnode */
if ( (vmp2 = find_vmnt(mounted_on->v_fs_e)) == NIL_VMNT) if ( (vmp2 = find_vmnt(mounted_on->v_fs_e)) == NIL_VMNT)
@ -464,8 +483,8 @@ Dev_t dev;
*/ */
count = 0; count = 0;
for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) { for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) {
if (vp->v_count > 0 && vp->v_dev == dev) { if (vp->v_ref_count > 0 && vp->v_dev == dev) {
count += vp->v_count; count += vp->v_ref_count;
} }
} }
@ -474,6 +493,8 @@ Dev_t dev;
return(EBUSY); /* can't umount a busy file system */ return(EBUSY); /* can't umount a busy file system */
} }
vnode_clean_refs(vmp->m_root_node);
/* Request FS the unmount */ /* Request FS the unmount */
if ((r = req_unmount(vmp->m_fs_e)) != OK) return r; if ((r = req_unmount(vmp->m_fs_e)) != OK) return r;
@ -509,10 +530,10 @@ Dev_t dev;
/* Root device is mounted on itself */ /* Root device is mounted on itself */
if (vmp->m_root_node != vmp->m_mounted_on) { if (vmp->m_root_node != vmp->m_mounted_on) {
put_vnode(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 { else {
vmp->m_mounted_on->v_count--; vmp->m_mounted_on->v_fs_count--;
} }
fs_e = vmp->m_fs_e; fs_e = vmp->m_fs_e;

View file

@ -34,7 +34,8 @@
#define offset_lo m2_l1 #define offset_lo m2_l1
#define offset_high m2_l2 #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 common_open, (int oflags, mode_t omode) );
FORWARD _PROTOTYPE( int pipe_open, (struct vnode *vp,mode_t bits,int oflags)); 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 filp *fil_ptr, *filp2;
struct vnode *vp, *vp2; struct vnode *vp, *vp2;
struct vmnt *vmp; struct vmnt *vmp;
char lastc[NAME_MAX]; char Xlastc[NAME_MAX];
char *pathrem;
int m; int m;
/* Request and response structures */ /* Request and response structures */
struct lookup_req lookup_req; struct lookup_req Xlookup_req;
struct open_req req; struct open_req Xreq;
struct node_details res;
/* Remap the bottom two bits of oflags. */ /* Remap the bottom two bits of oflags. */
m = oflags & O_ACCMODE; 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. */ /* See if file descriptor and filp slots are available. */
if ((r = get_fd(0, bits, &m_in.fd, &fil_ptr)) != OK) return(r); 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 O_CREATE, set umask */
if (oflags & O_CREAT) { if (oflags & O_CREAT) {
omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask); 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 */ /* Fill in lookup request fields */
lookup_req.path = user_fullpath; Xlookup_req.path = user_fullpath;
lookup_req.lastc = lastc; Xlookup_req.lastc = Xlastc;
lookup_req.flags = oflags&O_CREAT ? (oflags&O_EXCL ? LAST_DIR : Xlookup_req.flags = oflags&O_CREAT ? (oflags&O_EXCL ? LAST_DIR :
LAST_DIR_EATSYM) : EAT_PATH; 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 */ /* 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 /* Lookup was okay, fill in request fields for
* the actual open request. */ * the actual open request. */
req.inode_nr = res.inode_nr; 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 */ /* Check whether the vnode is already in use */
if ((vp2 = find_vnode(res.fs_e, res.inode_nr)) != NIL_VNODE) { if ((vp2 = find_vnode(res.fs_e, res.inode_nr)) != NIL_VNODE) {
vp = vp2; vp = vp2;
vp->v_size = res.fsize;; /* In case of trunc... */ vp->v_size = res.fsize; /* In case of trunc... */
vp->v_count++; vp->v_ref_count++;
vp->v_fs_count++;
} }
/* Otherwise use the free one */ /* Otherwise use the free one */
else { else {
@ -157,12 +207,16 @@ PRIVATE int common_open(register int oflags, mode_t omode)
vp->v_dev = vmp->m_dev; vp->v_dev = vmp->m_dev;
vp->v_inode_nr = res.inode_nr; vp->v_inode_nr = res.inode_nr;
vp->v_mode = res.fmode; vp->v_mode = res.fmode;
vp->v_uid = res.uid;
vp->v_gid = res.gid;
vp->v_size = res.fsize; vp->v_size = res.fsize;
vp->v_sdev = res.dev; 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_vmnt = vmp;
vp->v_index = res.inode_index; vp->v_index = res.inode_index;
} }
#endif
/* Claim the file descriptor and filp slot and fill them in. */ /* Claim the file descriptor and filp slot and fill them in. */
fp->fp_filp[m_in.fd] = fil_ptr; 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_flags = oflags;
fil_ptr->filp_vno = vp; fil_ptr->filp_vno = vp;
vp->v_isfifo= FALSE;
switch (vp->v_mode & I_TYPE) { switch (vp->v_mode & I_TYPE) {
case I_CHAR_SPECIAL: case I_CHAR_SPECIAL:
/* Invoke the driver for special processing. */ /* Invoke the driver for special processing. */
@ -180,6 +235,8 @@ PRIVATE int common_open(register int oflags, mode_t omode)
case I_BLOCK_SPECIAL: case I_BLOCK_SPECIAL:
/* Invoke the driver for special processing. */ /* Invoke the driver for special processing. */
r = dev_open(vp->v_sdev, who_e, bits | (oflags & ~O_ACCMODE)); 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 */ /* Check whether the device is mounted or not */
found = 0; found = 0;
@ -219,7 +276,10 @@ PRIVATE int common_open(register int oflags, mode_t omode)
break; break;
case I_NAMED_PIPE: 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_pipe = I_PIPE;
vp->v_isfifo= TRUE;
oflags |= O_APPEND; /* force append mode */ oflags |= O_APPEND; /* force append mode */
fil_ptr->filp_flags = oflags; fil_ptr->filp_flags = oflags;
r = pipe_open(vp, bits, 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); 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. * 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; vp->v_pipe = I_PIPE;
if((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) { 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 a write has been done, the inode is already marked as DIRTY. */
if (--rfilp->filp_count == 0) { 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. /* Save the file position in the v-node in case needed later.
* The read and write positions are saved separately. * The read and write positions are saved separately.
*/ */

View file

@ -21,6 +21,8 @@
#include "vnode.h" #include "vnode.h"
#include "param.h" #include "param.h"
FORWARD _PROTOTYPE( int Xlookup, (lookup_req_t *lookup_req,
node_details_t *node, char **pathrem) );
/*===========================================================================* /*===========================================================================*
* lookup * * lookup *
@ -104,6 +106,8 @@ node_details_t *node;
} }
if (!start_node) { if (!start_node) {
printf("VFSlookup: mounted partition couldn't be found\n"); 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; return ENOENT;
} }
@ -138,15 +142,300 @@ node_details_t *node;
r = req_lookup(&req, &res); r = req_lookup(&req, &res);
} }
/* If success, fill in response fields */ /* Fill in response fields */
if (OK == r) {
node->inode_nr = res.inode_nr; node->inode_nr = res.inode_nr;
node->fmode = res.fmode; node->fmode = res.fmode;
node->fsize = res.fsize; node->fsize = res.fsize;
node->dev = res.dev; node->dev = res.dev;
node->fs_e = res.fs_e; node->fs_e = res.fs_e;
} node->uid = res.uid;
node->gid = res.gid;
return r; 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;
}

View file

@ -59,7 +59,7 @@ PUBLIC int do_pipe()
struct node_details res; struct node_details res;
/* See if a free vnode is available */ /* 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"); printf("VFS: no vnode available!\n");
return err_code; return err_code;
} }
@ -105,7 +105,8 @@ PUBLIC int do_pipe()
vp->v_mode = res.fmode; vp->v_mode = res.fmode;
vp->v_index = res.inode_index; vp->v_index = res.inode_index;
vp->v_pipe = I_PIPE; 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; vp->v_size = 0;
if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT) { if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT) {

View file

@ -163,3 +163,76 @@ PUBLIC int do_access()
return req_access(&req); 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);
}

View file

@ -58,6 +58,7 @@ _PROTOTYPE( int do_unlink, (void) );
_PROTOTYPE( int do_rename, (void) ); _PROTOTYPE( int do_rename, (void) );
_PROTOTYPE( int do_truncate, (void) ); _PROTOTYPE( int do_truncate, (void) );
_PROTOTYPE( int do_ftruncate, (void) ); _PROTOTYPE( int do_ftruncate, (void) );
_PROTOTYPE( int truncate_vn, (struct vnode *vp, off_t newsize) );
/* lock.c */ /* lock.c */
_PROTOTYPE( int lock_op, (struct filp *f, int req) ); _PROTOTYPE( int lock_op, (struct filp *f, int req) );
@ -100,6 +101,9 @@ _PROTOTYPE( int do_slink, (void) );
/* path.c */ /* path.c */
_PROTOTYPE( int lookup, (lookup_req_t *request, node_details_t *node) ); _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 */ /* pipe.c */
_PROTOTYPE( int do_pipe, (void) ); _PROTOTYPE( int do_pipe, (void) );
@ -120,6 +124,8 @@ _PROTOTYPE( int do_access, (void) );
_PROTOTYPE( int do_chmod, (void) ); _PROTOTYPE( int do_chmod, (void) );
_PROTOTYPE( int do_chown, (void) ); _PROTOTYPE( int do_chown, (void) );
_PROTOTYPE( int do_umask, (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 */ /* read.c */
_PROTOTYPE( int do_read, (void) ); _PROTOTYPE( int do_read, (void) );
@ -129,8 +135,10 @@ _PROTOTYPE( int read_write, (int rw_flag) );
/* request.c */ /* request.c */
_PROTOTYPE( int fs_sendrec, (endpoint_t fs_e, message *reqm) ); _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_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_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, _PROTOTYPE( int req_readwrite, (readwrite_req_t *req,
readwrite_res_t *res) ); readwrite_res_t *res) );
_PROTOTYPE( int req_pipe, (pipe_req_t *req, node_details_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_mknod, (mknod_req_t *req) );
_PROTOTYPE( int req_mkdir, (mkdir_req_t *req) ); _PROTOTYPE( int req_mkdir, (mkdir_req_t *req) );
_PROTOTYPE( int req_inhibread, (node_req_t *req) ); _PROTOTYPE( int req_inhibread, (node_req_t *req) );
_PROTOTYPE( int req_stat, (stat_req_t *req) ); _PROTOTYPE( int req_stat, (int fs_e, ino_t inode_nr, int who_e,
_PROTOTYPE( int req_fstat, (stat_req_t *req) ); char *buf, int pos) );
_PROTOTYPE( int req_fstatfs, (stat_req_t *req) ); _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_unlink, (unlink_req_t *req) );
_PROTOTYPE( int req_rmdir, (unlink_req_t *req) ); _PROTOTYPE( int req_rmdir, (unlink_req_t *req) );
_PROTOTYPE( int req_utime, (utime_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_stime, (endpoint_t fs_e, time_t boottime) );
_PROTOTYPE( int req_sync, (endpoint_t fs_e) ); _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_link, (link_req_t *req) );
_PROTOTYPE( int req_slink, (slink_req_t *req) ); _PROTOTYPE( int req_slink, (slink_req_t *req) );
_PROTOTYPE( int req_rdlink, (rdlink_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) ); _PROTOTYPE( struct vmnt *find_vmnt, (int fs_e) );
/* vnode.c */ /* 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( struct vnode *find_vnode, (int fs_e, int numb) );
_PROTOTYPE( void dup_vnode, (struct vnode *vp) ); _PROTOTYPE( void dup_vnode, (struct vnode *vp) );
_PROTOTYPE( void put_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, (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 */ /* write.c */
_PROTOTYPE( int do_write, (void) ); _PROTOTYPE( int do_write, (void) );

View file

@ -192,6 +192,13 @@ int rw_flag; /* READING or WRITING */
req.user_addr = m_in.buffer; req.user_addr = m_in.buffer;
req.inode_index = vp->v_index; 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 */ /* Issue request */
r = req_readwrite(&req, &res); r = req_readwrite(&req, &res);

View file

@ -12,6 +12,8 @@
#include "fs.h" #include "fs.h"
#include <string.h> #include <string.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include <minix/callnr.h> #include <minix/callnr.h>
#include <minix/com.h> #include <minix/com.h>
#include <minix/keymap.h> #include <minix/keymap.h>
@ -50,6 +52,8 @@ node_details_t *res;
res->fmode = m.RES_MODE; res->fmode = m.RES_MODE;
res->fsize = m.RES_FILE_SIZE; res->fsize = m.RES_FILE_SIZE;
res->dev = m.RES_DEV; res->dev = m.RES_DEV;
res->uid = m.RES_UID;
res->gid = m.RES_GID;
return OK; return OK;
} }
@ -58,17 +62,20 @@ node_details_t *res;
/*===========================================================================* /*===========================================================================*
* req_putnode * * req_putnode *
*===========================================================================*/ *===========================================================================*/
PUBLIC int req_putnode(req) PUBLIC int req_putnode(fs_e, inode_nr, count)
node_req_t *req; int fs_e;
ino_t inode_nr;
int count;
{ {
message m; message m;
/* Fill in request message */ /* Fill in request message */
m.m_type = REQ_PUTNODE; 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 */ /* 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 * * req_readwrite *
*===========================================================================*/ *===========================================================================*/
@ -351,60 +401,81 @@ node_req_t *req;
/*===========================================================================* /*===========================================================================*
* req_stat * * req_stat *
*===========================================================================*/ *===========================================================================*/
PUBLIC int req_stat(req) PUBLIC int req_stat(fs_e, inode_nr, who_e, buf, pos)
stat_req_t *req; int fs_e;
ino_t inode_nr;
int who_e;
char *buf;
int pos;
{ {
cp_grant_id_t gid;
int r;
message m; 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 */ /* Fill in request message */
m.m_type = REQ_STAT; m.m_type = REQ_STAT;
m.REQ_INODE_NR = req->inode_nr; m.REQ_INODE_NR = inode_nr;
m.REQ_UID = req->uid; m.REQ_GRANT = gid;
m.REQ_GID = req->gid;
m.REQ_WHO_E = req->who_e;
m.REQ_USER_ADDR = req->buf;
/* Send/rec request */ /* Send/rec request */
return fs_sendrec(req->fs_e, &m); r= fs_sendrec(fs_e, &m);
cpf_revoke(gid);
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));
} }
return r;
/*===========================================================================*
* 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;
/* Send/rec request */
return fs_sendrec(req->fs_e, &m);
} }
/*===========================================================================* /*===========================================================================*
* req_fstatfs * * req_fstatfs *
*===========================================================================*/ *===========================================================================*/
PUBLIC int req_fstatfs(req) PUBLIC int req_fstatfs(fs_e, inode_nr, who_e, buf)
stat_req_t *req; int fs_e;
ino_t inode_nr;
int who_e;
char *buf;
{ {
int r;
cp_grant_id_t gid;
message m; message m;
gid= cpf_grant_magic(fs_e, who_e, (vir_bytes)buf, sizeof(struct statfs),
CPF_WRITE);
if (gid < 0)
return gid;
/* Fill in request message */ /* Fill in request message */
m.m_type = REQ_FSTATFS; m.m_type = REQ_FSTATFS;
m.REQ_FD_INODE_NR = req->inode_nr; m.REQ_INODE_NR = inode_nr;
m.REQ_FD_WHO_E = req->who_e; m.REQ_GRANT = gid;
m.REQ_FD_USER_ADDR = req->buf;
/* Send/rec request */ /* Send/rec request */
return fs_sendrec(req->fs_e, &m); 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 * * req_link *
*===========================================================================*/ *===========================================================================*/
@ -787,10 +829,14 @@ lookup_res_t *res;
res->fs_e = m.m_source; res->fs_e = m.m_source;
switch (r) { switch (r) {
case OK: case OK:
default:
res->inode_nr = m.RES_INODE_NR; res->inode_nr = m.RES_INODE_NR;
res->fmode = m.RES_MODE; res->fmode = m.RES_MODE;
res->fsize = m.RES_FILE_SIZE; res->fsize = m.RES_FILE_SIZE;
res->dev = m.RES_DEV; res->dev = m.RES_DEV;
res->uid= m.RES_UID;
res->gid= m.RES_GID;
res->char_processed = m.RES_OFFSET; /* For ENOENT */
break; break;
case EENTERMOUNT: case EENTERMOUNT:
res->inode_nr = m.RES_INODE_NR; res->inode_nr = m.RES_INODE_NR;

View file

@ -142,17 +142,6 @@ typedef struct mkdir_req {
} mkdir_req_t; } 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 */ /* Structure for REQ_UNLINK request */
typedef struct unlink_req { typedef struct unlink_req {
int fs_e; int fs_e;
@ -174,15 +163,6 @@ typedef struct utime_req {
} utime_req_t; } 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 */ /* Structure for REQ_LINK request */
typedef struct link_req { typedef struct link_req {
endpoint_t fs_e; endpoint_t fs_e;
@ -294,6 +274,8 @@ typedef struct lookup_res {
ino_t inode_nr; ino_t inode_nr;
mode_t fmode; mode_t fmode;
off_t fsize; off_t fsize;
uid_t uid;
gid_t gid;
/* For char/block special files */ /* For char/block special files */
dev_t dev; dev_t dev;

View file

@ -37,8 +37,6 @@ PUBLIC int do_fchdir()
{ {
/* Change directory on already-opened fd. */ /* Change directory on already-opened fd. */
struct filp *rfilp; struct filp *rfilp;
struct getdir_req req;
struct node_details res;
int r; int r;
/* Is the file descriptor valid? */ /* Is the file descriptor valid? */
@ -48,17 +46,11 @@ PUBLIC int do_fchdir()
if ((rfilp->filp_vno->v_mode & I_TYPE) != I_DIRECTORY) if ((rfilp->filp_vno->v_mode & I_TYPE) != I_DIRECTORY)
return ENOTDIR; 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 */ /* 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_ref_count++; /* change_into expects a reference */
rfilp->filp_vno->v_count++;
return change_into(&fp->fp_wd, rfilp->filp_vno); return change_into(&fp->fp_wd, rfilp->filp_vno);
} }
@ -129,61 +121,25 @@ char *name_ptr; /* pointer to the directory name to change to */
int len; /* length of the directory name string */ int len; /* length of the directory name string */
{ {
/* Do the actual work for chdir() and chroot(). */ /* Do the actual work for chdir() and chroot(). */
struct vnode *vp, *vp2; struct vnode *vp;
struct vmnt *vmp;
struct getdir_req req;
struct node_details res;
struct lookup_req lookup_req; struct lookup_req lookup_req;
int r; int r;
if (fetch_name(name_ptr, len, M3) != OK) return(err_code); 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 */ /* Fill in lookup request fields */
lookup_req.path = user_fullpath; lookup_req.path = user_fullpath;
lookup_req.lastc = NULL; lookup_req.lastc = NULL;
lookup_req.flags = EAT_PATH; lookup_req.flags = EAT_PATH;
/* Request lookup */ /* 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? */ /* Is it a dir? */
if ((res.fmode & I_TYPE) != I_DIRECTORY) if ((vp->v_mode & I_TYPE) != I_DIRECTORY)
{
put_vnode(vp);
return ENOTDIR; 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); return change_into(iip, vp);
@ -211,7 +167,6 @@ struct vnode *vp; /* this is what the inode has to become */
PUBLIC int do_stat() PUBLIC int do_stat()
{ {
/* Perform the stat(name, buf) system call. */ /* Perform the stat(name, buf) system call. */
struct stat_req req;
struct node_details res; struct node_details res;
struct lookup_req lookup_req; struct lookup_req lookup_req;
int r; int r;
@ -226,16 +181,8 @@ PUBLIC int do_stat()
/* Request lookup */ /* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r; 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 */ /* 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. */ /* Perform the fstat(fd, buf) system call. */
register struct filp *rfilp; register struct filp *rfilp;
int pipe_pos = 0; int pipe_pos = 0;
struct stat_req req;
/* Is the file descriptor valid? */ /* Is the file descriptor valid? */
if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) { 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 */ /* If we read from a pipe, send position too */
pipe_pos= 0;
if (rfilp->filp_vno->v_pipe == I_PIPE) { if (rfilp->filp_vno->v_pipe == I_PIPE) {
if (rfilp->filp_mode & R_BIT) if (rfilp->filp_mode & R_BIT)
if (ex64hi(rfilp->filp_pos) != 0) if (ex64hi(rfilp->filp_pos) != 0)
@ -266,15 +213,9 @@ PUBLIC int do_fstat()
pipe_pos = ex64lo(rfilp->filp_pos); 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 */ /* 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. */ /* Perform the fstatfs(fd, buf) system call. */
register struct filp *rfilp; register struct filp *rfilp;
struct stat_req req;
/* Is the file descriptor valid? */ /* Is the file descriptor valid? */
if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code); 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 */ /* 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() PUBLIC int do_lstat()
{ {
/* Perform the lstat(name, buf) system call. */ /* Perform the lstat(name, buf) system call. */
struct stat_req req;
struct node_details res; struct node_details res;
struct lookup_req lookup_req; struct lookup_req lookup_req;
int r; int r;
@ -324,16 +258,8 @@ PUBLIC int do_lstat()
/* Request lookup */ /* Request lookup */
if ((r = lookup(&lookup_req, &res)) != OK) return r; 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 */ /* Issue request */
return req_stat(&req); return req_stat(res.fs_e, res.inode_nr, who_e, m_in.name2, 0);
} }

View file

@ -14,6 +14,9 @@
#include "vnode.h" #include "vnode.h"
#include "vmnt.h" #include "vmnt.h"
#include "fproc.h"
#include "file.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
/*===========================================================================* /*===========================================================================*
@ -31,8 +34,12 @@ PUBLIC struct vnode *get_vnode(int fs_e, int inode_nr)
struct node_req req; struct node_req req;
struct node_details res; 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 */ /* 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"); printf("VFSget_vnode: no vnode available\n");
return NIL_VNODE; return NIL_VNODE;
} }
@ -60,22 +67,61 @@ PUBLIC struct vnode *get_vnode(int fs_e, int inode_nr)
vp->v_vmnt = vmp; vp->v_vmnt = vmp;
vp->v_dev = vmp->m_dev; vp->v_dev = vmp->m_dev;
vp->v_count = 1; vp->v_fs_count = 1;
vp->v_ref_count = 1;
return vp; 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 * * 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 */ /* Find a free vnode slot in the vnode table */
struct vnode *vp; struct vnode *vp;
for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++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; err_code = ENFILE;
return NIL_VNODE; return NIL_VNODE;
@ -91,7 +137,7 @@ PUBLIC struct vnode *find_vnode(int fs_e, int numb)
struct vnode *vp; struct vnode *vp;
for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++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; && vp->v_fs_e == fs_e) return vp;
return NIL_VNODE; 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 /* dup_vnode() is called to increment the vnode and therefore the
* referred inode's counter. * referred inode's counter.
*/ */
struct node_req req;
struct node_details res;
if (vp == NIL_VNODE) { if (vp == NIL_VNODE) {
printf("VFSdup_vnode NIL_VNODE\n"); printf("VFSdup_vnode NIL_VNODE\n");
return; return;
} }
/* Fill req struct */ vp->v_ref_count++;
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++;
} }
@ -134,28 +169,176 @@ PUBLIC void put_vnode(struct vnode *vp)
/* Decrease vnode's usage counter and decrease inode's usage counter in the /* Decrease vnode's usage counter and decrease inode's usage counter in the
* corresponding FS process. * corresponding FS process.
*/ */
struct node_req req;
if (vp == NIL_VNODE) { if (vp == NIL_VNODE) {
/*printf("VFSput_vnode NIL_VNODE\n");*/ /*printf("VFSput_vnode NIL_VNODE\n");*/
return; return;
} }
/* Fill in request fields */ if (vp < &vnode[0] || vp >= &vnode[NR_VNODES])
req.fs_e = vp->v_fs_e; {
req.inode_nr = vp->v_inode_nr; 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);
}
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);
}
/* Send request */ /* Send request */
if (req_putnode(&req) == OK) { if (req_putnode(vp->v_fs_e, vp->v_inode_nr, vp->v_fs_count) != OK)
/* Decrease counter */ printf("VFSput_vnode Warning: inode doesn't exist\n");
if (--vp->v_count == 0) {
vp->v_fs_count= 0;
vp->v_ref_count= 0;
vp->v_pipe = NO_PIPE; vp->v_pipe = NO_PIPE;
vp->v_sdev = NO_DEV; vp->v_sdev = NO_DEV;
vp->v_index = 0; 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;
} }
else
printf("VFSput_vnode Warning: inode doesn't exist\n"); 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

View file

@ -4,8 +4,12 @@ EXTERN struct vnode {
endpoint_t v_fs_e; /* FS process' endpoint number */ endpoint_t v_fs_e; /* FS process' endpoint number */
ino_t v_inode_nr; /* inode number on its (minor) device */ ino_t v_inode_nr; /* inode number on its (minor) device */
mode_t v_mode; /* file type, protection, etc. */ 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 */ 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 */ char v_pipe; /* set to I_PIPE if pipe */
off_t v_pipe_rd_pos; off_t v_pipe_rd_pos;
off_t v_pipe_wr_pos; off_t v_pipe_wr_pos;
@ -19,6 +23,11 @@ EXTERN struct vnode {
int v_blocksize; /* block size of the filesys */ int v_blocksize; /* block size of the filesys */
unsigned short v_index; /* inode's index in the FS inode table */ unsigned short v_index; /* inode's index in the FS inode table */
struct vmnt *v_vmnt; /* vmnt object of the partition */ struct vmnt *v_vmnt; /* vmnt object of the partition */
/* For debugging */
char *v_file;
int v_line;
int v_isfifo;
} vnode[NR_VNODES]; } vnode[NR_VNODES];
#define NIL_VNODE (struct vnode *) 0 /* indicates absence of vnode slot */ #define NIL_VNODE (struct vnode *) 0 /* indicates absence of vnode slot */