#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/highmem.h>
#include <linux/kdev_t.h>
#include<linux/sysfs.h> 
#include<linux/kobject.h>

#include "dm-verity-debug.h"

#define ALTA_BUF_SIZE    4096

static DEFINE_SPINLOCK(alta_lock);

char* alta_buf;
size_t * alta_offset,alta_size;

struct kobject *kobj_ref;


void set_print_buf(char * buf, size_t * offset, size_t size){
    alta_buf = buf;
    alta_offset = offset;
    alta_size = size;

    *alta_offset = 0;
}


void alta_print(const char *fmt, ...)
{
    size_t offset = *alta_offset;

    va_list aptr;
    va_start(aptr, fmt);
    *alta_offset += vscnprintf(alta_buf+offset,(size_t)alta_size - offset, fmt, aptr);
    va_end(aptr);
}

static void show_fc_blks_list(void){
    int i = 0;

    if(empty_b_info()){
        return;
    }

    if(get_fec_correct_blks() == 0){
        alta_print("\n");
        return;
    }

    if ((long long) MAX_FC_BLKS_LIST <= get_fec_correct_blks()){  
        alta_print(",\"fc_dev\":\"%s\"",b_info->dev_name[b_info->list_idx]);
        alta_print(",\"fc_blk\":\"%llu\"",b_info->fc_blks_list[b_info->list_idx]);
        i = (b_info->list_idx + 1) % MAX_FC_BLKS_LIST;
    }


    for( ; i != b_info->list_idx; i = (i + 1) % MAX_FC_BLKS_LIST){
        alta_print(",\"fc_dev\":\"%s\"",b_info->dev_name[i]);
        alta_print(",\"fc_blk\":\"%llu\"",b_info->fc_blks_list[i]);
    }
    alta_print("\n");
}

static void show_dmv_ctr_list(void){
    int i = 0, ctr_cnt = get_dmv_ctr_cnt();

    if(empty_b_info()){
        return;
    }

    alta_print(",\"dmv_dev_cnt\":\"%d\"",ctr_cnt);

    for( ; i < ctr_cnt; i++)
        alta_print(",\"dmv_dev\":\"%s\"",b_info->dmv_ctr_list[i]);
}

static void show_blks_cnt(void){
    int i,foc = get_fec_off_cnt();

    if(empty_b_info()){
        return;
    }
    alta_print("\"total_blks\":\"%llu\"",get_total_blks());
    alta_print(",\"skipped_blks\":\"%llu\"",get_skipped_blks());
    alta_print(",\"corrupted_blks\":\"%llu\"",get_corrupted_blks());
    alta_print(",\"fec_correct_blks\":\"%llu\"",get_fec_correct_blks());

    if(foc > 0){
        alta_print(",\"fec_off_cnt\":\"%d\"",foc);
        for(i = 0 ; i < foc; i++)
            alta_print(",\"fec_off_dev\":\"%s\"",b_info->fec_off_list[i]);
    }
}


ssize_t alta_bigdata_read(struct file *filep, char __user *buf, size_t size, loff_t *offset){
    ssize_t ret;
    size_t proc_offset = 0;
    char* proc_buf = kzalloc(ALTA_BUF_SIZE, GFP_KERNEL);

    if(!proc_buf)
        return -ENOMEM;

    spin_lock(&alta_lock);
    set_print_buf(proc_buf,&proc_offset,ALTA_BUF_SIZE);

    /* Print DMV info */
    if(empty_b_info()){
        alta_print("\"ERROR\":\"b_info_empty\"\n");
    }
    else {
        show_blks_cnt();
        show_dmv_ctr_list();
        show_fc_blks_list();
    }
    spin_unlock(&alta_lock);

    ret = simple_read_from_buffer(buf, size, offset, proc_buf, proc_offset);
    kfree(proc_buf);

    return ret; 
}

static ssize_t sysfs_show(struct kobject *kobj, 
        struct kobj_attribute *attr, char *buf)
{
    size_t sysfs_offset;
    set_print_buf(buf, &sysfs_offset, PAGE_SIZE);

    /* Print DMV info */
    if(empty_b_info()){
        alta_print("\"ERROR\":\"b_info_empty\"\n");
    }
    else {
        show_blks_cnt();
        show_dmv_ctr_list();
        show_fc_blks_list();
    }

    return sysfs_offset;
}


static const struct file_operations alta_proc_fops = {
    .owner          = THIS_MODULE,
    .read           = alta_bigdata_read,
};

struct kobj_attribute alta_attr = __ATTR(dmv_info, 0444, sysfs_show, NULL);

static int __init alta_bigdata_init(void){
    if(proc_create("alta_bigdata",0444,NULL,&alta_proc_fops) == NULL){
        printk(KERN_ERR "alta_bigdata: Error creating proc entry");
        goto bad_proc;
    }

    /*Creating a directory in /sys/kernel/ */
    kobj_ref = kobject_create_and_add("alta_bigdata",kernel_kobj);

    /*Creating sysfs file for dmv_info*/
    if(sysfs_create_file(kobj_ref,&alta_attr.attr)){
        printk(KERN_INFO"alta_bigdata: Cannot create sysfs file......\n");
        goto bad_sysfs;
    }

    pr_info("alta_bigdata : create /proc/alta_bigdata");
    return 0;

bad_sysfs:
    kobject_put(kobj_ref); 
    sysfs_remove_file(kernel_kobj, &alta_attr.attr);

bad_proc:
    free_b_info();
    remove_proc_entry("alta_bigdata", NULL);

    return -1;
}

static void __exit alta_bigdata_exit(void){
    kobject_put(kobj_ref); 
    sysfs_remove_file(kernel_kobj, &alta_attr.attr);

    free_b_info();
    remove_proc_entry("alta_bigdata", NULL);
}
module_init(alta_bigdata_init);
module_exit(alta_bigdata_exit);
