Merge remote-tracking branch 'aosp/upstream-f2fs-stable-linux-4.19.y' into android-4.19
* aosp/upstream-f2fs-stable-linux-4.19.y: f2fs: fix quota_sync failure due to f2fs_lock_op f2fs: support read iostat f2fs: Fix the accounting of dcc->undiscard_blks f2fs: fix to handle error path of f2fs_ra_meta_pages() f2fs: report the discard cmd errors properly f2fs: fix long latency due to discard during umount f2fs: add tracepoint for f2fs iostat f2fs: introduce sysfs/data_io_flag to attach REQ_META/FUA ubifs: wire up FS_IOC_GET_ENCRYPTION_NONCE f2fs: wire up FS_IOC_GET_ENCRYPTION_NONCE ext4: wire up FS_IOC_GET_ENCRYPTION_NONCE fscrypt: add FS_IOC_GET_ENCRYPTION_NONCE ioctl Change-Id: I976edb3288576caa0c56eff202690b1159fcf827 Signed-off-by: Jaegeuk Kim <jaegeuk@google.com>
This commit is contained in:
commit
8c54aad926
12 changed files with 282 additions and 36 deletions
|
@ -323,3 +323,18 @@ What: /sys/fs/f2fs/<disk>/mounted_time_sec
|
|||
Date: February 2020
|
||||
Contact: "Jaegeuk Kim" <jaegeuk@kernel.org>
|
||||
Description: Show the mounted time in secs of this partition.
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/data_io_flag
|
||||
Date: April 2020
|
||||
Contact: "Jaegeuk Kim" <jaegeuk@kernel.org>
|
||||
Description: Give a way to attach REQ_META|FUA to data writes
|
||||
given temperature-based bits. Now the bits indicate:
|
||||
* REQ_META | REQ_FUA |
|
||||
* 5 | 4 | 3 | 2 | 1 | 0 |
|
||||
* Cold | Warm | Hot | Cold | Warm | Hot |
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/iostat_period_ms
|
||||
Date: April 2020
|
||||
Contact: "Daeho Jeong" <daehojeong@google.com>
|
||||
Description: Give a way to change iostat_period time. 3secs by default.
|
||||
The new iostat trace gives stats gap given the period.
|
||||
|
|
|
@ -86,6 +86,8 @@ static struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index,
|
|||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
f2fs_update_iostat(sbi, FS_META_READ_IO, F2FS_BLKSIZE);
|
||||
|
||||
lock_page(page);
|
||||
if (unlikely(page->mapping != mapping)) {
|
||||
f2fs_put_page(page, 1);
|
||||
|
@ -220,6 +222,7 @@ int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
|
|||
.is_por = (type == META_POR),
|
||||
};
|
||||
struct blk_plug plug;
|
||||
int err;
|
||||
|
||||
if (unlikely(type == META_POR))
|
||||
fio.op_flags &= ~REQ_META;
|
||||
|
@ -263,8 +266,11 @@ int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
|
|||
}
|
||||
|
||||
fio.page = page;
|
||||
f2fs_submit_page_bio(&fio);
|
||||
f2fs_put_page(page, 0);
|
||||
err = f2fs_submit_page_bio(&fio);
|
||||
f2fs_put_page(page, err ? 1 : 0);
|
||||
|
||||
if (!err)
|
||||
f2fs_update_iostat(sbi, FS_META_READ_IO, F2FS_BLKSIZE);
|
||||
}
|
||||
out:
|
||||
blk_finish_plug(&plug);
|
||||
|
|
|
@ -985,7 +985,7 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc,
|
|||
loff_t psize;
|
||||
int i, err;
|
||||
|
||||
if (!f2fs_trylock_op(sbi))
|
||||
if (!IS_NOQUOTA(inode) && !f2fs_trylock_op(sbi))
|
||||
return -EAGAIN;
|
||||
|
||||
set_new_dnode(&dn, cc->inode, NULL, NULL, 0);
|
||||
|
|
|
@ -579,6 +579,28 @@ void f2fs_submit_bio(struct f2fs_sb_info *sbi,
|
|||
__submit_bio(sbi, bio, type);
|
||||
}
|
||||
|
||||
static void __attach_data_io_flag(struct f2fs_io_info *fio)
|
||||
{
|
||||
struct f2fs_sb_info *sbi = fio->sbi;
|
||||
unsigned int temp_mask = (1 << NR_TEMP_TYPE) - 1;
|
||||
unsigned int fua_flag = sbi->data_io_flag & temp_mask;
|
||||
unsigned int meta_flag = (sbi->data_io_flag >> NR_TEMP_TYPE) &
|
||||
temp_mask;
|
||||
/*
|
||||
* data io flag bits per temp:
|
||||
* REQ_META | REQ_FUA |
|
||||
* 5 | 4 | 3 | 2 | 1 | 0 |
|
||||
* Cold | Warm | Hot | Cold | Warm | Hot |
|
||||
*/
|
||||
if (fio->type != DATA)
|
||||
return;
|
||||
|
||||
if ((1 << fio->temp) & meta_flag)
|
||||
fio->op_flags |= REQ_META;
|
||||
if ((1 << fio->temp) & fua_flag)
|
||||
fio->op_flags |= REQ_FUA;
|
||||
}
|
||||
|
||||
static void __submit_merged_bio(struct f2fs_bio_info *io)
|
||||
{
|
||||
struct f2fs_io_info *fio = &io->fio;
|
||||
|
@ -586,6 +608,7 @@ static void __submit_merged_bio(struct f2fs_bio_info *io)
|
|||
if (!io->bio)
|
||||
return;
|
||||
|
||||
__attach_data_io_flag(fio);
|
||||
bio_set_op_attrs(io->bio, fio->op, fio->op_flags);
|
||||
|
||||
if (is_read_io(fio->op))
|
||||
|
@ -1096,6 +1119,7 @@ static int f2fs_submit_page_read(struct inode *inode, struct page *page,
|
|||
}
|
||||
ClearPageError(page);
|
||||
inc_page_count(sbi, F2FS_RD_DATA);
|
||||
f2fs_update_iostat(sbi, FS_DATA_READ_IO, F2FS_BLKSIZE);
|
||||
__f2fs_submit_read_bio(sbi, bio, DATA);
|
||||
return 0;
|
||||
}
|
||||
|
@ -2102,6 +2126,7 @@ static int f2fs_read_single_page(struct inode *inode, struct page *page,
|
|||
goto submit_and_realloc;
|
||||
|
||||
inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA);
|
||||
f2fs_update_iostat(F2FS_I_SB(inode), FS_DATA_READ_IO, F2FS_BLKSIZE);
|
||||
ClearPageError(page);
|
||||
*last_block_in_bio = block_nr;
|
||||
goto out;
|
||||
|
@ -2238,6 +2263,7 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
|
|||
goto submit_and_realloc;
|
||||
|
||||
inc_page_count(sbi, F2FS_RD_DATA);
|
||||
f2fs_update_iostat(sbi, FS_DATA_READ_IO, F2FS_BLKSIZE);
|
||||
ClearPageError(page);
|
||||
*last_block_in_bio = blkaddr;
|
||||
}
|
||||
|
@ -2724,8 +2750,8 @@ int f2fs_write_single_data_page(struct page *page, int *submitted,
|
|||
f2fs_available_free_memory(sbi, BASE_CHECK))))
|
||||
goto redirty_out;
|
||||
|
||||
/* Dentry blocks are controlled by checkpoint */
|
||||
if (S_ISDIR(inode->i_mode)) {
|
||||
/* Dentry/quota blocks are controlled by checkpoint */
|
||||
if (S_ISDIR(inode->i_mode) || IS_NOQUOTA(inode)) {
|
||||
fio.need_lock = LOCK_DONE;
|
||||
err = f2fs_do_write_data_page(&fio);
|
||||
goto done;
|
||||
|
@ -3628,6 +3654,9 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
|
|||
} else if (err < 0) {
|
||||
f2fs_write_failed(mapping, offset + count);
|
||||
}
|
||||
} else {
|
||||
if (err > 0)
|
||||
f2fs_update_iostat(sbi, APP_DIRECT_READ_IO, err);
|
||||
}
|
||||
|
||||
out:
|
||||
|
|
|
@ -1090,8 +1090,9 @@ enum cp_reason_type {
|
|||
};
|
||||
|
||||
enum iostat_type {
|
||||
APP_DIRECT_IO, /* app direct IOs */
|
||||
APP_BUFFERED_IO, /* app buffered IOs */
|
||||
/* WRITE IO */
|
||||
APP_DIRECT_IO, /* app direct write IOs */
|
||||
APP_BUFFERED_IO, /* app buffered write IOs */
|
||||
APP_WRITE_IO, /* app write IOs */
|
||||
APP_MAPPED_IO, /* app mapped IOs */
|
||||
FS_DATA_IO, /* data IOs from kworker/fsync/reclaimer */
|
||||
|
@ -1102,6 +1103,17 @@ enum iostat_type {
|
|||
FS_CP_DATA_IO, /* data IOs from checkpoint */
|
||||
FS_CP_NODE_IO, /* node IOs from checkpoint */
|
||||
FS_CP_META_IO, /* meta IOs from checkpoint */
|
||||
|
||||
/* READ IO */
|
||||
APP_DIRECT_READ_IO, /* app direct read IOs */
|
||||
APP_BUFFERED_READ_IO, /* app buffered read IOs */
|
||||
APP_READ_IO, /* app read IOs */
|
||||
APP_MAPPED_READ_IO, /* app mapped read IOs */
|
||||
FS_DATA_READ_IO, /* data read IOs */
|
||||
FS_NODE_READ_IO, /* node read IOs */
|
||||
FS_META_READ_IO, /* meta read IOs */
|
||||
|
||||
/* other */
|
||||
FS_DISCARD, /* discard */
|
||||
NR_IO_TYPE,
|
||||
};
|
||||
|
@ -1502,8 +1514,14 @@ struct f2fs_sb_info {
|
|||
|
||||
/* For app/fs IO statistics */
|
||||
spinlock_t iostat_lock;
|
||||
unsigned long long write_iostat[NR_IO_TYPE];
|
||||
unsigned long long rw_iostat[NR_IO_TYPE];
|
||||
unsigned long long prev_rw_iostat[NR_IO_TYPE];
|
||||
bool iostat_enable;
|
||||
unsigned long iostat_next_period;
|
||||
unsigned int iostat_period_ms;
|
||||
|
||||
/* to attach REQ_META|REQ_FUA flags */
|
||||
unsigned int data_io_flag;
|
||||
|
||||
/* For sysfs suppport */
|
||||
struct kobject s_kobj;
|
||||
|
@ -2995,29 +3013,45 @@ static inline int get_inline_xattr_addrs(struct inode *inode)
|
|||
sizeof((f2fs_inode)->field)) \
|
||||
<= (F2FS_OLD_ATTRIBUTE_SIZE + (extra_isize))) \
|
||||
|
||||
#define DEFAULT_IOSTAT_PERIOD_MS 3000
|
||||
#define MIN_IOSTAT_PERIOD_MS 100
|
||||
/* maximum period of iostat tracing is 1 day */
|
||||
#define MAX_IOSTAT_PERIOD_MS 8640000
|
||||
|
||||
static inline void f2fs_reset_iostat(struct f2fs_sb_info *sbi)
|
||||
{
|
||||
int i;
|
||||
|
||||
spin_lock(&sbi->iostat_lock);
|
||||
for (i = 0; i < NR_IO_TYPE; i++)
|
||||
sbi->write_iostat[i] = 0;
|
||||
for (i = 0; i < NR_IO_TYPE; i++) {
|
||||
sbi->rw_iostat[i] = 0;
|
||||
sbi->prev_rw_iostat[i] = 0;
|
||||
}
|
||||
spin_unlock(&sbi->iostat_lock);
|
||||
}
|
||||
|
||||
extern void f2fs_record_iostat(struct f2fs_sb_info *sbi);
|
||||
|
||||
static inline void f2fs_update_iostat(struct f2fs_sb_info *sbi,
|
||||
enum iostat_type type, unsigned long long io_bytes)
|
||||
{
|
||||
if (!sbi->iostat_enable)
|
||||
return;
|
||||
spin_lock(&sbi->iostat_lock);
|
||||
sbi->write_iostat[type] += io_bytes;
|
||||
sbi->rw_iostat[type] += io_bytes;
|
||||
|
||||
if (type == APP_WRITE_IO || type == APP_DIRECT_IO)
|
||||
sbi->write_iostat[APP_BUFFERED_IO] =
|
||||
sbi->write_iostat[APP_WRITE_IO] -
|
||||
sbi->write_iostat[APP_DIRECT_IO];
|
||||
sbi->rw_iostat[APP_BUFFERED_IO] =
|
||||
sbi->rw_iostat[APP_WRITE_IO] -
|
||||
sbi->rw_iostat[APP_DIRECT_IO];
|
||||
|
||||
if (type == APP_READ_IO || type == APP_DIRECT_READ_IO)
|
||||
sbi->rw_iostat[APP_BUFFERED_READ_IO] =
|
||||
sbi->rw_iostat[APP_READ_IO] -
|
||||
sbi->rw_iostat[APP_DIRECT_READ_IO];
|
||||
spin_unlock(&sbi->iostat_lock);
|
||||
|
||||
f2fs_record_iostat(sbi);
|
||||
}
|
||||
|
||||
#define __is_large_section(sbi) ((sbi)->segs_per_sec > 1)
|
||||
|
|
|
@ -41,6 +41,10 @@ static vm_fault_t f2fs_filemap_fault(struct vm_fault *vmf)
|
|||
ret = filemap_fault(vmf);
|
||||
up_read(&F2FS_I(inode)->i_mmap_sem);
|
||||
|
||||
if (!ret)
|
||||
f2fs_update_iostat(F2FS_I_SB(inode), APP_MAPPED_READ_IO,
|
||||
F2FS_BLKSIZE);
|
||||
|
||||
trace_f2fs_filemap_fault(inode, vmf->pgoff, (unsigned long)ret);
|
||||
|
||||
return ret;
|
||||
|
@ -3525,11 +3529,17 @@ static ssize_t f2fs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
|
|||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
struct inode *inode = file_inode(file);
|
||||
int ret;
|
||||
|
||||
if (!f2fs_is_compress_backend_ready(inode))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return generic_file_read_iter(iocb, iter);
|
||||
ret = generic_file_read_iter(iocb, iter);
|
||||
|
||||
if (ret > 0)
|
||||
f2fs_update_iostat(F2FS_I_SB(inode), APP_READ_IO, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
|
|
|
@ -737,6 +737,9 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
|
|||
goto put_encrypted_page;
|
||||
f2fs_put_page(fio.encrypted_page, 0);
|
||||
f2fs_put_page(page, 1);
|
||||
|
||||
f2fs_update_iostat(sbi, FS_DATA_READ_IO, F2FS_BLKSIZE);
|
||||
|
||||
return 0;
|
||||
put_encrypted_page:
|
||||
f2fs_put_page(fio.encrypted_page, 1);
|
||||
|
@ -840,6 +843,9 @@ static int move_data_block(struct inode *inode, block_t bidx,
|
|||
f2fs_put_page(mpage, 1);
|
||||
goto up_out;
|
||||
}
|
||||
|
||||
f2fs_update_iostat(fio.sbi, FS_DATA_READ_IO, F2FS_BLKSIZE);
|
||||
|
||||
lock_page(mpage);
|
||||
if (unlikely(mpage->mapping != META_MAPPING(fio.sbi) ||
|
||||
!PageUptodate(mpage))) {
|
||||
|
|
|
@ -1298,7 +1298,13 @@ static int read_node_page(struct page *page, int op_flags)
|
|||
}
|
||||
|
||||
fio.new_blkaddr = fio.old_blkaddr = ni.blk_addr;
|
||||
return f2fs_submit_page_bio(&fio);
|
||||
|
||||
err = f2fs_submit_page_bio(&fio);
|
||||
|
||||
if (!err)
|
||||
f2fs_update_iostat(sbi, FS_NODE_READ_IO, F2FS_BLKSIZE);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1029,9 +1029,9 @@ static void f2fs_submit_discard_endio(struct bio *bio)
|
|||
struct discard_cmd *dc = (struct discard_cmd *)bio->bi_private;
|
||||
unsigned long flags;
|
||||
|
||||
dc->error = blk_status_to_errno(bio->bi_status);
|
||||
|
||||
spin_lock_irqsave(&dc->lock, flags);
|
||||
if (!dc->error)
|
||||
dc->error = blk_status_to_errno(bio->bi_status);
|
||||
dc->bio_ref--;
|
||||
if (!dc->bio_ref && dc->state == D_SUBMIT) {
|
||||
dc->state = D_DONE;
|
||||
|
@ -1101,7 +1101,6 @@ static void __init_discard_policy(struct f2fs_sb_info *sbi,
|
|||
} else if (discard_type == DPOLICY_FSTRIM) {
|
||||
dpolicy->io_aware = false;
|
||||
} else if (discard_type == DPOLICY_UMOUNT) {
|
||||
dpolicy->max_requests = UINT_MAX;
|
||||
dpolicy->io_aware = false;
|
||||
/* we need to issue all to keep CP_TRIMMED_FLAG */
|
||||
dpolicy->granularity = 1;
|
||||
|
@ -1215,8 +1214,10 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi,
|
|||
len = total_len;
|
||||
}
|
||||
|
||||
if (!err && len)
|
||||
if (!err && len) {
|
||||
dcc->undiscard_blks -= len;
|
||||
__update_discard_tree_range(sbi, bdev, lstart, start, len);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -1463,6 +1464,8 @@ static unsigned int __issue_discard_cmd_orderly(struct f2fs_sb_info *sbi,
|
|||
|
||||
return issued;
|
||||
}
|
||||
static unsigned int __wait_all_discard_cmd(struct f2fs_sb_info *sbi,
|
||||
struct discard_policy *dpolicy);
|
||||
|
||||
static int __issue_discard_cmd(struct f2fs_sb_info *sbi,
|
||||
struct discard_policy *dpolicy)
|
||||
|
@ -1471,12 +1474,14 @@ static int __issue_discard_cmd(struct f2fs_sb_info *sbi,
|
|||
struct list_head *pend_list;
|
||||
struct discard_cmd *dc, *tmp;
|
||||
struct blk_plug plug;
|
||||
int i, issued = 0;
|
||||
int i, issued;
|
||||
bool io_interrupted = false;
|
||||
|
||||
if (dpolicy->timeout)
|
||||
f2fs_update_time(sbi, UMOUNT_DISCARD_TIMEOUT);
|
||||
|
||||
retry:
|
||||
issued = 0;
|
||||
for (i = MAX_PLIST_NUM - 1; i >= 0; i--) {
|
||||
if (dpolicy->timeout &&
|
||||
f2fs_time_over(sbi, UMOUNT_DISCARD_TIMEOUT))
|
||||
|
@ -1523,6 +1528,11 @@ static int __issue_discard_cmd(struct f2fs_sb_info *sbi,
|
|||
break;
|
||||
}
|
||||
|
||||
if (dpolicy->type == DPOLICY_UMOUNT && issued) {
|
||||
__wait_all_discard_cmd(sbi, dpolicy);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (!issued && io_interrupted)
|
||||
issued = -1;
|
||||
|
||||
|
|
|
@ -3486,6 +3486,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
|
|||
/* init iostat info */
|
||||
spin_lock_init(&sbi->iostat_lock);
|
||||
sbi->iostat_enable = false;
|
||||
sbi->iostat_period_ms = DEFAULT_IOSTAT_PERIOD_MS;
|
||||
|
||||
for (i = 0; i < NR_PAGE_TYPE; i++) {
|
||||
int n = (i == META) ? 1: NR_TEMP_TYPE;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "f2fs.h"
|
||||
#include "segment.h"
|
||||
#include "gc.h"
|
||||
#include <trace/events/f2fs.h>
|
||||
|
||||
static struct proc_dir_entry *f2fs_proc_root;
|
||||
|
||||
|
@ -374,7 +375,6 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
|
|||
return count;
|
||||
}
|
||||
|
||||
|
||||
if (!strcmp(a->attr.name, "iostat_enable")) {
|
||||
sbi->iostat_enable = !!t;
|
||||
if (!sbi->iostat_enable)
|
||||
|
@ -382,6 +382,15 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
|
|||
return count;
|
||||
}
|
||||
|
||||
if (!strcmp(a->attr.name, "iostat_period_ms")) {
|
||||
if (t < MIN_IOSTAT_PERIOD_MS || t > MAX_IOSTAT_PERIOD_MS)
|
||||
return -EINVAL;
|
||||
spin_lock(&sbi->iostat_lock);
|
||||
sbi->iostat_period_ms = (unsigned int)t;
|
||||
spin_unlock(&sbi->iostat_lock);
|
||||
return count;
|
||||
}
|
||||
|
||||
*ui = (unsigned int)t;
|
||||
|
||||
return count;
|
||||
|
@ -538,6 +547,7 @@ F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_idle_interval, interval_time[GC_TIME]);
|
|||
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info,
|
||||
umount_discard_timeout, interval_time[UMOUNT_DISCARD_TIMEOUT]);
|
||||
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_enable, iostat_enable);
|
||||
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_period_ms, iostat_period_ms);
|
||||
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, readdir_ra, readdir_ra);
|
||||
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_pin_file_thresh, gc_pin_file_threshold);
|
||||
F2FS_RW_ATTR(F2FS_SBI, f2fs_super_block, extension_list, extension_list);
|
||||
|
@ -545,6 +555,7 @@ F2FS_RW_ATTR(F2FS_SBI, f2fs_super_block, extension_list, extension_list);
|
|||
F2FS_RW_ATTR(FAULT_INFO_RATE, f2fs_fault_info, inject_rate, inject_rate);
|
||||
F2FS_RW_ATTR(FAULT_INFO_TYPE, f2fs_fault_info, inject_type, inject_type);
|
||||
#endif
|
||||
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, data_io_flag, data_io_flag);
|
||||
F2FS_GENERAL_RO_ATTR(dirty_segments);
|
||||
F2FS_GENERAL_RO_ATTR(free_segments);
|
||||
F2FS_GENERAL_RO_ATTR(lifetime_write_kbytes);
|
||||
|
@ -617,6 +628,7 @@ static struct attribute *f2fs_attrs[] = {
|
|||
ATTR_LIST(gc_idle_interval),
|
||||
ATTR_LIST(umount_discard_timeout),
|
||||
ATTR_LIST(iostat_enable),
|
||||
ATTR_LIST(iostat_period_ms),
|
||||
ATTR_LIST(readdir_ra),
|
||||
ATTR_LIST(gc_pin_file_thresh),
|
||||
ATTR_LIST(extension_list),
|
||||
|
@ -624,6 +636,7 @@ static struct attribute *f2fs_attrs[] = {
|
|||
ATTR_LIST(inject_rate),
|
||||
ATTR_LIST(inject_type),
|
||||
#endif
|
||||
ATTR_LIST(data_io_flag),
|
||||
ATTR_LIST(dirty_segments),
|
||||
ATTR_LIST(free_segments),
|
||||
ATTR_LIST(unusable),
|
||||
|
@ -750,6 +763,33 @@ static int __maybe_unused segment_bits_seq_show(struct seq_file *seq,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void f2fs_record_iostat(struct f2fs_sb_info *sbi)
|
||||
{
|
||||
unsigned long long iostat_diff[NR_IO_TYPE];
|
||||
int i;
|
||||
|
||||
if (time_is_after_jiffies(sbi->iostat_next_period))
|
||||
return;
|
||||
|
||||
/* Need double check under the lock */
|
||||
spin_lock(&sbi->iostat_lock);
|
||||
if (time_is_after_jiffies(sbi->iostat_next_period)) {
|
||||
spin_unlock(&sbi->iostat_lock);
|
||||
return;
|
||||
}
|
||||
sbi->iostat_next_period = jiffies +
|
||||
msecs_to_jiffies(sbi->iostat_period_ms);
|
||||
|
||||
for (i = 0; i < NR_IO_TYPE; i++) {
|
||||
iostat_diff[i] = sbi->rw_iostat[i] -
|
||||
sbi->prev_rw_iostat[i];
|
||||
sbi->prev_rw_iostat[i] = sbi->rw_iostat[i];
|
||||
}
|
||||
spin_unlock(&sbi->iostat_lock);
|
||||
|
||||
trace_f2fs_iostat(sbi, iostat_diff);
|
||||
}
|
||||
|
||||
static int __maybe_unused iostat_info_seq_show(struct seq_file *seq,
|
||||
void *offset)
|
||||
{
|
||||
|
@ -762,33 +802,51 @@ static int __maybe_unused iostat_info_seq_show(struct seq_file *seq,
|
|||
|
||||
seq_printf(seq, "time: %-16llu\n", now);
|
||||
|
||||
/* print app IOs */
|
||||
/* print app write IOs */
|
||||
seq_printf(seq, "app buffered: %-16llu\n",
|
||||
sbi->write_iostat[APP_BUFFERED_IO]);
|
||||
sbi->rw_iostat[APP_BUFFERED_IO]);
|
||||
seq_printf(seq, "app direct: %-16llu\n",
|
||||
sbi->write_iostat[APP_DIRECT_IO]);
|
||||
sbi->rw_iostat[APP_DIRECT_IO]);
|
||||
seq_printf(seq, "app mapped: %-16llu\n",
|
||||
sbi->write_iostat[APP_MAPPED_IO]);
|
||||
sbi->rw_iostat[APP_MAPPED_IO]);
|
||||
|
||||
/* print fs IOs */
|
||||
/* print fs write IOs */
|
||||
seq_printf(seq, "fs data: %-16llu\n",
|
||||
sbi->write_iostat[FS_DATA_IO]);
|
||||
sbi->rw_iostat[FS_DATA_IO]);
|
||||
seq_printf(seq, "fs node: %-16llu\n",
|
||||
sbi->write_iostat[FS_NODE_IO]);
|
||||
sbi->rw_iostat[FS_NODE_IO]);
|
||||
seq_printf(seq, "fs meta: %-16llu\n",
|
||||
sbi->write_iostat[FS_META_IO]);
|
||||
sbi->rw_iostat[FS_META_IO]);
|
||||
seq_printf(seq, "fs gc data: %-16llu\n",
|
||||
sbi->write_iostat[FS_GC_DATA_IO]);
|
||||
sbi->rw_iostat[FS_GC_DATA_IO]);
|
||||
seq_printf(seq, "fs gc node: %-16llu\n",
|
||||
sbi->write_iostat[FS_GC_NODE_IO]);
|
||||
sbi->rw_iostat[FS_GC_NODE_IO]);
|
||||
seq_printf(seq, "fs cp data: %-16llu\n",
|
||||
sbi->write_iostat[FS_CP_DATA_IO]);
|
||||
sbi->rw_iostat[FS_CP_DATA_IO]);
|
||||
seq_printf(seq, "fs cp node: %-16llu\n",
|
||||
sbi->write_iostat[FS_CP_NODE_IO]);
|
||||
sbi->rw_iostat[FS_CP_NODE_IO]);
|
||||
seq_printf(seq, "fs cp meta: %-16llu\n",
|
||||
sbi->write_iostat[FS_CP_META_IO]);
|
||||
sbi->rw_iostat[FS_CP_META_IO]);
|
||||
|
||||
/* print app read IOs */
|
||||
seq_printf(seq, "app buffered: %-16llu\n",
|
||||
sbi->rw_iostat[APP_BUFFERED_READ_IO]);
|
||||
seq_printf(seq, "app direct: %-16llu\n",
|
||||
sbi->rw_iostat[APP_DIRECT_READ_IO]);
|
||||
seq_printf(seq, "app mapped: %-16llu\n",
|
||||
sbi->rw_iostat[APP_MAPPED_READ_IO]);
|
||||
|
||||
/* print fs read IOs */
|
||||
seq_printf(seq, "fs data: %-16llu\n",
|
||||
sbi->rw_iostat[FS_DATA_READ_IO]);
|
||||
seq_printf(seq, "fs node: %-16llu\n",
|
||||
sbi->rw_iostat[FS_NODE_READ_IO]);
|
||||
seq_printf(seq, "fs meta: %-16llu\n",
|
||||
sbi->rw_iostat[FS_META_READ_IO]);
|
||||
|
||||
/* print other IOs */
|
||||
seq_printf(seq, "fs discard: %-16llu\n",
|
||||
sbi->write_iostat[FS_DISCARD]);
|
||||
sbi->rw_iostat[FS_DISCARD]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1822,6 +1822,77 @@ DEFINE_EVENT(f2fs_zip_end, f2fs_decompress_pages_end,
|
|||
TP_ARGS(inode, cluster_idx, compressed_size, ret)
|
||||
);
|
||||
|
||||
TRACE_EVENT(f2fs_iostat,
|
||||
|
||||
TP_PROTO(struct f2fs_sb_info *sbi, unsigned long long *iostat),
|
||||
|
||||
TP_ARGS(sbi, iostat),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(dev_t, dev)
|
||||
__field(unsigned long long, app_dio)
|
||||
__field(unsigned long long, app_bio)
|
||||
__field(unsigned long long, app_wio)
|
||||
__field(unsigned long long, app_mio)
|
||||
__field(unsigned long long, fs_dio)
|
||||
__field(unsigned long long, fs_nio)
|
||||
__field(unsigned long long, fs_mio)
|
||||
__field(unsigned long long, fs_gc_dio)
|
||||
__field(unsigned long long, fs_gc_nio)
|
||||
__field(unsigned long long, fs_cp_dio)
|
||||
__field(unsigned long long, fs_cp_nio)
|
||||
__field(unsigned long long, fs_cp_mio)
|
||||
__field(unsigned long long, app_drio)
|
||||
__field(unsigned long long, app_brio)
|
||||
__field(unsigned long long, app_rio)
|
||||
__field(unsigned long long, app_mrio)
|
||||
__field(unsigned long long, fs_drio)
|
||||
__field(unsigned long long, fs_nrio)
|
||||
__field(unsigned long long, fs_mrio)
|
||||
__field(unsigned long long, fs_discard)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->dev = sbi->sb->s_dev;
|
||||
__entry->app_dio = iostat[APP_DIRECT_IO];
|
||||
__entry->app_bio = iostat[APP_BUFFERED_IO];
|
||||
__entry->app_wio = iostat[APP_WRITE_IO];
|
||||
__entry->app_mio = iostat[APP_MAPPED_IO];
|
||||
__entry->fs_dio = iostat[FS_DATA_IO];
|
||||
__entry->fs_nio = iostat[FS_NODE_IO];
|
||||
__entry->fs_mio = iostat[FS_META_IO];
|
||||
__entry->fs_gc_dio = iostat[FS_GC_DATA_IO];
|
||||
__entry->fs_gc_nio = iostat[FS_GC_NODE_IO];
|
||||
__entry->fs_cp_dio = iostat[FS_CP_DATA_IO];
|
||||
__entry->fs_cp_nio = iostat[FS_CP_NODE_IO];
|
||||
__entry->fs_cp_mio = iostat[FS_CP_META_IO];
|
||||
__entry->app_drio = iostat[APP_DIRECT_READ_IO];
|
||||
__entry->app_brio = iostat[APP_BUFFERED_READ_IO];
|
||||
__entry->app_rio = iostat[APP_READ_IO];
|
||||
__entry->app_mrio = iostat[APP_MAPPED_READ_IO];
|
||||
__entry->fs_drio = iostat[FS_DATA_READ_IO];
|
||||
__entry->fs_nrio = iostat[FS_NODE_READ_IO];
|
||||
__entry->fs_mrio = iostat[FS_META_READ_IO];
|
||||
__entry->fs_discard = iostat[FS_DISCARD];
|
||||
),
|
||||
|
||||
TP_printk("dev = (%d,%d), "
|
||||
"app [write=%llu (direct=%llu, buffered=%llu), mapped=%llu], "
|
||||
"fs [data=%llu, node=%llu, meta=%llu, discard=%llu], "
|
||||
"gc [data=%llu, node=%llu], "
|
||||
"cp [data=%llu, node=%llu, meta=%llu], "
|
||||
"app [read=%llu (direct=%llu, buffered=%llu), mapped=%llu], "
|
||||
"fs [data=%llu, node=%llu, meta=%llu]",
|
||||
show_dev(__entry->dev), __entry->app_wio, __entry->app_dio,
|
||||
__entry->app_bio, __entry->app_mio, __entry->fs_dio,
|
||||
__entry->fs_nio, __entry->fs_mio, __entry->fs_discard,
|
||||
__entry->fs_gc_dio, __entry->fs_gc_nio, __entry->fs_cp_dio,
|
||||
__entry->fs_cp_nio, __entry->fs_cp_mio,
|
||||
__entry->app_rio, __entry->app_drio, __entry->app_brio,
|
||||
__entry->app_mrio, __entry->fs_drio, __entry->fs_nrio,
|
||||
__entry->fs_mrio)
|
||||
);
|
||||
|
||||
#endif /* _TRACE_F2FS_H */
|
||||
|
||||
/* This part must be outside protection */
|
||||
|
|
Loading…
Reference in a new issue