diff --git a/fs/hmfs/Makefile b/fs/hmfs/Makefile new file mode 100644 index 00000000..11542ca4 --- /dev/null +++ b/fs/hmfs/Makefile @@ -0,0 +1,20 @@ +ccflags-y += -DCONFIG_HMFS_DEBUG +ccflags-y += -DCONFIG_HMFS_DEBUG_GC +ccflags-y += -DCONFIG_HMFS_XATTR +#ccflags-y += -DCONFIG_HMFS_FAST_READ +ccflags-y += -DCONFIG_HMFS_ACL +ccflags-y += -DCONFIG_HMFS_DEBUG_RW_LOCK + +obj-m += hmfs.o + +hmfs-objs := super.o node.o inode.o checkpoint.o file.o data.o namei.o segment.o hash.o dir.o symlink.o gc.o recovery.o + +hmfs-objs += debug.o +hmfs-objs += xattr.o +hmfs-objs += util.o +hmfs-objs += acl.o + +all: + make -C /lib/modules/`uname -r`/build M=`pwd` modules +clean: + make -C /lib/modules/`uname -r`/build M=`pwd` clean diff --git a/fs/hmfs/build.sh b/fs/hmfs/build.sh new file mode 100755 index 00000000..ea169ef6 --- /dev/null +++ b/fs/hmfs/build.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +if [ "$1" == "hmfs" ] + then + insmod ./hmfs.ko + sudo mount -t hmfs -o physaddr=0x4B000000,init=100M none ~/mount_hmfs/ +elif [ "$1" == "nohmfs" ] + then + umount ~/mount_hmfs + rmmod hmfs +fi \ No newline at end of file diff --git a/fs/hmfs/checkpoint.c b/fs/hmfs/checkpoint.c index 3a6a0cf4..54838fe1 100644 --- a/fs/hmfs/checkpoint.c +++ b/fs/hmfs/checkpoint.c @@ -624,8 +624,8 @@ static int flush_orphan_inodes(struct hmfs_sb_info *sbi, block_t *orphan_addrs) orphan_addrs[i++] = orphan_addr; orphan_block = ADDR(sbi, orphan_addr); /* Reseverd for checkpoint address */ - orphan_block = (__le32 *)JUMP(orphan_block, sizeof(__le64)); end = (__le32 *)JUMP(orphan_block, HMFS_PAGE_SIZE); + orphan_block = (__le32 *)JUMP(orphan_block, sizeof(__le64)); } *orphan_block = cpu_to_le32(entry->ino); orphan_block++; diff --git a/fs/hmfs/debug.c b/fs/hmfs/debug.c index f85e286c..c56fd5ae 100644 --- a/fs/hmfs/debug.c +++ b/fs/hmfs/debug.c @@ -92,6 +92,8 @@ static int stat_show(struct seq_file *s, void *v) seq_printf(s, "main area range:%lu - %lu\n", (unsigned long)si->sbi->main_addr_start, (unsigned long)si->sbi->main_addr_end); + seq_printf(s, "GC Logs Segment Number:%lu\n", GET_SEGNO(si->sbi, + L_ADDR(si->sbi, si->sbi->gc_logs))); seq_printf(s, "max file size:%luk %luM %luG\n", max_file_size / 1024, max_file_size / 1024 / 1024, max_file_size / 1024 / 1024 / 1024); @@ -129,13 +131,25 @@ static int stat_show(struct seq_file *s, void *v) return 0; } +static char get_segment_state(struct hmfs_sb_info *sbi, seg_t i) +{ + struct free_segmap_info *free_i = FREE_I(sbi); + struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); + + if (test_bit(i, dirty_i->dirty_segmap)) + return '*'; + else if (!test_bit(i, free_i->free_segmap)) + return '#'; + else if (test_bit(i, free_i->prefree_segmap)) + return '^'; + else return '@'; +} + static int vb_show(struct seq_file *s, void *v) { struct hmfs_stat_info *si = s->private; struct hmfs_sb_info *sbi = si->sbi; int i, j; - struct free_segmap_info *free_i = FREE_I(sbi); - struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); seq_printf(s, "# free\n* dirty\n^ prefree\n@ in use\n"); for (i = 0, j = 0; i < TOTAL_SEGS(sbi); i++, j++) { @@ -143,21 +157,13 @@ static int vb_show(struct seq_file *s, void *v) seq_printf(s, "\n"); j = 0; } - if (test_bit(i, dirty_i->dirty_segmap)) - seq_printf(s, "*"); - else if (!test_bit(i, free_i->free_segmap)) - seq_printf(s, "#"); - else if (test_bit(i, free_i->prefree_segmap)) - seq_printf(s, "^"); - else seq_printf(s, "@"); + seq_printf(s, "%c", get_segment_state(sbi, i)); } seq_printf(s, "\n"); for (i = 0; i < TOTAL_SEGS(sbi); i++) { - seq_printf(s, "%d:%d %lu\n", i, get_valid_blocks(sbi, i), - get_seg_vblocks_in_summary(sbi, i)); - hmfs_bug_on(sbi, get_valid_blocks(sbi, i) != - get_seg_vblocks_in_summary(sbi, i)); + seq_printf(s, "%d(%c):%d %lu\n", i, get_segment_state(sbi, i), + get_valid_blocks(sbi, i), get_seg_vblocks_in_summary(sbi, i)); } return 0; @@ -206,7 +212,7 @@ static ssize_t info_read(struct file *file, char __user * buffer, size_t count, if (count + *ppos > si->buf_size) count = si->buf_size - *ppos; - if (copy_to_user(buffer, si->buffer, count)) { + if (copy_to_user(buffer, si->buffer + *ppos, count)) { return -EFAULT; } @@ -497,8 +503,7 @@ static size_t print_ssa_one(struct hmfs_sb_info *sbi, block_t blk_addr) } sum_entry = get_summary_by_addr(sbi, blk_addr); - - len += hmfs_print(si, 1, "-- [%016x] --\n", blk_addr >> HMFS_PAGE_SIZE_BITS); + len += hmfs_print(si, 1, "-- [%d %d] --\n", GET_SEGNO(sbi, blk_addr), GET_SEG_OFS(sbi, blk_addr)); len += hmfs_print(si, 1, " nid: %u\n", le32_to_cpu(sum_entry->nid)); len += hmfs_print(si, 1, " start_version: %u\n", le32_to_cpu(sum_entry->start_version)); diff --git a/fs/hmfs/dir.c b/fs/hmfs/dir.c index 0fa2399d..672d8d93 100644 --- a/fs/hmfs/dir.c +++ b/fs/hmfs/dir.c @@ -692,7 +692,6 @@ void hmfs_delete_entry(struct hmfs_dir_entry *dentry, /* Inline directory should never reach here */ hmfs_bug_on(sbi, is_inline_inode(dir)); - hmfs_dbg("%d\n",bidx); dir_i_size = i_size_read(dir); truncate_hole(dir, bidx, bidx + 1); if (dir_i_size >> HMFS_PAGE_SIZE_BITS == bidx + 1) { diff --git a/fs/hmfs/file.c b/fs/hmfs/file.c index 71eeb991..92e13de0 100644 --- a/fs/hmfs/file.c +++ b/fs/hmfs/file.c @@ -750,6 +750,7 @@ int truncate_data_blocks_range(struct dnode_of_data *dn, int count) new_node->i.i_addr[ofs] = NULL_ADDR; } + if (nr_free) { dec_valid_block_count(sbi, dn->inode, nr_free); mark_inode_dirty(dn->inode); diff --git a/fs/hmfs/gc.c b/fs/hmfs/gc.c index ee2ad3c9..3845bfc2 100644 --- a/fs/hmfs/gc.c +++ b/fs/hmfs/gc.c @@ -462,9 +462,8 @@ static void move_orphan_block(struct hmfs_sb_info *sbi, seg_t src_segno, block_t cp_addr; prepare_move_argument(&args, sbi, src_segno, src_off, src_sum, TYPE_NODE); - hmfs_cp = args.cp_i->cp; - cp_addr = le64_to_cpu(hmfs_cp->orphan_addrs[get_summary_offset(src_sum)]); - hmfs_bug_on(sbi, cp_addr != L_ADDR(args.src)); + cp_addr = le64_to_cpu(*((__le64 *)args.src)); + hmfs_cp = ADDR(sbi, cp_addr); hmfs_cp->orphan_addrs[get_summary_offset(src_sum)] = cpu_to_le64(args.dest_addr); @@ -514,7 +513,6 @@ static void garbage_collect(struct hmfs_sb_info *sbi, seg_t segno) nid_t nid; struct hmfs_summary_block *sum_blk; struct hmfs_summary *sum; - int tmp=0; none_valid = !get_seg_entry(sbi, segno)->valid_blocks; @@ -524,9 +522,10 @@ static void garbage_collect(struct hmfs_sb_info *sbi, seg_t segno) sum_blk = get_summary_block(sbi, segno); sum = sum_blk->entries; + //#ERROR: inconsistent of segno->valid_blocks for (off = 0; off < HMFS_PAGE_PER_SEG; ++off, sum++) { is_current = get_summary_start_version(sum) == cm_i->new_version; - + /* * We ignore two kinds of blocks: * - invalid blocks in older version @@ -537,12 +536,12 @@ static void garbage_collect(struct hmfs_sb_info *sbi, seg_t segno) if (is_current) { nid = get_summary_nid(sum); - if (IS_ERR(get_node(sbi, nid))) + if (IS_ERR(get_node(sbi, nid))){ continue; + } } hmfs_bug_on(sbi, get_summary_valid_bit(sum) && is_current); - switch (get_summary_type(sum)) { case SUM_TYPE_DATA: move_data_block(sbi, segno, off, sum); @@ -574,7 +573,6 @@ static void garbage_collect(struct hmfs_sb_info *sbi, seg_t segno) } } - hmfs_dbg("tmp:%d\n",tmp); recycle: recycle_segment(sbi, segno, none_valid); } diff --git a/fs/hmfs/namei.c b/fs/hmfs/namei.c index 14cd0dfa..fcfef6ba 100644 --- a/fs/hmfs/namei.c +++ b/fs/hmfs/namei.c @@ -238,7 +238,7 @@ static int hmfs_unlink(struct inode *dir, struct dentry *dentry) inode_write_unlock(dir); mutex_unlock_op(sbi, ilock); - mark_inode_dirty(inode); + mark_inode_dirty(dir); fail: return err; } diff --git a/fs/hmfs/node.c b/fs/hmfs/node.c index 6327a4a4..e93b7fad 100644 --- a/fs/hmfs/node.c +++ b/fs/hmfs/node.c @@ -1206,6 +1206,7 @@ static int __flush_nat_journals(struct hmfs_checkpoint *hmfs_cp, nat_journal = &hmfs_cp->nat_journals[*journal_pos]; + *journal_pos = *journal_pos + nr_dirty_nat; while (nr_dirty_nat > 0) { entry = list_entry(entry->list.prev, struct nat_entry, list); nat_journal->nid = cpu_to_le32(entry->ni.nid); @@ -1215,7 +1216,6 @@ static int __flush_nat_journals(struct hmfs_checkpoint *hmfs_cp, nat_journal++; entry->ni.flag |= NAT_FLAG_JOURNAL; } - *journal_pos = *journal_pos + nr_dirty_nat; return 0; } @@ -1482,6 +1482,7 @@ static void __mark_block_valid(struct hmfs_sb_info *sbi, return; } + set_summary_valid_bit(raw_summary); //leaf, alloc & copy nat entry block if (!height) { hmfs_bug_on(sbi, get_summary_type(raw_summary) != SUM_TYPE_NATD); diff --git a/fs/hmfs/segment.c b/fs/hmfs/segment.c index 46218ec1..bddcf4cf 100644 --- a/fs/hmfs/segment.c +++ b/fs/hmfs/segment.c @@ -6,6 +6,9 @@ * it fall into space where we have actually writen data * into. It's different from valid bits in summary entry */ + /* + * Hi,everybody,this is a test from caihui + */ bool is_valid_address(struct hmfs_sb_info *sbi, block_t addr) { seg_t segno = GET_SEGNO(sbi, addr); @@ -183,7 +186,7 @@ int get_new_segment(struct hmfs_sb_info *sbi, seg_t *newseg) hmfs_bug_on(sbi, test_bit(segno, free_i->free_segmap)); __set_inuse(sbi, segno); *newseg = segno; - /* Need to clear SSA */ + /* TODO: Need not to clear SSA */ ssa = get_summary_block(sbi, segno); memset_nt(ssa, 0, HMFS_SUMMARY_BLOCK_SIZE); unlock: @@ -479,6 +482,7 @@ void free_prefree_segments(struct hmfs_sb_info *sbi) int total_segs = TOTAL_SEGS(sbi); unsigned long *bitmap = free_i->prefree_segmap; seg_t segno = 0; + void *ssa; lock_write_segmap(free_i); while (1) { @@ -489,6 +493,8 @@ void free_prefree_segments(struct hmfs_sb_info *sbi) if (test_and_clear_bit(segno, free_i->free_segmap)) { free_i->free_segments++; } + ssa = get_summary_block(sbi, segno); + memset_nt(ssa, 0, HMFS_SUMMARY_BLOCK_SIZE); segno++; } unlock_write_segmap(free_i); diff --git a/fs/hmfs/test/create.sh b/fs/hmfs/test/create.sh new file mode 100755 index 00000000..84d00e16 --- /dev/null +++ b/fs/hmfs/test/create.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +num_file=2048 + +#create testing files, they will be orphan files later +for ((i=0; i<$num_file; i++)); do + touch ~/mount_hmfs/orphan_$i.txt + echo "this is a test file" > ~/mount_hmfs/orphan_$i.txt +done + +echo "$num_file files created..." \ No newline at end of file diff --git a/fs/hmfs/test/delete.sh b/fs/hmfs/test/delete.sh new file mode 100755 index 00000000..2981095f --- /dev/null +++ b/fs/hmfs/test/delete.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +num_file=2048 +for ((i=0; i<$num_file; i++)); do + #remove the file will create an orhan file + rm ~/mount_hmfs/orphan_$i.txt +done + +echo "$num_file files deleted..." + +#check the cmi info +. ./info.sh "cmi" + +#sync the file to enforce doing checkpoint +sync diff --git a/fs/hmfs/test/hold_file_open.py b/fs/hmfs/test/hold_file_open.py new file mode 100644 index 00000000..43401372 --- /dev/null +++ b/fs/hmfs/test/hold_file_open.py @@ -0,0 +1,14 @@ +#!/usr/bin/python3 +from os.path import expanduser + + +home = expanduser('~') +file_list = [] +for i in range(2048): + with open(home + "/mount_hmfs/orphan_{:d}.txt".format(i), 'w') as file: + file_list.append(file) + file.write("ssssssssssssssssssss") + +#hold files +while True: + pass diff --git a/fs/hmfs/test/info.sh b/fs/hmfs/test/info.sh new file mode 100755 index 00000000..6d24a2ed --- /dev/null +++ b/fs/hmfs/test/info.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +hmfs_debug_dir=/sys/kernel/debug/hmfs/1258291200/info +echo "$1" > ${hmfs_debug_dir} & cat ${hmfs_debug_dir} \ No newline at end of file diff --git a/fs/hmfs/test/mount_f2fs.sh b/fs/hmfs/test/mount_f2fs.sh new file mode 100755 index 00000000..f1d13e91 --- /dev/null +++ b/fs/hmfs/test/mount_f2fs.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# create a 100M file +dd if=/dev/zero of=/opt/dev0-backstore bs=1M count=100 + +# create the loopback block device +mknod /dev/fake-dev0 b 7 200 + +losetup /dev/fake-dev0 /opt/dev0-backstore +mount -t f2fs /dev/fake-dev0 ~/mount_f2fs/ \ No newline at end of file diff --git a/fs/hmfs/test/open.c b/fs/hmfs/test/open.c new file mode 100644 index 00000000..d2cd40e5 --- /dev/null +++ b/fs/hmfs/test/open.c @@ -0,0 +1,17 @@ +#include +#include + +int main(void) +{ + FILE* fps[2048]; + char filename[100]; + for (int i = 0; i < 2048; i++) { + sprintf(filename, "/home/wgtdkp/mount_hmfs/orphan_%d.txt", i); + printf("%s\n", filename); + fps[i] = fopen(filename, "r"); + if (!fps[i]) + printf("error!\n"); + } + while (1) {} + return 0; +} \ No newline at end of file diff --git a/fs/hmfs/test/orphan_test.sh b/fs/hmfs/test/orphan_test.sh new file mode 100755 index 00000000..e4105941 --- /dev/null +++ b/fs/hmfs/test/orphan_test.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +num_file=2048 +cd ~/mount_hmfs/ + +#create testing files, they will be orphan files later +for ((i=0; i<$num_file; i++)); do + touch orphan_$i.txt + echo "this is a test file" > orphan_$i.txt +done + +echo ${num_file} "file created" + +#python3 $HOME/hmfs/fs/hmfs/test/hold_file_open.py & + +#for ((i=0; i<$num_file; i++)); do + #remove the file will create an orhan file +# rm orphan_$i.txt +#done + +#cd $HOME/hmfs/fs/hmfs/test/ +#check the cmi info +#. ./info.sh "cmi" + +#sync the file to enforce doing checkpoint +#sync + + + + + diff --git a/fs/hmfs/test/reproduce.sh b/fs/hmfs/test/reproduce.sh new file mode 100755 index 00000000..db99fe55 --- /dev/null +++ b/fs/hmfs/test/reproduce.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +cd $HOME/hmfs/fs/hmfs/test/ + +. ./create.sh +. ./delete.sh +. ./create.sh +. ./delete.sh +. ./create.sh +#. ./delete.sh