Skip to content

Commit 4fc29c1

Browse files
committed
Merge tag 'for-f2fs-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs
Pull f2fs updates from Jaegeuk Kim: "The major change in this version is mitigating cpu overheads on write paths by replacing redundant inode page updates with mark_inode_dirty calls. And we tried to reduce lock contentions as well to improve filesystem scalability. Other feature is setting F2FS automatically when detecting host-managed SMR. Enhancements: - ioctl to move a range of data between files - inject orphan inode errors - avoid flush commands congestion - support lazytime Bug fixes: - return proper results for some dentry operations - fix deadlock in add_link failure - disable extent_cache for fcollapse/finsert" * tag 'for-f2fs-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (68 commits) f2fs: clean up coding style and redundancy f2fs: get victim segment again after new cp f2fs: handle error case with f2fs_bug_on f2fs: avoid data race when deciding checkpoin in f2fs_sync_file f2fs: support an ioctl to move a range of data blocks f2fs: fix to report error number of f2fs_find_entry f2fs: avoid memory allocation failure due to a long length f2fs: reset default idle interval value f2fs: use blk_plug in all the possible paths f2fs: fix to avoid data update racing between GC and DIO f2fs: add maximum prefree segments f2fs: disable extent_cache for fcollapse/finsert inodes f2fs: refactor __exchange_data_block for speed up f2fs: fix ERR_PTR returned by bio f2fs: avoid mark_inode_dirty f2fs: move i_size_write in f2fs_write_end f2fs: fix to avoid redundant discard during fstrim f2fs: avoid mismatching block range for discard f2fs: fix incorrect f_bfree calculation in ->statfs f2fs: use percpu_rw_semaphore ...
2 parents 0e6acf0 + 5302fb0 commit 4fc29c1

File tree

22 files changed

+1387
-750
lines changed

22 files changed

+1387
-750
lines changed

Documentation/filesystems/f2fs.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,9 @@ background_gc=%s Turn on/off cleaning operations, namely garbage
109109
disable_roll_forward Disable the roll-forward recovery routine
110110
norecovery Disable the roll-forward recovery routine, mounted read-
111111
only (i.e., -o ro,disable_roll_forward)
112-
discard Issue discard/TRIM commands when a segment is cleaned.
112+
discard/nodiscard Enable/disable real-time discard in f2fs, if discard is
113+
enabled, f2fs will issue discard/TRIM commands when a
114+
segment is cleaned.
113115
no_heap Disable heap-style segment allocation which finds free
114116
segments for data from the beginning of main area, while
115117
for node from the end of main area.
@@ -151,6 +153,9 @@ noinline_data Disable the inline data feature, inline data feature is
151153
enabled by default.
152154
data_flush Enable data flushing before checkpoint in order to
153155
persist data of regular and symlink.
156+
mode=%s Control block allocation mode which supports "adaptive"
157+
and "lfs". In "lfs" mode, there should be no random
158+
writes towards main area.
154159

155160
================================================================================
156161
DEBUGFS ENTRIES

