Skip to content

Commit

Permalink
Merge tag 'f2fs-for-5.5' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/jaegeuk/f2fs

Pull f2fs updates from Jaegeuk Kim:
 "In this round, we've introduced fairly small number of patches as below.

  Enhancements:
   - improve the in-place-update IO flow
   - allocate segment to guarantee no GC for pinned files

  Bug fixes:
   - fix updatetime in lazytime mode
   - potential memory leak in f2fs_listxattr
   - record parent inode number in rename2 correctly
   - fix deadlock in f2fs_gc along with atomic writes
   - avoid needless data migration in GC"

* tag 'f2fs-for-5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs:
  f2fs: stop GC when the victim becomes fully valid
  f2fs: expose main_blkaddr in sysfs
  f2fs: choose hardlimit when softlimit is larger than hardlimit in f2fs_statfs_project()
  f2fs: Fix deadlock in f2fs_gc() context during atomic files handling
  f2fs: show f2fs instance in printk_ratelimited
  f2fs: fix potential overflow
  f2fs: fix to update dir's i_pino during cross_rename
  f2fs: support aligned pinned file
  f2fs: avoid kernel panic on corruption test
  f2fs: fix wrong description in document
  f2fs: cache global IPU bio
  f2fs: fix to avoid memory leakage in f2fs_listxattr
  f2fs: check total_segments from devices in raw_super
  f2fs: update multi-dev metadata in resize_fs
  f2fs: mark recovery flag correctly in read_raw_super_block()
  f2fs: fix to update time in lazytime mode
  • Loading branch information
Linus Torvalds committed Nov 30, 2019
2 parents 4a55d36 + 803e74b commit 8f45533
Show file tree
Hide file tree
Showing 17 changed files with 421 additions and 107 deletions.
6 changes: 6 additions & 0 deletions Documentation/ABI/testing/sysfs-fs-f2fs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ Contact: "Jaegeuk Kim" <jaegeuk.kim@samsung.com>
Description:
Controls the issue rate of segment discard commands.

What: /sys/fs/f2fs/<disk>/max_blkaddr
Date: November 2019
Contact: "Ramon Pantin" <pantin@google.com>
Description:
Shows first block address of MAIN area.

What: /sys/fs/f2fs/<disk>/ipu_policy
Date: November 2013
Contact: "Jaegeuk Kim" <jaegeuk.kim@samsung.com>
Expand Down
5 changes: 4 additions & 1 deletion Documentation/filesystems/f2fs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,9 @@ Files in /sys/fs/f2fs/<devname>
reclaim the prefree segments to free segments.
By default, 5% over total # of segments.

main_blkaddr This value gives the first block address of
MAIN area in the partition.

max_small_discards This parameter controls the number of discard
commands that consist small blocks less than 2MB.
The candidates to be discarded are cached until
Expand Down Expand Up @@ -346,7 +349,7 @@ Files in /sys/fs/f2fs/<devname>

ram_thresh This parameter controls the memory footprint used
by free nids and cached nat entries. By default,
10 is set, which indicates 10 MB / 1 GB RAM.
1 is set, which indicates 10 MB / 1 GB RAM.

ra_nid_pages When building free nids, F2FS reads NAT blocks
ahead for speed up. Default is 0.
Expand Down
2 changes: 1 addition & 1 deletion fs/f2fs/checkpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ int f2fs_acquire_orphan_inode(struct f2fs_sb_info *sbi)

if (time_to_inject(sbi, FAULT_ORPHAN)) {
spin_unlock(&im->ino_lock);
f2fs_show_injection_info(FAULT_ORPHAN);
f2fs_show_injection_info(sbi, FAULT_ORPHAN);
return -ENOSPC;
}

Expand Down
190 changes: 153 additions & 37 deletions fs/f2fs/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#define NUM_PREALLOC_POST_READ_CTXS 128

static struct kmem_cache *bio_post_read_ctx_cache;
static struct kmem_cache *bio_entry_slab;
static mempool_t *bio_post_read_ctx_pool;

static bool __is_cp_guaranteed(struct page *page)
Expand Down Expand Up @@ -167,9 +168,10 @@ static bool f2fs_bio_post_read_required(struct bio *bio)

