From: Mohan Srinivasan <srmohan@google.com>
Date: Fri, 10 Feb 2017 22:26:23 +0000 (-0800)
Subject: ANDROID: fs: Refactor FS readpage/write tracepoints.
X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=a59d87323780e0de396fe037bae37d5d29bcb828;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git

ANDROID: fs: Refactor FS readpage/write tracepoints.

Refactor the fs readpage/write tracepoints to move the
inode->path lookup outside the tracepoint code, and pass a pointer
to the path into the tracepoint code instead. This is necessary
because the tracepoint code runs non-preemptible. Thanks to
Trilok Soni for catching this in 4.4.

Signed-off-by: Mohan Srinivasan <srmohan@google.com>

[AmitP: Folded following android-4.9 commit changes into this patch
        a5c4dbb05ab7 ("ANDROID: Replace spaces by '_' for some android filesystem tracepoints.")]
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
---

diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index ddfc3bbcd4de..724a983aa17d 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -515,8 +515,16 @@ 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);
+	if (trace_android_fs_dataread_start_enabled()) {
+		char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+		path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    inode);
+		trace_android_fs_dataread_start(inode, page_offset(page),
+						PAGE_SIZE, current->pid,
+						path, current->comm);
+	}
 
 	/*
 	 * Current inline data can only exist in the 1st page,
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index d5c7b206e5af..8d15bbe66775 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1244,8 +1244,16 @@ 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);
+	if (trace_android_fs_datawrite_start_enabled()) {
+		char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+		path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    inode);
+		trace_android_fs_datawrite_start(inode, pos, len,
+						 current->pid, path,
+						 current->comm);
+	}
 	trace_ext4_write_begin(inode, pos, len, flags);
 	/*
 	 * Reserve one block more for addition to orphan list in case
@@ -3029,8 +3037,16 @@ 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);
+	if (trace_android_fs_datawrite_start_enabled()) {
+		char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+		path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    inode);
+		trace_android_fs_datawrite_start(inode, pos, len,
+						 current->pid,
+						 path, current->comm);
+	}
 	trace_ext4_da_write_begin(inode, pos, len, flags);
 
 	if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {
@@ -3810,16 +3826,27 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
 		return 0;
 
 	if (trace_android_fs_dataread_start_enabled() &&
-	    (rw == READ))
+	    (rw == READ)) {
+		char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+		path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    inode);
 		trace_android_fs_dataread_start(inode, offset, count,
-						current->pid,
+						current->pid, path,
 						current->comm);
+	}
 	if (trace_android_fs_datawrite_start_enabled() &&
-	    (rw == WRITE))
+	    (rw == WRITE)) {
+		char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+		path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    inode);
 		trace_android_fs_datawrite_start(inode, offset, count,
-						 current->pid,
+						 current->pid, path,
 						 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);
diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
index bda47851a9d3..df22fcb3c41c 100644
--- a/fs/ext4/readpage.c
+++ b/fs/ext4/readpage.c
@@ -118,11 +118,17 @@ ext4_submit_bio_read(struct bio *bio)
 		struct page *first_page = bio->bi_io_vec[0].bv_page;
 
 		if (first_page != NULL) {
+			char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+			path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    first_page->mapping->host);
 			trace_android_fs_dataread_start(
 				first_page->mapping->host,
 				page_offset(first_page),
 				bio->bi_iter.bi_size,
 				current->pid,
+				path,
 				current->comm);
 		}
 	}
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 21ec7c38904c..f4741f016e28 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1936,8 +1936,16 @@ 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);
+	if (trace_android_fs_datawrite_start_enabled()) {
+		char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+		path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    inode);
+		trace_android_fs_datawrite_start(inode, pos, len,
+						 current->pid, path,
+						 current->comm);
+	}
 	trace_f2fs_write_begin(inode, pos, len, flags);
 
 	/*
@@ -2087,14 +2095,27 @@ 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))
+	    (rw == READ)) {
+		char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+		path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    inode);
 		trace_android_fs_dataread_start(inode, offset,
-						count, current->pid,
+						count, current->pid, path,
 						current->comm);
+	}
 	if (trace_android_fs_datawrite_start_enabled() &&
-	    (rw == WRITE))
+	    (rw == WRITE)) {
+		char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+		path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    inode);
 		trace_android_fs_datawrite_start(inode, offset, count,
-						 current->pid, current->comm);
+						 current->pid, path,
+						 current->comm);
+	}
 
 	down_read(&F2FS_I(inode)->dio_rwsem[rw]);
 	err = blockdev_direct_IO(iocb, inode, iter, get_data_block_dio);
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index f848eb3cdd97..9fb5fdc61888 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -86,9 +86,16 @@ 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);
+	if (trace_android_fs_dataread_start_enabled()) {
+		char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+		path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    inode);
+		trace_android_fs_dataread_start(inode, page_offset(page),
+						PAGE_SIZE, current->pid,
+						path, current->comm);
+	}
 
 	ipage = get_node_page(F2FS_I_SB(inode), inode->i_ino);
 	if (IS_ERR(ipage)) {
diff --git a/fs/mpage.c b/fs/mpage.c
index c31b6a48e6dc..93e3cf7bf27c 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -82,11 +82,17 @@ static struct bio *mpage_bio_submit(int op, int op_flags, struct bio *bio)
 		struct page *first_page = bio->bi_io_vec[0].bv_page;
 
 		if (first_page != NULL) {
+			char *path, pathbuf[MAX_TRACE_PATHBUF_LEN];
+
+			path = android_fstrace_get_pathname(pathbuf,
+						    MAX_TRACE_PATHBUF_LEN,
+						    first_page->mapping->host);
 			trace_android_fs_dataread_start(
 				first_page->mapping->host,
 				page_offset(first_page),
 				bio->bi_iter.bi_size,
 				current->pid,
+				path,
 				current->comm);
 		}
 	}
diff --git a/include/trace/events/android_fs.h b/include/trace/events/android_fs.h
index 531da433a7bc..49509533d3fa 100644
--- a/include/trace/events/android_fs.h
+++ b/include/trace/events/android_fs.h
@@ -9,8 +9,8 @@
 
 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));
+		 pid_t pid, char *pathname, char *command),
+	TP_ARGS(inode, offset, bytes, pid, pathname, command));
 
 DEFINE_EVENT(android_fs_data_end_template, android_fs_dataread_end,
 	TP_PROTO(struct inode *inode, loff_t offset, int bytes),
@@ -18,14 +18,48 @@ DEFINE_EVENT(android_fs_data_end_template, android_fs_dataread_end,
 
 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));
+		 pid_t pid, char *pathname, char *command),
+	TP_ARGS(inode, offset, bytes, pid, pathname, 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));
+	     TP_ARGS(inode, offset, bytes));
 
 #endif /* _TRACE_ANDROID_FS_H */
 
 /* This part must be outside protection */
 #include <trace/define_trace.h>
