Re: [f2fs-dev] [PATCH v2 7/7] f2fs: should check the remaining dentry bits
Change log from v1: o remove wron f2fs_bug_on() >From 545c0c9055b0d8dc5d134d9340b3cd80eeecdafa Mon Sep 17 00:00:00 2001 From: Jaegeuk KimDate: Mon, 25 Apr 2016 14:24:44 -0700 Subject: [PATCH] f2fs: should check the remaining dentry bits Let's consider a race condition between f2fs_add_regular_entry and find_target_dentry. 1. - f2fs_add_regular_entry updated len: 24 first. | Bits: 0 0 0 1 Lens: 24 0 0 3 (name: foo) |-> - find_target_dentry checks the first bit to find "foo", then ++pointer. 2. - f2fs_add_regular_entry updates bits. |>|>| Bits: 1 1 1 1 Lens: 24 0 0 3 (name: foo) | - find_target_dentry is checking second bit, but it's len is zero, which makes the process being terminated. In this case, user can add additional dentry named "foo" accordingly. This patch enables to check the remaining bits. Signed-off-by: He YunLei Signed-off-by: Jaegeuk Kim --- fs/f2fs/dir.c | 12 +++- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index e90380d..0ad7b9a 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -100,12 +100,6 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page, *res_page = dentry_page; else kunmap(dentry_page); - - /* -* For the most part, it should be a bug when name_len is zero. -* We stop here for figuring out where the bugs has occurred. -*/ - f2fs_bug_on(F2FS_P_SB(dentry_page), d.max < 0); return de; } @@ -149,9 +143,9 @@ struct f2fs_dir_entry *find_target_dentry(struct fscrypt_name *fname, /* remain bug on condition */ if (unlikely(!de->name_len)) - d->max = -1; - - bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); + bit_pos++; + else + bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); } de = NULL; -- 2.6.3 -- Find and fix application performance issues faster with Applications Manager Applications Manager provides deep performance insights into multiple tiers of your business applications. It resolves application problems quickly and reduces your MTTR. Get your free trial! https://ad.doubleclick.net/ddm/clk/302982198;130105516;z ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH 1/3] resize.f2fs: support to expand partition size
hi, kim On 2016/4/26 8:28, Jaegeuk Kim wrote: > Now user can expand existing partition with resize.f2fs. > Currently, it doesn't support shrink an image. > > For example, > # resize.f2fs -t [# of sectors] [image] > > Signed-off-by: Jaegeuk Kim> --- > fsck/Makefile.am | 4 +- > fsck/f2fs.h | 4 +- > fsck/fsck.h | 2 + > fsck/main.c | 64 ++ > fsck/resize.c | 578 > ++ > include/f2fs_fs.h | 17 ++ > man/Makefile.am | 2 +- > man/defrag.f2fs.8 | 3 +- > man/dump.f2fs.8 | 3 +- > man/fsck.f2fs.8 | 3 +- > man/mkfs.f2fs.8 | 3 +- > man/resize.f2fs.8 | 49 + > 12 files changed, 724 insertions(+), 8 deletions(-) > create mode 100644 fsck/resize.c > create mode 100644 man/resize.f2fs.8 > > diff --git a/fsck/Makefile.am b/fsck/Makefile.am > index 73df884..3586625 100644 > --- a/fsck/Makefile.am > +++ b/fsck/Makefile.am > @@ -3,9 +3,11 @@ > AM_CPPFLAGS = ${libuuid_CFLAGS} -I$(top_srcdir)/include > AM_CFLAGS = -Wall > sbin_PROGRAMS = fsck.f2fs > -fsck_f2fs_SOURCES = main.c fsck.c dump.c mount.c defrag.c f2fs.h fsck.h > $(top_srcdir)/include/f2fs_fs.h > +fsck_f2fs_SOURCES = main.c fsck.c dump.c mount.c defrag.c f2fs.h fsck.h > $(top_srcdir)/include/f2fs_fs.h \ > + resize.c > fsck_f2fs_LDADD = ${libuuid_LIBS} $(top_builddir)/lib/libf2fs.la > > install-data-hook: > ln -sf fsck.f2fs $(DESTDIR)/$(sbindir)/dump.f2fs > ln -sf fsck.f2fs $(DESTDIR)/$(sbindir)/defrag.f2fs > + ln -sf fsck.f2fs $(DESTDIR)/$(sbindir)/resize.f2fs > diff --git a/fsck/f2fs.h b/fsck/f2fs.h > index a618b47..4b3c666 100644 > --- a/fsck/f2fs.h > +++ b/fsck/f2fs.h > @@ -323,9 +323,9 @@ static inline block_t sum_blk_addr(struct f2fs_sb_info > *sbi, int base, int type) > #define segno_in_journal(jnl, i)(jnl->sit_j.entries[i].segno) > > #define SIT_ENTRY_OFFSET(sit_i, segno) \ > - (segno % sit_i->sents_per_block) > + ((segno) % sit_i->sents_per_block) > #define SIT_BLOCK_OFFSET(sit_i, segno) \ > - (segno / SIT_ENTRY_PER_BLOCK) > + ((segno) / SIT_ENTRY_PER_BLOCK) > #define TOTAL_SEGS(sbi) (SM_I(sbi)->main_segments) > > static inline bool IS_VALID_NID(struct f2fs_sb_info *sbi, u32 nid) > diff --git a/fsck/fsck.h b/fsck/fsck.h > index 5fc214e..db11b41 100644 > --- a/fsck/fsck.h > +++ b/fsck/fsck.h > @@ -179,4 +179,6 @@ extern int dump_info_from_blkaddr(struct f2fs_sb_info *, > u32); > /* defrag.c */ > int f2fs_defragment(struct f2fs_sb_info *, u64, u64, u64, int); > > +/* resize.c */ > +int f2fs_resize(struct f2fs_sb_info *); > #endif /* _FSCK_H_ */ > diff --git a/fsck/main.c b/fsck/main.c > index 6058c4d..885e2cf 100644 > --- a/fsck/main.c > +++ b/fsck/main.c > @@ -52,6 +52,15 @@ void defrag_usage() > exit(1); > } > > +void resize_usage() > +{ > + MSG(0, "\nUsage: resize.f2fs [options] device\n"); > + MSG(0, "[options]:\n"); > + MSG(0, " -d debug level [default:0]\n"); > + MSG(0, " -t target sectors [default: device size]\n"); > + exit(1); > +} > + > void f2fs_parse_options(int argc, char *argv[]) > { > int option = 0; > @@ -203,6 +212,34 @@ void f2fs_parse_options(int argc, char *argv[]) > } > ASSERT(ret >= 0); > } > + } else if (!strcmp("resize.f2fs", prog)) { > + const char *option_string = "d:t:"; > + > + config.func = RESIZE; > + while ((option = getopt(argc, argv, option_string)) != EOF) { > + int ret = 0; > + > + switch (option) { > + case 'd': > + config.dbg_lv = atoi(optarg); > + MSG(0, "Info: Debug level = %d\n", > + config.dbg_lv); > + break; > + case 't': > + if (strncmp(optarg, "0x", 2)) > + ret = sscanf(optarg, "%"PRIu64"", > + _sectors); > + else > + ret = sscanf(optarg, "%"PRIx64"", > + _sectors); > + break; > + default: > + MSG(0, "\tError: Unknown option %c\n", option); > + resize_usage(); > + break; > + } > + ASSERT(ret >= 0); > + } > } > > if ((optind + 1) != argc) { > @@ -213,6 +250,8 @@ void f2fs_parse_options(int argc, char *argv[]) > dump_usage(); > else if (config.func == DEFRAG) > defrag_usage(); > +
[f2fs-dev] [PATCH] fsck.f2fs: remove duplicated codes in sanity_check_raw_super
Remove duplicated codes in sanity_check_raw_super(). Signed-off-by: Junling Zheng--- fsck/mount.c | 4 1 file changed, 4 deletions(-) diff --git a/fsck/mount.c b/fsck/mount.c index 4bde179..f866c4f 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -376,10 +376,6 @@ int sanity_check_raw_super(struct f2fs_super_block *sb, u64 offset) if (get_sb(log_blocks_per_seg) != 9) return -1; - if (get_sb(log_sectorsize) > F2FS_MAX_LOG_SECTOR_SIZE || - get_sb(log_sectorsize) < F2FS_MIN_LOG_SECTOR_SIZE) - return -1; - /* Currently, support 512/1024/2048/4096 bytes sector size */ if (get_sb(log_sectorsize) > F2FS_MAX_LOG_SECTOR_SIZE || get_sb(log_sectorsize) < F2FS_MIN_LOG_SECTOR_SIZE) -- 1.9.1 -- Find and fix application performance issues faster with Applications Manager Applications Manager provides deep performance insights into multiple tiers of your business applications. It resolves application problems quickly and reduces your MTTR. Get your free trial! https://ad.doubleclick.net/ddm/clk/302982198;130105516;z ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH 1/3] resize.f2fs: support to expand partition size
On 2016/4/26 10:17, Jaegeuk Kim wrote: > Hello, > > ... > >>> + /* ovp / free segments */ >>> + set_cp(overprov_segment_count, config.new_overprovision); >>> + set_cp(rsvd_segment_count, config.new_reserved_segments); >> >> maybe something wrong here: >> set_cp(rsvd_segment_count, config.new_reserved_segments); >> set_cp(overprov_segment_count, (get_newsb(segment_count_main) - >> get_cp(rsvd_segment_count)) * >> config.new_overprovision / 100); >> set_cp(overprov_segment_count, get_cp(overprov_segment_count) + >> get_cp(rsvd_segment_count)); >> > > So, could you illustrate the point? > The new_overprovision and new_reserved_segments were calculated from the > target > partition size. > > Am I missing something? hi, Kim I test the resize and find something wrong with overprov_segment_count, and I find its calculation is different with mkfs tool. So I copy the method of calculation from mkfs tool. Thanks, > > Thanks, > >>> + free_segment_count = get_cp(free_segment_count); >>> + new_segment_count = get_newsb(segment_count_main) - >>> + get_sb(segment_count_main); >>> + >>> + set_cp(free_segment_count, free_segment_count + new_segment_count); >>> + set_cp(user_block_count, ((get_sb(segment_count_main) - >>> + get_cp(overprov_segment_count)) * config.blks_per_seg)); >>> + >>> + if (is_set_ckpt_flags(cp, CP_ORPHAN_PRESENT_FLAG)) >>> + orphan_blks = __start_sum_addr(sbi) - 1; >>> + >>> + set_cp(cp_pack_start_sum, 1 + get_newsb(cp_payload)); >>> + set_cp(cp_pack_total_block_count, 8 + orphan_blks + >>> get_newsb(cp_payload)); >>> + >>> + /* cur->segno - offset */ >>> + for (i = 0; i < NO_CHECK_TYPE; i++) { >>> + if (i < CURSEG_HOT_NODE) { >>> + set_cp(cur_data_segno[i], >>> + CURSEG_I(sbi, i)->segno - offset); >>> + } else { >>> + int n = i - CURSEG_HOT_NODE; >>> + >>> + set_cp(cur_node_segno[n], >>> + CURSEG_I(sbi, i)->segno - offset); >>> + } >>> + } >>> + >>> + /* sit / nat ver bitmap bytesize */ >>> + set_cp(sit_ver_bitmap_bytesize, >>> + ((get_newsb(segment_count_sit) / 2) << >>> + get_newsb(log_blocks_per_seg)) / 8); >>> + set_cp(nat_ver_bitmap_bytesize, >>> + ((get_newsb(segment_count_nat) / 2) << >>> + get_newsb(log_blocks_per_seg)) / 8); >>> + >>> + memcpy(new_cp, cp, (unsigned char *)cp->sit_nat_version_bitmap - >>> + (unsigned char *)cp); >>> + >>> + crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, new_cp, CHECKSUM_OFFSET); >>> + *((__le32 *)((unsigned char *)new_cp + CHECKSUM_OFFSET)) = >>> cpu_to_le32(crc); >>> + >>> + /* Write a new checkpoint in the other set */ >>> + new_cp_blk_no = old_cp_blk_no = get_sb(cp_blkaddr); >>> + if (sbi->cur_cp == 2) >>> + old_cp_blk_no += 1 << get_sb(log_blocks_per_seg); >>> + else >>> + new_cp_blk_no += 1 << get_sb(log_blocks_per_seg); >>> + >>> + /* write first cp */ >>> + ret = dev_write_block(new_cp, new_cp_blk_no++); >>> + ASSERT(ret >= 0); >>> + >>> + memset(buf, 0, BLOCK_SZ); >>> + for (i = 0; i < get_newsb(cp_payload); i++) { >>> + ret = dev_write_block(buf, new_cp_blk_no++); >>> + ASSERT(ret >= 0); >>> + } >>> + >>> + for (i = 0; i < orphan_blks; i++) { >>> + block_t orphan_blk_no = old_cp_blk_no + 1 + get_sb(cp_payload); >>> + >>> + ret = dev_read_block(buf, orphan_blk_no++); >>> + ASSERT(ret >= 0); >>> + >>> + ret = dev_write_block(buf, new_cp_blk_no++); >>> + ASSERT(ret >= 0); >>> + } >>> + >>> + /* update summary blocks having nullified journal entries */ >>> + for (i = 0; i < NO_CHECK_TYPE; i++) { >>> + struct curseg_info *curseg = CURSEG_I(sbi, i); >>> + >>> + ret = dev_write_block(curseg->sum_blk, new_cp_blk_no++); >>> + ASSERT(ret >= 0); >>> + } >>> + >>> + /* write the last cp */ >>> + ret = dev_write_block(new_cp, new_cp_blk_no++); >>> + ASSERT(ret >= 0); >>> + >>> + /* disable old checkpoint */ >>> + memset(buf, 0, BLOCK_SZ); >>> + ret = dev_write_block(buf, old_cp_blk_no); >>> + ASSERT(ret >= 0); >>> + >>> + free(buf); >>> + free(new_cp); >>> + DBG(0, "Info: Done to rebuild checkpoint blocks\n"); >>> +} >>> + >>> +static void rebuild_superblock(struct f2fs_sb_info *sbi, >>> + struct f2fs_super_block *new_sb) >>> +{ >>> + int index, ret; >>> + u_int8_t *buf; >>> + >>> + buf = calloc(BLOCK_SZ, 1); >>> + >>> + memcpy(buf + F2FS_SUPER_OFFSET, new_sb, sizeof(*new_sb)); >>> + for (index = 0; index < 2; index++) { >>> + ret = dev_write_block(buf, index); >>> +
[f2fs-dev] [PATCH 1/3] resize.f2fs: support to expand partition size
Now user can expand existing partition with resize.f2fs. Currently, it doesn't support shrink an image. For example, # resize.f2fs -t [# of sectors] [image] Signed-off-by: Jaegeuk Kim--- fsck/Makefile.am | 4 +- fsck/f2fs.h | 4 +- fsck/fsck.h | 2 + fsck/main.c | 64 ++ fsck/resize.c | 578 ++ include/f2fs_fs.h | 17 ++ man/Makefile.am | 2 +- man/defrag.f2fs.8 | 3 +- man/dump.f2fs.8 | 3 +- man/fsck.f2fs.8 | 3 +- man/mkfs.f2fs.8 | 3 +- man/resize.f2fs.8 | 49 + 12 files changed, 724 insertions(+), 8 deletions(-) create mode 100644 fsck/resize.c create mode 100644 man/resize.f2fs.8 diff --git a/fsck/Makefile.am b/fsck/Makefile.am index 73df884..3586625 100644 --- a/fsck/Makefile.am +++ b/fsck/Makefile.am @@ -3,9 +3,11 @@ AM_CPPFLAGS = ${libuuid_CFLAGS} -I$(top_srcdir)/include AM_CFLAGS = -Wall sbin_PROGRAMS = fsck.f2fs -fsck_f2fs_SOURCES = main.c fsck.c dump.c mount.c defrag.c f2fs.h fsck.h $(top_srcdir)/include/f2fs_fs.h +fsck_f2fs_SOURCES = main.c fsck.c dump.c mount.c defrag.c f2fs.h fsck.h $(top_srcdir)/include/f2fs_fs.h\ + resize.c fsck_f2fs_LDADD = ${libuuid_LIBS} $(top_builddir)/lib/libf2fs.la install-data-hook: ln -sf fsck.f2fs $(DESTDIR)/$(sbindir)/dump.f2fs ln -sf fsck.f2fs $(DESTDIR)/$(sbindir)/defrag.f2fs + ln -sf fsck.f2fs $(DESTDIR)/$(sbindir)/resize.f2fs diff --git a/fsck/f2fs.h b/fsck/f2fs.h index a618b47..4b3c666 100644 --- a/fsck/f2fs.h +++ b/fsck/f2fs.h @@ -323,9 +323,9 @@ static inline block_t sum_blk_addr(struct f2fs_sb_info *sbi, int base, int type) #define segno_in_journal(jnl, i)(jnl->sit_j.entries[i].segno) #define SIT_ENTRY_OFFSET(sit_i, segno) \ - (segno % sit_i->sents_per_block) + ((segno) % sit_i->sents_per_block) #define SIT_BLOCK_OFFSET(sit_i, segno) \ - (segno / SIT_ENTRY_PER_BLOCK) + ((segno) / SIT_ENTRY_PER_BLOCK) #define TOTAL_SEGS(sbi) (SM_I(sbi)->main_segments) static inline bool IS_VALID_NID(struct f2fs_sb_info *sbi, u32 nid) diff --git a/fsck/fsck.h b/fsck/fsck.h index 5fc214e..db11b41 100644 --- a/fsck/fsck.h +++ b/fsck/fsck.h @@ -179,4 +179,6 @@ extern int dump_info_from_blkaddr(struct f2fs_sb_info *, u32); /* defrag.c */ int f2fs_defragment(struct f2fs_sb_info *, u64, u64, u64, int); +/* resize.c */ +int f2fs_resize(struct f2fs_sb_info *); #endif /* _FSCK_H_ */ diff --git a/fsck/main.c b/fsck/main.c index 6058c4d..885e2cf 100644 --- a/fsck/main.c +++ b/fsck/main.c @@ -52,6 +52,15 @@ void defrag_usage() exit(1); } +void resize_usage() +{ + MSG(0, "\nUsage: resize.f2fs [options] device\n"); + MSG(0, "[options]:\n"); + MSG(0, " -d debug level [default:0]\n"); + MSG(0, " -t target sectors [default: device size]\n"); + exit(1); +} + void f2fs_parse_options(int argc, char *argv[]) { int option = 0; @@ -203,6 +212,34 @@ void f2fs_parse_options(int argc, char *argv[]) } ASSERT(ret >= 0); } + } else if (!strcmp("resize.f2fs", prog)) { + const char *option_string = "d:t:"; + + config.func = RESIZE; + while ((option = getopt(argc, argv, option_string)) != EOF) { + int ret = 0; + + switch (option) { + case 'd': + config.dbg_lv = atoi(optarg); + MSG(0, "Info: Debug level = %d\n", + config.dbg_lv); + break; + case 't': + if (strncmp(optarg, "0x", 2)) + ret = sscanf(optarg, "%"PRIu64"", + _sectors); + else + ret = sscanf(optarg, "%"PRIx64"", + _sectors); + break; + default: + MSG(0, "\tError: Unknown option %c\n", option); + resize_usage(); + break; + } + ASSERT(ret >= 0); + } } if ((optind + 1) != argc) { @@ -213,6 +250,8 @@ void f2fs_parse_options(int argc, char *argv[]) dump_usage(); else if (config.func == DEFRAG) defrag_usage(); + else if (config.func == RESIZE) + resize_usage(); } config.device_name = argv[optind]; } @@ -345,6 +384,27 @@ out_range: return -1; } +static int do_resize(struct
[f2fs-dev] [PATCH 2/3] sload.f2fs: support loading files into partition directly
This patch implements loading files into the existing partition. For example, # sload.f2fs -f ./ /dev/sdb1 Then, all the directories and files will be loaded into /dev/sdb1. By default, newly files should have inline_data and inline_xattr, if possible. Signed-off-by: Hou PengyangSigned-off-by: Liu Shuoran Signed-off-by: Jaegeuk Kim --- README| 1 + configure.ac | 1 + fsck/Makefile.am | 6 +- fsck/defrag.c | 2 +- fsck/dir.c| 584 ++ fsck/f2fs.h | 77 ++- fsck/fsck.h | 26 ++- fsck/main.c | 56 ++ fsck/mount.c | 90 - fsck/node.c | 250 +++ fsck/node.h | 101 ++ fsck/segment.c| 220 fsck/sload.c | 247 +++ fsck/xattr.c | 241 ++ fsck/xattr.h | 66 ++ include/f2fs_fs.h | 18 +- man/Makefile.am | 2 +- man/defrag.f2fs.8 | 3 +- man/dump.f2fs.8 | 3 +- man/fsck.f2fs.8 | 3 +- man/mkfs.f2fs.8 | 3 +- man/resize.f2fs.8 | 3 +- man/sload.f2fs.8 | 56 ++ 23 files changed, 2042 insertions(+), 17 deletions(-) create mode 100644 fsck/dir.c create mode 100644 fsck/node.c create mode 100644 fsck/node.h create mode 100644 fsck/segment.c create mode 100644 fsck/sload.c create mode 100644 fsck/xattr.c create mode 100644 fsck/xattr.h create mode 100644 man/sload.f2fs.8 diff --git a/README b/README index 222cbc3..77d9b49 100644 --- a/README +++ b/README @@ -12,6 +12,7 @@ Your should install the following packages. - pkg-config - autoconf - libtool + - libselinux1-dev Initial compilation --- diff --git a/configure.ac b/configure.ac index 1f6ff5a..42df775 100644 --- a/configure.ac +++ b/configure.ac @@ -54,6 +54,7 @@ AC_PATH_PROG([LDCONFIG], [ldconfig], # Checks for libraries. PKG_CHECK_MODULES([libuuid], [uuid]) +PKG_CHECK_MODULES([libselinux], [libselinux]) # Checks for header files. AC_CHECK_HEADERS([linux/fs.h fcntl.h mntent.h stdlib.h string.h \ diff --git a/fsck/Makefile.am b/fsck/Makefile.am index 3586625..7abcd00 100644 --- a/fsck/Makefile.am +++ b/fsck/Makefile.am @@ -4,10 +4,12 @@ AM_CPPFLAGS = ${libuuid_CFLAGS} -I$(top_srcdir)/include AM_CFLAGS = -Wall sbin_PROGRAMS = fsck.f2fs fsck_f2fs_SOURCES = main.c fsck.c dump.c mount.c defrag.c f2fs.h fsck.h $(top_srcdir)/include/f2fs_fs.h\ - resize.c -fsck_f2fs_LDADD = ${libuuid_LIBS} $(top_builddir)/lib/libf2fs.la + resize.c \ + node.c segment.c dir.c sload.c xattr.c +fsck_f2fs_LDADD = ${libselinux_LIBS} ${libuuid_LIBS} $(top_builddir)/lib/libf2fs.la install-data-hook: ln -sf fsck.f2fs $(DESTDIR)/$(sbindir)/dump.f2fs ln -sf fsck.f2fs $(DESTDIR)/$(sbindir)/defrag.f2fs ln -sf fsck.f2fs $(DESTDIR)/$(sbindir)/resize.f2fs + ln -sf fsck.f2fs $(DESTDIR)/$(sbindir)/sload.f2fs diff --git a/fsck/defrag.c b/fsck/defrag.c index 7abc0bf..079e7a7 100644 --- a/fsck/defrag.c +++ b/fsck/defrag.c @@ -51,7 +51,7 @@ static int migrate_block(struct f2fs_sb_info *sbi, u64 from, u64 to) update_data_blkaddr(sbi, le32_to_cpu(sum.nid), le16_to_cpu(sum.ofs_in_node), to); else - update_nat_blkaddr(sbi, le32_to_cpu(sum.nid), to); + update_nat_blkaddr(sbi, 0, le32_to_cpu(sum.nid), to); DBG(0, "Migrate %s block %"PRIx64" -> %"PRIx64"\n", IS_DATASEG(type) ? "data" : "node", diff --git a/fsck/dir.c b/fsck/dir.c new file mode 100644 index 000..18b79bd --- /dev/null +++ b/fsck/dir.c @@ -0,0 +1,584 @@ +/** + * dir.c + * + * Many parts of codes are copied from Linux kernel/fs/f2fs. + * + * Copyright (C) 2015 Huawei Ltd. + * Witten by: + * Hou Pengyang + * Liu Shuoran + * Jaegeuk Kim + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include "fsck.h" +#include "node.h" + +static unsigned int dir_buckets(unsigned int level) +{ + if (level < MAX_DIR_HASH_DEPTH / 2) + return 1 << level; + else + return MAX_DIR_BUCKETS; +} + +static unsigned int bucket_blocks(unsigned int level) +{ + if (level < MAX_DIR_HASH_DEPTH / 2) + return 2; + else + return 4; +} + +static unsigned long dir_block_index(unsigned int level, + int dir_level, unsigned int idx) +{ + unsigned long i; + unsigned long bidx = 0; + + for (i = 0; i < level; i++) + bidx += dir_buckets(i + dir_level) *
[f2fs-dev] [PATCH 3/3] script: add simple test script
This patch adds a script to test sload.f2fs, defrag.f2fs, and resize.f2fs. Signed-off-by: Jaegeuk Kim--- scripts/verify.sh | 137 ++ 1 file changed, 137 insertions(+) create mode 100755 scripts/verify.sh diff --git a/scripts/verify.sh b/scripts/verify.sh new file mode 100755 index 000..8a22a2d --- /dev/null +++ b/scripts/verify.sh @@ -0,0 +1,137 @@ +#!/bin/bash + +IMG=../test.img +TMP=/tmp/res +XFSTESTS=~/xfstests +TESTS="4 5 8 11 16 25 32 55 64" + +TARGET=./testdir +MNT=/mnt/resize + +mkdir $TARGET 2>/dev/null +mkdir $MNT 2>/dev/null + +umount $TARGET +umount $MNT + +_check_out() +{ + if [ $1 -ne 0 ]; then + grep ASSERT $TMP + echo FAIL RETURN $1 + exit + fi +} + +_get_sec() +{ + echo $(($1*1024*1024*1024/512)) +} + +_mkfs() +{ + echo "== Initialize $1 GB " + mkfs.f2fs $IMG `_get_sec $1` | grep sectors +} + +_mount() +{ + echo "== mount to $1 =" + mount -t f2fs -o loop,discard,inline_data,inline_xattr $IMG $1 2>&1 + _check_out $? +} + +_fsck() +{ + echo "== fsck.f2fs ===" + fsck.f2fs $IMG -t 2>&1 >$TMP + _check_out $? + grep FSCK $TMP +} + +_fsstress() +{ + echo "== fsstress $1 =" + $XFSTESTS/ltp/fsstress -x "echo 3 > /proc/sys/vm/drop_caches && sleep 1" -X 1 -r -f fsync=8 -f sync=0 -f write=8 -f dwrite=2 -f truncate=6 -f allocsp=0 -f bulkstat=0 -f bulkstat1=0 -f freesp=0 -f zero=1 -f collapse=1 -f insert=1 -f resvsp=0 -f unresvsp=0 -S t -p 10 -n $2 -d $1 >/dev/null +} + +_resize() +{ + echo "== resize.f2fs $1 GB ===" + resize.f2fs -t `_get_sec $1` $IMG 2>&1 >$TMP + _check_out $? + _fsck +} + +_resize_tests() +{ + for i in $TESTS + do + if [ $i -ge $1 ]; then + _resize $i + fi + done +} + +_sload() +{ + echo "== sload $1 " + sload.f2fs -f $1 $IMG 2>&1 + _check_out $? +} + +from_mount() +{ + echo "" + echo " $1 GB to $2 GB with $3 *** " + _mkfs $1 + _mount $3 + _fsstress $3 1 + umount $3 + _fsck + _resize_tests $2 +} + +from_sload() +{ + echo "" + echo " $1 GB to $2 GB with $3 *** " + + _mkfs $1 + _sload $3 + _fsck + + _mount $MNT + _fsstress $MNT 1 + umount $MNT + _fsck + + _resize_tests $2 + + _mount $MNT + _fsstress $MNT 1 + umount $MNT + _fsck +} + +test_all() +{ + for i in $TESTS + do + for j in $TESTS + do + if [ $i -lt $j ]; then + $1 $i $j $2 + fi + done + done +} + +test_all from_sload ~/grub + +rm -rf $TARGET/* +_fsstress $TARGET 5000 +test_all from_sload $TARGET +rm -rf $TARGET 2>/dev/null + +test_all from_mount $MNT -- 2.6.3 -- Find and fix application performance issues faster with Applications Manager Applications Manager provides deep performance insights into multiple tiers of your business applications. It resolves application problems quickly and reduces your MTTR. Get your free trial! https://ad.doubleclick.net/ddm/clk/302982198;130105516;z ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH 3/7] f2fs: split sync_node_pages with fsync_node_pages
This patch splits the existing sync_node_pages into (f)sync_node_pages. The fsync_node_pages is used for f2fs_sync_file only. Signed-off-by: Jaegeuk Kim--- fs/f2fs/checkpoint.c | 2 +- fs/f2fs/f2fs.h | 3 +- fs/f2fs/file.c | 2 +- fs/f2fs/gc.c | 2 +- fs/f2fs/node.c | 108 +-- 5 files changed, 84 insertions(+), 33 deletions(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index b92782f..bf040b5 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -892,7 +892,7 @@ retry_flush_nodes: if (get_pages(sbi, F2FS_DIRTY_NODES)) { up_write(>node_write); - err = sync_node_pages(sbi, 0, ); + err = sync_node_pages(sbi, ); if (err) { f2fs_unlock_all(sbi); goto out; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 3f15513..269abe5 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1784,7 +1784,8 @@ void ra_node_page(struct f2fs_sb_info *, nid_t); struct page *get_node_page(struct f2fs_sb_info *, pgoff_t); struct page *get_node_page_ra(struct page *, int); void sync_inode_page(struct dnode_of_data *); -int sync_node_pages(struct f2fs_sb_info *, nid_t, struct writeback_control *); +int fsync_node_pages(struct f2fs_sb_info *, nid_t, struct writeback_control *); +int sync_node_pages(struct f2fs_sb_info *, struct writeback_control *); bool alloc_nid(struct f2fs_sb_info *, nid_t *); void alloc_nid_done(struct f2fs_sb_info *, nid_t); void alloc_nid_failed(struct f2fs_sb_info *, nid_t); diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 7de90e6..3d53ee0 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -256,7 +256,7 @@ go_write: goto out; } sync_nodes: - sync_node_pages(sbi, ino, ); + fsync_node_pages(sbi, ino, ); /* if cp_error was enabled, we should avoid infinite loop */ if (unlikely(f2fs_cp_error(sbi))) { diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index b0051a9..e820465 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -841,7 +841,7 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, .nr_to_write = LONG_MAX, .for_reclaim = 0, }; - sync_node_pages(sbi, 0, ); + sync_node_pages(sbi, ); } else { f2fs_submit_merged_bio(sbi, DATA, WRITE); } diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index cccee50..675b730 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1222,12 +1222,84 @@ iput_out: iput(inode); } -int sync_node_pages(struct f2fs_sb_info *sbi, nid_t ino, +int fsync_node_pages(struct f2fs_sb_info *sbi, nid_t ino, struct writeback_control *wbc) { pgoff_t index, end; struct pagevec pvec; - int step = ino ? 2 : 0; + int nwritten = 0; + + pagevec_init(, 0); + index = 0; + end = ULONG_MAX; + + while (index <= end) { + int i, nr_pages; + nr_pages = pagevec_lookup_tag(, NODE_MAPPING(sbi), , + PAGECACHE_TAG_DIRTY, + min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1); + if (nr_pages == 0) + break; + + for (i = 0; i < nr_pages; i++) { + struct page *page = pvec.pages[i]; + + if (unlikely(f2fs_cp_error(sbi))) { + pagevec_release(); + return -EIO; + } + + if (!IS_DNODE(page) || !is_cold_node(page)) + continue; + if (ino_of_node(page) != ino) + continue; + + lock_page(page); + + if (unlikely(page->mapping != NODE_MAPPING(sbi))) { +continue_unlock: + unlock_page(page); + continue; + } + if (ino_of_node(page) != ino) + goto continue_unlock; + + if (!PageDirty(page)) { + /* someone wrote it for us */ + goto continue_unlock; + } + + f2fs_wait_on_page_writeback(page, NODE, true); + BUG_ON(PageWriteback(page)); + if (!clear_page_dirty_for_io(page)) + goto continue_unlock; + + set_fsync_mark(page, 1); + if (IS_INODE(page)) + set_dentry_mark(page, + need_dentry_mark(sbi, ino)); +
[f2fs-dev] [PATCH 4/7] f2fs: report unwritten status in fsync_node_pages
The fsync_node_pages should return pass or failure so that user could know fsync is completed or not. Signed-off-by: Jaegeuk Kim--- fs/f2fs/file.c | 4 +++- fs/f2fs/node.c | 13 ++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 3d53ee0..60fd64c 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -256,7 +256,9 @@ go_write: goto out; } sync_nodes: - fsync_node_pages(sbi, ino, ); + ret = fsync_node_pages(sbi, ino, ); + if (ret) + goto out; /* if cp_error was enabled, we should avoid infinite loop */ if (unlikely(f2fs_cp_error(sbi))) { diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 675b730..8a1e211 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1227,7 +1227,7 @@ int fsync_node_pages(struct f2fs_sb_info *sbi, nid_t ino, { pgoff_t index, end; struct pagevec pvec; - int nwritten = 0; + int ret = 0; pagevec_init(, 0); index = 0; @@ -1278,21 +1278,20 @@ continue_unlock: if (IS_INODE(page)) set_dentry_mark(page, need_dentry_mark(sbi, ino)); - nwritten++; - if (NODE_MAPPING(sbi)->a_ops->writepage(page, wbc)) + ret = NODE_MAPPING(sbi)->a_ops->writepage(page, wbc); + if (ret) { unlock_page(page); - - if (--wbc->nr_to_write == 0) break; + } } pagevec_release(); cond_resched(); - if (wbc->nr_to_write == 0) + if (ret) break; } - return nwritten; + return ret ? -EIO: 0; } int sync_node_pages(struct f2fs_sb_info *sbi, struct writeback_control *wbc) -- 2.6.3 -- Find and fix application performance issues faster with Applications Manager Applications Manager provides deep performance insights into multiple tiers of your business applications. It resolves application problems quickly and reduces your MTTR. Get your free trial! https://ad.doubleclick.net/ddm/clk/302982198;130105516;z ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH 5/7] f2fs: set fsync mark only for the last dnode
In order to give atomic writes, we should consider power failure during sync_node_pages in fsync. So, this patch marks fsync flag only in the last dnode block. Signed-off-by: Jaegeuk Kim--- fs/f2fs/f2fs.h | 4 +- fs/f2fs/file.c | 14 +-- fs/f2fs/node.c | 106 + fs/f2fs/recovery.c | 9 ++--- 4 files changed, 113 insertions(+), 20 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 269abe5..ca828b0 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -159,7 +159,6 @@ struct fsync_inode_entry { struct inode *inode;/* vfs inode pointer */ block_t blkaddr;/* block address locating the last fsync */ block_t last_dentry;/* block address locating the last dentry */ - block_t last_inode; /* block address locating the last inode */ }; #define nats_in_cursum(jnl)(le16_to_cpu(jnl->n_nats)) @@ -1784,7 +1783,8 @@ void ra_node_page(struct f2fs_sb_info *, nid_t); struct page *get_node_page(struct f2fs_sb_info *, pgoff_t); struct page *get_node_page_ra(struct page *, int); void sync_inode_page(struct dnode_of_data *); -int fsync_node_pages(struct f2fs_sb_info *, nid_t, struct writeback_control *); +int fsync_node_pages(struct f2fs_sb_info *, nid_t, struct writeback_control *, + bool); int sync_node_pages(struct f2fs_sb_info *, struct writeback_control *); bool alloc_nid(struct f2fs_sb_info *, nid_t *); void alloc_nid_done(struct f2fs_sb_info *, nid_t); diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 60fd64c..dc47d5c 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -182,7 +182,8 @@ static void try_to_fix_pino(struct inode *inode) } } -int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) +static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end, + int datasync, bool atomic) { struct inode *inode = file->f_mapping->host; struct f2fs_inode_info *fi = F2FS_I(inode); @@ -256,7 +257,7 @@ go_write: goto out; } sync_nodes: - ret = fsync_node_pages(sbi, ino, ); + ret = fsync_node_pages(sbi, ino, , atomic); if (ret) goto out; @@ -290,6 +291,11 @@ out: return ret; } +int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) +{ + return f2fs_do_sync_file(file, start, end, datasync, false); +} + static pgoff_t __get_first_dirty_index(struct address_space *mapping, pgoff_t pgofs, int whence) { @@ -1407,7 +1413,7 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp) } } - ret = f2fs_sync_file(filp, 0, LLONG_MAX, 0); + ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 0, true); err_out: mnt_drop_write_file(filp); return ret; @@ -1465,7 +1471,7 @@ static int f2fs_ioc_abort_volatile_write(struct file *filp) drop_inmem_pages(inode); if (f2fs_is_volatile_file(inode)) { clear_inode_flag(F2FS_I(inode), FI_VOLATILE_FILE); - ret = f2fs_sync_file(filp, 0, LLONG_MAX, 0); + ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 0, true); } mnt_drop_write_file(filp); diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 8a1e211..de070a5 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1222,13 +1222,81 @@ iput_out: iput(inode); } +static struct page *last_fsync_dnode(struct f2fs_sb_info *sbi, nid_t ino) +{ + pgoff_t index, end; + struct pagevec pvec; + struct page *last_page = NULL; + + pagevec_init(, 0); + index = 0; + end = ULONG_MAX; + + while (index <= end) { + int i, nr_pages; + nr_pages = pagevec_lookup_tag(, NODE_MAPPING(sbi), , + PAGECACHE_TAG_DIRTY, + min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1); + if (nr_pages == 0) + break; + + for (i = 0; i < nr_pages; i++) { + struct page *page = pvec.pages[i]; + + if (unlikely(f2fs_cp_error(sbi))) { + f2fs_put_page(last_page, 0); + pagevec_release(); + return ERR_PTR(-EIO); + } + + if (!IS_DNODE(page) || !is_cold_node(page)) + continue; + if (ino_of_node(page) != ino) + continue; + + lock_page(page); + + if (unlikely(page->mapping != NODE_MAPPING(sbi))) { +continue_unlock: + unlock_page(page); + continue; +
[f2fs-dev] [PATCH 1/7] f2fs: avoid needless lock for node pages when fsyncing a file
When fsync is called, sync_node_pages finds a proper direct node pages to flush. But, it locks unrelated direct node pages together unnecessarily. Signed-off-by: Jaegeuk Kim--- fs/f2fs/node.c | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 095fc2c..cccee50 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1272,10 +1272,14 @@ next_step: * we should not skip writing node pages. */ lock_node: - if (ino && ino_of_node(page) == ino) - lock_page(page); - else if (!trylock_page(page)) + if (ino) { + if (ino_of_node(page) == ino) + lock_page(page); + else + continue; + } else if (!trylock_page(page)) { continue; + } if (unlikely(page->mapping != NODE_MAPPING(sbi))) { continue_unlock: -- 2.6.3 -- Find and fix application performance issues faster with Applications Manager Applications Manager provides deep performance insights into multiple tiers of your business applications. It resolves application problems quickly and reduces your MTTR. Get your free trial! https://ad.doubleclick.net/ddm/clk/302982198;130105516;z ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH 6/7] f2fs: issue cache flush on direct IO
Under direct IO path with O_(D)SYNC, it needs to set proper APPEND or UPDATE flags, so taht f2fs_sync_file can make its data safe. Signed-off-by: Jaegeuk Kim--- fs/f2fs/data.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index e54489b..38ce5d6 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -673,6 +673,9 @@ next_block: err = reserve_new_block(); } else { err = __allocate_data_block(); + if (!err) + set_inode_flag(F2FS_I(inode), + FI_APPEND_WRITE); } if (err) goto sync_out; @@ -1685,8 +1688,12 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter, trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter)); err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block_dio); - if (err < 0 && iov_iter_rw(iter) == WRITE) - f2fs_write_failed(mapping, offset + count); + if (iov_iter_rw(iter) == WRITE) { + if (err > 0) + set_inode_flag(F2FS_I(inode), FI_UPDATE_WRITE); + else if (err < 0) + f2fs_write_failed(mapping, offset + count); + } trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err); -- 2.6.3 -- Find and fix application performance issues faster with Applications Manager Applications Manager provides deep performance insights into multiple tiers of your business applications. It resolves application problems quickly and reduces your MTTR. Get your free trial! https://ad.doubleclick.net/ddm/clk/302982198;130105516;z ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH 7/7] f2fs: should check the remaining dentry bits
Let's consider a race condition between f2fs_add_regular_entry and find_target_dentry. 1. - f2fs_add_regular_entry updated len: 24 first. | Bits: 0 0 0 1 Lens: 24 0 0 3 (name: foo) |-> - find_target_dentry checks the first bit to find "foo", then ++pointer. 2. - f2fs_add_regular_entry updates bits. |>|>| Bits: 1 1 1 1 Lens: 24 0 0 3 (name: foo) | - find_target_dentry is checking second bit, but it's len is zero, which makes the process being terminated. In this case, user can add additional dentry named "foo" accordingly. This patch enables to check the remaining bits. Signed-off-by: He YunLeiSigned-off-by: Jaegeuk Kim --- fs/f2fs/dir.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index e90380d..aed5e6d 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -149,9 +149,9 @@ struct f2fs_dir_entry *find_target_dentry(struct fscrypt_name *fname, /* remain bug on condition */ if (unlikely(!de->name_len)) - d->max = -1; - - bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); + bit_pos++; + else + bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); } de = NULL; -- 2.6.3 -- Find and fix application performance issues faster with Applications Manager Applications Manager provides deep performance insights into multiple tiers of your business applications. It resolves application problems quickly and reduces your MTTR. Get your free trial! https://ad.doubleclick.net/ddm/clk/302982198;130105516;z ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH 2/7] f2fs: avoid writing 0'th page in volatile writes
The first page of volatile writes usually contains a sort of header information which will be used for recovery. (e.g., journal header of sqlite) If this is written without other journal data, user needs to handle the stale journal information. Signed-off-by: Jaegeuk Kim--- fs/f2fs/data.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index c29bcf4..e54489b 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1177,8 +1177,10 @@ write: goto redirty_out; if (f2fs_is_drop_cache(inode)) goto out; - if (f2fs_is_volatile_file(inode) && !wbc->for_reclaim && - available_free_memory(sbi, BASE_CHECK)) + /* we should not write 0'th page having journal header */ + if (f2fs_is_volatile_file(inode) && (!page->index || + (!wbc->for_reclaim && + available_free_memory(sbi, BASE_CHECK goto redirty_out; /* Dentry blocks are controlled by checkpoint */ -- 2.6.3 -- Find and fix application performance issues faster with Applications Manager Applications Manager provides deep performance insights into multiple tiers of your business applications. It resolves application problems quickly and reduces your MTTR. Get your free trial! https://ad.doubleclick.net/ddm/clk/302982198;130105516;z ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel