Skip to content

Commit

Permalink
fixed memory leak bug and big refact
Browse files Browse the repository at this point in the history
  • Loading branch information
beraldoleal committed Jul 21, 2013
1 parent 0915302 commit a437f50
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 96 deletions.
83 changes: 30 additions & 53 deletions inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,14 @@ MODULE_AUTHOR("Beraldo Leal");
#define STREAM_BUF_LEN 1024

static struct packet_type netsfs_pseudo_proto;
static struct dentry *netsfs_root;
static const struct inode_operations netsfs_file_inode_operations;

struct dentry *netsfs_root;

struct dentry *get_root(void)
{
return netsfs_root;
}

/* User space ask to read the "stats" file. */
static ssize_t netsfs_read_stats(struct file *file, char __user *buf,
Expand Down Expand Up @@ -76,31 +81,28 @@ static ssize_t netsfs_read_stream(struct file *file, char __user *buf,
if (*ppos != 0)
return 0;

spin_lock(&file->f_dentry->d_parent->d_inode->i_lock);
d_private = file->f_dentry->d_parent->d_inode->i_private;
skb = cq_get(&d_private->queue_skbuff);
if (skb) {
mac_string = kmalloc(sizeof(char)*80, GFP_KERNEL);
network_string = kmalloc(sizeof(char)*80, GFP_KERNEL);

if (!mac_string) {
printk("AQUI PAU\n");
return -ENOMEM;
}

get_mac_string(mac_string, skb);
get_network_string(network_string, skb);

ret = sprintf(stream_buf, "%s\n%s\n", mac_string, network_string);

if (ret > 0)
ret = simple_read_from_buffer(buf, count, ppos, stream_buf, ret);

// mac_string = kmalloc(sizeof(char)*80, GFP_KERNEL);
// network_string = kmalloc(sizeof(char)*80, GFP_KERNEL);
//
// get_mac_string(mac_string, skb);
// get_network_string(network_string, skb);
//
// ret = sprintf(stream_buf, "%s\n%s\n", mac_string, network_string);
//
// if (ret > 0)
// ret = simple_read_from_buffer(buf, count, ppos, stream_buf, ret);
//
dev_kfree_skb(skb);
if (mac_string) kfree(mac_string);
if (network_string) kfree(network_string);
// if (mac_string) kfree(mac_string);
// if (network_string) kfree(network_string);
// kfree(dst);
// kfree(network);
}
spin_unlock(&file->f_dentry->d_parent->d_inode->i_lock);
return ret;
}

Expand All @@ -120,41 +122,9 @@ static ssize_t netsfs_file_read(struct file *file, char __user *buf,
return netsfs_read_stream(file, buf, count, ppos);
break;
default:
return 0;
break;
}


/*
skb = cq_get(&d_private->queue_skbuff);
if (skb) {
ether_type = get_ether_type(skb);
ip_protocol = get_ip_protocol(skb);
switch(iph->protocol){
case 1: ps = "ICMP"; break;
case 4: ps = "IPv4"; break;
case 6: ps = "TCP"; break;
case 17: ps = "UDP"; break;
default: sprintf(ps, "<%d>", iph->protocol); break;
}
ret = sprintf(stream_buf, "%llu %s %d Ether Type: ??, IP Protocol: ??\n",
skb->tstamp.tv64,
skb->dev->name,
skb->len);
printk("RET: %d\n", ret);
} else
return 0;
}
if (ret > 0) {
rv = copy_to_user(buf, stream_buf, ret);
(*ppos) += ret;
if (skb) kfree(skb);
}
return ret;
*/
return 0;
}

/* Comment options here to disable operations to user */
Expand Down Expand Up @@ -191,6 +161,9 @@ extern void netsfs_inc_inode_size(struct inode *inode, loff_t inc)
loff_t oldsize, newsize;
struct netsfs_dir_private *d_private;

if(inode == NULL)
inode = netsfs_root->d_inode;

