Skip to content

Commit

Permalink
Added unlink, rmdir and indirect report sections as well as fixed flo…
Browse files Browse the repository at this point in the history
…ating images in latex
  • Loading branch information
EngineersBox committed Oct 22, 2023
1 parent 8596047 commit 21d8ab6
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 2 deletions.
Binary file added assets/direcct_last_last.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/direct_last_non_last.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/direct_non_last_non_last.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/indirect_last_to_direct.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/indirect_to_direct.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/indirect_to_indirect.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions float_adjustment.tex
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
\usepackage{float}
\floatplacement{figure}{H}
1 change: 1 addition & 0 deletions gen_report.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
pandoc report.md \
--toc=true \
--toc-depth=5 \
-H float_adjustment.tex \
-V geometry:margin=3cm \
-V author='Jack Kilrain (u6940136) Daniel Herald (u7480080) Angus Atkinson (u7117106)' \
-V date='22 October 2023' \
Expand Down
102 changes: 100 additions & 2 deletions report.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,56 @@ This report discusses the implementation of several operations into VVSFS, the V

## Unlink Dentries and Removing Directories

TODO
### Unlink

Supporiting unlinking of dentries requires consideration around the behaviour of evicting entries from data blocks and potentially data blocks themselves.
In order to make this achievable, the unlink is split into two stages:
1. Find the dentry
2. Remove the dentry

Supporting find and remove operations is the `struct bufloc_t` implementation which stores block and dentry indices for ease of use. In addition to this, this
structure also has provisions to allow for the retention of the buffer object and dentry object (dependently) to aid in reducing the need for re-indexing into
buffers later (handled by flags `BL_PERSIST_BUFFER` and `BL_PERSIST_DENTRY`). These can also be resolved at a later time if necessary.

The method `vvsfs_find_dentry` is used to search through the data blocks and saturate a `bufloc_t` instance with the relevant information. This is then forwarded
to the `vvsfs_delete_entry` method to perform the actual removal. Search operations is merely a linear traversal of the blocks bound to the `inode`, attempting to
match the name and parent inode of a dentry to the target one.

Removing a dentry requires care to be taken around several cases for where the dentry is:

1. Last dentry in the last block
2. Non-last dentry in last block
3. Any position dentry in non-last block

In the first case, we can simply evict the dentry (by zeroing it) and we are done. After that we consider if there are dentries left, if so we deallocate the block
and remove it from the `inode->i_data` array.

![Last block last dentry](./assets/direcct_last_last.png)

The second case requires moving the last dentry in the last block to fill the hole of the one being evicted. We do this with a memmove to overwrite the target dentry,
then zero the old location of the last dentry in the last block.

![Last block non-last dentry](./assets/direct_last_non_last.png)

In the last case, we need to move the last dentry from the last block to our current block to fill the hole. This requires multiple buffer locations to be open at once,
ensuring we move and then zero the old location of the last dentry in the last block.

![Non-last block non-last dentry](./assets/direct_non_last_non_last.png)

Once all shifting and operations have been performed with dentries and blocks, the inode matching the dentry is deallocated and returned to the available pool (bitmap).

### Directory Removal

In order to perform directory removal, we rely on the `vvsfs_unlink` operation implemented as detailed in the above section. But before performing an arbitrary unlink
on the dentry matching the directory there are checks needed. Specifically, we need to ensure that the dentry is a directory it is empty, this is done by traversing the dentries within the
directory and verifying that there are none that are reserved. Reserved implies any of the following:

1. Is either a `.` or `..` entry (not supported on disk, so not a problem but checked regardless), in the `..` case, we also verify that the parent inode matches the
inode stored in the dentry.
2. Reseved inode number, specifically `0` as the root.

If any of these checks fail, we return `-ENOTDIR` when not a directory and `-ENOTEMPTY` when it is not empty. Assuming these pass, we forward to the `vvsfs_unlink` call
targetting the dentry associated with the directory to be removed.

## Renaming

Expand Down Expand Up @@ -47,7 +96,56 @@ TODO

## Indirect Blocks

TODO
There are three main areas that need to change to support indirect blocks, listing dentries, adding a new dentry and unlinking a dentry. In the first case of listing dentries,
this is the most straight forward. Instead of previously iterating over all the blocks in `i_data`, we traverse only the first 14 and load the dentries into memory,
then we check if a 15th exists (indicating indirect blocks are present), which is then buffered. Then we perform the same iteration over the block addresses within the
indirect block (via offset using `sizeof(uint32_t) * <iteration count>`). The iteration count (inclusive) is determined by subtracting 15 from the total block count.
We then traverse all dentries within each block, iterating 8 (dentries per block) times per block until the last entry where we use the total dentry cout modulo 8
as the limit. Note that due to the conventions of the code, there will never be a case where the indirect block is allocated with zero block entries within it.

When adding a new dentry, we first calculate the new block position and dentry offset using the following:

```c
uint32_t dentry_count = inode->i_size / VVSFS_DENTRYSIZE;
uint32_t new_dentry_block_pos = dentry_count / VVSFS_N_DENTRY_PER_BLOCK;
uint32_t new_dentry_block_off = dentry_count % VVSFS_N_DENTRY_PER_BLOCK;
```

If the `new_dentry_block_pos` is greater or equal to the current block count, we need to allocate a new block. This is done via `vvsfs_assign_data_block`, which
first determines if we are allocating a direct block, in which case it does and returns the new block address. If we are allocating an indirect block, we first
check if we have an indirect block allocated already, if we don't then it is created. Next we create a new block to store as the first indirect block and put
it's address in the indirect block. Lastly we return the first indirect block address.

If we don't need a new block, we call to `vvsfs_index_data_block` to get retrieve the data block address for the block associated wtih `new_dentry_block_pos`.
After this, we buffer the block, and write the dentry to the offset denoted by `new_dentry_block_off` which is guaranteed to be free, semantically guaranteed
by the logic flow that is.

From here on out, we initialise the dentry with the required data as necessary, name, inode number, etc.

Lastly, unlinking a dentry is a somewhat interesting set of changes. We need to extend the shifting behaviour to work with so-called spatially-disconnected
contiguous arrays. That is, the indirect and direct blocks are continugous notionally, as an array, whereby the indirect blocks require more calculation and
logic to index into. We need to support three main cases for dentry movement using indirect blocks:

1. Direct only (using previous logic)
2. Indirect only, dentry moves between indirect blocks
3. Indirect to direct, dentry moves between indirect and direct blocks.

The first case is straightforward, as we can check the block count, if it is less than 15, we delegate to the old logic. In the second case, we check that the block
index (stored in `struct bufloc_t` passed as an argument from `vvsfs_find_entry`), is greater than or equal to 15, in which case we are only moving dentries within
indirect blocks. From here we apply the same logic as the first case, but operate over indirect blocks instead of direct blocks. In the third case, we need to apply
the same logic from the old direct-only implementation, but buffer both direct and indrect blocks at the same time.

![Indirect to indirect](./assets/indirect_to_indirect.png)

In the case and thirs cases, a situation exists where the only dentry of the last (but not only) indirect block is moved, requiring deallocation of that indirect
block but not the indirect addresses block.

![Indirect to direct](./assets/indirect_to_direct.png)

Again for the second and third cases, one last point of complexity is checking if we are moving the only dentry in the only indirect block to a direct block. In
this case we deallocate the first indirect block and the last direct block (indirect addresses block).

![Indirect last to direct](./assets/indirect_last_to_direct.png)

# Extensions

Expand Down

0 comments on commit 21d8ab6

Please sign in to comment.