/* * sys_fstat */ int sys_fstat(int fd, userptr_t statptr) { DEBUG(DB_VFS, "fstat %d\n", fd); struct stat kbuf; int err; /* Check if fd is a valid file descriptor. */ struct filetable *ft = curthread->t_filetable; spinlock_acquire(&ft->ft_spinlock); /* If fd is not a valid file descriptor, return error */ if ((fd < 0) || (fd >= __OPEN_MAX) || (ft->ft_entries[fd] == NULL) || (ft->ft_entries[fd]->ft_vnode == NULL)) { spinlock_release(&ft->ft_spinlock); return EBADF; } /* Call VOP_STAT on the vnode */ err = VOP_STAT(ft->ft_entries[fd]->ft_vnode, &kbuf); spinlock_release(&ft->ft_spinlock); if (err) { return err; } return copyout(&kbuf, statptr, sizeof(struct stat)); }
void swap_init() { int ret = vfs_open((char*) SWAP_DISK_NAME, O_RDWR, 0, &swap_vnode); if (ret) { kprintf("WARN swap disk not found Ret = %d\n", ret); swap_state = SWAP_STATE_NOSWAP; return; } struct stat statbuf; ret = VOP_STAT(swap_vnode, &statbuf); if (ret) { kprintf("ERR Stat on swap disk failed\n"); swap_state = SWAP_STATE_NOSWAP; return; } swap_page_count = (statbuf.st_size / PAGE_SIZE) - 1; swap_map = (struct swap_entry*) kmalloc( sizeof(struct swap_entry) * swap_page_count); int i; for (i = 0; i < swap_page_count; i++) { swap_map[i].se_used = SWAP_PAGE_FREE; swap_map[i].se_paddr = i; } swap_lock = lock_create("swap_lock"); swap_state = SWAP_STATE_READY; kprintf("Swap init done. Total available pages = %d\n", swap_page_count); }
off_t lseek(int fd,off_t pos, int whence,int *err) { off_t nPos=0; struct stat eoFILE; //kprintf("lseek entered\n"); if ( fd < 0 || fd > OPEN_MAX) { *err = EBADF; return -1; } if (curthread->ft[fd] == NULL) { *err = EBADF; return -1; } //kprintf("curthread->ft[fd] == NULL\n"); //kprintf("fd < 0 || fd > OPEN_MAX\n"); if (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END) { *err = EINVAL; return -1; } //kprintf("whence != SEEK_SET || whence != SEEK_CUR || whence != SEEK_END\n"); //kprintf("Acquiring lock\n"); lock_acquire(curthread->ft[fd]->lock); //kprintf("Stat gathering\n"); VOP_STAT(curthread->ft[fd]->vn,&eoFILE); if (whence == SEEK_SET) { nPos = pos; } if (whence == SEEK_CUR) { nPos = curthread->ft[fd]->offset+pos; } if (whence == SEEK_END) { nPos = eoFILE.st_size+pos; } if (nPos < 0) { *err = EINVAL; lock_release(curthread->ft[fd]->lock); return -1; } //kprintf("NPos %llu\n",nPos); *err = VOP_TRYSEEK(curthread->ft[fd]->vn,nPos); if (*err) { lock_release(curthread->ft[fd]->lock); return -1; } curthread->ft[fd]->offset = nPos; lock_release(curthread->ft[fd]->lock); //kprintf("New position %llu\n",nPos); return curthread->ft[fd]->offset; }
/* * swap_bootstrap: Initializes swap information and finishes * bootstrapping the VM so that processes can use it. * * Synchronization: none (runs during boot before anyone else uses VM) */ void swap_bootstrap(size_t pmemsize) { int rv; struct stat st; char path[sizeof(swapfilename)]; off_t minsize; strcpy(path, swapfilename); rv = vfs_open(path, O_RDWR, &swapstore); if (rv) { kprintf("swap: Error %d opening swapfile %s\n", rv, swapfilename); kprintf("swap: Please create swapfile/swapdisk.\n"); panic("swap: Unable to continue.\n"); } minsize = pmemsize*10; VOP_STAT(swapstore, &st); if (st.st_size < minsize) { kprintf("swap: swapfile %s is only %lu bytes.\n", swapfilename, (unsigned long) st.st_size); kprintf("swap: with %lu bytes of physical memory it should " "be at least\n", (unsigned long) pmemsize); kprintf(" %lu bytes (%lu blocks).\n", (unsigned long) minsize, (unsigned long) minsize / 512); kprintf("swap: Please extend it.\n"); panic("swap: Unable to continue.\n"); } kprintf("swap: swapping to %s (%lu bytes; %lu pages)\n", swapfilename, (unsigned long) st.st_size, (unsigned long) st.st_size / PAGE_SIZE); swap_total_pages = st.st_size / PAGE_SIZE; swap_free_pages = swap_total_pages; swap_reserved_pages = 0; swapmap = bitmap_create(st.st_size/PAGE_SIZE); DEBUG(DB_VM, "creating swap map with %d entries\n", st.st_size/PAGE_SIZE); if (swapmap == NULL) { panic("swap: No memory for swap bitmap\n"); } swaplock = lock_create("swaplock"); if (swaplock == NULL) { panic("swap: No memory for swap lock\n"); } /* mark the first page of swap used so we can check for errors */ bitmap_mark(swapmap, 0); swap_free_pages--; }
static bool swap_device_suficient( size_t ram_size, size_t *swap_size ) { size_t min_size; struct stat stat; min_size = ram_size * SWAP_MIN_FACTOR; VOP_STAT( vn_sw, &stat ); *swap_size = stat.st_size; return stat.st_size >= min_size; }
int sys_lseek(int fd, off_t pos, int whence, off_t *new_pos) { int err; struct fd_file *file; struct stat stat; file = get_file_from_fd_table(curproc->p_fd_table, fd); if (file == NULL) { err = EBADF; goto err1; } lock_acquire(file->fdf_lock); if (!VOP_ISSEEKABLE(file->fdf_vnode)) { err = ESPIPE; goto err2; } switch (whence) { case SEEK_SET: *new_pos = pos; break; case SEEK_CUR: *new_pos = file->fdf_offset + pos; break; case SEEK_END: VOP_STAT(file->fdf_vnode, &stat); *new_pos = stat.st_size + pos; break; default: err = EINVAL; goto err2; } if (*new_pos < 0) { err = EINVAL; goto err2; } file->fdf_offset = *new_pos; lock_release(file->fdf_lock); return 0; err2: lock_release(file->fdf_lock); err1: return err; }
void coreswap_init() { struct stat temp; VOP_STAT(swap_file, &temp); coreswap_size = temp.st_size/PAGE_SIZE; swap_map = bitmap_create(coreswap_size); coreswap = (struct page_table_entry*)kmalloc(coreswap_size * sizeof(struct page_table_entry)); int coreswap_start=0; kprintf("COREMAP INIT: %d %d\n",coremap_start,coremap_size); for(int i = 0; i < temp.st_size/PAGE_SIZE; i++) { coreswap[i].paddr = (coreswap_start + (i * PAGE_SIZE)); } kprintf("COREMAP INIT: %d %d\n",coremap_start,coremap_size); }
/* * sys_lseek * */ int sys_lseek(int fd, off_t offset, int whence, off_t *retval) { DEBUG(DB_VFS, "Lseeking fd %d with offset %d\n", fd, (int)offset); struct filetable *ft = curthread->t_filetable; spinlock_acquire(&ft->ft_spinlock); /* If fd is not a valid file descriptor, return error. */ if ((fd < 0) || (fd >= __OPEN_MAX) || (ft->ft_entries[fd] == NULL) || (ft->ft_entries[fd]->ft_vnode == NULL)) { spinlock_release(&ft->ft_spinlock); return EBADF; } int pos; if (whence == SEEK_SET) { /* Update new position to offset.*/ pos = (int)offset; } else if (whence == SEEK_CUR) { /* Update new position to current position + pos. */ pos = (ft->ft_entries[fd]->ft_pos + (int)offset); } else if (whence == SEEK_END) { /* Update new positionto end-of-file + pos. */ struct stat ft_stat; VOP_STAT(ft->ft_entries[fd]->ft_vnode, &ft_stat); pos = ft_stat.st_size + offset; } else { /* whence value is invalid. return error. */ spinlock_release(&ft->ft_spinlock); return EINVAL; } /* If resulting position is negative, return error. */ if (pos < 0) { spinlock_release(&ft->ft_spinlock); return EINVAL; } int result = VOP_TRYSEEK(ft->ft_entries[fd]->ft_vnode, pos); if (result != 0) { DEBUG(DB_VFS, " tryseek failed with %d\n", result); spinlock_release(&ft->ft_spinlock); return ESPIPE; } ft->ft_entries[fd]->ft_pos = pos; *retval = (off_t)pos; spinlock_release(&ft->ft_spinlock); return 0; }
off_t sys_lseek(int fd,off_t pos, int whence, int *err){ if (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END){ *err = EINVAL; return -1; } if (fd < 0 || fd >= MAX_FILE_DESCRIPTOR){ *err = EBADF; return -1; } if (curthread->fd[fd] == NULL){ *err = EBADF; return -1; } lock_acquire(curthread->fd[fd]->mutex); if (curthread->fd[fd]->update_pos == 0){ *err = ESPIPE; lock_release(curthread->fd[fd]->mutex); return -1; } off_t newpos; struct stat stat; VOP_STAT(curthread->fd[fd]->file,&stat); if (whence == SEEK_SET) newpos = pos; if (whence == SEEK_CUR) newpos = curthread->fd[fd]->offset+pos; if (whence == SEEK_END) newpos = stat.st_size+pos; if (newpos < 0){ *err = EINVAL; lock_release(curthread->fd[fd]->mutex); return -1; } *err = VOP_TRYSEEK(curthread->fd[fd]->file,newpos); if (*err){ lock_release(curthread->fd[fd]->mutex); return -1; } curthread->fd[fd]->offset = newpos; lock_release(curthread->fd[fd]->mutex); return curthread->fd[fd]->offset; }
void swap_bootstrap(void) { int retval; struct stat a; // struct vnode *swap_vnode; retval = vfs_open(SWAP_DEVICE, O_RDWR, &swap_vnode); if(retval) { panic("could not open swap device\n") ; } VOP_STAT(swap_vnode, &a); swap_map = bitmapCreate(a.st_size / PAGE_SIZE); if(swap_map == NULL) { panic("could not create swap map\n") ; } vfs_close(swap_vnode); }
/* * Initialize the swap area and the bitmap to describe the area. We steal memory * from ram to store these data structures. Initialize each of the page's chunk * address. */ void init_swaparea() { int i; struct stat file_stat; //read the size of the disk0 into file_stat VOP_STAT(swap_fp, &file_stat); //swaparea size is in PAGE_SIZE unit swaparea_size = file_stat.st_size/PAGE_SIZE; //bitmap to describe the swaparea (in memory or in disk) swap_memmap = bitmap_create(swaparea_size); //allocate the swaparea into memory by stealing some memory from RAM swaparea = (struct _PTE*)kmalloc(swaparea_size * sizeof(struct _PTE)); //we are initializing swaparea first, so base address should be 0 swap_base = 0; //set chunk of each of the pages in the swaparea for(i = 0; i < file_stat.st_size/PAGE_SIZE; i++) { swaparea[i].paddr = (swap_base + (i * PAGE_SIZE)); } }
/* * sys_fstat */ int sys_fstat(int fd, userptr_t statptr) { struct stat kstat; int result; struct filetable *file_table = curthread->t_filetable; spinlock_acquire(&file_table->filetable_lock); //kprintf(" doing fstat"); //check for fd is valid or not if((fd > __OPEN_MAX) || (file_table->ft_entries[fd] == NULL) || (fd<0)){ spinlock_release(&file_table->filetable_lock); return EBADF; } //use vop_stat to return the info of file result = VOP_STAT(file_table->ft_entries[fd]->file_vnode, &kstat); if(result){ return result; } spinlock_release(&file_table->filetable_lock); //kprintf(" fstat done"); return copyout(&kstat, statptr, sizeof(struct stat)); }
int sys_lseek(int filehandle, off_t pos, int code, int *retval) { off_t newfp; int r; struct stat statbuf; /* check file handle */ r = check_fd_access(filehandle, curthread->t_fdt, F_ANY); if (r) return r; switch (code) { case SEEK_SET: newfp = pos; break; case SEEK_CUR: newfp = curthread->t_fdt->fd[filehandle]->fp + pos; break; case SEEK_END: r = VOP_STAT(curthread->t_fdt->fd[filehandle]->vn, &statbuf); if (r) return r; newfp = statbuf.st_size + pos; break; default: return EINVAL; } if (newfp < 0) { return EINVAL; } r = VOP_TRYSEEK(curthread->t_fdt->fd[filehandle]->vn, newfp); if (r < 0) { return r; } curthread->t_fdt->fd[filehandle]->fp = newfp; *retval = newfp; return 0; }
/* normal open() function - called by user */ int sys_open(const_userptr_t fileName, int flags, int * retval) { char fileNameFromUser[BUF_SIZE]; // file name from copyinstr bool append_flag = false; // if O_APPEND is one of the flags, this variable is set to TRUE int err; // Step 1: first check if the filename pointer is valid if (fileName == NULL) { err = EFAULT; return err; } // Step 2: then check if the flags are valid (use switch statement to check for valid flags) switch(flags) { case O_RDONLY: break; case O_WRONLY: break; case O_RDWR: break; case O_RDONLY|O_CREAT: break; case O_WRONLY|O_CREAT: break; case O_WRONLY|O_APPEND: append_flag = true; break; case O_RDWR|O_CREAT: break; case O_RDWR|O_APPEND: append_flag = true; break; case O_RDWR|O_CREAT|O_TRUNC: break; default: err = EINVAL; return err; } // Step 3: if steps 1 and 2 are passing, then find an empty slot in the tfd_table and allocate it to this file that is going to be opened int slot = -1; for (int i=3; i<OPEN_MAX; i++) { if (curthread->t_fdtable[i] == NULL) { slot = i; break; } } /* in case the file table is full and there are no empty slots */ if (slot == -1) { err = EMFILE; return err; } // Step 4: copy the valid filename into the kernel buffer, using the copyinstr function size_t actual; if ((err = copyinstr(fileName, fileNameFromUser, BUF_SIZE, &actual)) != 0) { return err; } // Step 5: call vfs_open, with correct arguments struct vnode * node; err = vfs_open(fileNameFromUser, flags, 0, &node); // add code here to check if vnode returned successfully if (err) { // if vnode not successful, then return appropriate error to user return err; } // Step 6: initialize the struct fhandle with correct values, taking the flags into consideration if (append_flag) { /* case where the APPEND flag is true, get the file size and set pass it as the offset */ struct stat buffer; VOP_STAT(node, &buffer); int bytes = buffer.st_size; *retval = slot; curthread->t_fdtable[slot] = fhandle_create(fileNameFromUser, flags, bytes, node); KASSERT(curthread->t_fdtable[slot] != NULL); } else { /* case where append flag is not TRUE */ *retval = slot; curthread->t_fdtable[slot] = fhandle_create(fileNameFromUser, flags, 0, node); KASSERT(curthread->t_fdtable[slot] != NULL); } /* on success, return 0 */ return 0; }
/* lseek() call handler */ int sys_lseek(int fd, off_t pos, int whence, off_t * retVal64){ int err; off_t currentPosition; off_t endPosition; off_t posSeek; struct stat buffer; /* Step 1: Check if the file descriptor passed in is valid */ if (fd >= OPEN_MAX || fd < 0) { // fd is out of bounds of the file table return EBADF; } struct fhandle * fdesc = curthread->t_fdtable[fd]; if (fdesc == NULL) { return EBADF; } /* Adding locks to synchronize the whole process */ lock_acquire(fdesc->lock); switch(whence) { // logic for different cases case SEEK_SET: //VOP_TRYSEEK(vnode, position) if (pos < 0) { lock_release(fdesc->lock); return EINVAL; // seek position is negative } posSeek = pos; if ((err = VOP_TRYSEEK(fdesc->vn, posSeek)) != 0) { lock_release(fdesc->lock); return ESPIPE; // in case the SEEK fails } fdesc->offset = posSeek; *retVal64 = fdesc->offset; break; case SEEK_CUR: currentPosition = fdesc->offset; posSeek = currentPosition + pos; if (posSeek < 0) { lock_release(fdesc->lock); return EINVAL; } if ((err = VOP_TRYSEEK(fdesc->vn, posSeek)) != 0) { lock_release(fdesc->lock); return ESPIPE; } fdesc->offset = posSeek; *retVal64 = fdesc->offset; break; case SEEK_END: VOP_STAT(fdesc->vn, &buffer); endPosition = buffer.st_size; posSeek = endPosition + pos; if (posSeek < 0) { lock_release(fdesc->lock); return EINVAL; } if ((err = VOP_TRYSEEK(fdesc->vn, posSeek)) != 0) { lock_release(fdesc->lock); return ESPIPE; } if (pos < 0) { fdesc->offset = posSeek + pos; } else { fdesc->offset = posSeek; } *retVal64 = fdesc->offset; break; default: return EINVAL; } lock_release(fdesc->lock); return 0; }