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 %12x %4x\n",
29 last_io
.major
, last_io
.minor
,
30 last_io
.pid
, "----------------",
32 last_io
.fio
.rw
, last_io
.fio
.blk_addr
,
34 memset(&last_io
, 0, sizeof(last_io
));
37 static int __file_type(struct inode
*inode
, pid_t pid
)
39 if (f2fs_is_atomic_file(inode
))
41 else if (f2fs_is_volatile_file(inode
))
42 return __VOLATILE_FILE
;
43 else if (S_ISDIR(inode
->i_mode
))
45 else if (inode
->i_ino
== F2FS_NODE_INO(F2FS_I_SB(inode
)))
47 else if (inode
->i_ino
== F2FS_META_INO(F2FS_I_SB(inode
)))
55 void f2fs_trace_pid(struct page
*page
)
57 struct inode
*inode
= page
->mapping
->host
;
58 pid_t pid
= task_pid_nr(current
);
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 if (radix_tree_insert(&pids
, pid
, current
)) {
75 spin_unlock(&pids_lock
);
76 radix_tree_preload_end();
81 trace_printk("%3x:%3x %4x %-16s\n",
82 MAJOR(inode
->i_sb
->s_dev
), MINOR(inode
->i_sb
->s_dev
),
85 spin_unlock(&pids_lock
);
86 radix_tree_preload_end();
89 void f2fs_trace_ios(struct f2fs_io_info
*fio
, int flush
)
100 inode
= fio
->page
->mapping
->host
;
101 pid
= page_private(fio
->page
);
103 major
= MAJOR(inode
->i_sb
->s_dev
);
104 minor
= MINOR(inode
->i_sb
->s_dev
);
106 if (last_io
.major
== major
&& last_io
.minor
== minor
&&
107 last_io
.pid
== pid
&&
108 last_io
.type
== __file_type(inode
, pid
) &&
109 last_io
.fio
.rw
== fio
->rw
&&
110 last_io
.fio
.blk_addr
+ last_io
.len
== fio
->blk_addr
) {
117 last_io
.major
= major
;
118 last_io
.minor
= minor
;
120 last_io
.type
= __file_type(inode
, pid
);
126 void f2fs_build_trace_ios(void)
128 spin_lock_init(&pids_lock
);
131 #define PIDVEC_SIZE 128
132 static unsigned int gang_lookup_pids(pid_t
*results
, unsigned long first_index
,
133 unsigned int max_items
)
135 struct radix_tree_iter iter
;
137 unsigned int ret
= 0;
139 if (unlikely(!max_items
))
142 radix_tree_for_each_slot(slot
, &pids
, &iter
, first_index
) {
143 results
[ret
] = iter
.index
;
144 if (++ret
== PIDVEC_SIZE
)
150 void f2fs_destroy_trace_ios(void)
152 pid_t pid
[PIDVEC_SIZE
];
156 spin_lock(&pids_lock
);
157 while ((found
= gang_lookup_pids(pid
, next_pid
, PIDVEC_SIZE
))) {
160 next_pid
= pid
[found
- 1] + 1;
161 for (idx
= 0; idx
< found
; idx
++)
162 radix_tree_delete(&pids
, pid
[idx
]);
164 spin_unlock(&pids_lock
);