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
);
63 if (radix_tree_preload(GFP_NOFS
))
66 spin_lock(&pids_lock
);
67 p
= radix_tree_lookup(&pids
, pid
);
71 radix_tree_delete(&pids
, pid
);
73 f2fs_radix_tree_insert(&pids
, pid
, current
);
75 trace_printk("%3x:%3x %4x %-16s\n",
76 MAJOR(inode
->i_sb
->s_dev
), MINOR(inode
->i_sb
->s_dev
),
79 spin_unlock(&pids_lock
);
80 radix_tree_preload_end();
83 void f2fs_trace_ios(struct f2fs_io_info
*fio
, int flush
)
94 inode
= fio
->page
->mapping
->host
;
95 pid
= page_private(fio
->page
);
97 major
= MAJOR(inode
->i_sb
->s_dev
);
98 minor
= MINOR(inode
->i_sb
->s_dev
);
100 if (last_io
.major
== major
&& last_io
.minor
== minor
&&
101 last_io
.pid
== pid
&&
102 last_io
.type
== __file_type(inode
, pid
) &&
103 last_io
.fio
.rw
== fio
->rw
&&
104 last_io
.fio
.blk_addr
+ last_io
.len
== fio
->blk_addr
) {
111 last_io
.major
= major
;
112 last_io
.minor
= minor
;
114 last_io
.type
= __file_type(inode
, pid
);
120 void f2fs_build_trace_ios(void)
122 spin_lock_init(&pids_lock
);
125 #define PIDVEC_SIZE 128
126 static unsigned int gang_lookup_pids(pid_t
*results
, unsigned long first_index
,
127 unsigned int max_items
)
129 struct radix_tree_iter iter
;
131 unsigned int ret
= 0;
133 if (unlikely(!max_items
))
136 radix_tree_for_each_slot(slot
, &pids
, &iter
, first_index
) {
137 results
[ret
] = iter
.index
;
138 if (++ret
== PIDVEC_SIZE
)
144 void f2fs_destroy_trace_ios(void)
146 pid_t pid
[PIDVEC_SIZE
];
150 spin_lock(&pids_lock
);
151 while ((found
= gang_lookup_pids(pid
, next_pid
, PIDVEC_SIZE
))) {
154 next_pid
= pid
[found
- 1] + 1;
155 for (idx
= 0; idx
< found
; idx
++)
156 radix_tree_delete(&pids
, pid
[idx
]);
158 spin_unlock(&pids_lock
);