ANDROID: fs: FS tracepoints to track IO.
authorMohan Srinivasan <srmohan@google.com>
Thu, 15 Dec 2016 00:39:51 +0000 (16:39 -0800)
committerAmit Pundir <amit.pundir@linaro.org>
Mon, 18 Dec 2017 15:41:22 +0000 (21:11 +0530)
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. (Merged from android4.4-common).

Signed-off-by: Mohan Srinivasan <srmohan@google.com>
fs/ext4/inline.c
fs/ext4/inode.c
fs/ext4/readpage.c
fs/f2fs/data.c
fs/f2fs/inline.c
fs/mpage.c
include/trace/events/android_fs.h [new file with mode: 0644]
include/trace/events/android_fs_template.h [new file with mode: 0644]

index 28c5c3abddb3057a1e16ab24ef356bedc26ab457..ddfc3bbcd4dea13d589346c0f6ffad5bdc1d6454 100644 (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))
@@ -514,6 +515,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.
@@ -525,6 +529,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);
index 90afeb7293a6b986078d98f8c0112a4d5d7033b9..d5c7b206e5af7061cf70a41af3777ee7e4583b67 100644 (file)
@@ -46,6 +46,7 @@
 #include "truncate.h"
 
 #include <trace/events/ext4.h>
+#include <trace/events/android_fs.h>
 
 #define MPAGE_DA_EXTENT_TAIL 0x01
 
@@ -1243,6 +1244,8 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
        if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
                return -EIO;
 
+       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
@@ -1380,6 +1383,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_has_inline_data(inode)) {
                ret = ext4_write_inline_data_end(inode, pos, len,
@@ -1484,6 +1488,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_SIZE - 1);
        to = from + len;
@@ -3024,6 +3029,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)) {
@@ -3142,6 +3149,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_SIZE - 1);
        end = start + copied - 1;
@@ -3780,6 +3788,7 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
        size_t count = iov_iter_count(iter);
        loff_t offset = iocb->ki_pos;
        ssize_t ret;
+       int rw = iov_iter_rw(iter);
 
 #ifdef CONFIG_EXT4_FS_ENCRYPTION
        if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode))
@@ -3800,12 +3809,31 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
        if (WARN_ON_ONCE(IS_DAX(inode)))
                return 0;
 
+       if (trace_android_fs_dataread_start_enabled() &&
+           (rw == READ))
+               trace_android_fs_dataread_start(inode, offset, count,
+                                               current->pid,
+                                               current->comm);
+       if (trace_android_fs_datawrite_start_enabled() &&
+           (rw == 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 (iov_iter_rw(iter) == READ)
                ret = ext4_direct_IO_read(iocb, iter);
        else
                ret = ext4_direct_IO_write(iocb, iter);
        trace_ext4_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), ret);
+
+       if (trace_android_fs_dataread_start_enabled() &&
+           (rw == READ))
+               trace_android_fs_dataread_end(inode, offset, count);
+       if (trace_android_fs_datawrite_start_enabled() &&
+           (rw == WRITE))
+               trace_android_fs_datawrite_end(inode, offset, count);
+
        return ret;
 }
 
index 9ffa6fad18dbef1528f3ddbacc67fafff370cf03..bda47851a9d3905e8667e7d20e4bdae6aaff3d3e 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/cleancache.h>
 
 #include "ext4.h"
