# A Lightweight File System Design for Unikernel
## 4 Implementations of ULFS
Each inode maintains file type, size, and location of the block that makes up the actual data of the file as shown in Figure 4. For indicating the locations of file blocks, two bids are maintained in the inode; the first represents the head of data blocks, whereas the second points to a bid block that is an index block to maintain bids of subsequent data blocks. Actually, a bid block does not maintain all bid information of a file directly but is structured as indirect blocks to find the sweet spot between space and performance. As shown in Figure 4, the maximum number of blocks accommodated by a bid block is 1023. A data block corresponding to the logical offset of a file can be quickly searched based on this structure. The file system hierarchy of ULFS is constructed by directories, which maintain file names and inode locations belonging to that directory as a fixed-length data structure. The data block of the root directory is fixed at bid number 2 and can be accessed quickly when referencing files by absolute path. Figure 3: Inode block structures of ULFS. Figure 2: Block allocation based on map blocks in ULFS. The proposed ULFS is similar to an early UNIX file system design [22], so it may be inefficient in complex file access patterns, but such a simple structure has merits in minimizing the operational demands on the file systems, especially for a single application workload. Note that we developed a lightweight file system from scratch, so it is differentiated from existing Unikernels that make use of the general-purpose kernel's file system as is, or simply slim down existing file systems. Before concluding this section, we briefly discuss the trade-offs and limitations of the ULFS design from two perspectives. Firstly, the ULFS presented in this paper represents an optimized file system design tailored for scenarios where a single thread operates within each Unikernel, as illustrated in Figure 5a. Therefore, in instances where multiple threads are active within a Unikernel, as depicted in Figure 5b, ULFS may suffer from race conditions. This limitation arises because ULFS does not implement multi-thread locking, potentially leading to inconsistencies across different threads. Secondly, ULFS is engineered to minimize resource consumption while enhancing I/O performance. This is achieved by streamlining data structures to simplify the size of modes or directory entries through fixed-length configurations. However, this approach might not be as effective against complex workloads. In particular, handling files larger than 4 KB requires the utilization of an indirect indexing block, which could increase latency in data access. Additionally, ULFS implements the POSIX APIs in a very simplified manner, and this simplicity could necessitate a wide range of application modifications or even make integration impossible for applications sensitive to specific file system semantics. For example, among the many fields returned by an fstat call, ULFS only sets st_ino, st_mode, and st_size, opting to default other fields that are typically unnecessary for most applications to ensure faster performance. However, applications sensitive to file ownership information might require considerable porting effort to integrate with ULFS. Thus, integrating with ULFS may pose challenges that require careful consideration for application compatibility. Figure 4: Example of finding a bid for the file offset (4,198,500) through bid blocks. Figure 5: Execution of single thread and multi-threads in each Unikernel. (**a**) Single thread. (**b**) Multi-threads.