Skip to content

Commit 9db28fe

Browse files
committed
Import from internal tree
0 parents  commit 9db28fe

File tree

13 files changed

+1919
-0
lines changed

13 files changed

+1919
-0
lines changed

.clang-format

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
BasedOnStyle: Chromium
2+
Language: Cpp
3+
MaxEmptyLinesToKeep: 3
4+
IndentCaseLabels: false
5+
AllowShortIfStatementsOnASingleLine: false
6+
AllowShortCaseLabelsOnASingleLine: false
7+
AllowShortLoopsOnASingleLine: false
8+
DerivePointerAlignment: false
9+
PointerAlignment: Right
10+
SpaceAfterCStyleCast: true
11+
TabWidth: 4
12+
UseTab: Never
13+
IndentWidth: 4
14+
BreakBeforeBraces: Linux
15+
AccessModifierOffset: -4

.gitignore

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Prerequisites
2+
*.d
3+
4+
# Object files
5+
*.o
6+
*.ko
7+
*.obj
8+
*.elf
9+
10+
# Linker output
11+
*.ilk
12+
*.map
13+
*.exp
14+
15+
# Precompiled Headers
16+
*.gch
17+
*.pch
18+
19+
# Libraries
20+
*.lib
21+
*.a
22+
*.la
23+
*.lo
24+
25+
# Shared objects
26+
*.dll
27+
*.so
28+
*.so.*
29+
*.dylib
30+
31+
# Executables
32+
*.exe
33+
*.out
34+
*.app
35+
*.i*86
36+
*.x86_64
37+
*.hex
38+
mkfs.simplefs
39+
40+
# Debug files
41+
*.dSYM/
42+
*.su
43+
*.idb
44+
*.pdb
45+
46+
# Kernel Module Compile Results
47+
*.mod*
48+
*.cmd
49+
.tmp_versions/
50+
modules.order
51+
Module.symvers
52+
Mkfile.old
53+
dkms.conf
54+
55+
# Other
56+
test.img

LICENSE

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
simplefs is freely redistributable under the two-clause BSD License:
2+
3+
Copyright (C) 2020 National Cheng Kung University, Taiwan.
4+
All rights reserved.
5+
6+
Redistribution and use in source and binary forms, with or without
7+
modification, are permitted provided that the following conditions
8+
are met:
9+
10+
1. Redistributions of source code must retain the above copyright notice,
11+
this list of conditions and the following disclaimer.
12+
2. Redistributions in binary form must reproduce the above copyright notice,
13+
this list of conditions and the following disclaimer in the documentation
14+
and/or other materials provided with the distribution.
15+
16+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19+
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
20+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26+
THE POSSIBILITY OF SUCH DAMAGE.

