f2fs: move f2fs to use reader-unfair rwsems
f2fs rw_semaphores work better if writers can starve readers, especially for the checkpoint thread, because writers are strictly more important than reader threads. This prevents significant priority inversion between low-priority readers that blocked while trying to acquire the read lock and a second acquisition of the write lock that might be blocking high priority work. Signed-off-by: Tim Murray <timmurray@google.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
@@ -471,7 +471,7 @@ int f2fs_commit_inmem_pages(struct inode *inode)
|
||||
|
||||
f2fs_balance_fs(sbi, true);
|
||||
|
||||
down_write(&fi->i_gc_rwsem[WRITE]);
|
||||
f2fs_down_write(&fi->i_gc_rwsem[WRITE]);
|
||||
|
||||
f2fs_lock_op(sbi);
|
||||
set_inode_flag(inode, FI_ATOMIC_COMMIT);
|
||||
@@ -483,7 +483,7 @@ int f2fs_commit_inmem_pages(struct inode *inode)
|
||||
clear_inode_flag(inode, FI_ATOMIC_COMMIT);
|
||||
|
||||
f2fs_unlock_op(sbi);
|
||||
up_write(&fi->i_gc_rwsem[WRITE]);
|
||||
f2fs_up_write(&fi->i_gc_rwsem[WRITE]);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -521,7 +521,7 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need)
|
||||
io_schedule();
|
||||
finish_wait(&sbi->gc_thread->fggc_wq, &wait);
|
||||
} else {
|
||||
down_write(&sbi->gc_lock);
|
||||
f2fs_down_write(&sbi->gc_lock);
|
||||
f2fs_gc(sbi, false, false, false, NULL_SEGNO);
|
||||
}
|
||||
}
|
||||
@@ -529,7 +529,7 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need)
|
||||
|
||||
static inline bool excess_dirty_threshold(struct f2fs_sb_info *sbi)
|
||||
{
|
||||
int factor = rwsem_is_locked(&sbi->cp_rwsem) ? 3 : 2;
|
||||
int factor = f2fs_rwsem_is_locked(&sbi->cp_rwsem) ? 3 : 2;
|
||||
unsigned int dents = get_pages(sbi, F2FS_DIRTY_DENTS);
|
||||
unsigned int qdata = get_pages(sbi, F2FS_DIRTY_QDATA);
|
||||
unsigned int nodes = get_pages(sbi, F2FS_DIRTY_NODES);
|
||||
@@ -570,7 +570,7 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi, bool from_bg)
|
||||
|
||||
/* there is background inflight IO or foreground operation recently */
|
||||
if (is_inflight_io(sbi, REQ_TIME) ||
|
||||
(!f2fs_time_over(sbi, REQ_TIME) && rwsem_is_locked(&sbi->cp_rwsem)))
|
||||
(!f2fs_time_over(sbi, REQ_TIME) && f2fs_rwsem_is_locked(&sbi->cp_rwsem)))
|
||||
return;
|
||||
|
||||
/* exceed periodical checkpoint timeout threshold */
|
||||
@@ -2821,7 +2821,7 @@ static void __f2fs_init_atgc_curseg(struct f2fs_sb_info *sbi)
|
||||
if (!sbi->am.atgc_enabled)
|
||||
return;
|
||||
|
||||
down_read(&SM_I(sbi)->curseg_lock);
|
||||
f2fs_down_read(&SM_I(sbi)->curseg_lock);
|
||||
|
||||
mutex_lock(&curseg->curseg_mutex);
|
||||
down_write(&SIT_I(sbi)->sentry_lock);
|
||||
@@ -2831,7 +2831,7 @@ static void __f2fs_init_atgc_curseg(struct f2fs_sb_info *sbi)
|
||||
up_write(&SIT_I(sbi)->sentry_lock);
|
||||
mutex_unlock(&curseg->curseg_mutex);
|
||||
|
||||
up_read(&SM_I(sbi)->curseg_lock);
|
||||
f2fs_up_read(&SM_I(sbi)->curseg_lock);
|
||||
|
||||
}
|
||||
void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi)
|
||||
@@ -2982,7 +2982,7 @@ void f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type,
|
||||
struct curseg_info *curseg = CURSEG_I(sbi, type);
|
||||
unsigned int segno;
|
||||
|
||||
down_read(&SM_I(sbi)->curseg_lock);
|
||||
f2fs_down_read(&SM_I(sbi)->curseg_lock);
|
||||
mutex_lock(&curseg->curseg_mutex);
|
||||
down_write(&SIT_I(sbi)->sentry_lock);
|
||||
|
||||
@@ -3006,7 +3006,7 @@ unlock:
|
||||
type, segno, curseg->segno);
|
||||
|
||||
mutex_unlock(&curseg->curseg_mutex);
|
||||
up_read(&SM_I(sbi)->curseg_lock);
|
||||
f2fs_up_read(&SM_I(sbi)->curseg_lock);
|
||||
}
|
||||
|
||||
static void __allocate_new_segment(struct f2fs_sb_info *sbi, int type,
|
||||
@@ -3038,23 +3038,23 @@ static void __allocate_new_section(struct f2fs_sb_info *sbi,
|
||||
|
||||
void f2fs_allocate_new_section(struct f2fs_sb_info *sbi, int type, bool force)
|
||||
{
|
||||
down_read(&SM_I(sbi)->curseg_lock);
|
||||
f2fs_down_read(&SM_I(sbi)->curseg_lock);
|
||||
down_write(&SIT_I(sbi)->sentry_lock);
|
||||
__allocate_new_section(sbi, type, force);
|
||||
up_write(&SIT_I(sbi)->sentry_lock);
|
||||
up_read(&SM_I(sbi)->curseg_lock);
|
||||
f2fs_up_read(&SM_I(sbi)->curseg_lock);
|
||||
}
|
||||
|
||||
void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi)
|
||||
{
|
||||
int i;
|
||||
|
||||
down_read(&SM_I(sbi)->curseg_lock);
|
||||
f2fs_down_read(&SM_I(sbi)->curseg_lock);
|
||||
down_write(&SIT_I(sbi)->sentry_lock);
|
||||
for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++)
|
||||
__allocate_new_segment(sbi, i, false, false);
|
||||
up_write(&SIT_I(sbi)->sentry_lock);
|
||||
up_read(&SM_I(sbi)->curseg_lock);
|
||||
f2fs_up_read(&SM_I(sbi)->curseg_lock);
|
||||
}
|
||||
|
||||
static const struct segment_allocation default_salloc_ops = {
|
||||
@@ -3192,9 +3192,9 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range)
|
||||
if (sbi->discard_blks == 0)
|
||||
goto out;
|
||||
|
||||
down_write(&sbi->gc_lock);
|
||||
f2fs_down_write(&sbi->gc_lock);
|
||||
err = f2fs_write_checkpoint(sbi, &cpc);
|
||||
up_write(&sbi->gc_lock);
|
||||
f2fs_up_write(&sbi->gc_lock);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@@ -3431,7 +3431,7 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
|
||||
bool from_gc = (type == CURSEG_ALL_DATA_ATGC);
|
||||
struct seg_entry *se = NULL;
|
||||
|
||||
down_read(&SM_I(sbi)->curseg_lock);
|
||||
f2fs_down_read(&SM_I(sbi)->curseg_lock);
|
||||
|
||||
mutex_lock(&curseg->curseg_mutex);
|
||||
down_write(&sit_i->sentry_lock);
|
||||
@@ -3514,7 +3514,7 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
|
||||
|
||||
mutex_unlock(&curseg->curseg_mutex);
|
||||
|
||||
up_read(&SM_I(sbi)->curseg_lock);
|
||||
f2fs_up_read(&SM_I(sbi)->curseg_lock);
|
||||
}
|
||||
|
||||
void f2fs_update_device_state(struct f2fs_sb_info *sbi, nid_t ino,
|
||||
@@ -3550,7 +3550,7 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio)
|
||||
bool keep_order = (f2fs_lfs_mode(fio->sbi) && type == CURSEG_COLD_DATA);
|
||||
|
||||
if (keep_order)
|
||||
down_read(&fio->sbi->io_order_lock);
|
||||
f2fs_down_read(&fio->sbi->io_order_lock);
|
||||
reallocate:
|
||||
f2fs_allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr,
|
||||
&fio->new_blkaddr, sum, type, fio);
|
||||
@@ -3570,7 +3570,7 @@ reallocate:
|
||||
f2fs_update_device_state(fio->sbi, fio->ino, fio->new_blkaddr, 1);
|
||||
|
||||
if (keep_order)
|
||||
up_read(&fio->sbi->io_order_lock);
|
||||
f2fs_up_read(&fio->sbi->io_order_lock);
|
||||
}
|
||||
|
||||
void f2fs_do_write_meta_page(struct f2fs_sb_info *sbi, struct page *page,
|
||||
@@ -3705,7 +3705,7 @@ void f2fs_do_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
|
||||
se = get_seg_entry(sbi, segno);
|
||||
type = se->type;
|
||||
|
||||
down_write(&SM_I(sbi)->curseg_lock);
|
||||
f2fs_down_write(&SM_I(sbi)->curseg_lock);
|
||||
|
||||
if (!recover_curseg) {
|
||||
/* for recovery flow */
|
||||
@@ -3774,7 +3774,7 @@ void f2fs_do_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
|
||||
|
||||
up_write(&sit_i->sentry_lock);
|
||||
mutex_unlock(&curseg->curseg_mutex);
|
||||
up_write(&SM_I(sbi)->curseg_lock);
|
||||
f2fs_up_write(&SM_I(sbi)->curseg_lock);
|
||||
}
|
||||
|
||||
void f2fs_replace_block(struct f2fs_sb_info *sbi, struct dnode_of_data *dn,
|
||||
@@ -5258,7 +5258,7 @@ int f2fs_build_segment_manager(struct f2fs_sb_info *sbi)
|
||||
|
||||
INIT_LIST_HEAD(&sm_info->sit_entry_set);
|
||||
|
||||
init_rwsem(&sm_info->curseg_lock);
|
||||
init_f2fs_rwsem(&sm_info->curseg_lock);
|
||||
|
||||
if (!f2fs_readonly(sbi->sb)) {
|
||||
err = f2fs_create_flush_cmd_control(sbi);
|
||||
|
||||
Reference in New Issue
Block a user