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