Makefile

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
obj-m += simplefs.o
2+
simplefs-objs := fs.o super.o inode.o file.o dir.o
3+
4+
KDIR ?= /lib/modules/$(shell uname -r)/build
5+
6+
MKFS = mkfs.simplefs
7+
8+
all: $(MKFS)
9+
make -C $(KDIR) M=$(PWD) modules
10+
11+
IMAGE ?= test.img
12+
IMAGESIZE ?= 50
13+
14+
$(MKFS): mkfs.c
15+
$(CC) -Wall -o $@ $<
16+
17+
$(IMAGE): $(MKFS)
18+
dd if=/dev/zero of=${IMAGE} bs=1M count=${IMAGESIZE}
19+
./$< $(IMAGE)
20+
21+
clean:
22+
make -C $(KDIR) M=$(PWD) clean
23+
rm -f *~ $(PWD)/*.ur-safe
24+
rm -f $(MKFS) $(IMAGE)
25+
26+
.PHONY: all clean

README.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# simplefs - a simple file system for Linux
2+
3+
The file system "simplefs" is helpful to understand Linux VFS and file system basics.
4+
The Linux VFS supports multiple file systems. The kernel does most of the work while the file system specific tasks are delegated to the individual file systems through the handlers. Instead of calling the functions directly the kernel uses various Operation Tables, which are a collection of handlers for each operation (these are actually structures of function pointers for each handlers/callbacks).
5+
6+
The super block operations are set at the time of mounting. The operation tables for inodes and files are set when the inode is opened. The first step before opening an inode is lookup. The inode of a file is looked up by calling the lookup handler of the parent inode.
7+
8+
## Current features
9+
10+
* Directories: create, remove, list, rename;
11+
* Regular files: create, remove, read/write (through page cache), rename;
12+
* No extended attribute support
13+
14+
## Build and Run
15+
16+
You can build the kernel module and tool with `make`.
17+
Generate test image via `make test.img`, which creates a zeroed file of 50 MiB.
18+
19+
You can then mount this image on a system with the simplefs kernel module installed.
20+
```shell
21+
sudo insmod simplefs.ko
22+
mkdir -p test
23+
sudo mount -o loop -t simplefs test.img test
24+
sudo umount test
25+
sudo rmmod simplefs
26+
```
27+
28+
## Design
29+
30+
At present, simplefs only provides straightforward features.
31+
32+
### Partition layout
33+
```
34+
+------------+-------------+-------------------+-------------------+-------------+
35+
| superblock | inode store | inode free bitmap | block free bitmap | data blocks |
36+
+------------+-------------+-------------------+-------------------+-------------+
37+
```
38+
Each block is 4 KiB large.
39+
40+
### Superblock
41+
The superblock is the first block of the partition (block 0). It contains the partition's metadata, such as the number of blocks, number of inodes, number of free inodes/blocks, ...
42+
43+
### Inode store
44+
Contains all the inodes of the partition. The maximum number of inodes is equal to the number of blocks of the partition. Each inode contains 40 B of data: standard data such as file size and number of used blocks, as well as a simplefs-specific field called `index_block`. This block contains:
45+
- for a directory: the list of files in this directory. A directory can contain at most 128 files, and filenames are limited to 28 characters to fit in a single block.
46+
```
47+
inode
48+
+-----------------------+
49+
| i_mode = IFDIR | 0755 | block 123
50+
| index_block = 123 ----|--------> +-----------+
51+
| i_size = 4 KiB | 0 | 24 (foo) |
52+
| i_blockcs = 1 | |-----------|
53+
+-----------------------+ 1 | 45 (bar) |
54+
|-----------|
55+
...
56+
|-----------|
57+
127 | 0 |
58+
+-----------+
59+
```
60+
- for a file: the list of blocks containing the actual data of this file. Since block IDs are stored as 32-bit values, at most 1024 links fit in a single block, limiting the size of a file to 4 MiB.
61+
````
62+
inode block 94
63+
+-----------------------+ +--------+
64+
| i_mode = IFDIR | 0644 | block 93 | | block 99
65+
| index_block =93 ----|--------> +---------+ | | +--------+
66+
| i_size = 10 KiB | 0 | 94 ---|-----> +--------+ | |
67+
| i_blockcs = 4 | |---------| | |
68+
+-----------------------+ 1 | 99 ---|------------------> +--------+
69+
|---------|
70+
2 | 66 ---|-----> block 66
71+
|---------| +--------+
72+
... | |
73+
|---------| | |
74+
127 | 0 | +--------+
75+
+---------+
76+
```
77+
78+
## TODO
79+
- support for extents
80+
- hard/symbolic link
81+
- journalling support
82+
83+
## License
84+
85+
`simplefs` is released under the BSD 2 clause license. Use of this source code is governed by
86+
a BSD-style license that can be found in the LICENSE file.

bitmap.h

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#ifndef SIMPLEFS_BITMAP_H
2+
#define SIMPLEFS_BITMAP_H
3+
4+
#include <linux/bitmap.h>
5+
#include "simplefs.h"
6+
7+
/*
8+
* Return the first free bit (set to 1) in a given in-memory bitmap spanning
9+
* over multiple blocks and clear it.
10+
* Return 0 if no free bit found (we assume that the first bit is never free
11+
* because of the superblock and the root inode, thus allowing us to use 0 as an
12+
* error value).
13+
*/
14+
static inline uint32_t get_first_free_bit(unsigned long *freemap,
15+
unsigned long size)
16+
{
17+
uint32_t ino = find_first_bit(freemap, size);
18+
if (ino == size)
19+
return 0;
20+
21+
bitmap_clear(freemap, ino, 1);
22+
23+
return ino;
24+
}
25+
26+
/*
27+
* Return an unused inode number and mark it used.
28+
* Return 0 if no free inode was found.
29+
*/
30+
static inline uint32_t get_free_inode(struct simplefs_sb_info *sbi)
31+
{
32+
uint32_t ret = get_first_free_bit(sbi->ifree_bitmap, sbi->nr_inodes);
33+
if (ret)
34+
sbi->nr_free_inodes--;
35+
return ret;
36+
}
37+
38+
/*
39+
* Return an unused block number and mark it used.
40+
* Return 0 if no free block was found.
41+
*/
42+
static inline uint32_t get_free_block(struct simplefs_sb_info *sbi)
43+
{
44+
uint32_t ret = get_first_free_bit(sbi->bfree_bitmap, sbi->nr_blocks);
45+
if (ret)
46+
sbi->nr_free_blocks--;
47+
return ret;
48+
}
49+
50+
/*
51+
* Mark the i-th bit in freemap as free (i.e. 1)
52+
*/
53+
static inline int put_free_bit(unsigned long *freemap,
54+
unsigned long size,
55+
uint32_t i)
56+
{
57+
/* i is greater than freemap size */
58+
if (i > size)
59+
return -1;
60+
61+
bitmap_set(freemap, i, 1);
62+
63+
return 0;
64+
}
65+
66+
/*
67+
* Mark an inode as unused.
68+
*/
69+
static inline void put_inode(struct simplefs_sb_info *sbi, uint32_t ino)
70+
{
71+
if (put_free_bit(sbi->ifree_bitmap, sbi->nr_inodes, ino))
72+
return;
73+
74+
sbi->nr_free_inodes++;
75+
}
76+
77+
/*
78+
* Mark a block as unused.
79+
*/
80+
static inline void put_block(struct simplefs_sb_info *sbi, uint32_t bno)
81+
{
82+
if (put_free_bit(sbi->bfree_bitmap, sbi->nr_blocks, bno))
83+
return;
84+
85+
sbi->nr_free_blocks++;
86+
}
87+
88+
#endif /* SIMPLEFS_BITMAP_H */

