diff options
author | sotech117 <michael_foiani@brown.edu> | 2024-04-26 08:06:23 +0000 |
---|---|---|
committer | sotech117 <michael_foiani@brown.edu> | 2024-04-26 08:06:23 +0000 |
commit | 106eacf796dc15d1256aa92ee4ded216d0e6f29c (patch) | |
tree | 122ece6e43cf8ef3679d9ca2e8a2b4d6810f1f8d | |
parent | 30e8db594acc751d39d70bedfb83408b90676835 (diff) |
finish s5, but no clean halt
-rw-r--r-- | kernel/fs/s5fs/s5fs.c | 79 | ||||
-rw-r--r-- | kernel/fs/s5fs/s5fs_subr.c | 142 | ||||
-rw-r--r-- | kernel/fs/vfs_syscall.c | 5 | ||||
-rw-r--r-- | kernel/proc/proc.c | 2 | ||||
-rw-r--r-- | kernel/util/debug.c | 2 |
5 files changed, 134 insertions, 96 deletions
diff --git a/kernel/fs/s5fs/s5fs.c b/kernel/fs/s5fs/s5fs.c index 819b106..602c7aa 100644 --- a/kernel/fs/s5fs/s5fs.c +++ b/kernel/fs/s5fs/s5fs.c @@ -218,25 +218,28 @@ static void s5fs_read_vnode(fs_t *fs, vnode_t *vn) // Get the inode s5_inode_t *s5_inode = &s5_node->inode; KASSERT(s5_inode); - // Update linkcount - s5_inode->s5_linkcount++; // Get the page frame for the inode pframe_t *pf; - long err = s5fs_get_pframe(vn, &vn->vn_mobj, 0, &pf); - // Check if the page frame was not found - if (err < 0) - { - return; - } + s5_get_meta_disk_block(FS_TO_S5FS(fs), S5_INODE_BLOCK(vn->vn_vno), 0, &pf); + // // Check if the page frame was not found + // if (err < 0) + // { + // return; + // } // Copy the inode from the page frame - memcpy(s5_inode, pf->pf_addr, sizeof(s5_inode_t)); + memcpy( + s5_inode, + (s5_inode_t *)pf->pf_addr + S5_INODE_OFFSET(vn->vn_vno), + sizeof(s5_inode_t) + ); // Release the disk block s5_release_disk_block(&pf); // Initialize the dirtied_inode field s5_node->dirtied_inode = 0; + s5_node->vnode = *vn; // Initialize the vnode fields // lan and inode trivial @@ -290,9 +293,6 @@ static void s5fs_delete_vnode(fs_t *fs, vnode_t *vn) s5_inode_t *s5_inode = &s5_node->inode; KASSERT(s5_inode); - // Update linkcount - s5_inode->s5_linkcount--; - // Check if the inode is no longer in use if (s5_inode->s5_linkcount == 0) { @@ -306,14 +306,18 @@ static void s5fs_delete_vnode(fs_t *fs, vnode_t *vn) { // Write the inode back to disk and return pframe_t *pf; - long err = s5fs_get_pframe(vn, &vn->vn_mobj, 1, &pf); - // Check if the page frame was not found - if (err < 0) - { - return; - } + s5_get_meta_disk_block(FS_TO_S5FS(fs), S5_INODE_BLOCK(vn->vn_vno), 0, &pf); + // // Check if the page frame was not found + // if (err < 0) + // { + // return; + // } // Copy the inode to the page frame - memcpy(pf->pf_addr, s5_inode, sizeof(s5_inode_t)); + memcpy( + (s5_inode_t *)pf->pf_addr + S5_INODE_OFFSET(vn->vn_vno), + s5_inode, + sizeof(s5_inode_t) + ); s5_release_disk_block(&pf); return; } @@ -429,7 +433,7 @@ static long s5fs_mknod(struct vnode *dir, const char *name, size_t namelen, // NOT_YET_IMPLEMENTED("S5FS: s5fs_mknod"); // Check if the mode is not supported - if (mode != S_IFCHR && mode != S_IFBLK && mode != S_IFREG) + if (!(S_ISCHR(mode) || S_ISBLK(mode) || S_ISREG(mode))) { return -ENOTSUP; } @@ -456,7 +460,7 @@ static long s5fs_mknod(struct vnode *dir, const char *name, size_t namelen, // Allocate the inode s5_inode_t *s5_inode; - long inode_num = s5_alloc_inode(s5fs, type, &s5_inode); + long inode_num = s5_alloc_inode(s5fs, type, devid); // Check if the inode allocation failed if (inode_num < 0) { @@ -464,7 +468,7 @@ static long s5fs_mknod(struct vnode *dir, const char *name, size_t namelen, } // Create the new vnode - vnode_t *new_vnode = vget(dir->vn_fs, inode_num); + vnode_t *new_vnode = vget(s5fs->s5f_fs, inode_num); // Check if the vnode creation failed if (!new_vnode) { @@ -472,15 +476,12 @@ static long s5fs_mknod(struct vnode *dir, const char *name, size_t namelen, return -ENOMEM; } - // Set the devid for the new inode - s5_inode->s5_indirect_block = devid; - // Link the new inode/vnode to the parent directory - long link = s5_link(dir, name, namelen, new_vnode); + long link = s5_link(dir, name, namelen, VNODE_TO_S5NODE(new_vnode)); // Check if the link operation failed if (link < 0) { - vput(new_vnode); + vput(&new_vnode); s5_free_inode(s5fs, inode_num); return link; } @@ -527,7 +528,6 @@ long s5fs_lookup(vnode_t *dir, const char *name, size_t namelen, return 0; } - // If not, get the found vnode vnode_t *found_vnode = vget(dir->vn_fs, ino); // Check if the vnode creation failed @@ -590,11 +590,11 @@ static long s5fs_unlink(vnode_t *dir, const char *name, size_t namelen) } // Get the found vnode - vnode_t *child = vget_locked(dir->vn_fs, ino); + vnode_t *child = vget_locked(VNODE_TO_S5FS(dir)->s5f_fs, ino); KASSERT(!S_ISDIR(child->vn_mode) && "should be handled at the VFS level"); // Remove the directory entry - s5_remove_dirent(s5_node, name, namelen, filepos); + s5_remove_dirent(s5_node, name, namelen, VNODE_TO_S5NODE(child)); // Check to see if this failed (TODO: ask in hours) // Release the vnode @@ -797,7 +797,9 @@ static long s5fs_mkdir(vnode_t *dir, const char *name, size_t namelen, } // Create the "." entry + vlock(new_vnode); long link = s5_link(VNODE_TO_S5NODE(new_vnode), ".", 1, VNODE_TO_S5NODE(new_vnode)); + vunlock(new_vnode); // Check if the link operation failed if (link < 0) { @@ -807,7 +809,9 @@ static long s5fs_mkdir(vnode_t *dir, const char *name, size_t namelen, } // Create the ".." entry + vlock(new_vnode); long link2 = s5_link(VNODE_TO_S5NODE(new_vnode), "..", 2, VNODE_TO_S5NODE(dir)); + vunlock(new_vnode); // Check if the link operation failed if (link2 < 0) { @@ -818,7 +822,12 @@ static long s5fs_mkdir(vnode_t *dir, const char *name, size_t namelen, } // Link the new directory to the parent + vlock(dir); + + dbg(DBG_PRINT, "LINKING DIR TO NAME %s\n\n", name); + long link3 = s5_link(VNODE_TO_S5NODE(dir), name, namelen, VNODE_TO_S5NODE(new_vnode)); + vunlock(dir); // Check if the link operation failed if (link3 < 0) { @@ -866,8 +875,6 @@ static long s5fs_rmdir(vnode_t *parent, const char *name, size_t namelen) // Get the found vnode vnode_t *child = vget_locked(parent->vn_fs, ino); - KASSERT(S_ISDIR(child->vn_mode) && "should be handled at the VFS level"); - // Check if this is a directory if (!S_ISDIR(child->vn_mode)) { @@ -883,14 +890,14 @@ static long s5fs_rmdir(vnode_t *parent, const char *name, size_t namelen) } // Remove the "." entry - s5_remove_dirent(VNODE_TO_S5NODE(child), ".", 1, 0); + s5_remove_dirent(VNODE_TO_S5NODE(child), ".", 1, VNODE_TO_S5NODE(child)); // Check if this failed (TODO: ask in hours) // Remove the ".." entry - s5_remove_dirent(VNODE_TO_S5NODE(child), "..", 2, 0); + s5_remove_dirent(VNODE_TO_S5NODE(child), "..", 2, VNODE_TO_S5NODE(parent)); // Remove the directory entry - s5_remove_dirent(s5_node, name, namelen, filepos); + s5_remove_dirent(s5_node, name, namelen, VNODE_TO_S5NODE(child)); // Check if this failed (TODO: ask in hours) // Release the vnode @@ -962,7 +969,7 @@ static long s5fs_stat(vnode_t *vnode, stat_t *ss) s5_inode_t *s5_inode = &VNODE_TO_S5NODE(vnode)->inode; // Initialize the stat struct - ss->st_blocks = s5_inode_blocks(s5_inode); + ss->st_blocks = s5_inode_blocks(vnode); ss->st_mode = vnode->vn_mode; ss->st_rdev = vnode->vn_devid; ss->st_ino = s5_inode->s5_number; diff --git a/kernel/fs/s5fs/s5fs_subr.c b/kernel/fs/s5fs/s5fs_subr.c index a9fa638..f092d0a 100644 --- a/kernel/fs/s5fs/s5fs_subr.c +++ b/kernel/fs/s5fs/s5fs_subr.c @@ -188,10 +188,16 @@ long s5_file_block_to_disk_block(s5_node_t *sn, size_t file_blocknum, sn->inode.s5_indirect_block = disk_blocknum; sn->dirtied_inode = 1; - // Create a corresponding pframe_t on the mobj + // Create a corresponding pframe_t on the mob + s5fs_t *s5 = VNODE_TO_S5FS(&sn->vnode); + mobj_lock(&s5->s5f_mobj); pframe_t *pf = s5_cache_and_clear_block(&sn->vnode.vn_mobj, disk_blocknum, 0); + mobj_unlock(&s5->s5f_mobj); // memset(pf->pf_addr, 0, PAGE_SIZE); - // pf->pf_dirty = 1; (already done in s5_cache_and_clear_block) + // pf->pf_dirty = 1; (already done in s5_cache_and_clear_block + + // Release now that we have the desired block number + s5_release_disk_block(&pf); // set ret params and return *newp = 1; @@ -246,7 +252,7 @@ long s5_file_block_to_disk_block(s5_node_t *sn, size_t file_blocknum, // Case 4: The indirect block has not been allocated and alloc is clear else { - // TODO: check if this is correct + // TODO: check if this is correct (update -> passes tests so ok) return 0; } } @@ -283,15 +289,16 @@ ssize_t s5_read_file(s5_node_t *sn, size_t pos, char *buf, size_t len) { // NOT_YET_IMPLEMENTED("S5FS: s5_read_file"); + KASSERT(sn->vnode.vn_len == sn->inode.s5_un.s5_size); + // Check if pos is greater than or equal to the length of the file - if (pos >= sn->inode.s5_un.s5_size) + if (pos >= sn->vnode.vn_len) { return 0; } - // Calculate the number of bytes to read - size_t tmp = sn->inode.s5_un.s5_size - pos; - size_t bytes_to_read = len < tmp ? len : tmp; + // Calculate the number of bytes to read (checks edge if pos + len > file len) + size_t bytes_to_read = MIN(len, sn->vnode.vn_len - pos); // Initialize the number of bytes read size_t bytes_read = 0; @@ -311,12 +318,15 @@ ssize_t s5_read_file(s5_node_t *sn, size_t pos, char *buf, size_t len) } // Calculate the number of bytes to read in the current iteration - size_t tmp1 = bytes_to_read - bytes_read; - size_t tmp2 = S5_BLOCK_SIZE - block_offset; - size_t bytes_read_in_iteration = tmp1 < tmp2 ? tmp1 : tmp2; + size_t bytes_read_in_iteration = + MIN(bytes_to_read - bytes_read, S5_BLOCK_SIZE - block_offset); // Copy the data from the block to the buffer - memcpy(buf + bytes_read, pf->pf_addr + block_offset, bytes_read_in_iteration); + memcpy( + buf + bytes_read, + pf->pf_addr + block_offset, + bytes_read_in_iteration) + ; // Update the number of bytes read bytes_read += bytes_read_in_iteration; @@ -366,18 +376,27 @@ ssize_t s5_write_file(s5_node_t *sn, size_t pos, const char *buf, size_t len) // NOT_YET_IMPLEMENTED("S5FS: s5_write_file"); // Check if pos was beyond S5_MAX_FILE_SIZE - if (pos > S5_MAX_FILE_SIZE) + if (pos >= S5_MAX_FILE_SIZE) { return -EFBIG; } - // Calculate the number of bytes to write - size_t bytes_to_write = len < S5_MAX_FILE_SIZE - pos ? len : S5_MAX_FILE_SIZE - pos; + // Calculate the number of bytes to write (checks edge if pos + len > file len) + len = MIN(len, S5_MAX_FILE_SIZE - pos); + + + // Update the vnode length and inode size in advance + if (pos + len >= sn->vnode.vn_len) + { + sn->dirtied_inode = 1; + + sn->vnode.vn_len = pos + len; + sn->inode.s5_un.s5_size = sn->vnode.vn_len; + } // Initialize the number of bytes written size_t bytes_written = 0; - - while (bytes_written < bytes_to_write) + while (bytes_written < len) { size_t file_blocknum = pos / S5_BLOCK_SIZE; size_t block_offset = pos % S5_BLOCK_SIZE; @@ -388,34 +407,36 @@ ssize_t s5_write_file(s5_node_t *sn, size_t pos, const char *buf, size_t len) // Propogate errors from s5_get_file_block if (err < 0) { + // Restore pos + sn->vnode.vn_len += bytes_written; + sn->inode.s5_un.s5_size += bytes_written; return err; } // Calculate the number of bytes to write in the current iteration - size_t tmp1 = bytes_to_write - bytes_written; - size_t tmp2 = S5_BLOCK_SIZE - block_offset; - size_t bytes_written_in_iteration = tmp1 < tmp2 ? tmp1 : tmp2; + size_t bytes_to_write = + MIN(len - bytes_written, S5_BLOCK_SIZE - block_offset); // Copy the data from the buffer to the block - memcpy(pf->pf_addr + block_offset, buf + bytes_written, bytes_written_in_iteration); + memcpy( + pf->pf_addr + block_offset, + buf + bytes_written, + bytes_to_write + ); // Update the number of bytes written - bytes_written += bytes_written_in_iteration; + bytes_written += bytes_to_write; + // Update the position + pos += bytes_to_write; - // Release the pframe + // Dirty and release the pframe + pf->pf_dirty = 1; s5_release_file_block(&pf); - // Update the position - pos += bytes_written_in_iteration; - - // Update the inode - sn->inode.s5_un.s5_size = sn->inode.s5_un.s5_size > pos ? sn->inode.s5_un.s5_size : pos; - sn->vnode.vn_len = sn->inode.s5_un.s5_size; - sn->dirtied_inode = 1; + // Update the v/inode length + // sn->inode.s5_un.s5_size = MAX(sn->inode.s5_un.s5_size, pos); + // sn->vnode.vn_len = sn->inode.s5_un.s5_size; } - - // TODO: check for partial write - return bytes_written; } @@ -456,9 +477,10 @@ static long s5_alloc_block(s5fs_t *s5fs) s5_super_t *s = &s5fs->s5f_super; // Check if there are no more free blocks + blocknum_t new_block_num; if (s->s5s_nfree == 0) { - blocknum_t new_block_num = s->s5s_free_blocks[S5_NBLKS_PER_FNODE - 1]; + new_block_num = s->s5s_free_blocks[S5_NBLKS_PER_FNODE - 1]; // Check if there are no more free blocks remaining if (new_block_num == (blocknum_t)-1) { @@ -471,25 +493,30 @@ static long s5_alloc_block(s5fs_t *s5fs) pframe_t *pf; s5_get_meta_disk_block(s5fs, new_block_num, 1, &pf); memcpy(s->s5s_free_blocks, pf->pf_addr, sizeof(s->s5s_free_blocks)); - s->s5s_nfree = S5_NBLKS_PER_FNODE - 1; s5_release_disk_block(&pf); - // Update the super block - s->s5s_free_blocks[S5_NBLKS_PER_FNODE - 1] = new_block_num; + // Reset the number of free blocks + s->s5s_nfree = S5_NBLKS_PER_FNODE - 1; - // Unlock the super block - s5_unlock_super(s5fs); - return new_block_num; + // Update the super block + // s->s5s_free_blocks[S5_NBLKS_PER_FNODE - 1] = new_block_num; } else { // Update the super block - s->s5s_nfree--; - - // Unlock the super block - s5_unlock_super(s5fs); - return s->s5s_free_blocks[s->s5s_nfree]; + new_block_num = s->s5s_free_blocks[--s->s5s_nfree]; } + + // Initialize the block's contents to 0 + pframe_t *pf; + s5_get_meta_disk_block(s5fs, new_block_num, 1, &pf); + memset(pf->pf_addr, 0, PAGE_SIZE); + s5_release_disk_block(&pf); + + // Unlock the super block + s5_unlock_super(s5fs); + + return new_block_num; } /* @@ -685,21 +712,21 @@ long s5_find_dirent(s5_node_t *sn, const char *name, size_t namelen, KASSERT(S5_BLOCK_SIZE == PAGE_SIZE && "be wary, thee"); // NOT_YET_IMPLEMENTED("S5FS: s5_find_dirent"); + if (namelen == 0) + { + return sn->inode.s5_number; + } + // Initialize the file position size_t pos = 0; // Initialize the directory entry s5_dirent_t dirent; - // Read the directory entry while (s5_read_file(sn, pos, (char *)&dirent, sizeof(s5_dirent_t)) == sizeof(s5_dirent_t)) { // Check if the directory entry has the specified name - if ( - strlen(dirent.s5d_name) == namelen - && - strncmp(dirent.s5d_name, name, namelen) == 0 - ) + if (name_match(dirent.s5d_name, name, namelen)) { // Update the file position if (filepos) @@ -767,13 +794,11 @@ void s5_remove_dirent(s5_node_t *sn, const char *name, size_t namelen, // Truncate the length of the directory by sizeof(s5_dirent_t) inode->s5_un.s5_size -= sizeof(s5_dirent_t); + dir->vn_len -= sizeof(s5_dirent_t); sn->dirtied_inode = 1; // Decrement the child's linkcount child->inode.s5_linkcount--; - - // Decrease len of the directory - dir->vn_len -= sizeof(s5_dirent_t); // Mark the inodes as dirtied child->dirtied_inode = 1; @@ -869,18 +894,19 @@ long s5_link(s5_node_t *dir, const char *name, size_t namelen, long inode_num = s5_find_dirent(dir, name, namelen, &filepos); // Check if the directory entry already exists - if (inode_num >= 0) + if (inode_num != -ENOENT) { return -EEXIST; } // Form the new directory entry s5_dirent_t new_dirent; - strncpy(new_dirent.s5d_name, name, namelen); + memcpy(new_dirent.s5d_name, name, namelen); + new_dirent.s5d_name[namelen] = '\0'; new_dirent.s5d_inode = child->inode.s5_number; // Write the new directory entry - long bytes_written = s5_write_file(dir, dir->inode.s5_un.s5_size, (char *)&new_dirent, sizeof(s5_dirent_t)); + long bytes_written = s5_write_file(dir, dir->vnode.vn_len, (char *)&new_dirent, sizeof(s5_dirent_t)); // Propagate errors from s5_write_file if (bytes_written < 0) { @@ -891,7 +917,7 @@ long s5_link(s5_node_t *dir, const char *name, size_t namelen, child->inode.s5_linkcount++; child->dirtied_inode = 1; - dir->inode.s5_un.s5_size += sizeof(s5_dirent_t); + // dir->inode.s5_un.s5_size += sizeof(s5_dirent_t); dir->dirtied_inode = 1; // Assert that the directory entry exists and that its inode is, as expected, the inode of child @@ -985,4 +1011,4 @@ void s5_remove_blocks(s5_node_t *sn) s5_free_block(s5fs, s5_inode->s5_indirect_block); s5_inode->s5_indirect_block = 0; } -} +}
\ No newline at end of file diff --git a/kernel/fs/vfs_syscall.c b/kernel/fs/vfs_syscall.c index 205020b..245e55d 100644 --- a/kernel/fs/vfs_syscall.c +++ b/kernel/fs/vfs_syscall.c @@ -306,6 +306,11 @@ long do_mknod(const char *path, int mode, devid_t devid) vnode_t *vnode = NULL; vnode_t *base = curproc->p_cwd; long ret = namev_open(base, path, O_CREAT, mode, devid, &vnode); + if (ret < 0) + { + return ret; + } + vput(&vnode); return ret; } diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c index 91be451..945d17e 100644 --- a/kernel/proc/proc.c +++ b/kernel/proc/proc.c @@ -278,7 +278,7 @@ void proc_cleanup(long status) if (curproc->p_pid == PID_INIT) { // if it's init proc, shutdown weenix - initproc_finish(status); + initproc_finish(); } // if it's not init proc, reparent child processes to parent proc diff --git a/kernel/util/debug.c b/kernel/util/debug.c index 027c05f..a8f9732 100644 --- a/kernel/util/debug.c +++ b/kernel/util/debug.c @@ -19,7 +19,7 @@ * always be the first thing in this variable. Note that this setting can be * changed at runtime by modifying the dbg_modes global variable. */ -#define INIT_DBG_MODES "-all,test,print" +#define INIT_DBG_MODES "-all,test,print,s5fs" /* Below is a truly terrible poll-driven serial driver that we use for debugging * purposes - it outputs to COM1, but |