aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsotech117 <michael_foiani@brown.edu>2024-04-26 08:06:23 +0000
committersotech117 <michael_foiani@brown.edu>2024-04-26 08:06:23 +0000
commit106eacf796dc15d1256aa92ee4ded216d0e6f29c (patch)
tree122ece6e43cf8ef3679d9ca2e8a2b4d6810f1f8d
parent30e8db594acc751d39d70bedfb83408b90676835 (diff)
finish s5, but no clean halt
-rw-r--r--kernel/fs/s5fs/s5fs.c79
-rw-r--r--kernel/fs/s5fs/s5fs_subr.c142
-rw-r--r--kernel/fs/vfs_syscall.c5
-rw-r--r--kernel/proc/proc.c2
-rw-r--r--kernel/util/debug.c2
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