dir.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#define pr_fmt(fmt) "simplefs: " fmt
2+
3+
#include <linux/buffer_head.h>
4+
#include <linux/fs.h>
5+
#include <linux/kernel.h>
6+
#include <linux/module.h>
7+
8+
#include "simplefs.h"
9+
10+
/*
11+
* Iterate over the files contained in dir and commit them in ctx.
12+
* This function is called by the VFS while ctx->pos changes.
13+
* Return 0 on success.
14+
*/
15+
static int simplefs_iterate(struct file *dir, struct dir_context *ctx)
16+
{
17+
struct inode *inode = file_inode(dir);
18+
struct simplefs_inode_info *ci = SIMPLEFS_INODE(inode);
19+
struct super_block *sb = inode->i_sb;
20+
struct buffer_head *bh = NULL;
21+
struct simplefs_dir_block *dblock = NULL;
22+
struct simplefs_file *f = NULL;
23+
int i;
24+
25+
/* Check that dir is a directory */
26+
if (!S_ISDIR(inode->i_mode))
27+
return -ENOTDIR;
28+
29+
/*
30+
* Check that ctx->pos is not bigger than what we can handle (including
31+
* . and ..)
32+
*/
33+
if (ctx->pos > SIMPLEFS_MAX_SUBFILES + 2)
34+
return 0;
35+
36+
/* Commit . and .. to ctx */
37+
if (!dir_emit_dots(dir, ctx))
38+
return 0;
39+
40+
/* Read the directory index block on disk */
41+
bh = sb_bread(sb, ci->index_block);
42+
if (!bh)
43+
return -EIO;
44+
dblock = (struct simplefs_dir_block *) bh->b_data;
45+
46+
/* Iterate over the index block and commit subfiles */
47+
for (i = ctx->pos - 2; i < SIMPLEFS_MAX_SUBFILES; i++) {
48+
f = &dblock->files[i];
49+
if (!f->inode)
50+
break;
51+
if (!dir_emit(ctx, f->filename, SIMPLEFS_FILENAME_LEN, f->inode,
52+
DT_UNKNOWN))
53+
break;
54+
ctx->pos++;
55+
}
56+
57+
brelse(bh);
58+
59+
return 0;
60+
}
61+
62+
const struct file_operations simplefs_dir_ops = {
63+
.owner = THIS_MODULE,
64+
.iterate_shared = simplefs_iterate,
65+
};

0 commit comments

Comments
 (0)