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 5 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
 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
-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:
 
@@ -53,7 +57,7 @@ include the following rule:
 
 5. Verify the fusd devices /dev/fusd/status and /dev/fusd/control
 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
 been correctly configured and restarted.
 

+ 83 - 10
kfusd/kfusd.c

@@ -78,6 +78,10 @@
 #include <linux/device.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/uaccess.h>
 #include <asm/ioctl.h>
@@ -132,6 +136,23 @@
 #   define CLASS_DEVICE_DESTROY(a, b) device_destroy(a, b)
 #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)
 
 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 */
    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.gid = current_gid();
 #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->poll_wait);
    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->transactions_sem);
 #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);
 
 /* 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);
 #else
 static int fusd_client_fault (struct vm_area_struct *vma, struct vm_fault *vmf, int *type);
 #endif
+
 static struct vm_operations_struct fusd_remap_vm_ops ={
                                                        .open = fusd_client_mm_open,
                                                        .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 */
-   /* 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);
 
    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_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;
+#endif
 
    fusd_client_mm_open(vma);
 
@@ -1817,24 +1845,36 @@ invalid_file:
    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)
 #else
 static int fusd_client_fault (struct vm_area_struct *vma, struct vm_fault *vmf, int *type)
 #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;
    unsigned long offset;
    struct page *page = NULL;
    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 );
+#endif
+
    // todo: worry about size
    if ( offset > mmap_instance->size )
       goto out;
 
    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);
 
 
@@ -2207,8 +2247,11 @@ STATIC int fusd_register_device (fusd_dev_t *fusd_dev,
       if ( sysfs )
       {
          /* 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);
-
+#endif
          /* because put_filesystem isn't exported */
          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 */
                name.name = "class";
                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);
 
                if ( classdir )
@@ -2232,7 +2276,7 @@ STATIC int fusd_register_device (fusd_dev_t *fusd_dev,
                   /* Found, now search for class wanted name */
                   name.name = register_msg.clazz;
                   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);
 
                   if ( classdir2 )
@@ -2659,6 +2703,31 @@ STATIC ssize_t fusd_writev (struct file *file,
                              iov[0].iov_base, iov[0].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
 STATIC ssize_t fusd_aio_write (struct kiocb *iocb,
                                const struct iovec *iov, 
@@ -2685,8 +2754,8 @@ STATIC long fusd_unlocked_ioctl (struct file *file,
                        unsigned int cmd, unsigned long arg)
 #endif
 {
-   void __user *argp = (void __user *) arg;
 #if 0
+   void __user *argp = (void __user *) arg;
    struct iovec iov;
 
    if ( ( argp != NULL ) && ( cmd == 0xb16b00b5 ) )
@@ -2914,7 +2983,11 @@ STATIC struct file_operations fusd_fops = {
                                            .open = fusd_open,
                                            .read = fusd_read,
                                            .write = fusd_write,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
+                                           .write_iter = fusd_write_iter,
+#else
                                            .aio_write = fusd_aio_write,
+#endif
                                            .unlocked_ioctl = fusd_unlocked_ioctl,
                                            .release = fusd_release,
                                            .poll = fusd_poll,