fs/f2fs/acl.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,6 @@ struct posix_acl *f2fs_get_acl(struct inode *inode, int type)
201201
static int __f2fs_set_acl(struct inode *inode, int type,
202202
struct posix_acl *acl, struct page *ipage)
203203
{
204-
struct f2fs_inode_info *fi = F2FS_I(inode);
205204
int name_index;
206205
void *value = NULL;
207206
size_t size = 0;
@@ -214,7 +213,7 @@ static int __f2fs_set_acl(struct inode *inode, int type,
214213
error = posix_acl_equiv_mode(acl, &inode->i_mode);
215214
if (error < 0)
216215
return error;
217-
set_acl_inode(fi, inode->i_mode);
216+
set_acl_inode(inode, inode->i_mode);
218217
if (error == 0)
219218
acl = NULL;
220219
}
@@ -233,7 +232,7 @@ static int __f2fs_set_acl(struct inode *inode, int type,
233232
if (acl) {
234233
value = f2fs_acl_to_disk(acl, &size);
235234
if (IS_ERR(value)) {
236-
clear_inode_flag(fi, FI_ACL_MODE);
235+
clear_inode_flag(inode, FI_ACL_MODE);
237236
return (int)PTR_ERR(value);
238237
}
239238
}
@@ -244,7 +243,7 @@ static int __f2fs_set_acl(struct inode *inode, int type,
244243
if (!error)
245244
set_cached_acl(inode, type, acl);
246245

247-
clear_inode_flag(fi, FI_ACL_MODE);
246+
clear_inode_flag(inode, FI_ACL_MODE);
248247
return error;
249248
}
250249

@@ -385,6 +384,8 @@ int f2fs_init_acl(struct inode *inode, struct inode *dir, struct page *ipage,
385384
if (error)
386385
return error;
387386

387+
f2fs_mark_inode_dirty_sync(inode);
388+
388389
if (default_acl) {
389390
error = __f2fs_set_acl(inode, ACL_TYPE_DEFAULT, default_acl,
390391
ipage);

fs/f2fs/acl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ struct f2fs_acl_header {
3737
#ifdef CONFIG_F2FS_FS_POSIX_ACL
3838

3939
extern struct posix_acl *f2fs_get_acl(struct inode *, int);
40-
extern int f2fs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
40+
extern int f2fs_set_acl(struct inode *, struct posix_acl *, int);
4141
extern int f2fs_init_acl(struct inode *, struct inode *, struct page *,
4242
struct page *);
4343
#else

fs/f2fs/checkpoint.c

Lines changed: 60 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ struct page *grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
4848
goto repeat;
4949
}
5050
f2fs_wait_on_page_writeback(page, META, true);
51-
SetPageUptodate(page);
51+
if (!PageUptodate(page))
52+
SetPageUptodate(page);
5253
return page;
5354
}
5455

@@ -266,6 +267,7 @@ static int f2fs_write_meta_pages(struct address_space *mapping,
266267
struct writeback_control *wbc)
267268
{
268269
struct f2fs_sb_info *sbi = F2FS_M_SB(mapping);
270+
struct blk_plug plug;
269271
long diff, written;
270272

271273
/* collect a number of dirty meta pages and write together */
@@ -278,7 +280,9 @@ static int f2fs_write_meta_pages(struct address_space *mapping,
278280
/* if mounting is failed, skip writing node pages */
279281
mutex_lock(&sbi->cp_mutex);
280282
diff = nr_pages_to_write(sbi, META, wbc);
283+
blk_start_plug(&plug);
281284
written = sync_meta_pages(sbi, META, wbc->nr_to_write);
285+
blk_finish_plug(&plug);
282286
mutex_unlock(&sbi->cp_mutex);
283287
wbc->nr_to_write = max((long)0, wbc->nr_to_write - written - diff);
284288
return 0;
@@ -366,9 +370,10 @@ static int f2fs_set_meta_page_dirty(struct page *page)
366370
{
367371
trace_f2fs_set_page_dirty(page, META);
368372

369-
SetPageUptodate(page);
373+
if (!PageUptodate(page))
374+
SetPageUptodate(page);
370375
if (!PageDirty(page)) {
371-
__set_page_dirty_nobuffers(page);
376+
f2fs_set_page_dirty_nobuffers(page);
372377
inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_META);
373378
SetPagePrivate(page);
374379
f2fs_trace_pid(page);
@@ -510,10 +515,11 @@ void release_orphan_inode(struct f2fs_sb_info *sbi)
510515
spin_unlock(&im->ino_lock);
511516
}
512517

513-
void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
518+
void add_orphan_inode(struct inode *inode)
514519
{
515520
/* add new orphan ino entry into list */
516-
__add_ino_entry(sbi, ino, ORPHAN_INO);
521+
__add_ino_entry(F2FS_I_SB(inode), inode->i_ino, ORPHAN_INO);
522+
update_inode_page(inode);
517523
}
518524

519525
void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
@@ -761,28 +767,25 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi)
761767
static void __add_dirty_inode(struct inode *inode, enum inode_type type)
762768
{
763769
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
764-
struct f2fs_inode_info *fi = F2FS_I(inode);
765770
int flag = (type == DIR_INODE) ? FI_DIRTY_DIR : FI_DIRTY_FILE;
766771

767-
if (is_inode_flag_set(fi, flag))
772+
if (is_inode_flag_set(inode, flag))
768773
return;
769774

770-
set_inode_flag(fi, flag);
771-
list_add_tail(&fi->dirty_list, &sbi->inode_list[type]);
775+
set_inode_flag(inode, flag);
776+
list_add_tail(&F2FS_I(inode)->dirty_list, &sbi->inode_list[type]);
772777
stat_inc_dirty_inode(sbi, type);
773778
}
774779

775780
static void __remove_dirty_inode(struct inode *inode, enum inode_type type)
776781
{
777-
struct f2fs_inode_info *fi = F2FS_I(inode);
778782
int flag = (type == DIR_INODE) ? FI_DIRTY_DIR : FI_DIRTY_FILE;
779783

780-
if (get_dirty_pages(inode) ||
781-
!is_inode_flag_set(F2FS_I(inode), flag))
784+
if (get_dirty_pages(inode) || !is_inode_flag_set(inode, flag))
782785
return;
783786

784-
list_del_init(&fi->dirty_list);
785-
clear_inode_flag(fi, flag);
787+
list_del_init(&F2FS_I(inode)->dirty_list);
788+
clear_inode_flag(inode, flag);
786789
stat_dec_dirty_inode(F2FS_I_SB(inode), type);
787790
}
788791

@@ -795,13 +798,12 @@ void update_dirty_page(struct inode *inode, struct page *page)
795798
!S_ISLNK(inode->i_mode))
796799
return;
797800

798-
if (type != FILE_INODE || test_opt(sbi, DATA_FLUSH)) {
799-
spin_lock(&sbi->inode_lock[type]);
801+
spin_lock(&sbi->inode_lock[type]);
802+
if (type != FILE_INODE || test_opt(sbi, DATA_FLUSH))
800803
__add_dirty_inode(inode, type);
801-
spin_unlock(&sbi->inode_lock[type]);
802-
}
803-
804804
inode_inc_dirty_pages(inode);
805+
spin_unlock(&sbi->inode_lock[type]);
806+
805807
SetPagePrivate(page);
806808
f2fs_trace_pid(page);
807809
}
@@ -864,6 +866,34 @@ int sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type)
864866
goto retry;
865867
}
866868