+
+#ifndef ANDROID_FSTRACE_GET_PATHNAME
+#define ANDROID_FSTRACE_GET_PATHNAME
+
+/* Sizes an on-stack array, so careful if sizing this up ! */
+#define MAX_TRACE_PATHBUF_LEN	256
+
+static inline char *
+android_fstrace_get_pathname(char *buf, int buflen, struct inode *inode)
+{
+	char *path;
+	struct dentry *d;
+
+	/*
+	 * d_obtain_alias() will either iput() if it locates an existing
+	 * dentry or transfer the reference to the new dentry created.
+	 * So get an extra reference here.
+	 */
+	ihold(inode);
+	d = d_obtain_alias(inode);
+	if (likely(!IS_ERR(d))) {
+		path = dentry_path_raw(d, buf, buflen);
+		if (unlikely(IS_ERR(path))) {
+			strcpy(buf, "ERROR");
+			path = buf;
+		}
+		dput(d);
+	} else {
+		strcpy(buf, "ERROR");
+		path = buf;
+	}
+	return path;
+}
+#endif
diff --git a/include/trace/events/android_fs_template.h b/include/trace/events/android_fs_template.h
index 618988b047c1..b23d17b56c63 100644
--- a/include/trace/events/android_fs_template.h
+++ b/include/trace/events/android_fs_template.h
@@ -5,11 +5,10 @@
 
 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),
+		 pid_t pid, char *pathname, char *command),
+	TP_ARGS(inode, offset, bytes, pid, pathname, command),
 	TP_STRUCT__entry(
-		__array(char, path, MAX_FILTER_STR_VAL);
-		__field(char *, pathname);
+		__string(pathbuf, pathname);
 		__field(loff_t,	offset);
 		__field(int,	bytes);
 		__field(loff_t,	i_size);
@@ -19,40 +18,26 @@ DECLARE_EVENT_CLASS(android_fs_data_start_template,
 	),
 	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.
+			 * Replace the spaces in filenames and cmdlines
+			 * because this screws up the tooling that parses
+			 * the traces.
 			 */
-			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);
+			__assign_str(pathbuf, pathname);
+			(void)strreplace(__get_str(pathbuf), ' ', '_');
 			__entry->offset		= offset;
 			__entry->bytes		= bytes;
 			__entry->i_size		= i_size_read(inode);
 			__assign_str(cmdline, command);
+			(void)strreplace(__get_str(cmdline), ' ', '_');
 			__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,
+		  __get_str(pathbuf), __entry->offset, __entry->bytes,
+		  __get_str(cmdline), __entry->pid, __entry->i_size,
 		  (unsigned long) __entry->ino)
 );