Browse Source

Add preliminary support for more recent kernel (~4.15)

It is currently building with a Debian 4.15.11-1, but hasn't been tested
and is expecting to crash really hard. Do no try unless you are ready to
hard crash your system. It should support most version between the
~2.6.32 and this 4.15.11.
Godzil 6 years ago
parent
commit
48264ec40a
2 changed files with 92 additions and 15 deletions
  1. 9 5
      README.markdown
  2. 83 10
      kfusd/kfusd.c

+ 9 - 5
README.markdown

@@ -6,12 +6,16 @@ FUSD: A Linux Framework for User-Space Devices
 
 
 This is FUSD snapshot 20110401, released 18 January 2012. This fork is based
 This is FUSD snapshot 20110401, released 18 January 2012. This fork is based
 on the found on the xiph.org SVN tracker. ( http://svn.xiph.org/trunk/fusd ) 
 on the found on the xiph.org SVN tracker. ( http://svn.xiph.org/trunk/fusd ) 
-They seems to no longuer update this tool (since 11 January 2007) and since it
-longuer compile with recent Linux kernel (at around 2.6.21) and since I need
-it in personal project, I ported it to newer version (current version is 2.6.32)
+They seems to no longer update this tool (since 11 January 2007) and since it
+longer compile with recent Linux kernel (at around 2.6.21) and since I need
+it in personal project, I ported it to newer version (current version is 2.6.32).
+It is currently no officialy supporting newer kernel, but changes are currently 
+going on to support newer kernel up to 4.15. It is currently building under this
+line, but don't expect it to work.
+ 
 
 
 Some feature are still missing missing or buggy form the Xiph version (due to
 Some feature are still missing missing or buggy form the Xiph version (due to
-changes on the kernel source tree), but it's completly useable.
+changes on the kernel source tree), but it is still usable.
 
 
 The official URL for this fork is:
 The official URL for this fork is:
 
 
@@ -53,7 +57,7 @@ include the following rule:
 
 
 5. Verify the fusd devices /dev/fusd/status and /dev/fusd/control
 5. Verify the fusd devices /dev/fusd/status and /dev/fusd/control
 exist. If the modprobe succeeds but no fusd devices appear,
 exist. If the modprobe succeeds but no fusd devices appear,
-doublecheck the udev rule config change and make sure udevd restarted
+double-check the udev rule config change and make sure udevd restarted
 successfully. The kfusd kernel module must be inserted after udev has
 successfully. The kfusd kernel module must be inserted after udev has
 been correctly configured and restarted.
 been correctly configured and restarted.
 
 

+ 83 - 10
kfusd/kfusd.c

@@ -78,6 +78,10 @@
 #include <linux/device.h>
 #include <linux/device.h>
 #include <linux/highmem.h>
 #include <linux/highmem.h>
 
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+#include <linux/sched/signal.h>
+#endif
+
 #include <asm/atomic.h>
 #include <asm/atomic.h>
 #include <asm/uaccess.h>
 #include <asm/uaccess.h>
 #include <asm/ioctl.h>
 #include <asm/ioctl.h>
@@ -132,6 +136,23 @@
 #   define CLASS_DEVICE_DESTROY(a, b) device_destroy(a, b)
 #   define CLASS_DEVICE_DESTROY(a, b) device_destroy(a, b)
 #endif
 #endif
 
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
+//result = GET_USER_PAGES(mmap_instance->fusd_dev->task, mmap_instance->fusd_dev->task->mm,
+//                           mmap_instance->addr + offset, 1, 1, 0, &page, NULL);
+#define GET_USER_PAGES(t,m,s,n,w,f,p,v) get_user_pages_remote(t,m,s,n,(w?FOLL_WRITE:0)|(f?FOLL_FORCE:0),p,v, NULL)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
+
+#define GET_USER_PAGES(t,m,s,n,w,f,p,v) get_user_pages_remote(t,m,s,n,w,f,p,v)
+#else
+#define GET_USER_PAGES(t,m,s,n,w,f,p,v) get_user_pages(t,m,s,n,w,f,p,v)
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
+#define FULL_NAME_HASH(a, b) full_name_hash(0, a, b)
+#else
+#define FULL_NAME_HASH(a, b) full_name_hash(a, b)
+#endif
+
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
 
 
 struct sysfs_elem_dir
 struct sysfs_elem_dir
@@ -847,7 +868,7 @@ STATIC int fusd_fops_call_send (fusd_file_t *fusd_file_arg,
 
 
    /* fill the rest of the structure */
    /* fill the rest of the structure */
    fusd_msg->parm.fops_msg.pid = current->pid;
    fusd_msg->parm.fops_msg.pid = current->pid;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
    fusd_msg->parm.fops_msg.uid = current_uid();
    fusd_msg->parm.fops_msg.uid = current_uid();
    fusd_msg->parm.fops_msg.gid = current_gid();
    fusd_msg->parm.fops_msg.gid = current_gid();
 #endif
 #endif
@@ -1149,7 +1170,7 @@ int fusd_dev_add_file (struct file *file, fusd_dev_t *fusd_dev, fusd_file_t **fu
    init_waitqueue_head(&fusd_file->file_wait);
    init_waitqueue_head(&fusd_file->file_wait);
    init_waitqueue_head(&fusd_file->poll_wait);
    init_waitqueue_head(&fusd_file->poll_wait);
    INIT_LIST_HEAD(&fusd_file->transactions);
    INIT_LIST_HEAD(&fusd_file->transactions);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)   
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
    init_MUTEX(&fusd_file->file_sem);
    init_MUTEX(&fusd_file->file_sem);
    init_MUTEX(&fusd_file->transactions_sem);
    init_MUTEX(&fusd_file->transactions_sem);
 #else
 #else
@@ -1711,11 +1732,14 @@ static void fusd_client_mm_open (struct vm_area_struct * vma);
 static void fusd_client_mm_close (struct vm_area_struct * vma);
 static void fusd_client_mm_close (struct vm_area_struct * vma);
 
 
 /* int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf); */
 /* int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf); */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,11,0)
+static int fusd_client_fault (struct vm_fault *vmf);
+#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)
 static int fusd_client_fault (struct vm_area_struct *vma, struct vm_fault *vmf);
 static int fusd_client_fault (struct vm_area_struct *vma, struct vm_fault *vmf);
 #else
 #else
 static int fusd_client_fault (struct vm_area_struct *vma, struct vm_fault *vmf, int *type);
 static int fusd_client_fault (struct vm_area_struct *vma, struct vm_fault *vmf, int *type);
 #endif
 #endif
+
 static struct vm_operations_struct fusd_remap_vm_ops ={
 static struct vm_operations_struct fusd_remap_vm_ops ={
                                                        .open = fusd_client_mm_open,
                                                        .open = fusd_client_mm_open,
                                                        .close = fusd_client_mm_close,
                                                        .close = fusd_client_mm_close,
@@ -1783,7 +1807,7 @@ static int fusd_client_mmap (struct file *file, struct vm_area_struct * vma)
    }
    }
 
 
    /* and wait for the reply */
    /* and wait for the reply */
-   /* todo: store and retrieve the transid from the interrupted messsage */
+   /* todo: store and retrieve the transid from the interrupted message */
    retval = fusd_fops_call_wait(fusd_file, &reply, transaction);
    retval = fusd_fops_call_wait(fusd_file, &reply, transaction);
 
 
    mmap_instance =
    mmap_instance =
@@ -1800,7 +1824,11 @@ static int fusd_client_mmap (struct file *file, struct vm_area_struct * vma)
 
 
    vma->vm_private_data = mmap_instance;
    vma->vm_private_data = mmap_instance;
    vma->vm_ops = &fusd_remap_vm_ops;
    vma->vm_ops = &fusd_remap_vm_ops;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
+   vma->vm_flags |= (VM_DONTEXPAND | VM_DONTDUMP);
+#else
    vma->vm_flags |= VM_RESERVED;
    vma->vm_flags |= VM_RESERVED;
+#endif
 
 
    fusd_client_mm_open(vma);
    fusd_client_mm_open(vma);
 
 
@@ -1817,24 +1845,36 @@ invalid_file:
    return -EPIPE;
    return -EPIPE;
 }
 }
 
 
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+static int fusd_client_fault (struct vm_fault *vmf)
+#elif LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 30)
 static int fusd_client_fault (struct vm_area_struct *vma, struct vm_fault *vmf)
 static int fusd_client_fault (struct vm_area_struct *vma, struct vm_fault *vmf)
 #else
 #else
 static int fusd_client_fault (struct vm_area_struct *vma, struct vm_fault *vmf, int *type)
 static int fusd_client_fault (struct vm_area_struct *vma, struct vm_fault *vmf, int *type)
 #endif
 #endif
 {
 {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+   struct vm_area_struct *vma = vmf->vma;
+#endif
+
    struct fusd_mmap_instance* mmap_instance = (struct fusd_mmap_instance*) vma->vm_private_data;
    struct fusd_mmap_instance* mmap_instance = (struct fusd_mmap_instance*) vma->vm_private_data;
    unsigned long offset;
    unsigned long offset;
    struct page *page = NULL;
    struct page *page = NULL;
    int result;
    int result;
 
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
+   offset = ( (unsigned long) vmf->address - vma->vm_start ) + ( vma->vm_pgoff << PAGE_SHIFT );
+#else
    offset = ( (unsigned long) vmf->virtual_address - vma->vm_start ) + ( vma->vm_pgoff << PAGE_SHIFT );
    offset = ( (unsigned long) vmf->virtual_address - vma->vm_start ) + ( vma->vm_pgoff << PAGE_SHIFT );
+#endif
+
    // todo: worry about size
    // todo: worry about size
    if ( offset > mmap_instance->size )
    if ( offset > mmap_instance->size )
       goto out;
       goto out;
 
 
    down_read(&mmap_instance->fusd_dev->task->mm->mmap_sem);
    down_read(&mmap_instance->fusd_dev->task->mm->mmap_sem);
-   result = get_user_pages(mmap_instance->fusd_dev->task, mmap_instance->fusd_dev->task->mm, mmap_instance->addr + offset, 1, 1, 0, &page, NULL);
+   result = GET_USER_PAGES(mmap_instance->fusd_dev->task, mmap_instance->fusd_dev->task->mm,
+                           mmap_instance->addr + offset, 1, 1, 0, &page, NULL);
    up_read(&mmap_instance->fusd_dev->task->mm->mmap_sem);
    up_read(&mmap_instance->fusd_dev->task->mm->mmap_sem);
 
 
 
 
@@ -2207,8 +2247,11 @@ STATIC int fusd_register_device (fusd_dev_t *fusd_dev,
       if ( sysfs )
       if ( sysfs )
       {
       {
          /* Get FS superblock */
          /* Get FS superblock */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+         sb = sget(sysfs, systest, NULL, 0, NULL);
+#else
          sb = sget(sysfs, systest, NULL, NULL);
          sb = sget(sysfs, systest, NULL, NULL);
-
+#endif
          /* because put_filesystem isn't exported */
          /* because put_filesystem isn't exported */
          module_put(sysfs->owner);
          module_put(sysfs->owner);
 
 
@@ -2224,7 +2267,8 @@ STATIC int fusd_register_device (fusd_dev_t *fusd_dev,
 	            /* Search for directory "class" in the root of this filesystem */
 	            /* Search for directory "class" in the root of this filesystem */
                name.name = "class";
                name.name = "class";
                name.len = 5;
                name.len = 5;
-               name.hash = full_name_hash(name.name, name.len);
+               name.hash = FULL_NAME_HASH(name.name, name.len);
+
                classdir = d_lookup(root, &name);
                classdir = d_lookup(root, &name);
 
 
                if ( classdir )
                if ( classdir )
@@ -2232,7 +2276,7 @@ STATIC int fusd_register_device (fusd_dev_t *fusd_dev,
                   /* Found, now search for class wanted name */
                   /* Found, now search for class wanted name */
                   name.name = register_msg.clazz;
                   name.name = register_msg.clazz;
                   name.len = strlen(name.name);
                   name.len = strlen(name.name);
-                  name.hash = full_name_hash(name.name, name.len);
+                  name.hash = FULL_NAME_HASH(name.name, name.len);
                   classdir2 = d_lookup(classdir, &name);
                   classdir2 = d_lookup(classdir, &name);
 
 
                   if ( classdir2 )
                   if ( classdir2 )
@@ -2659,6 +2703,31 @@ STATIC ssize_t fusd_writev (struct file *file,
                              iov[0].iov_base, iov[0].iov_len,
                              iov[0].iov_base, iov[0].iov_len,
                              iov[1].iov_base, iov[1].iov_len);
                              iov[1].iov_base, iov[1].iov_len);
 }
 }
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+ssize_t fusd_write_iter (struct kiocb *iocb, struct iov_iter *iov)
+{
+   unsigned long count = iov_iter_count(iov);
+   char *msg, *data;
+   size_t msg_len, data_len;
+
+   if ( count != 2 )
+   {
+      RDEBUG(2, "fusd_writev: got illegal iov count of %ld", count);
+      return -EINVAL;
+   }
+
+   msg = iov->iov->iov_base + iov->iov_offset;
+   msg_len = iov_iter_single_seg_count(iov);
+
+   iov_iter_advance(iov, msg_len);
+
+   data = iov->iov->iov_base + iov->iov_offset;
+   data_len = iov_iter_single_seg_count(iov);
+
+   return fusd_process_write(iocb->ki_filp,
+                             msg, msg_len,
+                             data, data_len);
+}
 #else
 #else
 STATIC ssize_t fusd_aio_write (struct kiocb *iocb,
 STATIC ssize_t fusd_aio_write (struct kiocb *iocb,
                                const struct iovec *iov, 
                                const struct iovec *iov, 
@@ -2685,8 +2754,8 @@ STATIC long fusd_unlocked_ioctl (struct file *file,
                        unsigned int cmd, unsigned long arg)
                        unsigned int cmd, unsigned long arg)
 #endif
 #endif
 {
 {
-   void __user *argp = (void __user *) arg;
 #if 0
 #if 0
+   void __user *argp = (void __user *) arg;
    struct iovec iov;
    struct iovec iov;
 
 
    if ( ( argp != NULL ) && ( cmd == 0xb16b00b5 ) )
    if ( ( argp != NULL ) && ( cmd == 0xb16b00b5 ) )
@@ -2914,7 +2983,11 @@ STATIC struct file_operations fusd_fops = {
                                            .open = fusd_open,
                                            .open = fusd_open,
                                            .read = fusd_read,
                                            .read = fusd_read,
                                            .write = fusd_write,
                                            .write = fusd_write,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+                                           .write_iter = fusd_write_iter,
+#else
                                            .aio_write = fusd_aio_write,
                                            .aio_write = fusd_aio_write,
+#endif
                                            .unlocked_ioctl = fusd_unlocked_ioctl,
                                            .unlocked_ioctl = fusd_unlocked_ioctl,
                                            .release = fusd_release,
                                            .release = fusd_release,
                                            .poll = fusd_poll,
                                            .poll = fusd_poll,