added search page on hash table in file
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Tue, 23 Oct 2012 06:28:18 +0000 (10:28 +0400)
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>
Tue, 23 Oct 2012 06:28:18 +0000 (10:28 +0400)
driver/new_dpf.h
driver/us_proc_inst.c

index 095dc7b..f775c33 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __NEW_DPF__
 #define __NEW_DPF__
 
-#include <linux/list.h>
+#include <linux/hash.h>
 #include "storage.h"
 
 struct page_probes {
@@ -9,7 +9,7 @@ struct page_probes {
        size_t cnt_ip;
        us_proc_ip_t *ip;
 
-       struct hlist_node node; // for file_probes
+       struct hlist_node hlist; // for file_probes
 };
 
 struct file_probes {
@@ -18,7 +18,8 @@ struct file_probes {
        int loaded;
        unsigned long map_addr;
 
-       struct hlist_head head; // for page_probes
+       unsigned long page_probes_hash_bits;
+       struct hlist_head *page_probes_table; // for page_probes
 };
 
 struct proc_probes {
@@ -32,7 +33,6 @@ struct proc_probes {
 static struct page_probes *page_p_new(unsigned long offset, us_proc_ip_t *ip, size_t cnt)
 {
        struct page_probes *obj = kmalloc(sizeof(*obj), GFP_ATOMIC);
-       printk("##### pp_new: offset=%x, cnt_addr=%u\n", offset, cnt);
 
        if (obj) {
                int i;
@@ -45,7 +45,7 @@ static struct page_probes *page_p_new(unsigned long offset, us_proc_ip_t *ip, si
                memcpy(obj->ip, ip, sizeof(*obj->ip)*cnt);
                obj->cnt_ip = cnt;
                obj->offset = offset;
-               INIT_HLIST_NODE(&obj->node);
+               INIT_HLIST_NODE(&obj->hlist);
        }
 
        return obj;
@@ -71,16 +71,34 @@ static void page_p_set_all_kp_addr(struct page_probes *page_p, const struct file
        }
 }
 
+static int calculation_hash_bits(int cnt)
+{
+       int bits;
+       for (bits = 1; cnt >>= 1; ++bits);
+
+       return bits;
+}
+
 // file_probes
-static struct file_probes *file_p_new(us_proc_lib_t *lib)
+static struct file_probes *file_p_new(us_proc_lib_t *lib, int page_cnt)
 {
        struct file_probes *obj = kmalloc(sizeof(*obj), GFP_ATOMIC);
 
        if (obj) {
+               int i, table_size;
                obj->dentry = lib->m_f_dentry;
                obj->path = lib->path;
                obj->loaded = 0;
-               INIT_HLIST_HEAD(&obj->head);
+               obj->map_addr = 0;
+
+               obj->page_probes_hash_bits = calculation_hash_bits(page_cnt);//PAGE_PROBES_HASH_BITS;
+               table_size = (1 << obj->page_probes_hash_bits);
+
+               obj->page_probes_table = kmalloc(sizeof(*obj->page_probes_table)*table_size, GFP_ATOMIC);
+
+               for (i = 0; i < table_size; ++i) {
+                       INIT_HLIST_HEAD(&obj->page_probes_table[i]);
+               }
        }
 
        return obj;
@@ -93,14 +111,14 @@ static void file_p_del(struct file_probes *file_p)
 
 static void file_p_add_page_p(struct file_probes *file_p, struct page_probes *page_p)
 {
-       hlist_add_head(&page_p->node, &file_p->head);
+       hlist_add_head_rcu(&page_p->hlist, &file_p->page_probes_table[hash_ptr(page_p->offset, file_p->page_probes_hash_bits)]);
 }
 
 static struct page_probes *file_p_find_page_p(struct file_probes *file_p, unsigned long page)
 {
-       struct page_probes *pp = NULL;
-       struct hlist_node *node = NULL;
-       struct hlist_head *head = &file_p->head;
+       struct page_probes *page_p;
+       struct hlist_node *node;
+       struct hlist_head *head;
        unsigned long offset;
 
        if (file_p->map_addr > page) {
@@ -111,9 +129,10 @@ static struct page_probes *file_p_find_page_p(struct file_probes *file_p, unsign
 
        offset = page - file_p->map_addr;
 
-       hlist_for_each_entry(pp, node, head, node) {
-               if (pp->offset == offset) {
-                       return pp;
+       head = &file_p->page_probes_table[hash_ptr(offset, file_p->page_probes_hash_bits)];
+       hlist_for_each_entry_rcu(page_p, node, head, hlist) {
+               if (page_p->offset == offset) {
+                       return page_p;
                }
        }
 
@@ -167,7 +186,6 @@ static struct page_probes *get_page_p_of_ips(unsigned long page, unsigned long m
        unsigned long cnt = max_index - min_index;
        us_proc_ip_t *ip = kmalloc(sizeof(*ip)*cnt, GFP_ATOMIC);
 
-       printk("#### min_index=%2u, max_index=%2u, cnt=%2u\n", min_index, max_index, cnt);
        for (idx = min_index; idx < max_index; ++idx) {
                ip[idx - min_index].offset = p_ips[idx].offset & ~PAGE_MASK;;
                ip[idx - min_index].jprobe = p_ips[idx].jprobe;
@@ -179,6 +197,8 @@ static struct page_probes *get_page_p_of_ips(unsigned long page, unsigned long m
        return page_p;
 }
 
+static void print_proc_probes(const struct proc_probes *proc_p);
+
 struct proc_probes *get_file_probes(const inst_us_proc_t *task_inst_info)
 {
        struct proc_probes *proc_p = kmalloc(sizeof(*proc_p), GFP_ATOMIC);
@@ -191,28 +211,46 @@ struct proc_probes *get_file_probes(const inst_us_proc_t *task_inst_info)
 
                for (i = 0; i < task_inst_info->libs_count; ++i) {
                        us_proc_lib_t *p_libs = &task_inst_info->p_libs[i];
-                       struct file_probes *file_p = file_p_new(p_libs);
+                       struct file_probes *file_p = NULL;
                        unsigned long page = 0, min_index = 0, max_index = 0, cnt = 0, idx = 0;
                        struct page_probes *page_p = NULL;
-                       int k;
-                       sort_libs(p_libs);
+                       int k, page_cnt = 0;
 
                        if (p_libs->ips_count == 0) {
                                continue;
                        }
 
-                       page = p_libs->p_ips[0].offset & PAGE_MASK;
+                       sort_libs(p_libs);
 
-                       printk("#### page=%x\n", page);
+                       // calculation page_cnt
+                       page = p_libs->p_ips[0].offset & PAGE_MASK;
                        min_index = 0;
                        for (k = 0; k < p_libs->ips_count; ++k) {
                                us_proc_ip_t *p_ips = &p_libs->p_ips[k];
                                unsigned long addr = p_ips->offset;
+                               if ( page != (addr & PAGE_MASK)) {
+                                       max_index = k;
+                                       ++page_cnt;
 
-                               printk("#### k=%2u, addr=%x\n", k, addr);
+                                       page = addr & PAGE_MASK;
+                                       min_index = max_index;
+                               }
+                       }
+
+                       ++page_cnt;
+
+                       printk("### file: %s, page_cnt=%d\n", p_libs->m_f_dentry->d_iname, page_cnt);
+                       file_p = file_p_new(p_libs, page_cnt);
+
+                       page = p_libs->p_ips[0].offset & PAGE_MASK;
+                       min_index = 0;
+                       for (k = 0; k < p_libs->ips_count; ++k) {
+                               us_proc_ip_t *p_ips = &p_libs->p_ips[k];
+                               unsigned long addr = p_ips->offset;
                                if ( page != (addr & PAGE_MASK)) {
                                        max_index = k;
                                        page_p = get_page_p_of_ips(page, min_index, max_index, p_libs->p_ips);
+
                                        file_p_add_page_p(file_p, page_p);
 
                                        page = addr & PAGE_MASK;
@@ -222,12 +260,15 @@ struct proc_probes *get_file_probes(const inst_us_proc_t *task_inst_info)
 
                        max_index = p_libs->ips_count;
                        page_p = get_page_p_of_ips(page, min_index, max_index, p_libs->p_ips);
-                       file_p_add_page_p(file_p, page_p);
 
+
+                       file_p_add_page_p(file_p, page_p);
                        proc_p->file_p[i] = file_p;
                }
        }
 
+       print_proc_probes(proc_p);
+
        return proc_p;
 }
 
@@ -269,25 +310,29 @@ static void print_page_probes(const struct page_probes *pp)
 
 static void print_file_probes(const struct file_probes *file_p)
 {
+       int i;
        struct page_probes *page_p = NULL;
        struct hlist_node *node = NULL;
-       struct hlist_head *head = &file_p->head;
+       struct hlist_head *head = NULL;
 
        printk("###   d_iname=%s, map_addr=%x\n",
                        file_p->dentry->d_iname, file_p->map_addr);
 
-       hlist_for_each_entry(page_p, node, head, node) {
-               print_page_probes(page_p);
+       for (i = 0; i < (1 << file_p->page_probes_hash_bits); ++i) {
+               head = &file_p->page_probes_table[i];
+               hlist_for_each_entry_rcu(page_p, node, head, hlist) {
+                       print_page_probes(page_p);
+               }
        }
 }
 
-static void print_proc_probes(const struct proc_probes *pp)
+static void print_proc_probes(const struct proc_probes *proc_p)
 {
        int i;
 
        printk("### print_proc_probes\n");
-       for (i = 0; i < pp->cnt; ++i) {
-               print_file_probes(pp->file_p[i]);
+       for (i = 0; i < proc_p->cnt; ++i) {
+               print_file_probes(proc_p->file_p[i]);
        }
        printk("### print_proc_probes\n");
 }
index 9613ce3..464bf48 100644 (file)
@@ -1349,7 +1349,6 @@ static void install_page_probes(unsigned long page, struct task_struct *task, st
                struct file_probes *file_p = proc_p_find_file_p(proc_p, vma);
                if(file_p) {
                        struct page_probes *page_p;
-
                        if (!file_p->loaded) {
                                set_mapping_file(file_p, proc_p, task, vma);
                                file_p->loaded = 1;