17 #define pr_fmt(fmt) "gcov: " fmt
20 #include <linux/module.h>
23 #include <linux/list.h>
24 #include <linux/string.h>
25 #include <linux/slab.h>
63 static const char objtree[] = OBJTREE;
64 static const char srctree[] =
SRCTREE;
66 static struct dentry *reset_dentry;
71 static int gcov_persist = 1;
73 static int __init gcov_persist_setup(
char *
str)
78 pr_warning(
"invalid gcov_persist parameter '%s'\n", str);
82 pr_info(
"setting gcov_persist to %d\n", gcov_persist);
86 __setup(
"gcov_persist=", gcov_persist_setup);
94 static void *gcov_seq_start(
struct seq_file *seq, loff_t *
pos)
99 for (i = 0; i < *
pos; i++) {
107 static void *gcov_seq_next(
struct seq_file *seq,
void *
data, loff_t *pos)
119 static int gcov_seq_show(
struct seq_file *seq,
void *data)
128 static void gcov_seq_stop(
struct seq_file *seq,
void *data)
134 .start = gcov_seq_start,
135 .next = gcov_seq_next,
136 .show = gcov_seq_show,
137 .stop = gcov_seq_stop,
192 info = get_accumulated_info(node);
200 goto err_free_iter_info;
218 static int gcov_seq_release(
struct inode *inode,
struct file *file)
255 static void reset_node(
struct gcov_node *node)
265 static void remove_node(
struct gcov_node *node);
272 static ssize_t gcov_seq_write(
struct file *file,
const char __user *
addr,
273 size_t len, loff_t *pos)
282 node = get_node_by_name(info->
filename);
303 static char *link_target(
const char *dir,
const char *
path,
const char *
ext)
336 rel = filename +
strlen(objtree) + 1;
337 if (ext->
dir == SRC_TREE)
338 result = link_target(srctree, rel, ext->
ext);
340 result = link_target(objtree, rel, ext->
ext);
343 result = link_target(
NULL, filename, ext->
ext);
349 #define SKEW_PREFIX ".tmp_"
355 static const char *deskew(
const char *basename)
378 for (i = 0; i < num; i++) {
383 basename =
strrchr(target,
'/');
404 .open = gcov_seq_open,
405 .release = gcov_seq_release,
408 .write = gcov_seq_write,
413 const char *name,
struct gcov_node *parent)
415 INIT_LIST_HEAD(&node->
list);
417 INIT_LIST_HEAD(&node->
all);
432 struct gcov_info *info,
const char *name)
445 init_node(node, info, name, parent);
449 parent->
dentry, node, &gcov_data_fops);
458 add_links(node, parent->
dentry);
460 list_add(&node->
all, &all_head);
471 static void remove_links(
struct gcov_node *node)
487 static void release_node(
struct gcov_node *node)
500 static void remove_node(
struct gcov_node *node)
504 while ((node != &root_node) && list_empty(&node->
children)) {
532 static ssize_t reset_write(
struct file *file,
const char __user *addr,
533 size_t len, loff_t *pos)
542 else if (list_empty(&node->
children)) {
554 static ssize_t reset_read(
struct file *file,
char __user *addr,
size_t len,
562 .write = reset_write,
571 static void add_node(
struct gcov_info *info)
584 for (curr = filename; (next =
strchr(curr,
'/')); curr = next + 1) {
588 if (
strcmp(curr,
".") == 0)
590 if (
strcmp(curr,
"..") == 0) {
596 node = get_child_by_name(parent, curr);
598 node = new_node(parent,
NULL, curr);
605 node = new_node(parent, info, curr);
633 pr_warning(
"could not add '%s' (out of memory)\n",
639 loaded_info[num] =
info;
648 "(incompatible version)\n", info->
filename);
658 pr_warning(
"could not add '%s' (incompatible "
695 "(out of memory)\n", info->
filename);
708 i = get_info_index(node, info);
710 pr_warning(
"could not remove '%s' (not found)\n",
715 save_info(node, info);
738 node = get_node_by_name(info->
filename);
742 add_info(node, info);
748 remove_info(node, info);
750 pr_warning(
"could not remove '%s' (not found)\n",
759 static __init int gcov_fs_init(
void)
769 if (!root_node.dentry)
776 NULL, &gcov_reset_fops);
785 if (root_node.dentry)