diff options
Diffstat (limited to 'kernel/fs/s5fs/s5fs_subr.c')
-rw-r--r-- | kernel/fs/s5fs/s5fs_subr.c | 142 |
1 files changed, 84 insertions, 58 deletions
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 |