+#include <trace/events/android_fs.h>
 
 static inline bool ext4_bio_encrypted(struct bio *bio)
 {
@@ -56,6 +57,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.
  *
@@ -73,6 +85,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)) {
                if (bio->bi_status) {
                        fscrypt_release_ctx(bio->bi_private);
@@ -96,6 +111,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(bio);
+}
+
 int ext4_mpage_readpages(struct address_space *mapping,
                         struct list_head *pages, struct page *page,
                         unsigned nr_pages)
@@ -236,7 +269,7 @@ int ext4_mpage_readpages(struct address_space *mapping,
                 */
                if (bio && (last_block_in_bio != blocks[0] - 1)) {
                submit_and_realloc:
-                       submit_bio(bio);
+                       ext4_submit_bio_read(bio);
                        bio = NULL;
                }
                if (bio == NULL) {
@@ -269,14 +302,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(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(bio);
+                       ext4_submit_bio_read(bio);
                        bio = NULL;
                }
                if (!PageUptodate(page))
@@ -289,6 +322,6 @@ int ext4_mpage_readpages(struct address_space *mapping,
        }
        BUG_ON(pages && !list_empty(pages));
        if (bio)
-               submit_bio(bio);
+               ext4_submit_bio_read(bio);
        return 0;
 }
index 36b535207c88906efae946f71195781497be87f5..21ec7c38904c6b7df620b8937128b0a3d64aa40e 100644 (file)
@@ -29,6 +29,7 @@
 #include "segment.h"
 #include "trace.h"
 #include <trace/events/f2fs.h>
+#include <trace/events/android_fs.h>
 
 static bool __is_cp_guaranteed(struct page *page)
 {
@@ -1935,6 +1936,8 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
        block_t blkaddr = NULL_ADDR;
        int err = 0;
 
+       trace_android_fs_datawrite_start(inode, pos, len,
+                                        current->pid, current->comm);
        trace_f2fs_write_begin(inode, pos, len, flags);
 
        /*
@@ -2024,6 +2027,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);
 
        /*
@@ -2082,6 +2086,16 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
 
        trace_f2fs_direct_IO_enter(inode, offset, count, rw);
 
+       if (trace_android_fs_dataread_start_enabled() &&
+           (rw == READ))
+               trace_android_fs_dataread_start(inode, offset,
+                                               count, current->pid,
+                                               current->comm);
+       if (trace_android_fs_datawrite_start_enabled() &&
+           (rw == WRITE))
+               trace_android_fs_datawrite_start(inode, offset, count,
+                                                current->pid, current->comm);
+
        down_read(&F2FS_I(inode)->dio_rwsem[rw]);
        err = blockdev_direct_IO(iocb, inode, iter, get_data_block_dio);
        up_read(&F2FS_I(inode)->dio_rwsem[rw]);
@@ -2096,6 +2110,13 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
                }
        }
 
+       if (trace_android_fs_dataread_start_enabled() &&
+           (rw == READ))
+               trace_android_fs_dataread_end(inode, offset, count);
+       if (trace_android_fs_datawrite_start_enabled() &&
+           (rw == WRITE))
+               trace_android_fs_datawrite_end(inode, offset, count);
+
        trace_f2fs_direct_IO_exit(inode, offset, count, rw, err);
 
        return err;
index 8322e4e7bb3fc432aabc8067b7ab459274c6d326..f848eb3cdd979fe5751f31f52c8081ad7dafeafb 100644 (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)
 {
@@ -85,14 +86,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;
        }
 
@@ -104,6 +113,8 @@ int f2fs_read_inline_data(struct inode *inode, struct page *page)
        if (!PageUptodate(page))
                SetPageUptodate(page);
        f2fs_put_page(ipage, 1);
+       trace_android_fs_dataread_end(inode, page_offset(page),
+                                     PAGE_SIZE);
        unlock_page(page);
        return 0;
 }
index b7e7f570733ad0766afe5d7f116e787c7ebf21f4..c31b6a48e6dc45892b4f9535881e9060beb6ef2b 100644 (file)
 #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.
  *
@@ -49,6 +57,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, op_is_write(bio_op(bio)),
@@ -60,6 +78,18 @@ static void mpage_end_io(struct bio *bio)
 
 static struct bio *mpage_bio_submit(int op, int op_flags, struct bio *bio)
 {
+       if (trace_android_fs_dataread_start_enabled() && (op == REQ_OP_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;
        bio_set_op_attrs(bio, op, op_flags);
        guard_bio_eod(op, bio);
diff --git a/include/trace/events/android_fs.h b/include/trace/events/android_fs.h
new file mode 100644 (file)
index 0000000..531da43
--- /dev/null
@@ -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>
diff --git a/include/trace/events/android_fs_template.h b/include/trace/events/android_fs_template.h
new file mode 100644 (file)
index 0000000..618988b
--- /dev/null
@@ -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 */