static void f2fs_read_end_io(struct bio *bio)
{
if (time_to_inject(F2FS_P_SB(bio_first_page_all(bio)),
FAULT_READ_IO)) {
f2fs_show_injection_info(FAULT_READ_IO);
struct f2fs_sb_info *sbi = F2FS_P_SB(bio_first_page_all(bio));

if (time_to_inject(sbi, FAULT_READ_IO)) {
f2fs_show_injection_info(sbi, FAULT_READ_IO);
bio->bi_status = BLK_STS_IOERR;
}

Expand All @@ -191,7 +193,7 @@ static void f2fs_write_end_io(struct bio *bio)
struct bvec_iter_all iter_all;

if (time_to_inject(sbi, FAULT_WRITE_IO)) {
f2fs_show_injection_info(FAULT_WRITE_IO);
f2fs_show_injection_info(sbi, FAULT_WRITE_IO);
bio->bi_status = BLK_STS_IOERR;
}

Expand Down Expand Up @@ -543,6 +545,126 @@ static bool io_is_mergeable(struct f2fs_sb_info *sbi, struct bio *bio,
return io_type_is_mergeable(io, fio);
}

static void add_bio_entry(struct f2fs_sb_info *sbi, struct bio *bio,
struct page *page, enum temp_type temp)
{
struct f2fs_bio_info *io = sbi->write_io[DATA] + temp;
struct bio_entry *be;

be = f2fs_kmem_cache_alloc(bio_entry_slab, GFP_NOFS);
be->bio = bio;
bio_get(bio);

if (bio_add_page(bio, page, PAGE_SIZE, 0) != PAGE_SIZE)
f2fs_bug_on(sbi, 1);

down_write(&io->bio_list_lock);
list_add_tail(&be->list, &io->bio_list);
up_write(&io->bio_list_lock);
}

static void del_bio_entry(struct bio_entry *be)
{
list_del(&be->list);
kmem_cache_free(bio_entry_slab, be);
}

static int add_ipu_page(struct f2fs_sb_info *sbi, struct bio **bio,
struct page *page)
{
enum temp_type temp;
bool found = false;
int ret = -EAGAIN;

for (temp = HOT; temp < NR_TEMP_TYPE && !found; temp++) {
struct f2fs_bio_info *io = sbi->write_io[DATA] + temp;
struct list_head *head = &io->bio_list;
struct bio_entry *be;

down_write(&io->bio_list_lock);
list_for_each_entry(be, head, list) {
if (be->bio != *bio)
continue;

found = true;

if (bio_add_page(*bio, page, PAGE_SIZE, 0) == PAGE_SIZE) {
ret = 0;
break;
}

/* bio is full */
del_bio_entry(be);
__submit_bio(sbi, *bio, DATA);
break;
}
up_write(&io->bio_list_lock);
}

if (ret) {
bio_put(*bio);
*bio = NULL;
}

return ret;
}

void f2fs_submit_merged_ipu_write(struct f2fs_sb_info *sbi,
struct bio **bio, struct page *page)
{
enum temp_type temp;
bool found = false;
struct bio *target = bio ? *bio : NULL;

for (temp = HOT; temp < NR_TEMP_TYPE && !found; temp++) {
struct f2fs_bio_info *io = sbi->write_io[DATA] + temp;
struct list_head *head = &io->bio_list;
struct bio_entry *be;

if (list_empty(head))
continue;

down_read(&io->bio_list_lock);
list_for_each_entry(be, head, list) {
if (target)
found = (target == be->bio);
else
found = __has_merged_page(be->bio, NULL,
page, 0);
if (found)
break;
}
up_read(&io->bio_list_lock);

if (!found)
continue;

found = false;

down_write(&io->bio_list_lock);
list_for_each_entry(be, head, list) {
if (target)
found = (target == be->bio);
else
found = __has_merged_page(be->bio, NULL,
page, 0);
if (found) {
target = be->bio;
del_bio_entry(be);
break;
}
}
up_write(&io->bio_list_lock);
}

if (found)
__submit_bio(sbi, target, DATA);
if (bio && *bio) {
bio_put(*bio);
*bio = NULL;
}
}

int f2fs_merge_page_bio(struct f2fs_io_info *fio)
{
struct bio *bio = *fio->bio;
Expand All @@ -557,20 +679,17 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio)
f2fs_trace_ios(fio, 0);

if (bio && !page_is_mergeable(fio->sbi, bio, *fio->last_block,
fio->new_blkaddr)) {
__submit_bio(fio->sbi, bio, fio->type);
bio = NULL;
}
fio->new_blkaddr))
f2fs_submit_merged_ipu_write(fio->sbi, &bio, NULL);
alloc_new:
if (!bio) {
bio = __bio_alloc(fio, BIO_MAX_PAGES);
bio_set_op_attrs(bio, fio->op, fio->op_flags);
}

if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
__submit_bio(fio->sbi, bio, fio->type);
bio = NULL;
goto alloc_new;
add_bio_entry(fio->sbi, bio, page, fio->temp);
} else {
if (add_ipu_page(fio->sbi, &bio, page))
goto alloc_new;
}

