aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk@kernel.org>2016-01-08 19:57:48 -0500
committerJaegeuk Kim <jaegeuk@kernel.org>2016-01-11 18:56:37 -0500
commitd0239e1bf5204d602281f93c01d46bcf3531098d (patch)
treee95f1b3567398de0dbe532689671050325e79eb5
parent6beceb5427aa8731f958d2484e0fd8ff21d604dc (diff)
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: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r--Documentation/ABI/testing/sysfs-fs-f2fs6
-rw-r--r--fs/f2fs/data.c1
-rw-r--r--fs/f2fs/dir.c4
-rw-r--r--fs/f2fs/f2fs.h15
-rw-r--r--fs/f2fs/file.c12
-rw-r--r--fs/f2fs/gc.c1
-rw-r--r--fs/f2fs/gc.h8
-rw-r--r--fs/f2fs/segment.c2
-rw-r--r--fs/f2fs/super.c4
-rw-r--r--fs/f2fs/xattr.c1
10 files changed, 44 insertions, 10 deletions
diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs
index 0345f2d1c727..e5200f354abf 100644
--- a/Documentation/ABI/testing/sysfs-fs-f2fs
+++ b/Documentation/ABI/testing/sysfs-fs-f2fs
@@ -87,6 +87,12 @@ Contact: "Jaegeuk Kim" <jaegeuk@kernel.org>
87Description: 87Description:
88 Controls the checkpoint timing. 88 Controls the checkpoint timing.
89 89
90What: /sys/fs/f2fs/<disk>/idle_interval
91Date: January 2016
92Contact: "Jaegeuk Kim" <jaegeuk@kernel.org>
93Description:
94 Controls the idle timing.
95
90What: /sys/fs/f2fs/<disk>/ra_nid_pages 96What: /sys/fs/f2fs/<disk>/ra_nid_pages
91Date: October 2015 97Date: October 2015
92Contact: "Chao Yu" <chao2.yu@samsung.com> 98Contact: "Chao Yu" <chao2.yu@samsung.com>
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index a3bce12b0cce..ac9e7c6aac74 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1596,6 +1596,7 @@ static int f2fs_write_end(struct file *file,
1596 } 1596 }
1597 1597
1598 f2fs_put_page(page, 1); 1598 f2fs_put_page(page, 1);
1599 f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
1599 return copied; 1600 return copied;
1600} 1601}
1601 1602
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 29bb8dd76a46..faa7495e2d7e 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -636,6 +636,7 @@ fail:
636 f2fs_put_page(dentry_page, 1); 636 f2fs_put_page(dentry_page, 1);
637out: 637out:
638 f2fs_fname_free_filename(&fname); 638 f2fs_fname_free_filename(&fname);
639 f2fs_update_time(F2FS_I_SB(dir), REQ_TIME);
639 return err; 640 return err;
640} 641}
641 642
@@ -657,6 +658,7 @@ int f2fs_do_tmpfile(struct inode *inode, struct inode *dir)
657 clear_inode_flag(F2FS_I(inode), FI_NEW_INODE); 658 clear_inode_flag(F2FS_I(inode), FI_NEW_INODE);
658fail: 659fail:
659 up_write(&F2FS_I(inode)->i_sem); 660 up_write(&F2FS_I(inode)->i_sem);
661 f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
660 return err; 662 return err;
661} 663}
662 664
@@ -701,6 +703,8 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
701 int slots = GET_DENTRY_SLOTS(le16_to_cpu(dentry->name_len)); 703 int slots = GET_DENTRY_SLOTS(le16_to_cpu(dentry->name_len));
702 int i; 704 int i;
703 705
706 f2fs_update_time(F2FS_I_SB(dir), REQ_TIME);
707
704 if (f2fs_has_inline_dentry(dir)) 708 if (f2fs_has_inline_dentry(dir))
705 return f2fs_delete_inline_entry(dentry, page, dir, inode); 709 return f2fs_delete_inline_entry(dentry, page, dir, inode);
706 710
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 5bbb6a407e79..4331b9fe6f27 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -21,6 +21,7 @@
21#include <linux/sched.h> 21#include <linux/sched.h>
22#include <linux/vmalloc.h> 22#include <linux/vmalloc.h>
23#include <linux/bio.h> 23#include <linux/bio.h>
24#include <linux/blkdev.h>
24 25
25#ifdef CONFIG_F2FS_CHECK_FS 26#ifdef CONFIG_F2FS_CHECK_FS
26#define f2fs_bug_on(sbi, condition) BUG_ON(condition) 27#define f2fs_bug_on(sbi, condition) BUG_ON(condition)
@@ -126,6 +127,7 @@ enum {
126#define BATCHED_TRIM_BLOCKS(sbi) \ 127#define BATCHED_TRIM_BLOCKS(sbi) \
127 (BATCHED_TRIM_SEGMENTS(sbi) << (sbi)->log_blocks_per_seg) 128 (BATCHED_TRIM_SEGMENTS(sbi) << (sbi)->log_blocks_per_seg)
128#define DEF_CP_INTERVAL 60 /* 60 secs */ 129#define DEF_CP_INTERVAL 60 /* 60 secs */
130#define DEF_IDLE_INTERVAL 120 /* 2 mins */
129 131
130struct cp_control { 132struct cp_control {
131 int reason; 133 int reason;
@@ -723,6 +725,7 @@ enum {
723 725
724enum { 726enum {
725 CP_TIME, 727 CP_TIME,
728 REQ_TIME,
726 MAX_TIME, 729 MAX_TIME,
727}; 730};
728 731
@@ -856,6 +859,18 @@ static inline bool f2fs_time_over(struct f2fs_sb_info *sbi, int type)
856 return time_after(jiffies, sbi->last_time[type] + interval); 859 return time_after(jiffies, sbi->last_time[type] + interval);
857} 860}
858 861
862static inline bool is_idle(struct f2fs_sb_info *sbi)
863{
864 struct block_device *bdev = sbi->sb->s_bdev;
865 struct request_queue *q = bdev_get_queue(bdev);
866 struct request_list *rl = &q->root_rl;
867
868 if (rl->count[BLK_RW_SYNC] || rl->count[BLK_RW_ASYNC])
869 return 0;
870
871 return f2fs_time_over(sbi, REQ_TIME);
872}
873
859/* 874/*
860 * Inline functions 875 * Inline functions
861 */ 876 */
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index ff06827aa369..3d43857e9892 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -96,6 +96,7 @@ mapped:
96 clear_cold_data(page); 96 clear_cold_data(page);
97out: 97out:
98 sb_end_pagefault(inode->i_sb); 98 sb_end_pagefault(inode->i_sb);
99 f2fs_update_time(sbi, REQ_TIME);
99 return block_page_mkwrite_return(err); 100 return block_page_mkwrite_return(err);
100} 101}
101 102
@@ -280,6 +281,7 @@ flush_out:
280 remove_ino_entry(sbi, ino, UPDATE_INO); 281 remove_ino_entry(sbi, ino, UPDATE_INO);
281 clear_inode_flag(fi, FI_UPDATE_WRITE); 282 clear_inode_flag(fi, FI_UPDATE_WRITE);
282 ret = f2fs_issue_flush(sbi); 283 ret = f2fs_issue_flush(sbi);
284 f2fs_update_time(sbi, REQ_TIME);
283out: 285out:
284 trace_f2fs_sync_file_exit(inode, need_cp, datasync, ret); 286 trace_f2fs_sync_file_exit(inode, need_cp, datasync, ret);
285 f2fs_trace_ios(NULL, 1); 287 f2fs_trace_ios(NULL, 1);
@@ -485,6 +487,7 @@ int truncate_data_blocks_range(struct dnode_of_data *dn, int count)
485 } 487 }
486 dn->ofs_in_node = ofs; 488 dn->ofs_in_node = ofs;
487 489
490 f2fs_update_time(sbi, REQ_TIME);
488 trace_f2fs_truncate_data_blocks_range(dn->inode, dn->nid, 491 trace_f2fs_truncate_data_blocks_range(dn->inode, dn->nid,
489 dn->ofs_in_node, nr_free); 492 dn->ofs_in_node, nr_free);
490 return nr_free; 493 return nr_free;
@@ -1236,6 +1239,7 @@ static long f2fs_fallocate(struct file *file, int mode,
1236 if (!ret) { 1239 if (!ret) {
1237 inode->i_mtime = inode->i_ctime = CURRENT_TIME; 1240 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
1238 mark_inode_dirty(inode); 1241 mark_inode_dirty(inode);
1242 f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
1239 } 1243 }
1240 1244
1241out: 1245out:
@@ -1351,6 +1355,8 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
1351 return ret; 1355 return ret;
1352 1356
1353 set_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE); 1357 set_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE);
1358 f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
1359
1354 return 0; 1360 return 0;
1355} 1361}
1356 1362
@@ -1398,6 +1404,7 @@ static int f2fs_ioc_start_volatile_write(struct file *filp)
1398 return ret; 1404 return ret;
1399 1405
1400 set_inode_flag(F2FS_I(inode), FI_VOLATILE_FILE); 1406 set_inode_flag(F2FS_I(inode), FI_VOLATILE_FILE);
1407 f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
1401 return 0; 1408 return 0;
1402} 1409}
1403 1410
@@ -1439,6 +1446,7 @@ static int f2fs_ioc_abort_volatile_write(struct file *filp)
1439 } 1446 }
1440 1447
1441 mnt_drop_write_file(filp); 1448 mnt_drop_write_file(filp);
1449 f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
1442 return ret; 1450 return ret;
1443} 1451}
1444 1452
@@ -1478,6 +1486,7 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
1478 default: 1486 default:
1479 return -EINVAL; 1487 return -EINVAL;
1480 } 1488 }
1489 f2fs_update_time(sbi, REQ_TIME);
1481 return 0; 1490 return 0;
1482} 1491}
1483 1492
@@ -1508,6 +1517,7 @@ static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg)
1508 if (copy_to_user((struct fstrim_range __user *)arg, &range, 1517 if (copy_to_user((struct fstrim_range __user *)arg, &range,
1509 sizeof(range))) 1518 sizeof(range)))
1510 return -EFAULT; 1519 return -EFAULT;
1520 f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
1511 return 0; 1521 return 0;
1512} 1522}
1513 1523
@@ -1531,6 +1541,7 @@ static int f2fs_ioc_set_encryption_policy(struct file *filp, unsigned long arg)
1531 sizeof(policy))) 1541 sizeof(policy)))
1532 return -EFAULT; 1542 return -EFAULT;
1533 1543
1544 f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
1534 return f2fs_process_policy(&policy, inode); 1545 return f2fs_process_policy(&policy, inode);
1535#else 1546#else
1536 return -EOPNOTSUPP; 1547 return -EOPNOTSUPP;
@@ -1807,6 +1818,7 @@ static int f2fs_ioc_defragment(struct file *filp, unsigned long arg)
1807 } 1818 }
1808 1819
1809 err = f2fs_defragment_range(sbi, filp, &range); 1820 err = f2fs_defragment_range(sbi, filp, &range);
1821 f2fs_update_time(sbi, REQ_TIME);
1810 if (err < 0) 1822 if (err < 0)
1811 goto out; 1823 goto out;
1812 1824
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index c09be339569c..f610c2a9bdde 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -16,7 +16,6 @@
16#include <linux/kthread.h> 16#include <linux/kthread.h>
17#include <linux/delay.h> 17#include <linux/delay.h>
18#include <linux/freezer.h> 18#include <linux/freezer.h>
19#include <linux/blkdev.h>
20 19
21#include "f2fs.h" 20#include "f2fs.h"
22#include "node.h" 21#include "node.h"
diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h
index b4a65be9f7d3..a993967dcdb9 100644
--- a/fs/f2fs/gc.h
+++ b/fs/f2fs/gc.h
@@ -100,11 +100,3 @@ static inline bool has_enough_invalid_blocks(struct f2fs_sb_info *sbi)
100 return true; 100 return true;
101 return false; 101 return false;
102} 102}
103
104static inline int is_idle(struct f2fs_sb_info *sbi)
105{
106 struct block_device *bdev = sbi->sb->s_bdev;
107 struct request_queue *q = bdev_get_queue(bdev);
108 struct request_list *rl = &q->root_rl;
109 return !(rl->count[BLK_RW_SYNC]) && !(rl->count[BLK_RW_ASYNC]);
110}
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index fed23d5a7b34..d8ad1abfa4fd 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -293,7 +293,7 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi)
293 if (!available_free_memory(sbi, NAT_ENTRIES) || 293 if (!available_free_memory(sbi, NAT_ENTRIES) ||
294 excess_prefree_segs(sbi) || 294 excess_prefree_segs(sbi) ||
295 !available_free_memory(sbi, INO_ENTRIES) || 295 !available_free_memory(sbi, INO_ENTRIES) ||
296 f2fs_time_over(sbi, CP_TIME)) { 296 (is_idle(sbi) && f2fs_time_over(sbi, CP_TIME))) {
297 if (test_opt(sbi, DATA_FLUSH)) 297 if (test_opt(sbi, DATA_FLUSH))
298 sync_dirty_inodes(sbi, FILE_INODE); 298 sync_dirty_inodes(sbi, FILE_INODE);
299 f2fs_sync_fs(sbi->sb, true); 299 f2fs_sync_fs(sbi->sb, true);
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 787047f59c00..3bf990b80026 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -219,6 +219,7 @@ F2FS_RW_ATTR(NM_INFO, f2fs_nm_info, ra_nid_pages, ra_nid_pages);
219F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_victim_search, max_victim_search); 219F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_victim_search, max_victim_search);
220F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level); 220F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level);
221F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, cp_interval, interval_time[CP_TIME]); 221F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, cp_interval, interval_time[CP_TIME]);
222F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, idle_interval, interval_time[REQ_TIME]);
222 223
223#define ATTR_LIST(name) (&f2fs_attr_##name.attr) 224#define ATTR_LIST(name) (&f2fs_attr_##name.attr)
224static struct attribute *f2fs_attrs[] = { 225static struct attribute *f2fs_attrs[] = {
@@ -237,6 +238,7 @@ static struct attribute *f2fs_attrs[] = {
237 ATTR_LIST(ram_thresh), 238 ATTR_LIST(ram_thresh),
238 ATTR_LIST(ra_nid_pages), 239 ATTR_LIST(ra_nid_pages),
239 ATTR_LIST(cp_interval), 240 ATTR_LIST(cp_interval),
241 ATTR_LIST(idle_interval),
240 NULL, 242 NULL,
241}; 243};
242 244
@@ -1123,6 +1125,7 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
1123 1125
1124 sbi->dir_level = DEF_DIR_LEVEL; 1126 sbi->dir_level = DEF_DIR_LEVEL;
1125 sbi->interval_time[CP_TIME] = DEF_CP_INTERVAL; 1127 sbi->interval_time[CP_TIME] = DEF_CP_INTERVAL;
1128 sbi->interval_time[REQ_TIME] = DEF_IDLE_INTERVAL;
1126 clear_sbi_flag(sbi, SBI_NEED_FSCK); 1129 clear_sbi_flag(sbi, SBI_NEED_FSCK);
1127 1130
1128 INIT_LIST_HEAD(&sbi->s_list); 1131 INIT_LIST_HEAD(&sbi->s_list);
@@ -1468,6 +1471,7 @@ try_onemore:
1468 } 1471 }
1469 1472
1470 f2fs_update_time(sbi, CP_TIME); 1473 f2fs_update_time(sbi, CP_TIME);
1474 f2fs_update_time(sbi, REQ_TIME);
1471 return 0; 1475 return 0;
1472 1476
1473free_kobj: 1477free_kobj:
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index 822a8af89c12..0108f487cc8e 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -618,5 +618,6 @@ int f2fs_setxattr(struct inode *inode, int index, const char *name,
618 up_write(&F2FS_I(inode)->i_sem); 618 up_write(&F2FS_I(inode)->i_sem);
619 f2fs_unlock_op(sbi); 619 f2fs_unlock_op(sbi);
620 620
621 f2fs_update_time(sbi, REQ_TIME);
621 return err; 622 return err;
622} 623}