Commit d0239e1b authored by Jaegeuk Kim's avatar Jaegeuk Kim

f2fs: detect idle time depending on user behavior

This patch adds last time that user requested filesystem operations.
This information is used to detect whether system is idle or not later.
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 6beceb54
...@@ -87,6 +87,12 @@ Contact: "Jaegeuk Kim" <jaegeuk@kernel.org> ...@@ -87,6 +87,12 @@ Contact: "Jaegeuk Kim" <jaegeuk@kernel.org>
Description: Description:
Controls the checkpoint timing. Controls the checkpoint timing.
What: /sys/fs/f2fs/<disk>/idle_interval
Date: January 2016
Contact: "Jaegeuk Kim" <jaegeuk@kernel.org>
Description:
Controls the idle timing.
What: /sys/fs/f2fs/<disk>/ra_nid_pages What: /sys/fs/f2fs/<disk>/ra_nid_pages
Date: October 2015 Date: October 2015
Contact: "Chao Yu" <chao2.yu@samsung.com> Contact: "Chao Yu" <chao2.yu@samsung.com>
......
...@@ -1596,6 +1596,7 @@ static int f2fs_write_end(struct file *file, ...@@ -1596,6 +1596,7 @@ static int f2fs_write_end(struct file *file,
} }
f2fs_put_page(page, 1); f2fs_put_page(page, 1);
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
return copied; return copied;
} }
......
...@@ -636,6 +636,7 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name, ...@@ -636,6 +636,7 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name,
f2fs_put_page(dentry_page, 1); f2fs_put_page(dentry_page, 1);
out: out:
f2fs_fname_free_filename(&fname); f2fs_fname_free_filename(&fname);
f2fs_update_time(F2FS_I_SB(dir), REQ_TIME);
return err; return err;
} }
...@@ -657,6 +658,7 @@ int f2fs_do_tmpfile(struct inode *inode, struct inode *dir) ...@@ -657,6 +658,7 @@ int f2fs_do_tmpfile(struct inode *inode, struct inode *dir)
clear_inode_flag(F2FS_I(inode), FI_NEW_INODE); clear_inode_flag(F2FS_I(inode), FI_NEW_INODE);
fail: fail:
up_write(&F2FS_I(inode)->i_sem); up_write(&F2FS_I(inode)->i_sem);
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
return err; return err;
} }
...@@ -701,6 +703,8 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, ...@@ -701,6 +703,8 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
int slots = GET_DENTRY_SLOTS(le16_to_cpu(dentry->name_len)); int slots = GET_DENTRY_SLOTS(le16_to_cpu(dentry->name_len));
int i; int i;
f2fs_update_time(F2FS_I_SB(dir), REQ_TIME);
if (f2fs_has_inline_dentry(dir)) if (f2fs_has_inline_dentry(dir))
return f2fs_delete_inline_entry(dentry, page, dir, inode); return f2fs_delete_inline_entry(dentry, page, dir, inode);
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/bio.h> #include <linux/bio.h>
#include <linux/blkdev.h>
#ifdef CONFIG_F2FS_CHECK_FS #ifdef CONFIG_F2FS_CHECK_FS
#define f2fs_bug_on(sbi, condition) BUG_ON(condition) #define f2fs_bug_on(sbi, condition) BUG_ON(condition)
...@@ -126,6 +127,7 @@ enum { ...@@ -126,6 +127,7 @@ enum {
#define BATCHED_TRIM_BLOCKS(sbi) \ #define BATCHED_TRIM_BLOCKS(sbi) \
(BATCHED_TRIM_SEGMENTS(sbi) << (sbi)->log_blocks_per_seg) (BATCHED_TRIM_SEGMENTS(sbi) << (sbi)->log_blocks_per_seg)
#define DEF_CP_INTERVAL 60 /* 60 secs */ #define DEF_CP_INTERVAL 60 /* 60 secs */
#define DEF_IDLE_INTERVAL 120 /* 2 mins */
struct cp_control { struct cp_control {
int reason; int reason;
...@@ -723,6 +725,7 @@ enum { ...@@ -723,6 +725,7 @@ enum {
enum { enum {
CP_TIME, CP_TIME,
REQ_TIME,
MAX_TIME, MAX_TIME,
}; };
...@@ -856,6 +859,18 @@ static inline bool f2fs_time_over(struct f2fs_sb_info *sbi, int type) ...@@ -856,6 +859,18 @@ static inline bool f2fs_time_over(struct f2fs_sb_info *sbi, int type)
return time_after(jiffies, sbi->last_time[type] + interval); return time_after(jiffies, sbi->last_time[type] + interval);
} }
static inline bool is_idle(struct f2fs_sb_info *sbi)
{
struct block_device *bdev = sbi->sb->s_bdev;
struct request_queue *q = bdev_get_queue(bdev);
struct request_list *rl = &q->root_rl;
if (rl->count[BLK_RW_SYNC] || rl->count[BLK_RW_ASYNC])
return 0;
return f2fs_time_over(sbi, REQ_TIME);
}
/* /*
* Inline functions * Inline functions
*/ */
......
...@@ -96,6 +96,7 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma, ...@@ -96,6 +96,7 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma,
clear_cold_data(page); clear_cold_data(page);
out: out:
sb_end_pagefault(inode->i_sb); sb_end_pagefault(inode->i_sb);
f2fs_update_time(sbi, REQ_TIME);
return block_page_mkwrite_return(err); return block_page_mkwrite_return(err);
} }
...@@ -280,6 +281,7 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) ...@@ -280,6 +281,7 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
remove_ino_entry(sbi, ino, UPDATE_INO); remove_ino_entry(sbi, ino, UPDATE_INO);
clear_inode_flag(fi, FI_UPDATE_WRITE); clear_inode_flag(fi, FI_UPDATE_WRITE);
ret = f2fs_issue_flush(sbi); ret = f2fs_issue_flush(sbi);
f2fs_update_time(sbi, REQ_TIME);
out: out:
trace_f2fs_sync_file_exit(inode, need_cp, datasync, ret); trace_f2fs_sync_file_exit(inode, need_cp, datasync, ret);
f2fs_trace_ios(NULL, 1); f2fs_trace_ios(NULL, 1);
...@@ -485,6 +487,7 @@ int truncate_data_blocks_range(struct dnode_of_data *dn, int count) ...@@ -485,6 +487,7 @@ int truncate_data_blocks_range(struct dnode_of_data *dn, int count)
} }
dn->ofs_in_node = ofs; dn->ofs_in_node = ofs;
f2fs_update_time(sbi, REQ_TIME);
trace_f2fs_truncate_data_blocks_range(dn->inode, dn->nid, trace_f2fs_truncate_data_blocks_range(dn->inode, dn->nid,
dn->ofs_in_node, nr_free); dn->ofs_in_node, nr_free);
return nr_free; return nr_free;
...@@ -1236,6 +1239,7 @@ static long f2fs_fallocate(struct file *file, int mode, ...@@ -1236,6 +1239,7 @@ static long f2fs_fallocate(struct file *file, int mode,
if (!ret) { if (!ret) {
inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_mtime = inode->i_ctime = CURRENT_TIME;
mark_inode_dirty(inode); mark_inode_dirty(inode);
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
} }
out: out:
...@@ -1351,6 +1355,8 @@ static int f2fs_ioc_start_atomic_write(struct file *filp) ...@@ -1351,6 +1355,8 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
return ret; return ret;
set_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE); set_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE);
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
return 0; return 0;
} }
...@@ -1398,6 +1404,7 @@ static int f2fs_ioc_start_volatile_write(struct file *filp) ...@@ -1398,6 +1404,7 @@ static int f2fs_ioc_start_volatile_write(struct file *filp)
return ret; return ret;
set_inode_flag(F2FS_I(inode), FI_VOLATILE_FILE); set_inode_flag(F2FS_I(inode), FI_VOLATILE_FILE);
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
return 0; return 0;
} }
...@@ -1439,6 +1446,7 @@ static int f2fs_ioc_abort_volatile_write(struct file *filp) ...@@ -1439,6 +1446,7 @@ static int f2fs_ioc_abort_volatile_write(struct file *filp)
} }
mnt_drop_write_file(filp); mnt_drop_write_file(filp);
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
return ret; return ret;
} }
...@@ -1478,6 +1486,7 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) ...@@ -1478,6 +1486,7 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
default: default:
return -EINVAL; return -EINVAL;
} }
f2fs_update_time(sbi, REQ_TIME);
return 0; return 0;
} }
...@@ -1508,6 +1517,7 @@ static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg) ...@@ -1508,6 +1517,7 @@ static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg)
if (copy_to_user((struct fstrim_range __user *)arg, &range, if (copy_to_user((struct fstrim_range __user *)arg, &range,
sizeof(range))) sizeof(range)))
return -EFAULT; return -EFAULT;
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
return 0; return 0;
} }
...@@ -1531,6 +1541,7 @@ static int f2fs_ioc_set_encryption_policy(struct file *filp, unsigned long arg) ...@@ -1531,6 +1541,7 @@ static int f2fs_ioc_set_encryption_policy(struct file *filp, unsigned long arg)
sizeof(policy))) sizeof(policy)))
return -EFAULT; return -EFAULT;
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
return f2fs_process_policy(&policy, inode); return f2fs_process_policy(&policy, inode);
#else #else
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -1807,6 +1818,7 @@ static int f2fs_ioc_defragment(struct file *filp, unsigned long arg) ...@@ -1807,6 +1818,7 @@ static int f2fs_ioc_defragment(struct file *filp, unsigned long arg)
} }
err = f2fs_defragment_range(sbi, filp, &range); err = f2fs_defragment_range(sbi, filp, &range);
f2fs_update_time(sbi, REQ_TIME);
if (err < 0) if (err < 0)
goto out; goto out;
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/freezer.h> #include <linux/freezer.h>
#include <linux/blkdev.h>
#include "f2fs.h" #include "f2fs.h"
#include "node.h" #include "node.h"
......
...@@ -100,11 +100,3 @@ static inline bool has_enough_invalid_blocks(struct f2fs_sb_info *sbi) ...@@ -100,11 +100,3 @@ static inline bool has_enough_invalid_blocks(struct f2fs_sb_info *sbi)
return true; return true;
return false; return false;
} }
static inline int is_idle(struct f2fs_sb_info *sbi)
{
struct block_device *bdev = sbi->sb->s_bdev;
struct request_queue *q = bdev_get_queue(bdev);
struct request_list *rl = &q->root_rl;
return !(rl->count[BLK_RW_SYNC]) && !(rl->count[BLK_RW_ASYNC]);
}
...@@ -293,7 +293,7 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi) ...@@ -293,7 +293,7 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi)
if (!available_free_memory(sbi, NAT_ENTRIES) || if (!available_free_memory(sbi, NAT_ENTRIES) ||
excess_prefree_segs(sbi) || excess_prefree_segs(sbi) ||
!available_free_memory(sbi, INO_ENTRIES) || !available_free_memory(sbi, INO_ENTRIES) ||
f2fs_time_over(sbi, CP_TIME)) { (is_idle(sbi) && f2fs_time_over(sbi, CP_TIME))) {
if (test_opt(sbi, DATA_FLUSH)) if (test_opt(sbi, DATA_FLUSH))
sync_dirty_inodes(sbi, FILE_INODE); sync_dirty_inodes(sbi, FILE_INODE);
f2fs_sync_fs(sbi->sb, true); f2fs_sync_fs(sbi->sb, true);
......
...@@ -219,6 +219,7 @@ F2FS_RW_ATTR(NM_INFO, f2fs_nm_info, ra_nid_pages, ra_nid_pages); ...@@ -219,6 +219,7 @@ F2FS_RW_ATTR(NM_INFO, f2fs_nm_info, ra_nid_pages, ra_nid_pages);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_victim_search, max_victim_search); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_victim_search, max_victim_search);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, cp_interval, interval_time[CP_TIME]); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, cp_interval, interval_time[CP_TIME]);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, idle_interval, interval_time[REQ_TIME]);
#define ATTR_LIST(name) (&f2fs_attr_##name.attr) #define ATTR_LIST(name) (&f2fs_attr_##name.attr)
static struct attribute *f2fs_attrs[] = { static struct attribute *f2fs_attrs[] = {
...@@ -237,6 +238,7 @@ static struct attribute *f2fs_attrs[] = { ...@@ -237,6 +238,7 @@ static struct attribute *f2fs_attrs[] = {
ATTR_LIST(ram_thresh), ATTR_LIST(ram_thresh),
ATTR_LIST(ra_nid_pages), ATTR_LIST(ra_nid_pages),
ATTR_LIST(cp_interval), ATTR_LIST(cp_interval),
ATTR_LIST(idle_interval),
NULL, NULL,
}; };
...@@ -1123,6 +1125,7 @@ static void init_sb_info(struct f2fs_sb_info *sbi) ...@@ -1123,6 +1125,7 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
sbi->dir_level = DEF_DIR_LEVEL; sbi->dir_level = DEF_DIR_LEVEL;
sbi->interval_time[CP_TIME] = DEF_CP_INTERVAL; sbi->interval_time[CP_TIME] = DEF_CP_INTERVAL;
sbi->interval_time[REQ_TIME] = DEF_IDLE_INTERVAL;
clear_sbi_flag(sbi, SBI_NEED_FSCK); clear_sbi_flag(sbi, SBI_NEED_FSCK);
INIT_LIST_HEAD(&sbi->s_list); INIT_LIST_HEAD(&sbi->s_list);
...@@ -1468,6 +1471,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -1468,6 +1471,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
} }
f2fs_update_time(sbi, CP_TIME); f2fs_update_time(sbi, CP_TIME);
f2fs_update_time(sbi, REQ_TIME);
return 0; return 0;
free_kobj: free_kobj:
......
...@@ -618,5 +618,6 @@ int f2fs_setxattr(struct inode *inode, int index, const char *name, ...@@ -618,5 +618,6 @@ int f2fs_setxattr(struct inode *inode, int index, const char *name,
up_write(&F2FS_I(inode)->i_sem); up_write(&F2FS_I(inode)->i_sem);
f2fs_unlock_op(sbi); f2fs_unlock_op(sbi);
f2fs_update_time(sbi, REQ_TIME);
return err; return err;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment