Re: [Yaffs] yaffs2 on kernel 4.15

Top Page
Attachments:
Message as email
+ (text/plain)
+ add-4.19-support.patch (text/x-patch)
Delete this message
Reply to this message
Author: akiko@mailbox.org
Date:  
To: YAFFS
Subject: Re: [Yaffs] yaffs2 on kernel 4.15
Okay, next try .. NOW the patch should be attached.

> Hi,
>
> the attached patch adds kernel support for 4.9.x to 4.19.x to the multi
> version. It is well tested for the 4.14 series and I have it running on
> 4.19.1. The solution for 4.17+ I added is not the best one, it works,
> but there may be side effects. This patch is made on top of the git
> master branch commit 3439fa4e.
>
> greetings,
> Akiko
>
> On 2018-09-13 20:48, Ketil Froyn wrote:
> > Hi,
> >
> > I'm trying to get yaffs2 working on Ubuntu 18.04, to run some
> > experiments with yaffs2 and nandsim. The linux kernel bundled with
> > Ubuntu is 4.15.0-34-generic (as Ubuntu chooses to call it).
> >
> > I tried to compile yaffs2, but I got some errors. I found the patches
> > for recent kernels suggested on this list by Martin Kaiser, and I
> > applied them, but I still have some problems. The errors I get seem to
> > be related to timer interface changes made in 4.15. For instance,
> > init_timer_on_stack() is replaced by timer_setup_on_stack(), the
> > timer_list struct has changed and the callback function has a
> > different declaration.
> >
> > For all I know this may be easy to fix for someone familiar with yaffs
> > internals, but I'd be dabbling with things I don't understand very
> > well. Has anyone else done this, or should I take a stab at it myself?
> >
> > Regards, Ketil
This patch adds support for all kernel from the 4.9 to the 4.19 series.
---
diff --git a/yaffs_guts.c b/yaffs_guts.c
index 7678896..40a5b46 100644
--- a/yaffs_guts.c
+++ b/yaffs_guts.c
@@ -4534,13 +4534,11 @@ int yaffs_get_obj_name(struct yaffs_obj *obj, YCHAR *name, int buffer_size)

         if (obj->hdr_chunk > 0) {
             result = yaffs_rd_chunk_tags_nand(obj->my_dev,
-                              obj->hdr_chunk,
-                              buffer, NULL);
+                obj->hdr_chunk, buffer, NULL);
+            if (result == YAFFS_OK)
+                yaffs_load_name_from_oh(obj->my_dev, name,
+                    oh->name, buffer_size);
         }
-        if (result == YAFFS_OK)
-            yaffs_load_name_from_oh(obj->my_dev, name, oh->name,
-                    buffer_size);
-
         yaffs_release_temp_buffer(obj->my_dev, buffer);
     }


diff --git a/yaffs_mtdif_multi.c b/yaffs_mtdif_multi.c
index 5b0e4fe..2d34b01 100644
--- a/yaffs_mtdif_multi.c
+++ b/yaffs_mtdif_multi.c
@@ -17,7 +17,11 @@
#include "linux/mtd/mtd.h"
#include "linux/types.h"
#include "linux/time.h"
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0))
#include "linux/mtd/nand.h"
+#else
+#include "linux/mtd/rawnand.h"
+#endif
#include "linux/kernel.h"
#include "linux/version.h"
#include "linux/types.h"
@@ -28,7 +32,6 @@
#include "yaffs_trace.h"
#include "yaffs_guts.h"
#include "yaffs_linux.h"
-
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
#define MTD_OPS_AUTO_OOB MTD_OOB_AUTO
#endif
@@ -42,24 +45,25 @@
#define mtd_block_markbad(m, offs) (m)->block_markbad(m, offs)
#endif

-
-
 int nandmtd_erase_block(struct yaffs_dev *dev, int block_no)
 {
     struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
-    u32 addr =
-        ((loff_t) block_no) * dev->param.total_bytes_per_chunk *
-        dev->param.chunks_per_block;
+    u32 addr = ((loff_t) block_no) * dev->param.total_bytes_per_chunk *
+        dev->param.chunks_per_block;
     struct erase_info ei;
     int retval = 0;


+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0))
     ei.mtd = mtd;
+#endif
     ei.addr = addr;
     ei.len = dev->param.total_bytes_per_chunk * dev->param.chunks_per_block;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0))
     ei.time = 1000;
     ei.retries = 2;
     ei.callback = NULL;
     ei.priv = (u_long) dev;
+#endif


     retval = mtd_erase(mtd, &ei);


@@ -69,10 +73,9 @@ int nandmtd_erase_block(struct yaffs_dev *dev, int block_no)
     return YAFFS_FAIL;
 }


-
-static     int yaffs_mtd_write(struct yaffs_dev *dev, int nand_chunk,
-                   const u8 *data, int data_len,
-                   const u8 *oob, int oob_len)
+static int yaffs_mtd_write(struct yaffs_dev *dev, int nand_chunk,
+               const u8 *data, int data_len,
+               const u8 *oob, int oob_len)
 {
     struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
     loff_t addr;
@@ -80,8 +83,8 @@ static     int yaffs_mtd_write(struct yaffs_dev *dev, int nand_chunk,
     int retval;


     yaffs_trace(YAFFS_TRACE_MTD,
-            "yaffs_mtd_write(%p, %d, %p, %d, %p, %d)\n",
-            dev, nand_chunk, data, data_len, oob, oob_len);
+        "yaffs_mtd_write(%p, %d, %p, %d, %p, %d)\n",
+        dev, nand_chunk, data, data_len, oob, oob_len);


     if (!data || !data_len) {
         data = NULL;
@@ -169,7 +172,7 @@ static int yaffs_mtd_read(struct yaffs_dev *dev, int nand_chunk,
     return YAFFS_OK;
 }


-static     int yaffs_mtd_erase(struct yaffs_dev *dev, int block_no)
+static int yaffs_mtd_erase(struct yaffs_dev *dev, int block_no)
 {
     struct mtd_info *mtd = yaffs_dev_to_mtd(dev);


@@ -182,13 +185,17 @@ static     int yaffs_mtd_erase(struct yaffs_dev *dev, int block_no)
              dev->param.chunks_per_block;
     addr = ((loff_t) block_no) * block_size;


+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0))
     ei.mtd = mtd;
+#endif
     ei.addr = addr;
     ei.len = block_size;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0))
     ei.time = 1000;
     ei.retries = 2;
     ei.callback = NULL;
     ei.priv = (u_long) dev;
+#endif


     retval = mtd_erase(mtd, &ei);


@@ -232,7 +239,6 @@ static int yaffs_mtd_deinitialise(struct yaffs_dev *dev)
     return YAFFS_OK;
 }


-
 void yaffs_mtd_drv_install(struct yaffs_dev *dev)
 {
     struct yaffs_driver *drv = &dev->drv;
@@ -246,7 +252,6 @@ void yaffs_mtd_drv_install(struct yaffs_dev *dev)
     drv->drv_deinitialise_fn = yaffs_mtd_deinitialise;
 }


-
 struct mtd_info * yaffs_get_mtd_device(dev_t sdev)
 {
     struct mtd_info *mtd;
@@ -301,9 +306,8 @@ int yaffs_verify_mtd(struct mtd_info *mtd, int yaffs_version, int inband_tags)
     return 0;
 }


-
 void yaffs_put_mtd_device(struct mtd_info *mtd)
 {
-    if(mtd)
+    if (mtd)
         put_mtd_device(mtd);
 }
diff --git a/yaffs_vfs_multi.c b/yaffs_vfs_multi.c
index de3dd75..a714cab 100644
--- a/yaffs_vfs_multi.c
+++ b/yaffs_vfs_multi.c
@@ -35,6 +35,9 @@
  * for any version of Linux.
  */
 #include <linux/version.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0))
+#include <linux/iversion.h>
+#endif


#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10))
#define YAFFS_COMPILE_BACKGROUND
@@ -109,10 +112,10 @@
#include <linux/statfs.h>

 #define UnlockPage(p) unlock_page(p)
-#define Page_Uptodate(page)    test_bit(PG_uptodate, &(page)->flags)
+#define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags)


 /* FIXME: use sb->s_id instead ? */
-#define yaffs_devname(sb, buf)    bdevname(sb->s_bdev, buf)
+#define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf)


#else

@@ -130,13 +133,15 @@
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
#define YPROC_ROOT (&proc_root)
#else
-#define YPROC_ROOT NULL
+#define YPROC_ROOT NULL
#endif

 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
 #define Y_INIT_TIMER(a)    init_timer(a)
-#else
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
 #define Y_INIT_TIMER(a)    init_timer_on_stack(a)
+#else
+#define Y_INIT_TIMER(a,cb) timer_setup_on_stack(a,cb,0)
 #endif


#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27))
@@ -172,18 +177,12 @@ static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size)
#include "yaffs_trace.h"
#include "yaffs_guts.h"
#include "yaffs_attribs.h"
-
#include "yaffs_linux.h"
-
#include "yaffs_mtdif.h"
#include "yaffs_packedtags2.h"
#include "yaffs_getblockinfo.h"

