aboutsummaryrefslogtreecommitdiff
path: root/kernel/fs/s5fs/s5fs_subr.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/fs/s5fs/s5fs_subr.c')
-rw-r--r--kernel/fs/s5fs/s5fs_subr.c142
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