ANDROID: fs: FS tracepoints to track IO.

Adds tracepoints in ext4/f2fs/mpage to track readpages/buffered
write()s. This allows us to track files that are being read/written
to PIDs.

Change-Id: I26bd36f933108927d6903da04d8cb42fd9c3ef3d
Signed-off-by: Mohan Srinivasan <srmohan@google.com>
This commit is contained in:
Mohan Srinivasan 2016-09-19 17:33:50 -07:00 committed by Amit Pundir
parent 27f0430c61
commit 31f42471b1
8 changed files with 242 additions and 4 deletions

View file

@ -18,6 +18,7 @@
#include "ext4.h"
#include "xattr.h"
#include "truncate.h"
#include <trace/events/android_fs.h>
#define EXT4_XATTR_SYSTEM_DATA "data"
#define EXT4_MIN_INLINE_DATA_SIZE ((sizeof(__le32) * EXT4_N_BLOCKS))
@ -500,6 +501,9 @@ int ext4_readpage_inline(struct inode *inode, struct page *page)
return -EAGAIN;
}
trace_android_fs_dataread_start(inode, page_offset(page), PAGE_SIZE,
current->pid, current->comm);
/*
* Current inline data can only exist in the 1st page,
* So for all the other pages, just set them uptodate.
@ -511,6 +515,8 @@ int ext4_readpage_inline(struct inode *inode, struct page *page)
SetPageUptodate(page);
}
trace_android_fs_dataread_end(inode, page_offset(page), PAGE_SIZE);
up_read(&EXT4_I(inode)->xattr_sem);
unlock_page(page);

View file

@ -44,6 +44,7 @@
#include "truncate.h"
#include <trace/events/ext4.h>
#include <trace/events/android_fs.h>
#define MPAGE_DA_EXTENT_TAIL 0x01
@ -1016,6 +1017,8 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
pgoff_t index;
unsigned from, to;
trace_android_fs_datawrite_start(inode, pos, len,
current->pid, current->comm);
trace_ext4_write_begin(inode, pos, len, flags);
/*
* Reserve one block more for addition to orphan list in case
@ -1152,6 +1155,7 @@ static int ext4_write_end(struct file *file,
int ret = 0, ret2;
int i_size_changed = 0;
trace_android_fs_datawrite_end(inode, pos, len);
trace_ext4_write_end(inode, pos, len, copied);
if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) {
ret = ext4_jbd2_file_inode(handle, inode);
@ -1260,6 +1264,7 @@ static int ext4_journalled_write_end(struct file *file,
unsigned from, to;
int size_changed = 0;
trace_android_fs_datawrite_end(inode, pos, len);
trace_ext4_journalled_write_end(inode, pos, len, copied);
from = pos & (PAGE_CACHE_SIZE - 1);
to = from + len;
@ -2727,6 +2732,8 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
len, flags, pagep, fsdata);
}
*fsdata = (void *)0;
trace_android_fs_datawrite_start(inode, pos, len,
current->pid, current->comm);
trace_ext4_da_write_begin(inode, pos, len, flags);
if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {
@ -2845,6 +2852,7 @@ static int ext4_da_write_end(struct file *file,
return ext4_write_end(file, mapping, pos,
len, copied, page, fsdata);
trace_android_fs_datawrite_end(inode, pos, len);
trace_ext4_da_write_end(inode, pos, len, copied);
start = pos & (PAGE_CACHE_SIZE - 1);
end = start + copied - 1;
@ -3333,12 +3341,31 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
if (ext4_has_inline_data(inode))
return 0;
if (trace_android_fs_dataread_start_enabled() &&
(iov_iter_rw(iter) == READ))
trace_android_fs_dataread_start(inode, offset, count,
current->pid,
current->comm);
if (trace_android_fs_datawrite_start_enabled() &&
(iov_iter_rw(iter) == WRITE))
trace_android_fs_datawrite_start(inode, offset, count,
current->pid,
current->comm);
trace_ext4_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
ret = ext4_ext_direct_IO(iocb, iter, offset);
else
ret = ext4_ind_direct_IO(iocb, iter, offset);
trace_ext4_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), ret);
if (trace_android_fs_dataread_start_enabled() &&
(iov_iter_rw(iter) == READ))
trace_android_fs_dataread_end(inode, offset, count);
if (trace_android_fs_datawrite_start_enabled() &&
(iov_iter_rw(iter) == WRITE))
trace_android_fs_datawrite_end(inode, offset, count);
return ret;
}

View file

@ -45,6 +45,7 @@
#include <linux/cleancache.h>
#include "ext4.h"
#include <trace/events/android_fs.h>
/*
* Call ext4_decrypt on every single page, reusing the encryption
@ -86,6 +87,17 @@ static inline bool ext4_bio_encrypted(struct bio *bio)
#endif
}
static void
ext4_trace_read_completion(struct bio *bio)
{
struct page *first_page = bio->bi_io_vec[0].bv_page;
if (first_page != NULL)
trace_android_fs_dataread_end(first_page->mapping->host,
page_offset(first_page),
bio->bi_iter.bi_size);
}
/*
* I/O completion handler for multipage BIOs.
*
@ -103,6 +115,9 @@ static void mpage_end_io(struct bio *bio)
struct bio_vec *bv;
int i;
if (trace_android_fs_dataread_start_enabled())
ext4_trace_read_completion(bio);
if (ext4_bio_encrypted(bio)) {
struct ext4_crypto_ctx *ctx = bio->bi_private;
@ -130,6 +145,24 @@ static void mpage_end_io(struct bio *bio)
bio_put(bio);
}
static void
ext4_submit_bio_read(struct bio *bio)
{
if (trace_android_fs_dataread_start_enabled()) {
struct page *first_page = bio->bi_io_vec[0].bv_page;
if (first_page != NULL) {
trace_android_fs_dataread_start(
first_page->mapping->host,
page_offset(first_page),
bio->bi_iter.bi_size,
current->pid,
current->comm);
}
}
submit_bio(READ, bio);
}
int ext4_mpage_readpages(struct address_space *mapping,
struct list_head *pages, struct page *page,
unsigned nr_pages)
@ -271,7 +304,7 @@ int ext4_mpage_readpages(struct address_space *mapping,
*/
if (bio && (last_block_in_bio != blocks[0] - 1)) {
submit_and_realloc:
submit_bio(READ, bio);
ext4_submit_bio_read(bio);
bio = NULL;
}
if (bio == NULL) {
@ -303,14 +336,14 @@ int ext4_mpage_readpages(struct address_space *mapping,
if (((map.m_flags & EXT4_MAP_BOUNDARY) &&
(relative_block == map.m_len)) ||
(first_hole != blocks_per_page)) {
submit_bio(READ, bio);
ext4_submit_bio_read(bio);
bio = NULL;
} else
last_block_in_bio = blocks[blocks_per_page - 1];
goto next_page;
confused:
if (bio) {
submit_bio(READ, bio);
ext4_submit_bio_read(bio);
bio = NULL;
}
if (!PageUptodate(page))
@ -323,6 +356,6 @@ int ext4_mpage_readpages(struct address_space *mapping,
}
BUG_ON(pages && !list_empty(pages));
if (bio)
submit_bio(READ, bio);
ext4_submit_bio_read(bio);
return 0;
}

View file

@ -26,6 +26,7 @@
#include "segment.h"
#include "trace.h"
#include <trace/events/f2fs.h>
#include <trace/events/android_fs.h>
static void f2fs_read_end_io(struct bio *bio)
{
@ -1401,6 +1402,8 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
struct dnode_of_data dn;
int err = 0;
trace_android_fs_datawrite_start(inode, pos, len,
current->pid, current->comm);
trace_f2fs_write_begin(inode, pos, len, flags);
f2fs_balance_fs(sbi);
@ -1529,6 +1532,7 @@ static int f2fs_write_end(struct file *file,
{
struct inode *inode = page->mapping->host;
trace_android_fs_datawrite_end(inode, pos, len);
trace_f2fs_write_end(inode, pos, len, copied);
set_page_dirty(page);
@ -1582,6 +1586,16 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
if (trace_android_fs_dataread_start_enabled() &&
(iov_iter_rw(iter) == READ))
trace_android_fs_dataread_start(inode, offset,
count, current->pid,
current->comm);
if (trace_android_fs_datawrite_start_enabled() &&
(iov_iter_rw(iter) == WRITE))
trace_android_fs_datawrite_start(inode, offset, count,
current->pid, current->comm);
if (iov_iter_rw(iter) == WRITE) {
__allocate_data_blocks(inode, offset, count);
if (unlikely(f2fs_cp_error(F2FS_I_SB(inode)))) {
@ -1595,6 +1609,13 @@ out:
if (err < 0 && iov_iter_rw(iter) == WRITE)
f2fs_write_failed(mapping, offset + count);
if (trace_android_fs_dataread_start_enabled() &&
(iov_iter_rw(iter) == READ))
trace_android_fs_dataread_end(inode, offset, count);
if (trace_android_fs_datawrite_start_enabled() &&
(iov_iter_rw(iter) == WRITE))
trace_android_fs_datawrite_end(inode, offset, count);
trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err);
return err;

View file

@ -13,6 +13,7 @@
#include "f2fs.h"
#include "node.h"
#include <trace/events/android_fs.h>
bool f2fs_may_inline_data(struct inode *inode)
{
@ -84,14 +85,22 @@ int f2fs_read_inline_data(struct inode *inode, struct page *page)
{
struct page *ipage;
trace_android_fs_dataread_start(inode, page_offset(page),
PAGE_SIZE, current->pid,
current->comm);
ipage = get_node_page(F2FS_I_SB(inode), inode->i_ino);
if (IS_ERR(ipage)) {
trace_android_fs_dataread_end(inode, page_offset(page),
PAGE_SIZE);
unlock_page(page);
return PTR_ERR(ipage);
}
if (!f2fs_has_inline_data(inode)) {
f2fs_put_page(ipage, 1);
trace_android_fs_dataread_end(inode, page_offset(page),
PAGE_SIZE);
return -EAGAIN;
}
@ -102,6 +111,8 @@ int f2fs_read_inline_data(struct inode *inode, struct page *page)
SetPageUptodate(page);
f2fs_put_page(ipage, 1);
trace_android_fs_dataread_end(inode, page_offset(page),
PAGE_SIZE);
unlock_page(page);
return 0;
}

View file

@ -30,6 +30,14 @@
#include <linux/cleancache.h>
#include "internal.h"
#define CREATE_TRACE_POINTS
#include <trace/events/android_fs.h>
EXPORT_TRACEPOINT_SYMBOL(android_fs_datawrite_start);
EXPORT_TRACEPOINT_SYMBOL(android_fs_datawrite_end);
EXPORT_TRACEPOINT_SYMBOL(android_fs_dataread_start);
EXPORT_TRACEPOINT_SYMBOL(android_fs_dataread_end);
/*
* I/O completion handler for multipage BIOs.
*
@ -47,6 +55,16 @@ static void mpage_end_io(struct bio *bio)
struct bio_vec *bv;
int i;
if (trace_android_fs_dataread_end_enabled() &&
(bio_data_dir(bio) == READ)) {
struct page *first_page = bio->bi_io_vec[0].bv_page;
if (first_page != NULL)
trace_android_fs_dataread_end(first_page->mapping->host,
page_offset(first_page),
bio->bi_iter.bi_size);
}
bio_for_each_segment_all(bv, bio, i) {
struct page *page = bv->bv_page;
page_endio(page, bio_data_dir(bio), bio->bi_error);
@ -57,6 +75,18 @@ static void mpage_end_io(struct bio *bio)
static struct bio *mpage_bio_submit(int rw, struct bio *bio)
{
if (trace_android_fs_dataread_start_enabled() && (rw == READ)) {
struct page *first_page = bio->bi_io_vec[0].bv_page;
if (first_page != NULL) {
trace_android_fs_dataread_start(
first_page->mapping->host,
page_offset(first_page),
bio->bi_iter.bi_size,
current->pid,
current->comm);
}
}
bio->bi_end_io = mpage_end_io;
guard_bio_eod(rw, bio);
submit_bio(rw, bio);

View file

@ -0,0 +1,31 @@
#undef TRACE_SYSTEM
#define TRACE_SYSTEM android_fs
#if !defined(_TRACE_ANDROID_FS_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_ANDROID_FS_H
#include <linux/tracepoint.h>
#include <trace/events/android_fs_template.h>
DEFINE_EVENT(android_fs_data_start_template, android_fs_dataread_start,
TP_PROTO(struct inode *inode, loff_t offset, int bytes,
pid_t pid, char *command),
TP_ARGS(inode, offset, bytes, pid, command));
DEFINE_EVENT(android_fs_data_end_template, android_fs_dataread_end,
TP_PROTO(struct inode *inode, loff_t offset, int bytes),
TP_ARGS(inode, offset, bytes));
DEFINE_EVENT(android_fs_data_start_template, android_fs_datawrite_start,
TP_PROTO(struct inode *inode, loff_t offset, int bytes,
pid_t pid, char *command),
TP_ARGS(inode, offset, bytes, pid, command));
DEFINE_EVENT(android_fs_data_end_template, android_fs_datawrite_end,
TP_PROTO(struct inode *inode, loff_t offset, int bytes),
TP_ARGS(inode, offset, bytes));
#endif /* _TRACE_ANDROID_FS_H */
/* This part must be outside protection */
#include <trace/define_trace.h>

View file

@ -0,0 +1,79 @@
#if !defined(_TRACE_ANDROID_FS_TEMPLATE_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_ANDROID_FS_TEMPLATE_H
#include <linux/tracepoint.h>
DECLARE_EVENT_CLASS(android_fs_data_start_template,
TP_PROTO(struct inode *inode, loff_t offset, int bytes,
pid_t pid, char *command),
TP_ARGS(inode, offset, bytes, pid, command),
TP_STRUCT__entry(
__array(char, path, MAX_FILTER_STR_VAL);
__field(char *, pathname);
__field(loff_t, offset);
__field(int, bytes);
__field(loff_t, i_size);
__string(cmdline, command);
__field(pid_t, pid);
__field(ino_t, ino);
),
TP_fast_assign(
{
struct dentry *d;
/*
* Grab a reference to the inode here because
* d_obtain_alias() will either drop the inode
* reference if it locates an existing dentry
* or transfer the reference to the new dentry
* created. In our case, the file is still open,
* so the dentry is guaranteed to exist (connected),
* so d_obtain_alias() drops the reference we
* grabbed here.
*/
ihold(inode);
d = d_obtain_alias(inode);
if (!IS_ERR(d)) {
__entry->pathname = dentry_path(d,
__entry->path,
MAX_FILTER_STR_VAL);
dput(d);
} else
__entry->pathname = ERR_PTR(-EINVAL);
__entry->offset = offset;
__entry->bytes = bytes;
__entry->i_size = i_size_read(inode);
__assign_str(cmdline, command);
__entry->pid = pid;
__entry->ino = inode->i_ino;
}
),
TP_printk("entry_name %s, offset %llu, bytes %d, cmdline %s,"
" pid %d, i_size %llu, ino %lu",
(IS_ERR(__entry->pathname) ? "ERROR" : __entry->pathname),
__entry->offset, __entry->bytes, __get_str(cmdline),
__entry->pid, __entry->i_size,
(unsigned long) __entry->ino)
);
DECLARE_EVENT_CLASS(android_fs_data_end_template,
TP_PROTO(struct inode *inode, loff_t offset, int bytes),
TP_ARGS(inode, offset, bytes),
TP_STRUCT__entry(
__field(ino_t, ino);
__field(loff_t, offset);
__field(int, bytes);
),
TP_fast_assign(
{
__entry->ino = inode->i_ino;
__entry->offset = offset;
__entry->bytes = bytes;
}
),
TP_printk("ino %lu, offset %llu, bytes %d",
(unsigned long) __entry->ino,
__entry->offset, __entry->bytes)
);
#endif /* _TRACE_ANDROID_FS_TEMPLATE_H */