-unsigned int yaffs_trace_mask =
-        YAFFS_TRACE_BAD_BLOCKS |
-        YAFFS_TRACE_ALWAYS |
-        0;
-
+unsigned int yaffs_trace_mask = YAFFS_TRACE_BAD_BLOCKS | YAFFS_TRACE_ALWAYS | 0;
 unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS;
 unsigned int yaffs_auto_checkpoint = 1;
 unsigned int yaffs_gc_control = 1;
@@ -262,9 +261,19 @@ MODULE_PARM(yaffs_gc_control, "i");
 #define YAFFS_NEW_GET_LINK 0
 #endif


+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0))
+#define update_dir_time(dir) do {\
+        (dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \
+    } while (0)
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(4,18,0))
 #define update_dir_time(dir) do {\
-            (dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \
-        } while (0)
+        (dir)->i_ctime = (dir)->i_mtime = current_kernel_time(); \
+    } while (0)
+#else
+#define update_dir_time(dir) do {\
+        (dir)->i_ctime = (dir)->i_mtime = current_kernel_time64(); \
+    } while (0)
+#endif


#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0))
static inline int setattr_prepare(struct dentry *dentry, struct iattr *attr)
@@ -1646,7 +1655,11 @@ static int yaffs_unlink(struct inode *dir, struct dentry *dentry)

     if (ret_val == YAFFS_OK) {
         inode_dec_link_count(dentry->d_inode);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0))
+        inode_inc_iversion(dir);
+#else
         dir->i_version++;
+#endif
         yaffs_gross_unlock(dev);
         update_dir_time(dir);
         return 0;
@@ -2129,10 +2142,26 @@ static unsigned yaffs_bg_gc_urgency(struct yaffs_dev *dev)


#ifdef YAFFS_COMPILE_BACKGROUND

+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
+struct timer_struct {
+    struct task_struct *task;
+    struct timer_list timer;
+};
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
+static void yaffs_background_waker(struct timer_list *t)
+{
+    struct timer_struct *ts = from_timer(ts, t, timer);
+
+    wake_up_process(ts->task);
+}
+#else
 void yaffs_background_waker(unsigned long data)
 {
     wake_up_process((struct task_struct *)data);
 }
+#endif


 static int yaffs_bg_thread_fn(void *data)
 {
@@ -2145,7 +2174,11 @@ static int yaffs_bg_thread_fn(void *data)
     unsigned int urgency;


     int gc_result;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
+    struct timer_struct timer;
+#else
     struct timer_list timer;
+#endif


     yaffs_trace(YAFFS_TRACE_BACKGROUND,
         "yaffs_background starting for dev %p", (void *)dev);
@@ -2191,24 +2224,32 @@ static int yaffs_bg_thread_fn(void *data)
                         }
         }
         yaffs_gross_unlock(dev);
-#if 1
         expires = next_dir_update;
         if (time_before(next_gc, expires))
             expires = next_gc;
         if (time_before(expires, now))
             expires = now + HZ;


+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
+        Y_INIT_TIMER(&timer.timer, yaffs_background_waker);
+        timer.timer.expires = expires + 1;
+        timer.task = current;
+#else
         Y_INIT_TIMER(&timer);
         timer.expires = expires + 1;
         timer.data = (unsigned long)current;
         timer.function = yaffs_background_waker;
+#endif


         set_current_state(TASK_INTERRUPTIBLE);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
+        add_timer(&timer.timer);
+        schedule();
+        del_timer_sync(&timer.timer);
+#else
         add_timer(&timer);
         schedule();
         del_timer_sync(&timer);
-#else
-        msleep(10);
 #endif
     }


@@ -3745,8 +3786,8 @@ static void __exit exit_yaffs_fs(void)
}

 module_init(init_yaffs_fs)
-    module_exit(exit_yaffs_fs)
+module_exit(exit_yaffs_fs)


-    MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system");
+MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system");
 MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2011");
 MODULE_LICENSE("GPL");
diff --git a/yportenv_multi.h b/yportenv_multi.h
index 3df7d56..68c239c 100644
--- a/yportenv_multi.h
+++ b/yportenv_multi.h
@@ -61,10 +61,18 @@
 #define YAFFS_LOSTNFOUND_MODE        0700


#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0))
#define Y_CURRENT_TIME CURRENT_TIME.tv_sec
+#else
+#define Y_CURRENT_TIME current_kernel_time().tv_sec
+#endif
#define Y_TIME_CONVERT(x) (x).tv_sec
#else
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0))
#define Y_CURRENT_TIME CURRENT_TIME
+#else
+#define Y_CURRENT_TIME current_kernel_time()
+#endif
#define Y_TIME_CONVERT(x) (x)
#endif