3 #include <linux/slab.h>
4 #include <linux/list.h>
5 #include <linux/hash.h>
8 static int calculation_hash_bits(int cnt)
11 for (bits = 1; cnt >>= 1; ++bits);
16 struct sspt_file *sspt_file_create(const char *path, struct dentry *dentry, int page_cnt)
18 struct sspt_file *obj = kmalloc(sizeof(*obj), GFP_ATOMIC);
28 obj->page_probes_hash_bits = calculation_hash_bits(page_cnt);//PAGE_PROBES_HASH_BITS;
29 table_size = (1 << obj->page_probes_hash_bits);
31 obj->page_probes_table = kmalloc(sizeof(*obj->page_probes_table)*table_size, GFP_ATOMIC);
33 for (i = 0; i < table_size; ++i) {
34 INIT_HLIST_HEAD(&obj->page_probes_table[i]);
41 void sspt_file_free(struct sspt_file *file)
43 struct hlist_node *p, *n;
44 struct hlist_head *head;
45 struct sspt_page *page;
46 int i, table_size = (1 << file->page_probes_hash_bits);
48 for (i = 0; i < table_size; ++i) {
49 head = &file->page_probes_table[i];
50 hlist_for_each_entry_safe(page, p, n, head, hlist) {
51 hlist_del(&page->hlist);
56 kfree(file->page_probes_table);
60 static void file_p_add_page_p(struct sspt_file *file, struct sspt_page *page)
62 hlist_add_head(&page->hlist, &file->page_probes_table[hash_ptr(page->offset, file->page_probes_hash_bits)]);
65 struct sspt_file *sspt_file_copy(const struct sspt_file *file)
67 struct sspt_file *file_out;
70 printk("### WARNING: file_p == NULL\n");
74 file_out = kmalloc(sizeof(*file_out), GFP_ATOMIC);
76 struct sspt_page *page = NULL;
77 struct hlist_node *node = NULL;
78 struct hlist_head *head = NULL;
80 INIT_LIST_HEAD(&file_out->list);
81 file_out->dentry = file->dentry;
82 file_out->path = file->path;
84 file_out->vm_start = 0;
87 file_out->page_probes_hash_bits = file->page_probes_hash_bits;
88 table_size = (1 << file_out->page_probes_hash_bits);
90 file_out->page_probes_table =
91 kmalloc(sizeof(*file_out->page_probes_table)*table_size, GFP_ATOMIC);
93 for (i = 0; i < table_size; ++i) {
94 INIT_HLIST_HEAD(&file_out->page_probes_table[i]);
98 for (i = 0; i < table_size; ++i) {
99 head = &file->page_probes_table[i];
100 hlist_for_each_entry(page, node, head, hlist) {
101 file_p_add_page_p(file_out, page_p_copy(page));
109 static struct sspt_page *file_p_find_page_p(struct sspt_file *file, unsigned long offset)
111 struct hlist_node *node;
112 struct hlist_head *head;
113 struct sspt_page *page;
115 head = &file->page_probes_table[hash_ptr(offset, file->page_probes_hash_bits)];
116 hlist_for_each_entry(page, node, head, hlist) {
117 if (page->offset == offset) {
125 static struct sspt_page *file_p_find_page_p_or_new(struct sspt_file *file, unsigned long offset)
127 struct sspt_page *page = file_p_find_page_p(file, offset);
130 page = page_p_new(offset);
131 file_p_add_page_p(file, page);
137 struct sspt_page *sspt_find_page_mapped(struct sspt_file *file, unsigned long page)
139 unsigned long offset;
141 if (file->vm_start > page || file->vm_end < page) {
143 printk("ERROR: file_p[vm_start..vm_end] <> page: file_p[vm_start=%x, vm_end=%x, path=%s, d_iname=%s] page=%x\n",
144 file->vm_start, file->vm_end, file->path, file->dentry->d_iname, page);
148 offset = page - file->vm_start;
150 return file_p_find_page_p(file, offset);
153 void sspt_file_add_ip(struct sspt_file *file, struct ip_data *ip_d)
155 unsigned long offset = ip_d->offset & PAGE_MASK;
156 struct sspt_page *page = file_p_find_page_p_or_new(file, offset);
159 struct us_ip *ip = create_ip_by_ip_data(ip_d);
161 page_p_add_ip(page, ip);
164 struct sspt_page *sspt_get_page(struct sspt_file *file, unsigned long offset_addr)
166 unsigned long offset = offset_addr & PAGE_MASK;
167 struct sspt_page *page = file_p_find_page_p_or_new(file, offset);
169 spin_lock(&page->lock);
174 void sspt_put_page(struct sspt_page *page)
176 spin_unlock(&page->lock);