4 * Copyright (c) 2014 Motorola Mobility
5 * Copyright (c) 2014 Jaegeuk Kim <jaegeuk@kernel.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/f2fs_fs.h>
13 #include <linux/sched.h>
14 #include <linux/radix-tree.h>
19 static RADIX_TREE(pids
, GFP_ATOMIC
);
20 static spinlock_t pids_lock
;
21 static struct last_io_info last_io
;
23 static inline void __print_last_io(void)
28 trace_printk("%3x:%3x %4x %-16s %2x %5x %5x %12x %4x\n",
29 last_io
.major
, last_io
.minor
,
30 last_io
.pid
, "----------------",
32 last_io
.fio
.op
, last_io
.fio
.op_flags
,
33 last_io
.fio
.new_blkaddr
,
35 memset(&last_io
, 0, sizeof(last_io
));
38 static int __file_type(struct inode
*inode
, pid_t pid
)
40 if (f2fs_is_atomic_file(inode
))
42 else if (f2fs_is_volatile_file(inode
))
43 return __VOLATILE_FILE
;
44 else if (S_ISDIR(inode
->i_mode
))
46 else if (inode
->i_ino
== F2FS_NODE_INO(F2FS_I_SB(inode
)))
48 else if (inode
->i_ino
== F2FS_META_INO(F2FS_I_SB(inode
)))
56 void f2fs_trace_pid(struct page
*page
)
58 struct inode
*inode
= page
->mapping
->host
;
59 pid_t pid
= task_pid_nr(current
);
62 set_page_private(page
, (unsigned long)pid
);
64 if (radix_tree_preload(GFP_NOFS
))
67 spin_lock(&pids_lock
);
68 p
= radix_tree_lookup(&pids
, pid
);
72 radix_tree_delete(&pids
, pid
);
74 f2fs_radix_tree_insert(&pids
, pid
, current
);
76 trace_printk("%3x:%3x %4x %-16s\n",
77 MAJOR(inode
->i_sb
->s_dev
), MINOR(inode
->i_sb
->s_dev
),
80 spin_unlock(&pids_lock
);
81 radix_tree_preload_end();
84 void f2fs_trace_ios(struct f2fs_io_info
*fio
, int flush
)
95 inode
= fio
->page
->mapping
->host
;
96 pid
= page_private(fio
->page
);
98 major
= MAJOR(inode
->i_sb
->s_dev
);
99 minor
= MINOR(inode
->i_sb
->s_dev
);
101 if (last_io
.major
== major
&& last_io
.minor
== minor
&&
102 last_io
.pid
== pid
&&
103 last_io
.type
== __file_type(inode
, pid
) &&
104 last_io
.fio
.op
== fio
->op
&&
105 last_io
.fio
.op_flags
== fio
->op_flags
&&
106 last_io
.fio
.new_blkaddr
+ last_io
.len
==
114 last_io
.major
= major
;
115 last_io
.minor
= minor
;
117 last_io
.type
= __file_type(inode
, pid
);
123 void f2fs_build_trace_ios(void)
125 spin_lock_init(&pids_lock
);
128 #define PIDVEC_SIZE 128
129 static unsigned int gang_lookup_pids(pid_t
*results
, unsigned long first_index
,
130 unsigned int max_items
)
132 struct radix_tree_iter iter
;
134 unsigned int ret
= 0;
136 if (unlikely(!max_items
))
139 radix_tree_for_each_slot(slot
, &pids
, &iter
, first_index
) {
140 results
[ret
] = iter
.index
;
141 if (++ret
== max_items
)
147 void f2fs_destroy_trace_ios(void)
149 pid_t pid
[PIDVEC_SIZE
];
153 spin_lock(&pids_lock
);
154 while ((found
= gang_lookup_pids(pid
, next_pid
, PIDVEC_SIZE
))) {
157 next_pid
= pid
[found
- 1] + 1;
158 for (idx
= 0; idx
< found
; idx
++)
159 radix_tree_delete(&pids
, pid
[idx
]);
161 spin_unlock(&pids_lock
);