[Feature][T108][bug-view-1989] add ext4 file write async for ota files P2
Change-Id: Ifde9601d9963aba991475e2c27f3ee1902ac8a25
diff --git a/config/defconfig_asr1806p301 b/config/defconfig_asr1806p301
index 1b33184..46b16b6 100755
--- a/config/defconfig_asr1806p301
+++ b/config/defconfig_asr1806p301
@@ -3783,6 +3783,7 @@
# CONFIG_PACKAGE_kmod-tpm-i2c-atmel is not set
# CONFIG_PACKAGE_kmod-tpm-i2c-infineon is not set
CONFIG_PACKAGE_kmod-zram=y
+CONFIG_PACKAGE_kmod-opt-cmd-36=y
# end of Other modules
#
diff --git a/package/kernel/opt-cmd-36/Makefile b/package/kernel/opt-cmd-36/Makefile
new file mode 100755
index 0000000..71b3101
--- /dev/null
+++ b/package/kernel/opt-cmd-36/Makefile
@@ -0,0 +1,68 @@
+#
+# Copyright (C) 2007 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=opt-cmd-36
+PKG_VERSION:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+PREBUILT_DIR:=$(CURDIR)/files
+
+PKG_MAINTAINER:=<you.chen@mobiletek.cn>
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/opt-cmd-36
+ TITLE:=Mbtk Optimize command 36
+ DEPENDS:=@TARGET_mmp
+ FILES:=$(PKG_BUILD_DIR)/opt_cmd_36.ko
+ VERSION:=$(LINUX_VERSION)+$(PKG_NAME)-$(PKG_VERSION)
+endef
+
+define KernelPackage/opt_cmd_36/description
+ Kernel support for Optimize command 36
+endef
+
+EXTRA_CFLAGS:= \
+
+
+MAKE_CMD:=$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \
+ ARCH="$(LINUX_KARCH)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ M="$(PKG_BUILD_DIR)" \
+ cmd_ar='rm -f $$$$@; $(TARGET_CROSS)ar cDrs $$$$@ $$$$(real-prereqs)' \
+ EXTRA_CFLAGS="$(EXTRA_CFLAGS)"
+
+
+CLEAN_CMD:=rm -rf $(PKG_BUILD_DIR)/{*.o,*.mod.*,modules.order,Module.symvers,ipkg-*,*.ko,*.a,ipkg-*} \
+ rm -rf $(MRVLDIR)/fastpath/{*.o,*.mod.*,modules.order,Module.symvers,ipkg-*,*.ko,*.a,ipkg-*}
+
+define Build/Prepare/Prebuilt
+ @rm -rf $(PKG_BUILD_DIR)
+endef
+
+$(STAMP_PREPARED): FORCE
+
+define Build/Prepare
+ @mkdir -p $(PKG_BUILD_DIR)
+ @cp -rf $(PREBUILT_DIR)/* $(PKG_BUILD_DIR)
+endef
+
+define Build/Compile
+ $(MAKE_CMD) modules
+ mkdir -p $(BIN_DIR)/symbol/modules
+ cp -rf $(PKG_BUILD_DIR)/opt_cmd_36.o $(BIN_DIR)/symbol/modules/
+endef
+
+define Build/Clean
+ $(if $(wildcard $(USE_SOURCE_DIR)), $(CLEAN_CMD),)
+endef
+
+$(eval $(call KernelPackage,opt-cmd-36))
diff --git a/package/kernel/opt-cmd-36/files/Kconfig b/package/kernel/opt-cmd-36/files/Kconfig
new file mode 100755
index 0000000..4ea775f
--- /dev/null
+++ b/package/kernel/opt-cmd-36/files/Kconfig
@@ -0,0 +1,20 @@
+
+config MRVL_FASTPATH
+ tristate "Marvell Fastpath"
+ default m
+ depends on NF_CT_NETLINK && NF_CONNTRACK_FASTPATH
+ select NETIF_RX_FASTPATH_HOOK
+ help
+ Enable marvell fastpath in the application processor
+
+if !NF_CT_NETLINK || !NF_CONNTRACK_FASTPATH
+
+comment "Fastpath support disabled"
+
+comment "NF_CT_NETLINK disabled"
+ depends on !NF_CT_NETLINK
+
+comment "NF_CONNTRACK_FASTPATH disabled"
+ depends on !NF_CONNTRACK_FASTPATH
+
+endif
diff --git a/package/kernel/opt-cmd-36/files/Makefile b/package/kernel/opt-cmd-36/files/Makefile
new file mode 100755
index 0000000..64de5a5
--- /dev/null
+++ b/package/kernel/opt-cmd-36/files/Makefile
@@ -0,0 +1,20 @@
+ifneq ($(KERNELRELEASE),)
+
+obj-m := opt_cmd_36.o
+
+opt_cmd_36-y := hook_ext4.o
+
+else
+
+all:
+ @echo
+ @echo "usage:"
+ @echo " make -C <kernel_build_dir> M=\`pwd\` ARCH=arm CROSS_COMPILE=<...> modules"
+ @echo
+ $(error)
+clean:
+ rm -f *.o .*.cmd modules.order Module.symvers mfp.ko mfp.mod.c
+ rm -rf .tmp_versions
+
+endif
+
diff --git a/package/kernel/opt-cmd-36/files/hook_ext4.c b/package/kernel/opt-cmd-36/files/hook_ext4.c
new file mode 100755
index 0000000..f71adc1
--- /dev/null
+++ b/package/kernel/opt-cmd-36/files/hook_ext4.c
@@ -0,0 +1,680 @@
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/namei.h>
+#include <linux/uio.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/debugfs.h>
+#include <linux/interrupt.h>
+
+extern char *d_path(const struct path *, char *, int);
+static struct file_operations org_operations;
+static struct file_operations hooked_operations;
+static struct inode_operations org_inode_operations;
+static struct file_operations *p_curr_file_operations;
+
+static char opt_file_name[256] = {0};
+static char * hooked_files[32] = {
+ "/media/download/mdm.download",
+ "/media/download/sbl.download",
+ "/media/download/mcu_a.download",
+ "/media/download/mcu_b.download",
+ "/media/download/ble.download",
+ "/media/download/file.download",
+ "/media/download/runtime_file",
+ "/media/download/swk1",
+ "/media/download/swk2",
+ 0,
+};
+static int g_hooked_file_cnt = 0;
+static spinlock_t my_lock;
+static struct work_struct my_work;
+static struct work_struct rename_file_work;
+static loff_t g_next_pos;
+static loff_t g_ki_pos;
+static bool g_scheduled = false;
+static struct file * g_hooked_file_filp;
+static const char * g_hooked_file_name;
+static char g_hooked_tmp_file[256];
+static bool g_hooked_tmp_file_writen;
+static char * g_last_hook_file = NULL;
+
+struct cached_items_type
+{
+ struct file * filp;
+ void * cached_buffer;
+ int cached_buffer_len;
+ loff_t curr_offset;
+ void * allocate_ptr;
+};
+
+struct cached_buffer_type
+{
+ void * cached_buffer;
+ void * ptr;
+};
+
+#define BUF_CNT_MASK 0xff
+#define ITEM_CNT_MASK 0xfff
+static struct cached_items_type cached_items[ITEM_CNT_MASK + 1] = {0};
+static struct cached_buffer_type g_buffers[BUF_CNT_MASK+1] = {0};
+static int head_pos = 0;
+static int tail_pos = 0;
+static int max_cnt = 0;
+
+static int buffer_head_pos = 0;
+static int buffer_tail_pos = BUF_CNT_MASK;
+
+static size_t init_and_push_item(struct file *filp, struct kiocb *iocb, struct iov_iter *from)
+{
+ unsigned long flags;
+ int index = (tail_pos) & ITEM_CNT_MASK;
+ int ret, buffer_index;
+ loff_t local_pos = 0;
+ size_t cnt = 0;
+ //if (iocb != NULL)
+ if (g_next_pos != -1)
+ {
+ if (g_next_pos != g_ki_pos)
+ printk("cy: next pos %ld current :%ld\n", g_next_pos);
+ local_pos = g_next_pos;
+ g_next_pos = -1;
+ // if (local_pos != 0 && g_ki_pos != local_pos) {
+ // printk("cy: got pos %ld, curr %ld\n", local_pos, g_ki_pos);
+ // }
+ }
+ else
+ {
+ local_pos = g_ki_pos;
+ }
+
+ cnt = iov_iter_count(from);
+ if (buffer_head_pos >= buffer_tail_pos || cnt > 16*PAGE_SIZE)
+ {
+ cached_items[index].allocate_ptr = kmalloc((cnt/PAGE_SIZE + 2)*PAGE_SIZE, GFP_KERNEL);
+ if (cached_items[index].allocate_ptr == NULL)
+ return 0;
+ cached_items[index].cached_buffer = (char*)((((long long)cached_items[index].allocate_ptr)/PAGE_SIZE + 1)*PAGE_SIZE);
+ }
+ else
+ {
+ buffer_index = (buffer_head_pos++ & BUF_CNT_MASK);
+ cached_items[index].allocate_ptr = NULL;
+ cached_items[index].cached_buffer = g_buffers[buffer_index].cached_buffer;
+ }
+
+ cached_items[index].filp = filp;
+ ret = copy_from_iter(cached_items[index].cached_buffer, cnt, from);
+ cached_items[index].cached_buffer_len = cnt;
+ cached_items[index].curr_offset = local_pos;
+ g_ki_pos = local_pos + cnt;
+
+ tail_pos++;
+ if (!g_scheduled)
+ {
+ g_scheduled = true;
+ schedule_work(&my_work);
+ }
+ return cnt;
+}
+
+struct cached_items_type * get_head_item(void)
+{
+ if (head_pos >= tail_pos)
+ return NULL;
+ return &cached_items[head_pos++ & ITEM_CNT_MASK];
+}
+
+static int my_ext4_file_open(struct inode * inode, struct file * filp)
+{
+ int i, j, ret, found;
+ unsigned long flags;
+ struct file * local_file;
+ char buff[256];
+ ret = org_operations.open(inode, filp);
+ //ret = 0;
+ if (ret == 0)
+ {
+ found = 0;
+ for(i=0; i<32 && found < g_hooked_file_cnt; i++) {
+ if (hooked_files[i] != NULL && strcmp(hooked_files[i], file_path(filp, buff, 256)) == 0)
+ {
+ printk("found hooked file11, %s write ptr %p private_data %p\n", hooked_files[i], filp->f_op->write, filp->private_data);
+
+ for(j=0;j<5;j++) {
+ if (g_hooked_file_filp != NULL)
+ usleep_range(2000,2100);
+ else
+ break;
+ }
+ if (g_hooked_file_filp != NULL)
+ {
+ if (g_last_hook_file == NULL || strcmp(hooked_files[i], g_last_hook_file) != 0)
+ break;
+
+ for(j=0;j<100;j++) {
+ if (g_hooked_file_filp != NULL)
+ usleep_range(20000,21000);
+ else
+ break;
+ }
+ }
+
+ spin_lock_irqsave(&my_lock, flags);
+ head_pos = 0;
+ tail_pos = 0;
+ max_cnt = 0;
+ g_ki_pos = 0;
+ buffer_head_pos = 0;
+ buffer_tail_pos = BUF_CNT_MASK;
+ g_last_hook_file = hooked_files[i];
+ p_curr_file_operations->open = org_operations.open;
+ spin_unlock_irqrestore(&my_lock, flags);
+
+ g_hooked_tmp_file_writen = false;
+ g_hooked_file_name = hooked_files[i];
+ sprintf(g_hooked_tmp_file, "%s.dl", hooked_files[i]);
+ printk("cy: after name is %s\n", g_hooked_tmp_file);
+ local_file = filp_open(g_hooked_tmp_file, O_RDWR | O_CREAT | O_TRUNC, 0644);
+
+ spin_lock_irqsave(&my_lock, flags);
+ if (!IS_ERR(local_file))
+ {
+ g_hooked_file_filp = local_file;
+ filp->private_data = local_file;
+ filp->f_op = &hooked_operations;
+ }
+ else
+ {
+ g_hooked_file_filp = NULL;
+ }
+ p_curr_file_operations->open = my_ext4_file_open;
+ spin_unlock_irqrestore(&my_lock, flags);
+ break;
+ }
+ else if (hooked_files[i] != NULL) {
+ found++;
+ }
+ }
+ //dump_stack();
+ }
+ return ret;
+}
+
+static loff_t my_ext4_llseek(struct file *file, loff_t offset, int whence)
+{
+ //printk("cy: %s, %ld, %d\n", __func__, offset, whence);
+ if (whence == SEEK_SET) {
+ g_next_pos = offset;
+ if (g_hooked_tmp_file_writen)
+ return offset;
+ else
+ return org_operations.llseek(file, offset, whence);
+ }
+ else
+ {
+ printk("unhandle %d\n", whence);
+ return org_operations.llseek(file, offset, whence);
+ }
+}
+
+static ssize_t my_ext4_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+{
+ printk("cy: %s\n", __func__);
+ return org_operations.read_iter(iocb, to);
+}
+
+static ssize_t my_ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
+{
+
+ int i, ret;
+ int left_cnt, waited = 0;
+ loff_t write_cnt=0;
+ for (i=0; i<40;i++)
+ {
+ left_cnt = tail_pos - head_pos;
+ if ( left_cnt> max_cnt){
+ max_cnt = left_cnt;
+ if ((max_cnt & 0x1f) == 0)
+ printk("cy: got max %d", max_cnt);
+ }
+ if (left_cnt < ITEM_CNT_MASK)
+ {
+ break;
+ }
+ if (!g_scheduled)
+ {
+ g_scheduled = true;
+ schedule_work(&my_work);
+ }
+ waited = 1;
+ usleep_range(1000,1100);
+ }
+
+ if (i >= 40) {
+ printk("cy: write fail\n");
+ return -1;
+ }
+ else if (i > 1){
+ printk("cy: got full\n");
+ }
+
+ //printk("cy: my_ext4_file_write_iter %p\n", iocb->ki_filp->private_data);
+ if (iocb->ki_filp->private_data != NULL)
+ {
+ write_cnt = init_and_push_item(iocb->ki_filp->private_data, iocb, from);
+ g_hooked_tmp_file_writen = true;
+ }
+
+ // if (left_cnt > 64)
+ // usleep_range(7000,7100);
+ // else if (left_cnt > 32)
+ // usleep_range(5000,5100);
+ // else if (left_cnt > 8)
+ // usleep_range(3000,3100);
+ // else if (left_cnt > 1 && !waited)
+ // usleep_range(500,600);
+ return write_cnt;
+}
+
+static int my_ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
+{
+ printk("cy: %s\n", __func__);
+ return org_operations.fsync(file, start, end, datasync);
+}
+
+static int my_ext4_release_file(struct inode *inode, struct file *filp)
+{
+ int i, ret;
+ // struct file *local_filp=NULL;
+ char buff[256];
+ char buff2[256];
+ char * file_name;
+ //printk("cy: %s\n", __func__);
+ if (filp == NULL)
+ return -1;
+ // dump_stack();
+ for (i=0; i<40;i++)
+ {
+ if (tail_pos == head_pos)
+ break;
+ usleep_range(300,350);
+ }
+
+ //printk("cy: close file wait count %d\n", i);
+ if (filp->private_data != NULL)
+ {
+ filp->private_data = 0;
+ }
+ ret = org_operations.release(inode, filp);
+ if (g_hooked_file_filp != NULL)
+ {
+ schedule_work(&rename_file_work);
+ }
+ return ret;
+}
+
+static void my_callback(struct work_struct *work)
+{
+ ssize_t ret;
+ loff_t local_pos = 0;
+ struct cached_items_type * p;
+ p = get_head_item();
+ // if (p != NULL)
+ // usleep_range(200,250);
+
+ while(p != NULL) {
+ local_pos = p->curr_offset;
+ ret = __kernel_write(p->filp, p->cached_buffer, p->cached_buffer_len, &local_pos);
+ //g_ki_pos = p->curr_offset + p->cached_buffer_len;
+ if (p->allocate_ptr)
+ {
+ kfree(p->allocate_ptr);
+ p->allocate_ptr = NULL;
+ p->cached_buffer = NULL;
+ }
+ else
+ {
+ buffer_tail_pos++;
+ p->cached_buffer = NULL;
+ }
+ p = get_head_item();
+ }
+ g_scheduled = false;
+}
+
+static void rename_file_callback(struct work_struct *work)
+{
+ int ret, i;
+ struct path old_path, new_path;
+ struct dentry *old_dentry, *new_dentry;
+ if (g_hooked_file_filp == NULL)
+ return;
+ printk("cy4: close ld file finish\n");
+ if (!g_hooked_tmp_file_writen)
+ {
+ ret = filp_close(g_hooked_file_filp, 0);
+ g_hooked_file_filp = NULL;
+ return;
+ }
+ printk("cy: head pos %d, tail pos %d\n", head_pos, tail_pos);
+ if (!g_scheduled) // write thread not running, check again
+ {
+ printk("cy: not g_scheduled\n");
+ my_callback(&my_work);
+ }
+ for (i=0; i<5000;i++)
+ {
+ if (head_pos == tail_pos)
+ {
+ break;
+ }
+ if (!g_scheduled)
+ {
+ printk("cy: not g_scheduled 2\n");
+ my_callback(&my_work);
+ break;
+ }
+ usleep_range(1000,1100);
+ if ((i & 0x3ff) == 0 )
+ printk("cy: wait file write done, sleep again\n");
+ }
+ printk("cy: wait times %d\n", i);
+ ret = filp_close(g_hooked_file_filp, 0);
+ g_hooked_file_filp = NULL;
+ ret = kern_path(g_hooked_tmp_file, LOOKUP_PARENT, &old_path);
+ if (ret != 0)
+ goto out2;
+ ret = kern_path(g_hooked_file_name, LOOKUP_PARENT, &new_path);
+ if (ret != 0)
+ goto out1;
+
+ old_dentry = old_path.dentry;
+ new_dentry = new_path.dentry;
+ if (old_dentry != NULL && new_dentry != NULL && old_path.dentry->d_parent != NULL && new_path.dentry->d_parent != NULL)
+ {
+ ret = vfs_rename(old_path.dentry->d_parent->d_inode, old_dentry, new_path.dentry->d_parent->d_inode, new_dentry, NULL, RENAME_EXCHANGE);
+ }
+ else
+ {
+ printk("cy: got null ptr\n");
+ }
+ path_put(&new_path);
+out1:
+ path_put(&old_path);
+out2:
+ g_hooked_tmp_file_writen = false;
+ printk("cy:rename file finish\n");
+}
+
+#define DEBUGFS_READ_FUNC(name) \
+ static ssize_t asr_dbgfs_##name##_read(struct file *file, \
+ char __user *user_buf, \
+ size_t count, loff_t *ppos);
+
+#define DEBUGFS_WRITE_FUNC(name) \
+ static ssize_t asr_dbgfs_##name##_write(struct file *file, \
+ const char __user *user_buf,\
+ size_t count, loff_t *ppos);
+
+
+#define DEBUGFS_ADD_FILE(name, parent, mode) do { \
+ if (!debugfs_create_file(#name, mode, parent, NULL, \
+ &asr_dbgfs_##name##_ops)) \
+ goto err; \
+} while (0)
+
+#define DEBUGFS_WRITE_FILE_OPS(name) \
+ DEBUGFS_WRITE_FUNC(name); \
+static const struct file_operations asr_dbgfs_##name##_ops = { \
+ .write = asr_dbgfs_##name##_write, \
+ .open = simple_open, \
+ .llseek = generic_file_llseek, \
+};
+
+#define DEBUGFS_READ_FILE_OPS(name) \
+ DEBUGFS_READ_FUNC(name); \
+static const struct file_operations asr_dbgfs_##name##_ops = { \
+ .read = asr_dbgfs_##name##_read, \
+ .open = simple_open, \
+ .llseek = generic_file_llseek, \
+};
+
+static void strip_enter(char * buf, int len){
+ int i;
+ for(i=0;i<len;i++) {
+ if (buf[i] == '\r' || buf[i] == '\n' || buf[i]=='\0') {
+ buf[i] = '\0';
+ return;
+ }
+ }
+}
+
+static ssize_t asr_dbgfs_add_hook_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ int i;
+ char buf[256]={0};
+ size_t len = min_t(size_t, sizeof(buf) - 1, count);
+ printk("cy: add hook count %d\n", count);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+ strip_enter(buf, 256);
+ printk("cy: add hook buf %s\n", buf);
+ for(i=0;i<32;i++) {
+ if (hooked_files[i] == NULL) {
+ hooked_files[i] = kmalloc(count+1, GFP_KERNEL);
+ strcpy(hooked_files[i], buf);
+ g_hooked_file_cnt++;
+ break;
+ }
+ }
+ if (i >= 32)
+ return -EFAULT;
+ return count;
+}
+DEBUGFS_WRITE_FILE_OPS(add_hook);
+
+static ssize_t asr_dbgfs_del_hook_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ int i;
+ char buf[256]={0};
+ size_t len = min_t(size_t, sizeof(buf) - 1, count);
+ printk("cy: del hook count %d\n", count);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+
+ strip_enter(buf, 256);
+ printk("cy: del hook buf %s\n", buf);
+ for(i=0;i<32;i++) {
+ if (hooked_files[i] != NULL && strcmp(hooked_files[i], buf) == 0) {
+ hooked_files[i] = NULL;
+ g_hooked_file_cnt--;
+ break;
+ }
+ }
+ if (i >= 32)
+ return -EFAULT;
+ return count;
+}
+DEBUGFS_WRITE_FILE_OPS(del_hook);
+
+static ssize_t asr_dbgfs_show_all_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ int i, found, ret, read;
+ char *buf;
+ int bufsz = 256 * g_hooked_file_cnt;
+ buf = kmalloc(bufsz, GFP_ATOMIC);
+ if (buf == NULL)
+ return 0;
+ found = 0;
+ ret = 0;
+ for(i=0;i<32 && found < g_hooked_file_cnt;i++) {
+ if (hooked_files[i] != NULL) {
+ found++;
+ ret += scnprintf(&buf[ret], 258, "%s\n", hooked_files[i]);
+ }
+ }
+ read = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
+
+ kfree(buf);
+
+ return read;
+}
+DEBUGFS_READ_FILE_OPS(show_all);
+
+static struct dentry * hook_root=NULL;
+
+static int asr_dbgfs_register(void)
+{
+ if (!(hook_root = debugfs_create_dir("opt_cmd_36",NULL)))
+ return -1;
+ DEBUGFS_ADD_FILE(add_hook, hook_root, S_IWUSR | S_IRUSR);
+ DEBUGFS_ADD_FILE(del_hook, hook_root, S_IWUSR | S_IRUSR);
+ DEBUGFS_ADD_FILE(show_all, hook_root, S_IRUSR);
+ return 0;
+err:
+ debugfs_remove_recursive(hook_root);
+ return -1;
+}
+
+static void asr_dbgfs_unregister(void)
+{
+ if (hook_root != NULL)
+ {
+ debugfs_remove_recursive(hook_root);
+ hook_root = NULL;
+ }
+}
+
+static int __init opt_cmd_36_init(void)
+{
+ int ret, i;
+ unsigned long flags;
+ struct file *filp;
+ char * ptr;
+ char *filename = "/media/.test_create";
+ g_hooked_file_filp = NULL;
+ g_hooked_tmp_file_writen = false;
+
+ for(i=0; i<32;i++) {
+ if (hooked_files[i] != NULL) {
+ printk("cy: got %s\n", hooked_files[i]);
+ g_hooked_file_cnt++;
+ }
+ else if (strlen(opt_file_name) > 0)
+ {
+ hooked_files[i] = opt_file_name;
+ g_hooked_file_cnt++;
+ break;
+ }
+ }
+ filp = filp_open(filename, O_RDONLY | O_CREAT, 0644);
+ if (IS_ERR(filp) || filp->f_op == NULL) {
+ printk(KERN_ERR "Failed to open file: %ld\n", PTR_ERR(filp));
+ return -1;
+ }
+
+ printk("cy11: opt_cmd_36_init param [%s]\n", opt_file_name);
+ INIT_WORK(&my_work, my_callback);
+ INIT_WORK(&rename_file_work, rename_file_callback);
+
+ for(i=0;i<=BUF_CNT_MASK;i++)
+ {
+ g_buffers[i].ptr = kmalloc(32*PAGE_SIZE, GFP_KERNEL);
+ ptr = (char*)((((long long)g_buffers[i].ptr)/PAGE_SIZE + 1)*PAGE_SIZE);
+ g_buffers[i].cached_buffer = ptr;
+ //cached_items[i].org_ptr = kmalloc(32*PAGE_SIZE, GFP_KERNEL);
+ //ptr = (char*)((((long long)cached_items[i].org_ptr)/PAGE_SIZE + 1)*PAGE_SIZE);
+ //cached_items[i].cached_buffer = ptr;
+ }
+
+ spin_lock_irqsave(&my_lock, flags);
+ p_curr_file_operations = filp->f_op;
+
+ org_operations.llseek = p_curr_file_operations->llseek;
+ org_operations.read_iter = p_curr_file_operations->read_iter;
+ org_operations.write_iter = p_curr_file_operations->write_iter;
+ org_operations.unlocked_ioctl = p_curr_file_operations->unlocked_ioctl;
+#ifdef CONFIG_COMPAT
+ org_operations.compat_ioctl = p_curr_file_operations->compat_ioctl;
+#endif
+ org_operations.mmap = p_curr_file_operations->mmap;
+ org_operations.mmap_supported_flags = p_curr_file_operations->mmap_supported_flags;
+ org_operations.open = p_curr_file_operations->open;
+ org_operations.release = p_curr_file_operations->release;
+ org_operations.fsync = p_curr_file_operations->fsync;
+ org_operations.get_unmapped_area = p_curr_file_operations->get_unmapped_area;
+ org_operations.splice_read = p_curr_file_operations->splice_read;
+ org_operations.splice_write = p_curr_file_operations->splice_write;
+ org_operations.fallocate = p_curr_file_operations->fallocate;
+
+ hooked_operations.llseek = my_ext4_llseek;
+ //hooked_operations.write = hooked_write;
+ //hooked_operations.read_iter = my_ext4_file_read_iter;
+ hooked_operations.read_iter = p_curr_file_operations->read_iter;
+ hooked_operations.write_iter = my_ext4_file_write_iter;
+ //hooked_operations.write_iter = p_curr_file_operations->write_iter;
+ hooked_operations.unlocked_ioctl = p_curr_file_operations->unlocked_ioctl;
+#ifdef CONFIG_COMPAT
+ hooked_operations.compat_ioctl = p_curr_file_operations->compat_ioctl;
+#endif
+ hooked_operations.mmap = p_curr_file_operations->mmap;
+ hooked_operations.mmap_supported_flags = p_curr_file_operations->mmap_supported_flags;
+ hooked_operations.open = p_curr_file_operations->open;
+ //hooked_operations.release = p_curr_file_operations->release;
+ hooked_operations.release = my_ext4_release_file;
+ //hooked_operations.fsync = p_curr_file_operations->fsync;
+ hooked_operations.fsync = my_ext4_sync_file;
+ hooked_operations.get_unmapped_area = p_curr_file_operations->get_unmapped_area;
+ hooked_operations.splice_read = p_curr_file_operations->splice_read;
+ hooked_operations.splice_write = p_curr_file_operations->splice_write;
+ hooked_operations.fallocate = p_curr_file_operations->fallocate;
+
+ p_curr_file_operations->open = my_ext4_file_open;
+ spin_unlock_irqrestore(&my_lock, flags);
+
+ ret = filp_close(filp, 0);
+
+ asr_dbgfs_register();
+
+ pr_debug("init done\n");
+ return 0;
+
+}
+
+
+static void __exit opt_cmd_36_exit(void)
+{
+ int i;
+ unsigned long flags;
+ spin_lock_irqsave(&my_lock, flags);
+ p_curr_file_operations->open = org_operations.open;
+ spin_unlock_irqrestore(&my_lock, flags);
+
+ for(i=0;i<=BUF_CNT_MASK;i++)
+ {
+ // if (cached_items[i].org_ptr != NULL)
+ // kfree(cached_items[i].org_ptr);
+ if (g_buffers[i].ptr != NULL)
+ kfree(g_buffers[i].ptr);
+ }
+
+ asr_dbgfs_unregister();
+
+ pr_debug("exit done\n");
+}
+
+module_param_string(opt_file_name, opt_file_name, 256, 0);
+
+module_init(opt_cmd_36_init)
+module_exit(opt_cmd_36_exit)
+
+MODULE_LICENSE("GPL");