869+
int f2fs_sync_inode_meta(struct f2fs_sb_info *sbi)
870+
{
871+
struct list_head *head = &sbi->inode_list[DIRTY_META];
872+
struct inode *inode;
873+
struct f2fs_inode_info *fi;
874+
s64 total = get_pages(sbi, F2FS_DIRTY_IMETA);
875+
876+
while (total--) {
877+
if (unlikely(f2fs_cp_error(sbi)))
878+
return -EIO;
879+
880+
spin_lock(&sbi->inode_lock[DIRTY_META]);
881+
if (list_empty(head)) {
882+
spin_unlock(&sbi->inode_lock[DIRTY_META]);
883+
return 0;
884+
}
885+
fi = list_entry(head->next, struct f2fs_inode_info,
886+
gdirty_list);
887+
inode = igrab(&fi->vfs_inode);
888+
spin_unlock(&sbi->inode_lock[DIRTY_META]);
889+
if (inode) {
890+
update_inode_page(inode);
891+
iput(inode);
892+
}
893+
};
894+
return 0;
895+
}
896+
867897
/*
868898
* Freeze all the FS-operations for checkpoint.
869899
*/
@@ -890,6 +920,14 @@ static int block_operations(struct f2fs_sb_info *sbi)
890920
goto retry_flush_dents;
891921
}
892922

923+
if (get_pages(sbi, F2FS_DIRTY_IMETA)) {
924+
f2fs_unlock_all(sbi);
925+
err = f2fs_sync_inode_meta(sbi);
926+
if (err)
927+
goto out;
928+
goto retry_flush_dents;
929+
}
930+
893931
/*
894932
* POR: we should ensure that there are no dirty node pages
895933
* until finishing nat/sit flush.
@@ -914,6 +952,8 @@ static int block_operations(struct f2fs_sb_info *sbi)
914952
static void unblock_operations(struct f2fs_sb_info *sbi)
915953
{
916954
up_write(&sbi->node_write);
955+
956+
build_free_nids(sbi);
917957
f2fs_unlock_all(sbi);
918958
}
919959

@@ -954,7 +994,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
954994
* This avoids to conduct wrong roll-forward operations and uses
955995
* metapages, so should be called prior to sync_meta_pages below.
956996
*/
957-
if (discard_next_dnode(sbi, discard_blk))
997+
if (!test_opt(sbi, LFS) && discard_next_dnode(sbi, discard_blk))
958998
invalidate = true;
959999

9601000
/* Flush all the NAT/SIT pages */

0 commit comments

Comments
 (0)