//printk(KERN_INFO "%s: Updating inode %lu size to %lld\n",
// THIS_MODULE->name,
// inode->i_ino,
Expand Down Expand Up @@ -504,13 +477,17 @@ struct dentry *netsfs_mount(struct file_system_type *fs_type,
{
struct dentry *root;

// printk("%s:%s:%d - Start.\n", THIS_MODULE->name, __FUNCTION__, __LINE__);
root = mount_nodev(fs_type, flags, data, netsfs_fill_super);
if (IS_ERR(root))
goto out;

netsfs_root = root;

printk("netsfs_mount: netsfs_root=%p\n", netsfs_root);

/* Create stats and stream in root dir */
netsfs_create_files(NULL);

/* register a packet handler */
netsfs_pseudo_proto.type = htons(ETH_P_ALL);
netsfs_pseudo_proto.dev = NULL;
Expand Down
12 changes: 12 additions & 0 deletions internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ struct netsfs_dir_private {
loff_t bytes; // total bytes
};



/* fifo size in elements (struct sk_buff) */
#define FIFO_SIZE 32

Expand All @@ -59,6 +61,8 @@ extern void netsfs_create_files(struct dentry *parent);
extern void netsfs_create_dir(const char *proto_name, struct dentry *parent, struct dentry **dentry);
extern void netsfs_inc_inode_size(struct inode *inode, loff_t inc);

extern struct dentry *get_root(void);

struct netsfs_mount_opts {
umode_t mode;
};
Expand Down Expand Up @@ -96,6 +100,14 @@ static inline int cq_put(struct kfifo *kfifo, void *p)
return kfifo_in(kfifo, (void *)&p, sizeof(p));
}

static inline int cq_is_full(struct kfifo *kfifo)
{
if (cq_howmany(kfifo) == FIFO_SIZE)
return 1;
else
return 0;
}

static inline void *cq_get(struct kfifo *kfifo)
{
unsigned int sz;
Expand Down
113 changes: 70 additions & 43 deletions proto.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ int get_network_string(char *str, struct sk_buff *skb)

struct iphdr *iphdr;
char *src, *dst;

sprintf(str, "[NETWORK]");
return 0;


iphdr = ip_hdr(skb);

src = kmalloc(sizeof(char)*15, GFP_KERNEL);
Expand Down Expand Up @@ -339,57 +344,79 @@ static void netsfs_top(struct work_struct *work)
struct netsfs_skb_info *netsfsinfo;
struct dentry *network_dentry, *transport_dentry, *app_dentry;
unsigned int len;
struct sk_buff *skb, *temp_skb;
struct dentry *netsfs_root;

int ret;
struct sk_buff *buff;
struct netsfs_dir_private *d_private;
struct netsfs_dir_private *root_private;

netsfsinfo = container_of(work, struct netsfs_skb_info, my_work);
len = get_skb_len(netsfsinfo->skb);

/* Create top level files */
netsfs_create_files(NULL);

/* Create L3 dir */
netsfs_create_dir(get_ether_type(netsfsinfo->skb), NULL, &network_dentry);

if (network_dentry) {
/* Create L3 files */
netsfs_create_files(network_dentry);

netsfs_inc_inode_size(network_dentry->d_parent->d_inode, len);
netsfs_inc_inode_size(network_dentry->d_inode, len);

/* Put skbuff in kfifo */
buff = netsfsinfo->skb;
d_private = network_dentry->d_inode->i_private;

/* Free skb only when fifo is full */
ret = cq_put(&d_private->queue_skbuff, buff);

/* Create L4 dir */
netsfs_create_dir(get_ip_protocol(netsfsinfo->skb), network_dentry, &transport_dentry);
if (transport_dentry) {
/* Create L4 files */
netsfs_create_files(transport_dentry);

netsfs_inc_inode_size(transport_dentry->d_inode, len);

/* TODO: Currently, L5 only for TCP. */
if (ip_hdr(netsfsinfo->skb)->protocol == IPPROTO_TCP) {
netsfs_create_dir(get_application_protocol(netsfsinfo->skb), transport_dentry, &app_dentry);
if (app_dentry) {
netsfs_create_files(app_dentry);
netsfs_inc_inode_size(app_dentry->d_inode, len);
}
}
}


if (ret == 0)
dev_kfree_skb(netsfsinfo->skb);
/* increment netsfs root counters in stats */
len = get_skb_len(netsfsinfo->skb);
netsfs_inc_inode_size(NULL, len);
//
/* Make a skb copy to pass to kfifo */
skb = skb_copy(netsfsinfo->skb, GFP_KERNEL);
if (skb == NULL)
goto free;

netsfs_root = get_root();

spin_lock(&netsfs_root->d_inode->i_lock);
/* If kfifo is full, dequeue */
root_private = netsfs_root->d_inode->i_private;
if (cq_is_full(&root_private->queue_skbuff)) {
temp_skb = cq_get(&root_private->queue_skbuff);
kfree_skb(temp_skb);
}

/* Put skb in kfifo and only free when fifo is full */
ret = cq_put(&root_private->queue_skbuff, skb);

spin_unlock(&netsfs_root->d_inode->i_lock);
if (ret == 0)
printk("[netsfs] Probably preempted and queue is full\n");

// /* Create L3 dir */
// netsfs_create_dir(get_ether_type(skb), NULL, &network_dentry);
//
// if (network_dentry) {
// /* Create L3 files */
// netsfs_create_files(network_dentry);
//
// netsfs_inc_inode_size(network_dentry->d_parent->d_inode, len);
// netsfs_inc_inode_size(network_dentry->d_inode, len);
//
// /* Put skbuff in kfifo and only free when fifo is full */
// d_private = network_dentry->d_inode->i_private;
// ret = cq_put(&d_private->queue_skbuff, skb);
//
// /* Create L4 dir */
// netsfs_create_dir(get_ip_protocol(skb), network_dentry, &transport_dentry);
// if (transport_dentry) {
// /* Create L4 files */
// netsfs_create_files(transport_dentry);
//
// netsfs_inc_inode_size(transport_dentry->d_inode, len);
//
//
//// /* TODO: Currently, L5 only for TCP. */
//// if (ip_hdr(skb->protocol) == IPPROTO_TCP) {
//// netsfs_create_dir(get_application_protocol(skb), transport_dentry, &app_dentry);
//// if (app_dentry) {
//// netsfs_create_files(app_dentry);
//// netsfs_inc_inode_size(app_dentry->d_inode, len);
//// }
//// }
// }

// kfree_skb(skb);

free:
kfree_skb(netsfsinfo->skb);
// kfree(netsfsinfo);
kfree( (void *) work);
}

Expand Down

0 comments on commit a437f50

Please sign in to comment.