Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+44 -10
+6
Documentation/ABI/testing/sysfs-fs-f2fs
··· 87 87 Description: 88 88 Controls the checkpoint timing. 89 89 90 + What: /sys/fs/f2fs/<disk>/idle_interval 91 + Date: January 2016 92 + Contact: "Jaegeuk Kim" <jaegeuk@kernel.org> 93 + Description: 94 + Controls the idle timing. 95 + 90 96 What: /sys/fs/f2fs/<disk>/ra_nid_pages 91 97 Date: October 2015 92 98 Contact: "Chao Yu" <chao2.yu@samsung.com>
+1
fs/f2fs/data.c
··· 1596 1596 } 1597 1597 1598 1598 f2fs_put_page(page, 1); 1599 + f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); 1599 1600 return copied; 1600 1601 } 1601 1602
+4
fs/f2fs/dir.c
··· 636 636 f2fs_put_page(dentry_page, 1); 637 637 out: 638 638 f2fs_fname_free_filename(&fname); 639 + f2fs_update_time(F2FS_I_SB(dir), REQ_TIME); 639 640 return err; 640 641 } 641 642 ··· 658 657 clear_inode_flag(F2FS_I(inode), FI_NEW_INODE); 659 658 fail: 660 659 up_write(&F2FS_I(inode)->i_sem); 660 + f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); 661 661 return err; 662 662 } 663 663 ··· 702 700 unsigned int bit_pos; 703 701 int slots = GET_DENTRY_SLOTS(le16_to_cpu(dentry->name_len)); 704 702 int i; 703 + 704 + f2fs_update_time(F2FS_I_SB(dir), REQ_TIME); 705 705 706 706 if (f2fs_has_inline_dentry(dir)) 707 707 return f2fs_delete_inline_entry(dentry, page, dir, inode);
+15
fs/f2fs/f2fs.h
··· 21 21 #include <linux/sched.h> 22 22 #include <linux/vmalloc.h> 23 23 #include <linux/bio.h> 24 + #include <linux/blkdev.h> 24 25 25 26 #ifdef CONFIG_F2FS_CHECK_FS 26 27 #define f2fs_bug_on(sbi, condition) BUG_ON(condition) ··· 127 126 #define BATCHED_TRIM_BLOCKS(sbi) \ 128 127 (BATCHED_TRIM_SEGMENTS(sbi) << (sbi)->log_blocks_per_seg) 129 128 #define DEF_CP_INTERVAL 60 /* 60 secs */ 129 + #define DEF_IDLE_INTERVAL 120 /* 2 mins */ 130 130 131 131 struct cp_control { 132 132 int reason; ··· 725 723 726 724 enum { 727 725 CP_TIME, 726 + REQ_TIME, 728 727 MAX_TIME, 729 728 }; 730 729 ··· 857 854 unsigned long interval = timespec_to_jiffies(&ts); 858 855 859 856 return time_after(jiffies, sbi->last_time[type] + interval); 857 + } 858 + 859 + static inline bool is_idle(struct f2fs_sb_info *sbi) 860 + { 861 + struct block_device *bdev = sbi->sb->s_bdev; 862 + struct request_queue *q = bdev_get_queue(bdev); 863 + struct request_list *rl = &q->root_rl; 864 + 865 + if (rl->count[BLK_RW_SYNC] || rl->count[BLK_RW_ASYNC]) 866 + return 0; 867 + 868 + return f2fs_time_over(sbi, REQ_TIME); 860 869 } 861 870 862 871 /*
+12
fs/f2fs/file.c
··· 96 96 clear_cold_data(page); 97 97 out: 98 98 sb_end_pagefault(inode->i_sb); 99 + f2fs_update_time(sbi, REQ_TIME); 99 100 return block_page_mkwrite_return(err); 100 101 } 101 102 ··· 281 280 remove_ino_entry(sbi, ino, UPDATE_INO); 282 281 clear_inode_flag(fi, FI_UPDATE_WRITE); 283 282 ret = f2fs_issue_flush(sbi); 283 + f2fs_update_time(sbi, REQ_TIME); 284 284 out: 285 285 trace_f2fs_sync_file_exit(inode, need_cp, datasync, ret); 286 286 f2fs_trace_ios(NULL, 1); ··· 487 485 } 488 486 dn->ofs_in_node = ofs; 489 487 488 + f2fs_update_time(sbi, REQ_TIME); 490 489 trace_f2fs_truncate_data_blocks_range(dn->inode, dn->nid, 491 490 dn->ofs_in_node, nr_free); 492 491 return nr_free; ··· 1239 1236 if (!ret) { 1240 1237 inode->i_mtime = inode->i_ctime = CURRENT_TIME; 1241 1238 mark_inode_dirty(inode); 1239 + f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); 1242 1240 } 1243 1241 1244 1242 out: ··· 1355 1351 return ret; 1356 1352 1357 1353 set_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE); 1354 + f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); 1355 + 1358 1356 return 0; 1359 1357 } 1360 1358 ··· 1404 1398 return ret; 1405 1399 1406 1400 set_inode_flag(F2FS_I(inode), FI_VOLATILE_FILE); 1401 + f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); 1407 1402 return 0; 1408 1403 } 1409 1404 ··· 1446 1439 } 1447 1440 1448 1441 mnt_drop_write_file(filp); 1442 + f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); 1449 1443 return ret; 1450 1444 } 1451 1445 ··· 1486 1478 default: 1487 1479 return -EINVAL; 1488 1480 } 1481 + f2fs_update_time(sbi, REQ_TIME); 1489 1482 return 0; 1490 1483 } 1491 1484 ··· 1517 1508 if (copy_to_user((struct fstrim_range __user *)arg, &range, 1518 1509 sizeof(range))) 1519 1510 return -EFAULT; 1511 + f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); 1520 1512 return 0; 1521 1513 } 1522 1514 ··· 1541 1531 sizeof(policy))) 1542 1532 return -EFAULT; 1543 1533 1534 + f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); 1544 1535 return f2fs_process_policy(&policy, inode); 1545 1536 #else 1546 1537 return -EOPNOTSUPP; ··· 1818 1807 } 1819 1808 1820 1809 err = f2fs_defragment_range(sbi, filp, &range); 1810 + f2fs_update_time(sbi, REQ_TIME); 1821 1811 if (err < 0) 1822 1812 goto out; 1823 1813
-1
fs/f2fs/gc.c
··· 16 16 #include <linux/kthread.h> 17 17 #include <linux/delay.h> 18 18 #include <linux/freezer.h> 19 - #include <linux/blkdev.h> 20 19 21 20 #include "f2fs.h" 22 21 #include "node.h"
-8
fs/f2fs/gc.h
··· 100 100 return true; 101 101 return false; 102 102 } 103 - 104 - static 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 - }
+1 -1
fs/f2fs/segment.c
··· 293 293 if (!available_free_memory(sbi, NAT_ENTRIES) || 294 294 excess_prefree_segs(sbi) || 295 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 297 if (test_opt(sbi, DATA_FLUSH)) 298 298 sync_dirty_inodes(sbi, FILE_INODE); 299 299 f2fs_sync_fs(sbi->sb, true);
+4
fs/f2fs/super.c
··· 219 219 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_victim_search, max_victim_search); 220 220 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level); 221 221 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, cp_interval, interval_time[CP_TIME]); 222 + F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, idle_interval, interval_time[REQ_TIME]); 222 223 223 224 #define ATTR_LIST(name) (&f2fs_attr_##name.attr) 224 225 static struct attribute *f2fs_attrs[] = { ··· 238 237 ATTR_LIST(ram_thresh), 239 238 ATTR_LIST(ra_nid_pages), 240 239 ATTR_LIST(cp_interval), 240 + ATTR_LIST(idle_interval), 241 241 NULL, 242 242 }; 243 243 ··· 1125 1123 1126 1124 sbi->dir_level = DEF_DIR_LEVEL; 1127 1125 sbi->interval_time[CP_TIME] = DEF_CP_INTERVAL; 1126 + sbi->interval_time[REQ_TIME] = DEF_IDLE_INTERVAL; 1128 1127 clear_sbi_flag(sbi, SBI_NEED_FSCK); 1129 1128 1130 1129 INIT_LIST_HEAD(&sbi->s_list); ··· 1471 1468 } 1472 1469 1473 1470 f2fs_update_time(sbi, CP_TIME); 1471 + f2fs_update_time(sbi, REQ_TIME); 1474 1472 return 0; 1475 1473 1476 1474 free_kobj:
+1
fs/f2fs/xattr.c
··· 618 618 up_write(&F2FS_I(inode)->i_sem); 619 619 f2fs_unlock_op(sbi); 620 620 621 + f2fs_update_time(sbi, REQ_TIME); 621 622 return err; 622 623 }