if (fio->io_wbc)
Expand All @@ -584,19 +703,6 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio)
return 0;
}

static void f2fs_submit_ipu_bio(struct f2fs_sb_info *sbi, struct bio **bio,
struct page *page)
{
if (!bio)
return;

if (!__has_merged_page(*bio, NULL, page, 0))
return;

__submit_bio(sbi, *bio, DATA);
*bio = NULL;
}

void f2fs_submit_page_write(struct f2fs_io_info *fio)
{
struct f2fs_sb_info *sbi = fio->sbi;
Expand Down Expand Up @@ -2098,7 +2204,7 @@ static int __write_data_page(struct page *page, bool *submitted,
loff_t i_size = i_size_read(inode);
const pgoff_t end_index = ((unsigned long long) i_size)
>> PAGE_SHIFT;
loff_t psize = (page->index + 1) << PAGE_SHIFT;
loff_t psize = (loff_t)(page->index + 1) << PAGE_SHIFT;
unsigned offset = 0;
bool need_balance_fs = false;
int err = 0;
Expand Down Expand Up @@ -2215,14 +2321,12 @@ static int __write_data_page(struct page *page, bool *submitted,

unlock_page(page);
if (!S_ISDIR(inode->i_mode) && !IS_NOQUOTA(inode) &&
!F2FS_I(inode)->cp_task) {
f2fs_submit_ipu_bio(sbi, bio, page);
!F2FS_I(inode)->cp_task)
f2fs_balance_fs(sbi, need_balance_fs);
}

if (unlikely(f2fs_cp_error(sbi))) {
f2fs_submit_ipu_bio(sbi, bio, page);
f2fs_submit_merged_write(sbi, DATA);
f2fs_submit_merged_ipu_write(sbi, bio, NULL);
submitted = NULL;
}

Expand Down Expand Up @@ -2342,13 +2446,11 @@ static int f2fs_write_cache_pages(struct address_space *mapping,
}

if (PageWriteback(page)) {
if (wbc->sync_mode != WB_SYNC_NONE) {
if (wbc->sync_mode != WB_SYNC_NONE)
f2fs_wait_on_page_writeback(page,
DATA, true, true);
f2fs_submit_ipu_bio(sbi, &bio, page);
} else {
else
goto continue_unlock;
}
}

if (!clear_page_dirty_for_io(page))
Expand Down Expand Up @@ -2406,7 +2508,7 @@ static int f2fs_write_cache_pages(struct address_space *mapping,
NULL, 0, DATA);
/* submit cached bio of IPU write */
if (bio)
__submit_bio(sbi, bio, DATA);
f2fs_submit_merged_ipu_write(sbi, &bio, NULL);

return ret;
}
Expand Down Expand Up @@ -3211,8 +3313,22 @@ int __init f2fs_init_post_read_processing(void)
return -ENOMEM;
}

void __exit f2fs_destroy_post_read_processing(void)
void f2fs_destroy_post_read_processing(void)
{
mempool_destroy(bio_post_read_ctx_pool);
kmem_cache_destroy(bio_post_read_ctx_cache);
}

int __init f2fs_init_bio_entry_cache(void)
{
bio_entry_slab = f2fs_kmem_cache_create("bio_entry_slab",
sizeof(struct bio_entry));
if (!bio_entry_slab)
return -ENOMEM;
return 0;
}

void __exit f2fs_destroy_bio_entry_cache(void)
{
kmem_cache_destroy(bio_entry_slab);
}
7 changes: 4 additions & 3 deletions fs/f2fs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name,

start:
if (time_to_inject(F2FS_I_SB(dir), FAULT_DIR_DEPTH)) {
f2fs_show_injection_info(FAULT_DIR_DEPTH);
f2fs_show_injection_info(F2FS_I_SB(dir), FAULT_DIR_DEPTH);
return -ENOSPC;
}

Expand Down Expand Up @@ -919,8 +919,9 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
bit_pos++;
ctx->pos = start_pos + bit_pos;
printk_ratelimited(
"%s, invalid namelen(0), ino:%u, run fsck to fix.",
KERN_WARNING, le32_to_cpu(de->ino));
"%sF2FS-fs (%s): invalid namelen(0), ino:%u, run fsck to fix.",
KERN_WARNING, sbi->sb->s_id,
le32_to_cpu(de->ino));
set_sbi_flag(sbi, SBI_NEED_FSCK);
continue;
}
Expand Down
Loading

0 comments on commit 8f45533

Please sign in to comment.