/*===========================================================================* * do_vm_call * *===========================================================================*/ int do_vm_call(void) { /* A call that VM does to VFS. * We must reply with the fixed type VM_VFS_REPLY (and put our result info * in the rest of the message) so VM can tell the difference between a * request from VFS and a reply to this call. */ int req = job_m_in.VFS_VMCALL_REQ; int req_fd = job_m_in.VFS_VMCALL_FD; u32_t req_id = job_m_in.VFS_VMCALL_REQID; endpoint_t ep = job_m_in.VFS_VMCALL_ENDPOINT; u64_t offset = job_m_in.VFS_VMCALL_OFFSET; u32_t length = job_m_in.VFS_VMCALL_LENGTH; int result = OK; int slot; struct fproc *rfp, *vmf; struct filp *f = NULL; int r; if(job_m_in.m_source != VM_PROC_NR) return ENOSYS; if(isokendpt(ep, &slot) != OK) rfp = NULL; else rfp = &fproc[slot]; vmf = fproc_addr(VM_PROC_NR); assert(fp == vmf); assert(rfp != vmf); switch(req) { case VMVFSREQ_FDLOOKUP: { int procfd; /* Lookup fd in referenced process. */ if(!rfp) { printf("VFS: why isn't ep %d here?!\n", ep); result = ESRCH; goto reqdone; } if((result = dupvm(rfp, req_fd, &procfd, &f)) != OK) { #if 0 /* Noisy diagnostic for mmap() by ld.so */ printf("vfs: dupvm failed\n"); #endif goto reqdone; } if(S_ISBLK(f->filp_vno->v_mode)) { assert(f->filp_vno->v_sdev != NO_DEV); job_m_out.VMV_DEV = f->filp_vno->v_sdev; job_m_out.VMV_INO = VMC_NO_INODE; job_m_out.VMV_SIZE_PAGES = LONG_MAX; } else { job_m_out.VMV_DEV = f->filp_vno->v_dev; job_m_out.VMV_INO = f->filp_vno->v_inode_nr; job_m_out.VMV_SIZE_PAGES = roundup(f->filp_vno->v_size, PAGE_SIZE)/PAGE_SIZE; } job_m_out.VMV_FD = procfd; result = OK; break; } case VMVFSREQ_FDCLOSE: { result = close_fd(fp, req_fd); if(result != OK) { printf("VFS: VM fd close for fd %d, %d (%d)\n", req_fd, fp->fp_endpoint, result); } break; } case VMVFSREQ_FDIO: { result = actual_lseek(fp, req_fd, SEEK_SET, offset, NULL); if(result == OK) { result = actual_read_write_peek(fp, PEEKING, req_fd, /* vir_bytes */ 0, length); } break; } default: panic("VFS: bad request code from VM\n"); break; } reqdone: if(f) unlock_filp(f); /* fp is VM still. */ assert(fp == vmf); job_m_out.VMV_ENDPOINT = ep; job_m_out.VMV_RESULT = result; job_m_out.VMV_REQID = req_id; /* Reply asynchronously as VM may not be able to receive * an ipc_sendnb() message. */ job_m_out.m_type = VM_VFS_REPLY; r = asynsend3(VM_PROC_NR, &job_m_out, 0); if(r != OK) printf("VFS: couldn't asynsend3() to VM\n"); /* VFS does not reply any further */ return SUSPEND; }
/*===========================================================================* * do_read_write_peek * *===========================================================================*/ int do_read_write_peek(int rw_flag, int io_fd, vir_bytes io_buf, size_t io_nbytes) { return actual_read_write_peek(fp, rw_flag, io_fd, io_buf, io_nbytes); }