Skip to content

Commit

Permalink
f2fs: detect idle time depending on user behavior
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jaegeuk Kim committed Jan 11, 2016
1 parent 6beceb5 commit d0239e1
Show file tree
Hide file tree
Showing 10 changed files with 44 additions and 10 deletions.
6 changes: 6 additions & 0 deletions Documentation/ABI/testing/sysfs-fs-f2fs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ Contact: "Jaegeuk Kim" <jaegeuk@kernel.org>
Description:
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
Date: October 2015
Contact: "Chao Yu" <chao2.yu@samsung.com>
Expand Down
1 change: 1 addition & 0 deletions fs/f2fs/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -1596,6 +1596,7 @@ static int f2fs_write_end(struct file *file,
}

f2fs_put_page(page, 1);
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
return copied;
}

Expand Down
4 changes: 4 additions & 0 deletions fs/f2fs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,7 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name,
f2fs_put_page(dentry_page, 1);
out:
f2fs_fname_free_filename(&fname);
f2fs_update_time(F2FS_I_SB(dir), REQ_TIME);
return err;
}

Expand All @@ -657,6 +658,7 @@ int f2fs_do_tmpfile(struct inode *inode, struct inode *dir)
clear_inode_flag(F2FS_I(inode), FI_NEW_INODE);
fail:
up_write(&F2FS_I(inode)->i_sem);
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
return err;
}

Expand Down Expand Up @@ -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 i;

f2fs_update_time(F2FS_I_SB(dir), REQ_TIME);

if (f2fs_has_inline_dentry(dir))
return f2fs_delete_inline_entry(dentry, page, dir, inode);

Expand Down
15 changes: 15 additions & 0 deletions fs/f2fs/f2fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <linux/sched.h>
#include <linux/vmalloc.h>
#include <linux/bio.h>
#include <linux/blkdev.h>

#ifdef CONFIG_F2FS_CHECK_FS
#define f2fs_bug_on(sbi, condition) BUG_ON(condition)
Expand Down Expand Up @@ -126,6 +127,7 @@ enum {
#define BATCHED_TRIM_BLOCKS(sbi) \
(BATCHED_TRIM_SEGMENTS(sbi) << (sbi)->log_blocks_per_seg)
#define DEF_CP_INTERVAL 60 /* 60 secs */
#define DEF_IDLE_INTERVAL 120 /* 2 mins */

struct cp_control {
int reason;
Expand Down Expand Up @@ -723,6 +725,7 @@ enum {

enum {
CP_TIME,
REQ_TIME,
MAX_TIME,
};

Expand Down Expand Up @@ -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);
}

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
*/
Expand Down
12 changes: 12 additions & 0 deletions fs/f2fs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma,
clear_cold_data(page);
out:
sb_end_pagefault(inode->i_sb);
f2fs_update_time(sbi, REQ_TIME);
return block_page_mkwrite_return(err);
}

Expand Down Expand Up @@ -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);
clear_inode_flag(fi, FI_UPDATE_WRITE);
ret = f2fs_issue_flush(sbi);
f2fs_update_time(sbi, REQ_TIME);
out:
trace_f2fs_sync_file_exit(inode, need_cp, datasync, ret);
f2fs_trace_ios(NULL, 1);
Expand Down Expand Up @@ -485,6 +487,7 @@ int truncate_data_blocks_range(struct dnode_of_data *dn, int count)
}
dn->ofs_in_node = ofs;

f2fs_update_time(sbi, REQ_TIME);
trace_f2fs_truncate_data_blocks_range(dn->inode, dn->nid,
dn->ofs_in_node, nr_free);
return nr_free;
Expand Down Expand Up @@ -1236,6 +1239,7 @@ static long f2fs_fallocate(struct file *file, int mode,
if (!ret) {
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
mark_inode_dirty(inode);
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
}

out:
Expand Down Expand Up @@ -1351,6 +1355,8 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
return ret;

set_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE);
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);

return 0;
}

Expand Down Expand Up @@ -1398,6 +1404,7 @@ static int f2fs_ioc_start_volatile_write(struct file *filp)
return ret;

set_inode_flag(F2FS_I(inode), FI_VOLATILE_FILE);
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
return 0;
}

Expand Down Expand Up @@ -1439,6 +1446,7 @@ static int f2fs_ioc_abort_volatile_write(struct file *filp)
}

mnt_drop_write_file(filp);
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
return ret;
}

Expand Down Expand Up @@ -1478,6 +1486,7 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
default:
return -EINVAL;
}
f2fs_update_time(sbi, REQ_TIME);
return 0;
}

Expand Down Expand Up @@ -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,
sizeof(range)))
return -EFAULT;
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
return 0;
}

Expand All @@ -1531,6 +1541,7 @@ static int f2fs_ioc_set_encryption_policy(struct file *filp, unsigned long arg)
sizeof(policy)))
return -EFAULT;

f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
return f2fs_process_policy(&policy, inode);
#else
return -EOPNOTSUPP;
Expand Down Expand Up @@ -1807,6 +1818,7 @@ static int f2fs_ioc_defragment(struct file *filp, unsigned long arg)
}

err = f2fs_defragment_range(sbi, filp, &range);
f2fs_update_time(sbi, REQ_TIME);
if (err < 0)
goto out;

Expand Down
1 change: 0 additions & 1 deletion fs/f2fs/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/freezer.h>
#include <linux/blkdev.h>

#include "f2fs.h"
#include "node.h"
Expand Down
8 changes: 0 additions & 8 deletions fs/f2fs/gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,3 @@ static inline bool has_enough_invalid_blocks(struct f2fs_sb_info *sbi)
return true;
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]);
}
2 changes: 1 addition & 1 deletion fs/f2fs/segment.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi)
if (!available_free_memory(sbi, NAT_ENTRIES) ||
excess_prefree_segs(sbi) ||
!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))
sync_dirty_inodes(sbi, FILE_INODE);
f2fs_sync_fs(sbi->sb, true);
Expand Down
4 changes: 4 additions & 0 deletions fs/f2fs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -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, 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, idle_interval, interval_time[REQ_TIME]);

#define ATTR_LIST(name) (&f2fs_attr_##name.attr)
static struct attribute *f2fs_attrs[] = {
Expand All @@ -237,6 +238,7 @@ static struct attribute *f2fs_attrs[] = {
ATTR_LIST(ram_thresh),
ATTR_LIST(ra_nid_pages),
ATTR_LIST(cp_interval),
ATTR_LIST(idle_interval),
NULL,
};

Expand Down Expand Up @@ -1123,6 +1125,7 @@ static void init_sb_info(struct f2fs_sb_info *sbi)

sbi->dir_level = DEF_DIR_LEVEL;
sbi->interval_time[CP_TIME] = DEF_CP_INTERVAL;
sbi->interval_time[REQ_TIME] = DEF_IDLE_INTERVAL;
clear_sbi_flag(sbi, SBI_NEED_FSCK);

INIT_LIST_HEAD(&sbi->s_list);
Expand Down Expand Up @@ -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, REQ_TIME);
return 0;

free_kobj:
Expand Down
1 change: 1 addition & 0 deletions fs/f2fs/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -618,5 +618,6 @@ int f2fs_setxattr(struct inode *inode, int index, const char *name,
up_write(&F2FS_I(inode)->i_sem);
f2fs_unlock_op(sbi);

f2fs_update_time(sbi, REQ_TIME);
return err;
}

0 comments on commit d0239e1

Please sign in to comment.