if swap.ini has undefined path to lib or app driver will return this wrong path
authorKudrjavtsev Nickita <n.kudryavcev@samsung.com>
Tue, 5 Mar 2013 11:46:09 +0000 (15:46 +0400)
committerKudrjavtsev Nickita <n.kudryavcev@samsung.com>
Tue, 5 Mar 2013 11:46:09 +0000 (15:46 +0400)
driver/Kbuild
driver/device_driver.c
driver/ec_ioctl.h
driver/error_storage.c [new file with mode: 0644]
driver/error_storage.h [new file with mode: 0644]
driver/storage.c
driver/storage.h

index f7c2c8d..b50621d 100644 (file)
@@ -1,6 +1,6 @@
 EXTRA_CFLAGS := $(extra_cflags)
 
 obj-m := swap_driver.o
-swap_driver-y := device_driver.o ec.o legacy.o module.o probes.o \
+swap_driver-y := error_storage.o device_driver.o ec.o legacy.o module.o probes.o \
                  probes_manager.o storage.o us_proc_inst.o  java_inst.o \
                  sspt/ip.o sspt/sspt_page.o sspt/sspt_file.o sspt/sspt_procs.o
index 9259124..1699aee 100644 (file)
@@ -414,6 +414,9 @@ static long device_ioctl (struct file *file UNUSED, unsigned int cmd, unsigned l
                        result = -1;
                        break;
                }
+               if (has_last_error() == -1) {
+                       result = -1;
+               }
 
                break;
        }
@@ -675,7 +678,11 @@ sad_cleanup:
                        DPRINTF("Get Size of Predefined User Space Probes");
                        break;
                }
-
+       case EC_IOCTL_GET_LAST_ERROR:
+               {
+                       result = get_last_error((void*)arg);
+                       break;
+               }
        default:
                EPRINTF ("Unknown driver command = %u", cmd);
                result = -EINVAL;
index 2428235..740e73c 100644 (file)
@@ -74,6 +74,8 @@ typedef enum
 
        EC_IOCTL_SET_PID,
 
+       // error consist of wrong path to apps or libs
+       EC_IOCTL_GET_LAST_ERROR,
 } EC_IOCTL_CMD;
 
 typedef struct
diff --git a/driver/error_storage.c b/driver/error_storage.c
new file mode 100644 (file)
index 0000000..0398212
--- /dev/null
@@ -0,0 +1,106 @@
+#include <linux/string.h>
+#include <linux/vmalloc.h>
+#include <asm/uaccess.h>
+#include "error_storage.h"
+
+static int create_errno_buffer(void);
+static void delete_errno_buffer(void);
+static unsigned int get_max_error_buffer_size(void);
+
+static struct errno_struct
+{
+        unsigned int size;
+        char *buffer;
+};
+
+static struct errno_struct *last_error = NULL;
+
+static int create_errno_buffer(void)
+{
+        struct errno_struct *error = NULL;
+        if (last_error != NULL){
+                return -1;
+       }
+        error = (struct errno_struct*)vmalloc(sizeof(struct errno_struct));
+        if (error == NULL){
+                return -1;
+       }
+        error->buffer = vmalloc(MAX_ERROR_BUF_PATH);
+        if (error->buffer == NULL)
+        {
+                vfree(error);
+                return -1;
+        }
+        error->buffer[0] = '\0';
+        error->size = 0;
+        last_error = (struct errno_struct*) error;
+
+        return 0;
+}
+
+static unsigned int get_max_error_buffer_size(void)
+{
+       return (unsigned int)MAX_ERROR_BUF_PATH;
+}
+
+int update_errno_buffer(const char *buffer)
+{
+        unsigned int size;
+
+        if (last_error == NULL)
+        {
+                if (create_errno_buffer() != 0)
+                        return -1;
+        }
+
+        size = strlen(buffer);
+
+        if (last_error->size + size + 1 >= get_max_error_buffer_size()) {
+                return -1;
+       }
+
+        strncat((char*)(last_error->buffer), buffer, size);
+
+        last_error->size += size + 1;
+        last_error->buffer[last_error->size - 1] = ',';
+        last_error->buffer[last_error->size] = '\0';
+
+        return 0;
+}
+
+static void delete_errno_buffer(void)
+{
+        if (last_error == NULL)
+                return;
+
+        vfree((char*)last_error->buffer);
+        vfree(last_error);
+
+        last_error = NULL;
+
+        return;
+}
+
+int get_last_error(void* u_addr)
+{
+        int result;
+
+        if (last_error == NULL)
+                return -1;
+
+        result = copy_to_user ((void*)u_addr, (void*)(last_error->buffer), last_error->size + 1);
+        if (result) {
+                result = -EFAULT;
+        }
+
+        delete_errno_buffer();
+
+        return result;
+}
+
+int has_last_error()
+{
+        if(last_error == NULL)
+                return 0;
+        return -1;
+}
diff --git a/driver/error_storage.h b/driver/error_storage.h
new file mode 100644 (file)
index 0000000..d32b4f1
--- /dev/null
@@ -0,0 +1,6 @@
+#define MAX_ERROR_BUF_PATH 256
+
+// copy error buffer from kernelspace to userspace
+int get_last_error(void* u_addr);
+int has_last_error(void);
+int update_errno_buffer(const char *buffer);
index 393eb17..3542229 100644 (file)
@@ -700,6 +700,7 @@ int link_bundle(void)
                if (strcmp(us_proc_info.path, "*")) {
                        us_proc_info.m_f_dentry = dentry_by_path(us_proc_info.path);
                        if (us_proc_info.m_f_dentry == NULL) {
+                               update_errno_buffer(us_proc_info.path);
                                return -1;
                        }
                }
@@ -769,6 +770,7 @@ int link_bundle(void)
                                {
                                        if (strcmp(d_lib->path_dyn, "") == 0) {
                                                EPRINTF("Cannot find path for lib %s!", d_lib->path);
+                                               update_errno_buffer(d_lib->path);
                                                /* Just skip all the IPs and go to next lib */
                                                p += d_lib->ips_count * 3 * sizeof(u_int32_t);
                                                d_lib->ips_count = 0;
@@ -788,6 +790,7 @@ int link_bundle(void)
                        d_lib->m_f_dentry = dentry_by_path(d_lib->path);
                        if (d_lib->m_f_dentry == NULL) {
                                EPRINTF ("failed to lookup dentry for path %s!", d_lib->path);
+                               update_errno_buffer(d_lib->path);
                                /* Just skip all the IPs and go to next lib */
                                p += d_lib->ips_count * 3 * sizeof(u_int32_t);
                                d_lib->ips_count = 0;
index 4c6289f..a778091 100644 (file)
@@ -29,6 +29,9 @@
 #include "probes.h"
 #include "event_tmpl.h"
 
+extern int update_errno_buffer(const char *buffer);
+extern int get_last_error(void* u_addr);
+extern int has_last_error(void);
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 extern int EnableContinuousRetrieval(void);
@@ -64,7 +67,6 @@ extern void pack_task_event_info (struct task_struct *task, probe_id_t probe_id,
 
 /* Set most links from us_proc_info to data in the bundle */
 int link_bundle(void);
-
 /* Undo the actions of link_bundle() */
 void unlink_bundle(void);