/* This file contains the wrapper functions for issueing a request * and receiving response from FS processes. * Each function builds a request message according to the request * parameter, calls the most low-level fs_sendrec and copies * back the response. * The low-level fs_sendrec handles the recovery mechanism from * a dead driver and reissues the request. */ #include "fs.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "fproc.h" #include "vmnt.h" #include "vnode.h" #include "param.h" FORWARD _PROTOTYPE(int fs_sendrec_f, (char *file, int line, endpoint_t fs_e, message *reqm) ); #define fs_sendrec(e, m) fs_sendrec_f(__FILE__, __LINE__, (e), (m)) /*===========================================================================* * req_breadwrite * *===========================================================================*/ PUBLIC int req_breadwrite( endpoint_t fs_e, endpoint_t user_e, dev_t dev, u64_t pos, unsigned int num_of_bytes, char *user_addr, int rw_flag, u64_t *new_posp, unsigned int *cum_iop ) { int r; cp_grant_id_t grant_id; message m; grant_id = cpf_grant_magic(fs_e, user_e, (vir_bytes) user_addr, num_of_bytes, (rw_flag == READING ? CPF_WRITE : CPF_READ)); if(grant_id == -1) panic("req_breadwrite: cpf_grant_magic failed"); /* Fill in request message */ m.m_type = rw_flag == READING ? REQ_BREAD : REQ_BWRITE; m.REQ_DEV2 = dev; m.REQ_GRANT = grant_id; m.REQ_SEEK_POS_LO = ex64lo(pos); m.REQ_SEEK_POS_HI = ex64hi(pos); m.REQ_NBYTES = num_of_bytes; /* Send/rec request */ r = fs_sendrec(fs_e, &m); cpf_revoke(grant_id); if (r != OK) return(r); /* Fill in response structure */ *new_posp = make64(m.RES_SEEK_POS_LO, m.RES_SEEK_POS_HI); *cum_iop = m.RES_NBYTES; return(OK); } /*===========================================================================* * req_chmod * *===========================================================================*/ PUBLIC int req_chmod( int fs_e, ino_t inode_nr, mode_t rmode, mode_t *new_modep ) { message m; int r; /* Fill in request message */ m.m_type = REQ_CHMOD; m.REQ_INODE_NR = inode_nr; m.REQ_MODE = rmode; /* Send/rec request */ r = fs_sendrec(fs_e, &m); /* Copy back actual mode. */ *new_modep = m.RES_MODE; return(r); } /*===========================================================================* * req_chown * *===========================================================================*/ PUBLIC int req_chown( endpoint_t fs_e, ino_t inode_nr, uid_t newuid, gid_t newgid, mode_t *new_modep ) { message m; int r; /* Fill in request message */ m.m_type = REQ_CHOWN; m.REQ_INODE_NR = inode_nr; m.REQ_UID = newuid; m.REQ_GID = newgid; /* Send/rec request */ r = fs_sendrec(fs_e, &m); /* Return new mode to caller. */ *new_modep = m.RES_MODE; return(r); } /*===========================================================================* * req_create * *===========================================================================*/ PUBLIC int req_create( int fs_e, ino_t inode_nr, int omode, uid_t uid, gid_t gid, char *path, node_details_t *res ) { int r; cp_grant_id_t grant_id; size_t len; message m; if (path[0] == '/') panic("req_create: filename starts with '/'"); len = strlen(path) + 1; grant_id = cpf_grant_direct(fs_e, (vir_bytes) path, len, CPF_READ); if (grant_id == -1) panic("req_create: cpf_grant_direct failed"); /* 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_GRANT = grant_id; m.REQ_PATH_LEN = len; /* Send/rec request */ r = fs_sendrec(fs_e, &m); cpf_revoke(grant_id); if (r != 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_LO; res->uid = m.RES_UID; res->gid = m.RES_GID; res->dev = m.RES_DEV; return(OK); } /*===========================================================================* * req_flush * *===========================================================================*/ PUBLIC int req_flush(endpoint_t fs_e, dev_t dev) { message m; /* Fill in request message */ m.m_type = REQ_FLUSH; m.REQ_DEV = dev; /* Send/rec request */ return fs_sendrec(fs_e, &m); } /*===========================================================================* * req_fstatfs * *===========================================================================*/ PUBLIC int req_fstatfs(int fs_e, int who_e, char *buf) { int r; cp_grant_id_t grant_id; message m; grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, sizeof(struct statfs), CPF_WRITE); if(grant_id == -1) panic("req_fstatfs: cpf_grant_magic failed"); /* Fill in request message */ m.m_type = REQ_FSTATFS; m.REQ_GRANT = grant_id; /* Send/rec request */ r = fs_sendrec(fs_e, &m); cpf_revoke(grant_id); return(r); } /*===========================================================================* * req_statvfs * *===========================================================================*/ PUBLIC int req_statvfs(int fs_e, int who_e, char *buf) { int r; cp_grant_id_t grant_id; message m; grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, sizeof(struct statvfs), CPF_WRITE); if(grant_id == -1) panic("req_statvfs: cpf_grant_magic failed"); /* Fill in request message */ m.m_type = REQ_STATVFS; m.REQ_GRANT = grant_id; /* Send/rec request */ r = fs_sendrec(fs_e, &m); cpf_revoke(grant_id); return(r); } /*===========================================================================* * req_ftrunc * *===========================================================================*/ PUBLIC int req_ftrunc(endpoint_t fs_e, ino_t inode_nr, off_t start, off_t end) { message m; /* Fill in request message */ m.m_type = REQ_FTRUNC; m.REQ_INODE_NR = inode_nr; m.REQ_TRC_START_LO = start; m.REQ_TRC_START_HI = 0; /* Not used for now, so clear it. */ m.REQ_TRC_END_LO = end; m.REQ_TRC_END_HI = 0; /* Not used for now, so clear it. */ /* Send/rec request */ return fs_sendrec(fs_e, &m); } /*===========================================================================* * req_getdents * *===========================================================================*/ PUBLIC int req_getdents( endpoint_t fs_e, ino_t inode_nr, u64_t pos, char *buf, size_t size, u64_t *new_pos, int direct ) { int r; message m; cp_grant_id_t grant_id; if (direct) { grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, size, CPF_WRITE); } else { grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, size, CPF_WRITE); } if (grant_id < 0) panic("req_getdents: cpf_grant_direct/cpf_grant_magic failed: %d", grant_id); m.m_type = REQ_GETDENTS; m.REQ_INODE_NR = inode_nr; m.REQ_GRANT = grant_id; m.REQ_MEM_SIZE = size; m.REQ_SEEK_POS_LO = ex64lo(pos); m.REQ_SEEK_POS_HI = 0; /* Not used for now, so clear it. */ r = fs_sendrec(fs_e, &m); cpf_revoke(grant_id); if (r == OK) { *new_pos = cvul64(m.RES_SEEK_POS_LO); r = m.RES_NBYTES; } return(r); } /*===========================================================================* * req_inhibread * *===========================================================================*/ PUBLIC int req_inhibread(endpoint_t fs_e, ino_t inode_nr) { message m; /* Fill in request message */ m.m_type = REQ_INHIBREAD; m.REQ_INODE_NR = inode_nr; /* Send/rec request */ return fs_sendrec(fs_e, &m); } /*===========================================================================* * req_link * *===========================================================================*/ PUBLIC int req_link( endpoint_t fs_e, ino_t link_parent, char *lastc, ino_t linked_file ) { int r; cp_grant_id_t grant_id; const size_t len = strlen(lastc) + 1; message m; grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ); if(grant_id == -1) panic("req_link: cpf_grant_direct failed"); /* Fill in request message */ m.m_type = REQ_LINK; m.REQ_INODE_NR = linked_file; m.REQ_DIR_INO = link_parent; m.REQ_GRANT = grant_id; m.REQ_PATH_LEN = len; /* Send/rec request */ r = fs_sendrec(fs_e, &m); cpf_revoke(grant_id); return(r); } /*===========================================================================* * req_lookup * *===========================================================================*/ PUBLIC int req_lookup( endpoint_t fs_e, ino_t dir_ino, ino_t root_ino, uid_t uid, gid_t gid, int flags, lookup_res_t *res, struct fproc *rfp ) { int r; size_t len; cp_grant_id_t grant_id=0, grant_id2=0; message m; vfs_ucred_t credentials; grant_id = cpf_grant_direct(fs_e, (vir_bytes) user_fullpath, sizeof(user_fullpath), CPF_READ | CPF_WRITE); if(grant_id == -1) panic("req_lookup: cpf_grant_direct failed"); len = strlen(user_fullpath) + 1; m.m_type = REQ_LOOKUP; m.REQ_GRANT = grant_id; m.REQ_PATH_LEN = len; m.REQ_PATH_SIZE = sizeof(user_fullpath); m.REQ_DIR_INO = dir_ino; m.REQ_ROOT_INO = root_ino; if(rfp->fp_ngroups > 0) { /* Is the process member of multiple groups? */ /* In that case the FS has to copy the uid/gid credentials */ int i; /* Set credentials */ credentials.vu_uid = rfp->fp_effuid; credentials.vu_gid = rfp->fp_effgid; credentials.vu_ngroups = rfp->fp_ngroups; for (i = 0; i < rfp->fp_ngroups; i++) credentials.vu_sgroups[i] = rfp->fp_sgroups[i]; grant_id2 = cpf_grant_direct(fs_e, (vir_bytes) &credentials, sizeof(credentials), CPF_READ); if(grant_id2 == -1) panic("req_lookup: cpf_grant_direct failed"); m.REQ_GRANT2 = grant_id2; m.REQ_UCRED_SIZE= sizeof(credentials); flags |= PATH_GET_UCRED; } else { /* When there's only one gid, we can send it directly */ m.REQ_UID = uid; m.REQ_GID = gid; flags &= ~PATH_GET_UCRED; } m.REQ_FLAGS = flags; /* Send/rec request */ r = fs_sendrec(fs_e, &m); cpf_revoke(grant_id); if(rfp->fp_ngroups > 0) cpf_revoke(grant_id2); /* Fill in response according to the return value */ res->fs_e = m.m_source; switch (r) { case OK: res->inode_nr = m.RES_INODE_NR; res->fmode = m.RES_MODE; res->fsize = m.RES_FILE_SIZE_LO; res->dev = m.RES_DEV; res->uid= m.RES_UID; res->gid= m.RES_GID; break; case EENTERMOUNT: res->inode_nr = m.RES_INODE_NR; res->char_processed = m.RES_OFFSET; res->symloop = m.RES_SYMLOOP; break; case ELEAVEMOUNT: res->char_processed = m.RES_OFFSET; res->symloop = m.RES_SYMLOOP; break; case ESYMLINK: res->char_processed = m.RES_OFFSET; res->symloop = m.RES_SYMLOOP; break; default: break; } return(r); } /*===========================================================================* * req_mkdir * *===========================================================================*/ PUBLIC int req_mkdir( endpoint_t fs_e, ino_t inode_nr, char *lastc, uid_t uid, gid_t gid, mode_t dmode ) { int r; cp_grant_id_t grant_id; size_t len; message m; len = strlen(lastc) + 1; grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ); if(grant_id == -1) panic("req_mkdir: cpf_grant_direct failed"); /* Fill in request message */ m.m_type = REQ_MKDIR; m.REQ_INODE_NR = inode_nr; m.REQ_MODE = dmode; m.REQ_UID = uid; m.REQ_GID = gid; m.REQ_GRANT = grant_id; m.REQ_PATH_LEN = len; /* Send/rec request */ r = fs_sendrec(fs_e, &m); cpf_revoke(grant_id); return(r); } /*===========================================================================* * req_mknod * *===========================================================================*/ PUBLIC int req_mknod( endpoint_t fs_e, ino_t inode_nr, char *lastc, uid_t uid, gid_t gid, mode_t dmode, dev_t dev ) { int r; size_t len; cp_grant_id_t grant_id; message m; len = strlen(lastc) + 1; grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ); if(grant_id == -1) panic("req_mknod: cpf_grant_direct failed"); /* Fill in request message */ m.m_type = REQ_MKNOD; m.REQ_INODE_NR = inode_nr; m.REQ_MODE = dmode; m.REQ_DEV = dev; m.REQ_UID = uid; m.REQ_GID = gid; m.REQ_GRANT = grant_id; m.REQ_PATH_LEN = len; /* Send/rec request */ r = fs_sendrec(fs_e, &m); cpf_revoke(grant_id); return(r); } /*===========================================================================* * req_mountpoint * *===========================================================================*/ PUBLIC int req_mountpoint(endpoint_t fs_e, ino_t inode_nr) { message m; /* Fill in request message */ m.m_type = REQ_MOUNTPOINT; m.REQ_INODE_NR = inode_nr; /* Send/rec request */ return fs_sendrec(fs_e, &m); } /*===========================================================================* * req_newnode * *===========================================================================*/ PUBLIC int req_newnode( endpoint_t fs_e, uid_t uid, gid_t gid, mode_t dmode, dev_t dev, struct node_details *res ) { int r; message m; /* Fill in request message */ m.m_type = REQ_NEWNODE; m.REQ_MODE = dmode; m.REQ_DEV = dev; m.REQ_UID = uid; m.REQ_GID = gid; /* Send/rec request */ r = fs_sendrec(fs_e, &m); res->fs_e = m.m_source; res->inode_nr = m.RES_INODE_NR; res->fmode = m.RES_MODE; res->fsize = m.RES_FILE_SIZE_LO; res->dev = m.RES_DEV; res->uid = m.RES_UID; res->gid = m.RES_GID; return(r); } /*===========================================================================* * req_newdriver * *===========================================================================*/ PUBLIC int req_newdriver( endpoint_t fs_e, dev_t dev, endpoint_t driver_e ) { /* Note: this is the only request function that doesn't use the * fs_sendrec internal routine, since we want to avoid the dead * driver recovery mechanism here. This function is actually called * during the recovery. */ message m; int r; /* Fill in request message */ m.m_type = REQ_NEW_DRIVER; m.REQ_DEV = dev; m.REQ_DRIVER_E = driver_e; /* Issue request */ if((r = sendrec(fs_e, &m)) != OK) { printf("%s:%d VFS req_newdriver: error sending message %d to %d\n", __FILE__, __LINE__, r, fs_e); util_stacktrace(); return(r); } return(OK); } /*===========================================================================* * req_putnode * *===========================================================================*/ 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 = inode_nr; m.REQ_COUNT = count; /* Send/rec request */ return fs_sendrec(fs_e, &m); } /*===========================================================================* * req_rdlink * *===========================================================================*/ PUBLIC int req_rdlink(fs_e, inode_nr, who_e, buf, len, direct) endpoint_t fs_e; ino_t inode_nr; endpoint_t who_e; char *buf; size_t len; int direct; /* set to 1 to use direct grants instead of magic grants */ { message m; int r; cp_grant_id_t grant_id; if (direct) { grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, len, CPF_WRITE); } else { grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, len, CPF_WRITE); } if(grant_id == -1) panic("req_rdlink: cpf_grant_magic failed"); /* Fill in request message */ m.m_type = REQ_RDLINK; m.REQ_INODE_NR = inode_nr; m.REQ_GRANT = grant_id; m.REQ_MEM_SIZE = len; /* Send/rec request */ r = fs_sendrec(fs_e, &m); cpf_revoke(grant_id); if(r == OK) r = m.RES_NBYTES; return(r); } /*===========================================================================* * req_readsuper * *===========================================================================*/ PUBLIC int req_readsuper( endpoint_t fs_e, char *label, dev_t dev, int readonly, int isroot, struct node_details *res_nodep ) { int r; cp_grant_id_t grant_id; size_t len; message m; len = strlen(label)+1; grant_id = cpf_grant_direct(fs_e, (vir_bytes) label, len, CPF_READ); if (grant_id == -1) panic("req_readsuper: cpf_grant_direct failed"); /* Fill in request message */ m.m_type = REQ_READSUPER; m.REQ_FLAGS = 0; if(readonly) m.REQ_FLAGS |= REQ_RDONLY; if(isroot) m.REQ_FLAGS |= REQ_ISROOT; m.REQ_GRANT = grant_id; m.REQ_DEV = dev; m.REQ_PATH_LEN = len; /* Send/rec request */ r = fs_sendrec(fs_e, &m); cpf_revoke(grant_id); if(r == OK) { /* Fill in response structure */ res_nodep->fs_e = m.m_source; res_nodep->inode_nr = m.RES_INODE_NR; res_nodep->fmode = m.RES_MODE; res_nodep->fsize = m.RES_FILE_SIZE_LO; res_nodep->uid = m.RES_UID; res_nodep->gid = m.RES_GID; } return(r); } /*===========================================================================* * req_readwrite * *===========================================================================*/ PUBLIC int req_readwrite(fs_e, inode_nr, pos, rw_flag, user_e, user_addr, num_of_bytes, new_posp, cum_iop) endpoint_t fs_e; ino_t inode_nr; u64_t pos; int rw_flag; endpoint_t user_e; char *user_addr; unsigned int num_of_bytes; u64_t *new_posp; unsigned int *cum_iop; { int r; cp_grant_id_t grant_id; message m; if (ex64hi(pos) != 0) panic("req_readwrite: pos too large"); grant_id = cpf_grant_magic(fs_e, user_e, (vir_bytes) user_addr, num_of_bytes, (rw_flag==READING ? CPF_WRITE:CPF_READ)); if (grant_id == -1) panic("req_readwrite: cpf_grant_magic failed"); /* Fill in request message */ m.m_type = rw_flag == READING ? REQ_READ : REQ_WRITE; m.REQ_INODE_NR = inode_nr; m.REQ_GRANT = grant_id; m.REQ_SEEK_POS_LO = ex64lo(pos); m.REQ_SEEK_POS_HI = 0; /* Not used for now, so clear it. */ m.REQ_NBYTES = num_of_bytes; /* Send/rec request */ r = fs_sendrec(fs_e, &m); cpf_revoke(grant_id); if (r == OK) { /* Fill in response structure */ *new_posp = cvul64(m.RES_SEEK_POS_LO); *cum_iop = m.RES_NBYTES; } return(r); } /*===========================================================================* * req_rename * *===========================================================================*/ PUBLIC int req_rename(fs_e, old_dir, old_name, new_dir, new_name) endpoint_t fs_e; ino_t old_dir; char *old_name; ino_t new_dir; char *new_name; { int r; cp_grant_id_t gid_old, gid_new; size_t len_old, len_new; message m; len_old = strlen(old_name) + 1; gid_old = cpf_grant_direct(fs_e, (vir_bytes) old_name, len_old, CPF_READ); if(gid_old == -1) panic("req_rename: cpf_grant_direct failed"); len_new = strlen(new_name) + 1; gid_new = cpf_grant_direct(fs_e, (vir_bytes) new_name, len_new, CPF_READ); if(gid_new == -1) panic("req_rename: cpf_grant_direct failed"); /* Fill in request message */ m.m_type = REQ_RENAME; m.REQ_REN_OLD_DIR = old_dir; m.REQ_REN_NEW_DIR = new_dir; m.REQ_REN_GRANT_OLD = gid_old; m.REQ_REN_LEN_OLD = len_old; m.REQ_REN_GRANT_NEW = gid_new; m.REQ_REN_LEN_NEW = len_new; /* Send/rec request */ r = fs_sendrec(fs_e, &m); cpf_revoke(gid_old); cpf_revoke(gid_new); return(r); } /*===========================================================================* * req_rmdir * *===========================================================================*/ PUBLIC int req_rmdir(fs_e, inode_nr, lastc) endpoint_t fs_e; ino_t inode_nr; char *lastc; { int r; cp_grant_id_t grant_id; size_t len; message m; len = strlen(lastc) + 1; grant_id = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ); if(grant_id == -1) panic("req_rmdir: cpf_grant_direct failed"); /* Fill in request message */ m.m_type = REQ_RMDIR; m.REQ_INODE_NR = inode_nr; m.REQ_GRANT = grant_id; m.REQ_PATH_LEN = len; /* Send/rec request */ r = fs_sendrec(fs_e, &m); cpf_revoke(grant_id); return(r); } /*===========================================================================* * req_slink * *===========================================================================*/ PUBLIC int req_slink( endpoint_t fs_e, ino_t inode_nr, char *lastc, endpoint_t who_e, char *path_addr, unsigned short path_length, uid_t uid, gid_t gid ) { int r; size_t len; cp_grant_id_t gid_name, gid_buf; message m; len = strlen(lastc) + 1; gid_name = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ); if(gid_name == -1) panic("req_slink: cpf_grant_direct failed"); gid_buf = cpf_grant_magic(fs_e, who_e, (vir_bytes) path_addr, path_length, CPF_READ); if(gid_buf == -1) { cpf_revoke(gid_name); panic("req_slink: cpf_grant_magic failed"); } /* Fill in request message */ m.m_type = REQ_SLINK; m.REQ_INODE_NR = inode_nr; m.REQ_UID = uid; m.REQ_GID = gid; m.REQ_GRANT = gid_name; m.REQ_PATH_LEN = len; m.REQ_GRANT3 = gid_buf; m.REQ_MEM_SIZE = path_length; /* Send/rec request */ r = fs_sendrec(fs_e, &m); cpf_revoke(gid_name); cpf_revoke(gid_buf); return(r); } /*===========================================================================* * req_stat * *===========================================================================*/ PUBLIC int req_stat(fs_e, inode_nr, who_e, buf, pos, stat_version) int fs_e; ino_t inode_nr; int who_e; char *buf; int pos; int stat_version; { cp_grant_id_t grant_id; int r; message m; struct stat sb; struct minix_prev_stat old_sb; /* for backward compatibility */ if (pos != 0 || stat_version != 0) grant_id = cpf_grant_direct(fs_e, (vir_bytes) &sb, sizeof(struct stat), CPF_WRITE); else grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, sizeof(struct stat), CPF_WRITE); if (grant_id < 0) panic("req_stat: cpf_grant_* failed"); /* Fill in request message */ m.m_type = REQ_STAT; m.REQ_INODE_NR = inode_nr; m.REQ_GRANT = grant_id; /* Send/rec request */ r = fs_sendrec(fs_e, &m); cpf_revoke(grant_id); if (r != OK || (pos == 0 && stat_version == 0)) return(r); if (pos != 0) sb.st_size -= pos; if (stat_version == 0) { r = sys_vircopy(SELF, D, (vir_bytes) &sb, who_e, D, (vir_bytes) buf, sizeof(struct stat)); return(r); } /* User needs old struct stat. * Just 1 prev version at this moment */ assert(stat_version == 1); /* XXX until that st_Xtime macroses used, we have to undefine them, * because of minix_prev_stat */ #undef st_atime #undef st_ctime #undef st_mtime /* Copy field by field because of st_gid type mismath and * difference in order after atime. */ old_sb.st_dev = sb.st_dev; old_sb.st_ino = sb.st_ino; old_sb.st_mode = sb.st_mode; old_sb.st_nlink = sb.st_nlink; old_sb.st_uid = sb.st_uid; old_sb.st_gid = sb.st_gid; old_sb.st_rdev = sb.st_rdev; old_sb.st_size = sb.st_size; #if defined(_NETBSD_SOURCE) old_sb.st_atime = sb.st_atimespec.tv_sec; old_sb.st_mtime = sb.st_mtimespec.tv_sec; old_sb.st_ctime = sb.st_ctimespec.tv_sec; #else old_sb.st_atime = sb.st_atime; old_sb.st_mtime = sb.st_mtime; old_sb.st_ctime = sb.st_ctime; #endif r = sys_vircopy(SELF, D, (vir_bytes) &old_sb, who_e, D, (vir_bytes) buf, sizeof(struct minix_prev_stat)); return(r); } /*===========================================================================* * req_sync * *===========================================================================*/ PUBLIC int req_sync(fs_e) endpoint_t fs_e; { message m; /* Fill in request message */ m.m_type = REQ_SYNC; /* Send/rec request */ return fs_sendrec(fs_e, &m); } /*===========================================================================* * req_unlink * *===========================================================================*/ PUBLIC int req_unlink(fs_e, inode_nr, lastc) endpoint_t fs_e; ino_t inode_nr; char *lastc; { cp_grant_id_t grant_id; size_t len; int r; message m; len = strlen(lastc) + 1; grant_id = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ); if(grant_id == -1) panic("req_unlink: cpf_grant_direct failed"); /* Fill in request message */ m.m_type = REQ_UNLINK; m.REQ_INODE_NR = inode_nr; m.REQ_GRANT = grant_id; m.REQ_PATH_LEN = len; /* Send/rec request */ r = fs_sendrec(fs_e, &m); cpf_revoke(grant_id); return(r); } /*===========================================================================* * req_unmount * *===========================================================================*/ PUBLIC int req_unmount(fs_e) endpoint_t fs_e; { message m; /* Fill in request message */ m.m_type = REQ_UNMOUNT; /* Send/rec request */ return fs_sendrec(fs_e, &m); } /*===========================================================================* * req_utime * *===========================================================================*/ PUBLIC int req_utime(fs_e, inode_nr, actime, modtime) endpoint_t fs_e; ino_t inode_nr; time_t actime; time_t modtime; { message m; /* Fill in request message */ m.m_type = REQ_UTIME; m.REQ_INODE_NR = inode_nr; m.REQ_ACTIME = actime; m.REQ_MODTIME = modtime; /* Send/rec request */ return fs_sendrec(fs_e, &m); } /*===========================================================================* * fs_sendrec * *===========================================================================*/ PRIVATE int fs_sendrec_f(char *file, int line, endpoint_t fs_e, message *reqm) { /* This is the low level function that sends requests to FS processes. * It also handles driver recovery mechanism and reissuing the * request which failed due to a dead driver. */ int r; message origm; if(fs_e <= 0 || fs_e == NONE) panic("talking to bogus endpoint: %d", fs_e); /* Make a copy of the request so that we can load it back in * case of a dead driver */ origm = *reqm; /* In response to the request we sent, some file systems may send back their * own VFS request, instead of a reply. VFS currently offers limited support * for this. As long as the FS keeps sending requests, we process them and * send back a reply. We break out of the loop as soon as the FS sends a * reply to the original request. * * There is no form of locking or whatever on global data structures, so it * is quite easy to mess things up; hence, 'limited' support. A future async * VFS will solve this problem for good. */ for (;;) { /* Do the actual send, receive */ if (OK != (r = sendrec(fs_e, reqm))) { printf("VFS:fs_sendrec:%s:%d: error sending message. " "FS_e: %d req_nr: %d err: %d\n", file, line, fs_e, reqm->m_type, r); util_stacktrace(); return(r); } /* If the type field is 0 (OK) or negative (E*), this is a reply. If it * contains a positive nonzero value, this is a request. */ if (reqm->m_type <= 0) break; /* Reply */ if (reqm->m_type == -EENTERMOUNT || reqm->m_type == -ELEAVEMOUNT || reqm->m_type == -ESYMLINK) { reqm->m_type = -reqm->m_type; break; /* Reply */ } /* Request */ nested_fs_call(reqm); } #if 0 if(r == OK) { /* Sendrec was okay */ break; } /* Dead driver */ if (r == EDEADSRCDST || r == EDSTDIED || r == ESRCDIED) { old_driver_e = NONE; /* Find old driver by endpoint */ for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) { if (vmp->m_fs_e == fs_e) { /* found FS */ #if 0 old_driver_e = vmp->m_driver_e; #endif dmap_unmap_by_endpt(old_driver_e); /* unmap driver */ break; } } /* No FS ?? */ if (old_driver_e == NONE) panic("VFSdead_driver: couldn't find FS: %d", fs_e); /* Wait for a new driver. */ for (;;) { new_driver_e = 0; printf("VFSdead_driver: waiting for new driver\n"); r = sef_receive(RS_PROC_NR, &m); if (r != OK) { panic("VFSdead_driver: unable to receive from RS: %d", r); } if (m.m_type == DEVCTL) { /* Map new driver */ r = fs_devctl(m.ctl_req, m.dev_nr, m.driver_nr, m.dev_style, m.m_force); if (m.ctl_req == DEV_MAP && r == OK) { new_driver_e = m.driver_nr; printf("VFSdead_driver: new driver endpoint: %d\n", new_driver_e); } } else { panic("VFSdead_driver: got message from RS type: %d", m.m_type); } m.m_type = r; if ((r = send(RS_PROC_NR, &m)) != OK) { panic("VFSdead_driver: unable to send to RS: %d", r); } /* New driver is ready */ if (new_driver_e) break; } /* Copy back original request */ *reqm = origm; continue; } printf("fs_sendrec: unhandled error %d sending to %d\n", r, fs_e); panic("fs_sendrec: unhandled error"); } #endif /* Return message type */ return(reqm->m_type); }