kernel: update yaffs code to the latest version
authorGabor Juhos <juhosg@openwrt.org>
Tue, 31 Mar 2015 15:31:57 +0000 (15:31 +0000)
committerGabor Juhos <juhosg@openwrt.org>
Tue, 31 Mar 2015 15:31:57 +0000 (15:31 +0000)
Use the latest version of the yaffs code. Fetched from the
yaffs2 git tree and it is based on the following commit:

  commit 7e5cf0fa1b694f835cdc184a8395b229fa29f9ae
  Author: Charles Manning <cdhmanning@gmail.com>
  Date:   Thu Aug 7 11:25:05 2014 +1200

    yaffs-direct: Basic tests. Add lpthread flag for background gc support

Signed-off-by: Charles Manning <cdhmanning@gmail.com>
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
SVN-Revision: 45188

35 files changed:
target/linux/generic/files/fs/yaffs2/NOTE.openwrt
target/linux/generic/files/fs/yaffs2/yaffs_attribs.c
target/linux/generic/files/fs/yaffs2/yaffs_guts.c
target/linux/generic/files/fs/yaffs2/yaffs_guts.h
target/linux/generic/files/fs/yaffs2/yaffs_mtdif.c
target/linux/generic/files/fs/yaffs2/yaffs_packedtags1.h
target/linux/generic/files/fs/yaffs2/yaffs_summary.c
target/linux/generic/files/fs/yaffs2/yaffs_vfs.c
target/linux/generic/files/fs/yaffs2/yaffs_yaffs2.c
target/linux/generic/patches-3.14/501-yaffs-3.5-convert-to-use-kuid_t-kgid_t.patch [deleted file]
target/linux/generic/patches-3.14/501-yaffs-add-missing-flush-arguments.patch [new file with mode: 0644]
target/linux/generic/patches-3.14/502-yaffs-3.10-disable-proc-entry.patch [deleted file]
target/linux/generic/patches-3.14/502-yaffs-fix-compat-tags-handling.patch [new file with mode: 0644]
target/linux/generic/patches-3.14/503-yaffs-3.12-convert-readdir-to-iterate.patch [deleted file]
target/linux/generic/patches-3.14/503-yaffs-add-tags-9bytes-mount-option.patch
target/linux/generic/patches-3.14/504-yaffs-3.16-new-fops.patch [new file with mode: 0644]
target/linux/generic/patches-3.14/504-yaffs-fix-compat-tags-handling.patch [deleted file]
target/linux/generic/patches-3.18/501-yaffs-3.5-convert-to-use-kuid_t-kgid_t.patch [deleted file]
target/linux/generic/patches-3.18/501-yaffs-add-missing-flush-arguments.patch [new file with mode: 0644]
target/linux/generic/patches-3.18/502-yaffs-3.10-disable-proc-entry.patch [deleted file]
target/linux/generic/patches-3.18/502-yaffs-fix-compat-tags-handling.patch [new file with mode: 0644]
target/linux/generic/patches-3.18/503-yaffs-3.12-convert-readdir-to-iterate.patch [deleted file]
target/linux/generic/patches-3.18/503-yaffs-add-tags-9bytes-mount-option.patch
target/linux/generic/patches-3.18/504-yaffs-3.16-new-fops.patch [new file with mode: 0644]
target/linux/generic/patches-3.18/504-yaffs-fix-compat-tags-handling.patch [deleted file]
target/linux/generic/patches-3.18/505-yaffs-3.16-new-fops.patch [deleted file]
target/linux/generic/patches-4.0/501-yaffs-3.5-convert-to-use-kuid_t-kgid_t.patch [deleted file]
target/linux/generic/patches-4.0/501-yaffs-add-missing-flush-arguments.patch [new file with mode: 0644]
target/linux/generic/patches-4.0/502-yaffs-3.10-disable-proc-entry.patch [deleted file]
target/linux/generic/patches-4.0/502-yaffs-fix-compat-tags-handling.patch [new file with mode: 0644]
target/linux/generic/patches-4.0/503-yaffs-3.12-convert-readdir-to-iterate.patch [deleted file]
target/linux/generic/patches-4.0/503-yaffs-add-tags-9bytes-mount-option.patch
target/linux/generic/patches-4.0/504-yaffs-3.16-new-fops.patch [new file with mode: 0644]
target/linux/generic/patches-4.0/504-yaffs-fix-compat-tags-handling.patch [deleted file]
target/linux/generic/patches-4.0/505-yaffs-3.16-new-fops.patch [deleted file]

index 0be479d66ccfad30a2c52e9cae67467a41b6c053..ad807bdc09f643525e8a124ef7e1810528a1c32a 100644 (file)
@@ -1,4 +1,4 @@
 The yaffs2 source has been fetched from the yaffs2 GIT tree.
 
 URL: git://www.aleph1.co.uk/yaffs2
-Version: bc76682d93955cfb33051beb503ad9f8a5450578 (2013-12-03)
+Version: 7e5cf0fa1b694f835cdc184a8395b229fa29f9ae (2014-08-07)
index 3d778f2266248d47658eacc0882ef13ef720a668..711941f137f554a2a32cd32edafd60049f7bc435 100644 (file)
 #include "yaffs_guts.h"
 #include "yaffs_attribs.h"
 
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
+#define IATTR_UID ia_uid
+#define IATTR_GID ia_gid
+#else
+#define IATTR_UID ia_uid.val
+#define IATTR_GID ia_gid.val
+#endif
+
 void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh)
 {
        obj->yst_uid = oh->yst_uid;
@@ -77,9 +85,9 @@ int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr)
        if (valid & ATTR_MODE)
                obj->yst_mode = attr->ia_mode;
        if (valid & ATTR_UID)
-               obj->yst_uid = attr->ia_uid;
+               obj->yst_uid = attr->IATTR_UID;
        if (valid & ATTR_GID)
-               obj->yst_gid = attr->ia_gid;
+               obj->yst_gid = attr->IATTR_GID;
 
        if (valid & ATTR_ATIME)
                obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
@@ -103,9 +111,9 @@ int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr)
 
        attr->ia_mode = obj->yst_mode;
        valid |= ATTR_MODE;
-       attr->ia_uid = obj->yst_uid;
+       attr->IATTR_UID = obj->yst_uid;
        valid |= ATTR_UID;
-       attr->ia_gid = obj->yst_gid;
+       attr->IATTR_GID = obj->yst_gid;
        valid |= ATTR_GID;
 
        Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime;
index 1fd464d68af798c5fcdd02c537c7804bcbd05a5f..1c0ae71320a52fc5645e09fd76e5203c348ab8c7 100644 (file)
@@ -631,6 +631,78 @@ static void yaffs_retire_block(struct yaffs_dev *dev, int flash_block)
 
 /*---------------- Name handling functions ------------*/
 
+static void yaffs_load_name_from_oh(struct yaffs_dev *dev, YCHAR *name,
+                                   const YCHAR *oh_name, int buff_size)
+{
+#ifdef CONFIG_YAFFS_AUTO_UNICODE
+       if (dev->param.auto_unicode) {
+               if (*oh_name) {
+                       /* It is an ASCII name, do an ASCII to
+                        * unicode conversion */
+                       const char *ascii_oh_name = (const char *)oh_name;
+                       int n = buff_size - 1;
+                       while (n > 0 && *ascii_oh_name) {
+                               *name = *ascii_oh_name;
+                               name++;
+                               ascii_oh_name++;
+                               n--;
+                       }
+               } else {
+                       strncpy(name, oh_name + 1, buff_size - 1);
+               }
+       } else {
+#else
+       (void) dev;
+       {
+#endif
+               strncpy(name, oh_name, buff_size - 1);
+       }
+}
+
+static void yaffs_load_oh_from_name(struct yaffs_dev *dev, YCHAR *oh_name,
+                                   const YCHAR *name)
+{
+#ifdef CONFIG_YAFFS_AUTO_UNICODE
+
+       int is_ascii;
+       const YCHAR *w;
+
+       if (dev->param.auto_unicode) {
+
+               is_ascii = 1;
+               w = name;
+
+               /* Figure out if the name will fit in ascii character set */
+               while (is_ascii && *w) {
+                       if ((*w) & 0xff00)
+                               is_ascii = 0;
+                       w++;
+               }
+
+               if (is_ascii) {
+                       /* It is an ASCII name, so convert unicode to ascii */
+                       char *ascii_oh_name = (char *)oh_name;
+                       int n = YAFFS_MAX_NAME_LENGTH - 1;
+                       while (n > 0 && *name) {
+                               *ascii_oh_name = *name;
+                               name++;
+                               ascii_oh_name++;
+                               n--;
+                       }
+               } else {
+                       /* Unicode name, so save starting at the second YCHAR */
+                       *oh_name = 0;
+                       strncpy(oh_name + 1, name, YAFFS_MAX_NAME_LENGTH - 2);
+               }
+       } else {
+#else
+       dev = dev;
+       {
+#endif
+               strncpy(oh_name, name, YAFFS_MAX_NAME_LENGTH - 1);
+       }
+}
+
 static u16 yaffs_calc_name_sum(const YCHAR *name)
 {
        u16 sum = 0;
@@ -1377,56 +1449,49 @@ static int yaffs_obj_cache_dirty(struct yaffs_obj *obj)
        return 0;
 }
 
-static void yaffs_flush_file_cache(struct yaffs_obj *obj)
+static void yaffs_flush_single_cache(struct yaffs_cache *cache, int discard)
+{
+
+       if (!cache || cache->locked)
+               return;
+
+       /* Write it out and free it up  if need be.*/
+       if (cache->dirty) {
+               yaffs_wr_data_obj(cache->object,
+                                 cache->chunk_id,
+                                 cache->data,
+                                 cache->n_bytes,
+                                 1);
+
+               cache->dirty = 0;
+       }
+
+       if (discard)
+               cache->object = NULL;
+}
+
+static void yaffs_flush_file_cache(struct yaffs_obj *obj, int discard)
 {
        struct yaffs_dev *dev = obj->my_dev;
-       int lowest = -99;       /* Stop compiler whining. */
        int i;
        struct yaffs_cache *cache;
-       int chunk_written = 0;
        int n_caches = obj->my_dev->param.n_caches;
 
        if (n_caches < 1)
                return;
-       do {
-               cache = NULL;
-
-               /* Find the lowest dirty chunk for this object */
-               for (i = 0; i < n_caches; i++) {
-                       if (dev->cache[i].object == obj &&
-                           dev->cache[i].dirty) {
-                               if (!cache ||
-                                   dev->cache[i].chunk_id < lowest) {
-                                       cache = &dev->cache[i];
-                                       lowest = cache->chunk_id;
-                               }
-                       }
-               }
 
-               if (cache && !cache->locked) {
-                       /* Write it out and free it up */
-                       chunk_written =
-                           yaffs_wr_data_obj(cache->object,
-                                             cache->chunk_id,
-                                             cache->data,
-                                             cache->n_bytes, 1);
-                       cache->dirty = 0;
-                       cache->object = NULL;
-               }
-       } while (cache && chunk_written > 0);
 
-       if (cache)
-               /* Hoosterman, disk full while writing cache out. */
-               yaffs_trace(YAFFS_TRACE_ERROR,
-                       "yaffs tragedy: no space during cache write");
+       /* Find the chunks for this object and flush them. */
+       for (i = 0; i < n_caches; i++) {
+               cache = &dev->cache[i];
+               if (cache->object == obj)
+                       yaffs_flush_single_cache(cache, discard);
+       }
+
 }
 
-/*yaffs_flush_whole_cache(dev)
- *
- *
- */
 
-void yaffs_flush_whole_cache(struct yaffs_dev *dev)
+void yaffs_flush_whole_cache(struct yaffs_dev *dev, int discard)
 {
        struct yaffs_obj *obj;
        int n_caches = dev->param.n_caches;
@@ -1442,12 +1507,12 @@ void yaffs_flush_whole_cache(struct yaffs_dev *dev)
                                obj = dev->cache[i].object;
                }
                if (obj)
-                       yaffs_flush_file_cache(obj);
+                       yaffs_flush_file_cache(obj, discard);
        } while (obj);
 
 }
 
-/* Grab us a cache chunk for use.
+/* Grab us an unused cache chunk for use.
  * First look for an empty one.
  * Then look for the least recently used non-dirty one.
  * Then look for the least recently used dirty one...., flush and look again.
@@ -1462,56 +1527,50 @@ static struct yaffs_cache *yaffs_grab_chunk_worker(struct yaffs_dev *dev)
                                return &dev->cache[i];
                }
        }
+
        return NULL;
 }
 
 static struct yaffs_cache *yaffs_grab_chunk_cache(struct yaffs_dev *dev)
 {
        struct yaffs_cache *cache;
-       struct yaffs_obj *the_obj;
        int usage;
        int i;
-       int pushout;
 
        if (dev->param.n_caches < 1)
                return NULL;
 
-       /* Try find a non-dirty one... */
+       /* First look for an unused cache */
 
        cache = yaffs_grab_chunk_worker(dev);
 
-       if (!cache) {
-               /* They were all dirty, find the LRU object and flush
-                * its cache, then  find again.
-                * NB what's here is not very accurate,
-                * we actually flush the object with the LRU chunk.
-                */
+       if (cache)
+               return cache;
 
-               /* With locking we can't assume we can use entry zero,
-                * Set the_obj to a valid pointer for Coverity. */
-               the_obj = dev->cache[0].object;
-               usage = -1;
-               cache = NULL;
-               pushout = -1;
+       /*
+        * Thery were all in use.
+        * Find the LRU cache and flush it if it is dirty.
+        */
 
-               for (i = 0; i < dev->param.n_caches; i++) {
-                       if (dev->cache[i].object &&
-                           !dev->cache[i].locked &&
-                           (dev->cache[i].last_use < usage ||
-                           !cache)) {
+       usage = -1;
+       cache = NULL;
+
+       for (i = 0; i < dev->param.n_caches; i++) {
+               if (dev->cache[i].object &&
+                   !dev->cache[i].locked &&
+                   (dev->cache[i].last_use < usage || !cache)) {
                                usage = dev->cache[i].last_use;
-                               the_obj = dev->cache[i].object;
                                cache = &dev->cache[i];
-                               pushout = i;
-                       }
-               }
-
-               if (!cache || cache->dirty) {
-                       /* Flush and try again */
-                       yaffs_flush_file_cache(the_obj);
-                       cache = yaffs_grab_chunk_worker(dev);
                }
        }
+
+#if 1
+       yaffs_flush_single_cache(cache, 1);
+#else
+       yaffs_flush_file_cache(cache->object, 1);
+       cache = yaffs_grab_chunk_worker(dev);
+#endif
+
        return cache;
 }
 
@@ -3189,78 +3248,6 @@ static void yaffs_check_obj_details_loaded(struct yaffs_obj *in)
        yaffs_release_temp_buffer(dev, buf);
 }
 
-static void yaffs_load_name_from_oh(struct yaffs_dev *dev, YCHAR *name,
-                                   const YCHAR *oh_name, int buff_size)
-{
-#ifdef CONFIG_YAFFS_AUTO_UNICODE
-       if (dev->param.auto_unicode) {
-               if (*oh_name) {
-                       /* It is an ASCII name, do an ASCII to
-                        * unicode conversion */
-                       const char *ascii_oh_name = (const char *)oh_name;
-                       int n = buff_size - 1;
-                       while (n > 0 && *ascii_oh_name) {
-                               *name = *ascii_oh_name;
-                               name++;
-                               ascii_oh_name++;
-                               n--;
-                       }
-               } else {
-                       strncpy(name, oh_name + 1, buff_size - 1);
-               }
-       } else {
-#else
-       (void) dev;
-       {
-#endif
-               strncpy(name, oh_name, buff_size - 1);
-       }
-}
-
-static void yaffs_load_oh_from_name(struct yaffs_dev *dev, YCHAR *oh_name,
-                                   const YCHAR *name)
-{
-#ifdef CONFIG_YAFFS_AUTO_UNICODE
-
-       int is_ascii;
-       YCHAR *w;
-
-       if (dev->param.auto_unicode) {
-
-               is_ascii = 1;
-               w = name;
-
-               /* Figure out if the name will fit in ascii character set */
-               while (is_ascii && *w) {
-                       if ((*w) & 0xff00)
-                               is_ascii = 0;
-                       w++;
-               }
-
-               if (is_ascii) {
-                       /* It is an ASCII name, so convert unicode to ascii */
-                       char *ascii_oh_name = (char *)oh_name;
-                       int n = YAFFS_MAX_NAME_LENGTH - 1;
-                       while (n > 0 && *name) {
-                               *ascii_oh_name = *name;
-                               name++;
-                               ascii_oh_name++;
-                               n--;
-                       }
-               } else {
-                       /* Unicode name, so save starting at the second YCHAR */
-                       *oh_name = 0;
-                       strncpy(oh_name + 1, name, YAFFS_MAX_NAME_LENGTH - 2);
-               }
-       } else {
-#else
-       dev = dev;
-       {
-#endif
-               strncpy(oh_name, name, YAFFS_MAX_NAME_LENGTH - 1);
-       }
-}
-
 /* UpdateObjectHeader updates the header on NAND for an object.
  * If name is not NULL, then that new name is used.
  */
@@ -3765,7 +3752,7 @@ int yaffs_resize_file(struct yaffs_obj *in, loff_t new_size)
        struct yaffs_dev *dev = in->my_dev;
        loff_t old_size = in->variant.file_variant.file_size;
 
-       yaffs_flush_file_cache(in);
+       yaffs_flush_file_cache(in, 1);
        yaffs_invalidate_whole_cache(in);
 
        yaffs_check_gc(dev, 0);
@@ -3798,12 +3785,15 @@ int yaffs_resize_file(struct yaffs_obj *in, loff_t new_size)
        return YAFFS_OK;
 }
 
-int yaffs_flush_file(struct yaffs_obj *in, int update_time, int data_sync)
+int yaffs_flush_file(struct yaffs_obj *in,
+                    int update_time,
+                    int data_sync,
+                    int discard_cache)
 {
        if (!in->dirty)
                return YAFFS_OK;
 
-       yaffs_flush_file_cache(in);
+       yaffs_flush_file_cache(in, discard_cache);
 
        if (data_sync)
                return YAFFS_OK;
@@ -3950,6 +3940,70 @@ int yaffs_del_obj(struct yaffs_obj *obj)
        return ret_val;
 }
 
+
+static void yaffs_empty_dir_to_dir(struct yaffs_obj *from_dir,
+                                  struct yaffs_obj *to_dir)
+{
+       struct yaffs_obj *obj;
+       struct list_head *lh;
+       struct list_head *n;
+
+       list_for_each_safe(lh, n, &from_dir->variant.dir_variant.children) {
+               obj = list_entry(lh, struct yaffs_obj, siblings);
+               yaffs_add_obj_to_dir(to_dir, obj);
+       }
+}
+
+struct yaffs_obj *yaffs_retype_obj(struct yaffs_obj *obj,
+                                  enum yaffs_obj_type type)
+{
+       /* Tear down the old variant */
+       switch (obj->variant_type) {
+       case YAFFS_OBJECT_TYPE_FILE:
+               /* Nuke file data */
+               yaffs_resize_file(obj, 0);
+               yaffs_free_tnode(obj->my_dev, obj->variant.file_variant.top);
+               obj->variant.file_variant.top = NULL;
+               break;
+       case YAFFS_OBJECT_TYPE_DIRECTORY:
+               /* Put the children in lost and found. */
+               yaffs_empty_dir_to_dir(obj, obj->my_dev->lost_n_found);
+               if (!list_empty(&obj->variant.dir_variant.dirty))
+                       list_del_init(&obj->variant.dir_variant.dirty);
+               break;
+       case YAFFS_OBJECT_TYPE_SYMLINK:
+               /* Nuke symplink data */
+               kfree(obj->variant.symlink_variant.alias);
+               obj->variant.symlink_variant.alias = NULL;
+               break;
+       case YAFFS_OBJECT_TYPE_HARDLINK:
+               list_del_init(&obj->hard_links);
+               break;
+       default:
+               break;
+       }
+
+       memset(&obj->variant, 0, sizeof(obj->variant));
+
+       /*Set up new variant if the memset is not enough. */
+       switch (type) {
+       case YAFFS_OBJECT_TYPE_DIRECTORY:
+               INIT_LIST_HEAD(&obj->variant.dir_variant.children);
+               INIT_LIST_HEAD(&obj->variant.dir_variant.dirty);
+               break;
+       case YAFFS_OBJECT_TYPE_FILE:
+       case YAFFS_OBJECT_TYPE_SYMLINK:
+       case YAFFS_OBJECT_TYPE_HARDLINK:
+       default:
+               break;
+       }
+
+       obj->variant_type = type;
+
+       return obj;
+
+}
+
 static int yaffs_unlink_worker(struct yaffs_obj *obj)
 {
        int del_now = 0;
@@ -4678,7 +4732,7 @@ int yaffs_guts_ll_init(struct yaffs_dev *dev)
 }
 
 
-int yaffs_format_dev(struct yaffs_dev *dev)
+int yaffs_guts_format_dev(struct yaffs_dev *dev)
 {
        int i;
        enum yaffs_block_state state;
index 05785367cb2e30a00daba4f928165d14ddaf0c33..231f8ac567eb86e3583f4c1fc436e9c89a4ca2c8 100644 (file)
@@ -144,12 +144,12 @@ struct yaffs_cache {
  */
 
 struct yaffs_tags {
-       unsigned chunk_id:20;
-       unsigned serial_number:2;
-       unsigned n_bytes_lsb:10;
-       unsigned obj_id:18;
-       unsigned ecc:12;
-       unsigned n_bytes_msb:2;
+       u32 chunk_id:20;
+       u32 serial_number:2;
+       u32 n_bytes_lsb:10;
+       u32 obj_id:18;
+       u32 ecc:12;
+       u32 n_bytes_msb:2;
 };
 
 union yaffs_tags_union {
@@ -287,9 +287,9 @@ enum yaffs_block_state {
 
 struct yaffs_block_info {
 
-       int soft_del_pages:10;  /* number of soft deleted pages */
-       int pages_in_use:10;    /* number of pages in use */
-       unsigned block_state:4; /* One of the above block states. */
+       s32 soft_del_pages:10;  /* number of soft deleted pages */
+       s32 pages_in_use:10;    /* number of pages in use */
+       u32 block_state:4;      /* One of the above block states. */
                                /* NB use unsigned because enum is sometimes
                                 * an int */
        u32 needs_retiring:1;   /* Data has failed on this block, */
@@ -688,8 +688,8 @@ struct yaffs_dev {
        /* Block Info */
        struct yaffs_block_info *block_info;
        u8 *chunk_bits;         /* bitmap of chunks in use */
-       unsigned block_info_alt:1;      /* allocated using alternative alloc */
-       unsigned chunk_bits_alt:1;      /* allocated using alternative alloc */
+       u8 block_info_alt:1;    /* allocated using alternative alloc */
+       u8 chunk_bits_alt:1;    /* allocated using alternative alloc */
        int chunk_bit_stride;   /* Number of bytes of chunk_bits per block.
                                 * Must be consistent with chunks_per_block.
                                 */
@@ -776,6 +776,7 @@ struct yaffs_dev {
        u32 n_page_writes;
        u32 n_page_reads;
        u32 n_erasures;
+       u32 n_bad_queries;
        u32 n_bad_markings;
        u32 n_erase_failures;
        u32 n_gc_copies;
@@ -854,6 +855,9 @@ int yaffs_rename_obj(struct yaffs_obj *old_dir, const YCHAR * old_name,
 
 int yaffs_unlinker(struct yaffs_obj *dir, const YCHAR * name);
 int yaffs_del_obj(struct yaffs_obj *obj);
+struct yaffs_obj *yaffs_retype_obj(struct yaffs_obj *obj,
+                                  enum yaffs_obj_type type);
+
 
 int yaffs_get_obj_name(struct yaffs_obj *obj, YCHAR * name, int buffer_size);
 loff_t yaffs_get_obj_length(struct yaffs_obj *obj);
@@ -872,10 +876,13 @@ struct yaffs_obj *yaffs_create_file(struct yaffs_obj *parent,
                                    const YCHAR *name, u32 mode, u32 uid,
                                    u32 gid);
 
-int yaffs_flush_file(struct yaffs_obj *obj, int update_time, int data_sync);
+int yaffs_flush_file(struct yaffs_obj *in,
+                    int update_time,
+                    int data_sync,
+                    int discard_cache);
 
 /* Flushing and checkpointing */
-void yaffs_flush_whole_cache(struct yaffs_dev *dev);
+void yaffs_flush_whole_cache(struct yaffs_dev *dev, int discard);
 
 int yaffs_checkpoint_save(struct yaffs_dev *dev);
 int yaffs_checkpoint_restore(struct yaffs_dev *dev);
@@ -978,7 +985,7 @@ u32 yaffs_get_group_base(struct yaffs_dev *dev, struct yaffs_tnode *tn,
 
 int yaffs_is_non_empty_dir(struct yaffs_obj *obj);
 
-int yaffs_format_dev(struct yaffs_dev *dev);
+int yaffs_guts_format_dev(struct yaffs_dev *dev);
 
 void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr,
                                int *chunk_out, u32 *offset_out);
index 7ae63c54a903d2032ecc72aba5640d24203a44f5..7c01461ab93de21de9e5e272ec5bcfd58504255c 100644 (file)
 #include "linux/kernel.h"
 #include "linux/version.h"
 #include "linux/types.h"
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
+#include "uapi/linux/major.h"
+#endif
 
 #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
index b80f0a5b15740f0e38deabd18400aef65667d470..3015d58a0743a8ee23b19f89ed3b49834e61314e 100644 (file)
 #include "yaffs_guts.h"
 
 struct yaffs_packed_tags1 {
-       unsigned chunk_id:20;
-       unsigned serial_number:2;
-       unsigned n_bytes:10;
-       unsigned obj_id:18;
-       unsigned ecc:12;
-       unsigned deleted:1;
-       unsigned unused_stuff:1;
+       u32 chunk_id:20;
+       u32 serial_number:2;
+       u32 n_bytes:10;
+       u32 obj_id:18;
+       u32 ecc:12;
+       u32 deleted:1;
+       u32 unused_stuff:1;
        unsigned should_be_ff;
 
 };
index 6f3c7839fa6fb25556a9065bea3ccdfb1ea588b3..3c9e72321ea4ce6c4d03a545c34a0d6948cc8160 100644 (file)
@@ -235,7 +235,6 @@ int yaffs_summary_read(struct yaffs_dev *dev,
        if (result == YAFFS_OK) {
                /* Verify header */
                if (hdr.version != YAFFS_SUMMARY_VERSION ||
-                   hdr.block != blk ||
                    hdr.seq != bi->seq_number ||
                    hdr.sum != yaffs_summary_sum(dev))
                        result = YAFFS_FAIL;
index 67050d4e3d2c1f7dd7b88a946567968a203ee251..76bc1db59f19ea5dffbc3234da46e6295a14cc8f 100644 (file)
@@ -236,6 +236,15 @@ MODULE_PARM(yaffs_gc_control, "i");
 #define Y_CLEAR_INODE(i) end_writeback(i)
 #endif
 
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
+#define YAFFS_USE_DIR_ITERATE
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0))
+#define YAFFS_NEW_PROCFS
+#include <linux/seq_file.h>
+#endif
+
 
 #define update_dir_time(dir) do {\
                        (dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \
@@ -1023,7 +1032,11 @@ static int yaffs_readlink(struct dentry *dentry, char __user * buffer,
        if (!alias)
                return -ENOMEM;
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)
        ret = vfs_readlink(dentry, buffer, buflen, alias);
+#else
+       ret = readlink_copy(buffer, buflen, alias);
+#endif
        kfree(alias);
        return ret;
 }
@@ -1206,6 +1219,23 @@ struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,
 #define YCRED(x) (x->cred)
 #endif
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
+#define YPROC_uid(p) (YCRED(p)->fsuid)
+#define YPROC_gid(p) (YCRED(p)->fsgid)
+#define EXTRACT_gid(x) x
+#define EXTRACT_uid(x) x
+#define MAKE_gid(x) x
+#define MAKE_uid(x) x
+#else
+#define YPROC_uid(p) from_kuid(&init_user_ns, YCRED(p)->fsuid)
+#define YPROC_gid(p) from_kgid(&init_user_ns, YCRED(p)->fsgid)
+#define EXTRACT_gid(x) from_kgid(&init_user_ns, x)
+#define EXTRACT_uid(x) from_kuid(&init_user_ns, x)
+#define MAKE_gid(x) make_kgid(&init_user_ns, x)
+#define MAKE_uid(x) make_kuid(&init_user_ns, x)
+#endif
+
+
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
 static int yaffs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
                       dev_t rdev)
@@ -1225,9 +1255,9 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
        struct yaffs_obj *parent = yaffs_inode_to_obj(dir);
 
        int error = -ENOSPC;
-       uid_t uid = YCRED(current)->fsuid;
+       uid_t uid = YPROC_uid(current);
        gid_t gid =
-           (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
+           (dir->i_mode & S_ISGID) ? EXTRACT_gid(dir->i_gid) : YPROC_gid(current);
 
        if ((dir->i_mode & S_ISGID) && S_ISDIR(mode))
                mode |= S_ISGID;
@@ -1424,9 +1454,9 @@ static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
 {
        struct yaffs_obj *obj;
        struct yaffs_dev *dev;
-       uid_t uid = YCRED(current)->fsuid;
+       uid_t uid = YPROC_uid(current);
        gid_t gid =
-           (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
+           (dir->i_mode & S_ISGID) ? EXTRACT_gid(dir->i_gid) : YPROC_gid(current);
 
        yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink");
 
@@ -1674,6 +1704,77 @@ static void yaffs_remove_obj_callback(struct yaffs_obj *obj)
 
 /*-----------------------------------------------------------------*/
 
+#ifdef YAFFS_USE_DIR_ITERATE
+static int yaffs_iterate(struct file *f, struct dir_context *dc)
+{
+       struct yaffs_obj *obj;
+       struct yaffs_dev *dev;
+       struct yaffs_search_context *sc;
+       unsigned long curoffs;
+       struct yaffs_obj *l;
+       int ret_val = 0;
+
+       char name[YAFFS_MAX_NAME_LENGTH + 1];
+
+       obj = yaffs_dentry_to_obj(f->f_dentry);
+       dev = obj->my_dev;
+
+       yaffs_gross_lock(dev);
+
+       yaffs_dev_to_lc(dev)->readdir_process = current;
+
+       sc = yaffs_new_search(obj);
+       if (!sc) {
+               ret_val = -ENOMEM;
+               goto out;
+       }
+
+       if (!dir_emit_dots(f, dc))
+               return 0;
+
+       curoffs = 1;
+
+       while (sc->next_return) {
+               curoffs++;
+               l = sc->next_return;
+               if (curoffs >= dc->pos) {
+                       int this_inode = yaffs_get_obj_inode(l);
+                       int this_type = yaffs_get_obj_type(l);
+
+                       yaffs_get_obj_name(l, name, YAFFS_MAX_NAME_LENGTH + 1);
+                       yaffs_trace(YAFFS_TRACE_OS,
+                               "yaffs_readdir: %s inode %d",
+                               name, yaffs_get_obj_inode(l));
+
+                       yaffs_gross_unlock(dev);
+
+                       if (!dir_emit(dc,
+                                     name,
+                                     strlen(name),
+                                     this_inode,
+                                     this_type)) {
+                               yaffs_gross_lock(dev);
+                               goto out;
+                       }
+
+                       yaffs_gross_lock(dev);
+
+                       dc->pos++;
+                       f->f_pos++;
+               }
+               yaffs_search_advance(sc);
+       }
+
+out:
+       yaffs_search_end(sc);
+       yaffs_dev_to_lc(dev)->readdir_process = NULL;
+       yaffs_gross_unlock(dev);
+
+       return ret_val;
+}
+
+#else
+
 static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
 {
        struct yaffs_obj *obj;
@@ -1781,9 +1882,15 @@ out:
        return ret_val;
 }
 
+#endif
+
 static const struct file_operations yaffs_dir_operations = {
        .read = generic_read_dir,
+#ifdef YAFFS_USE_DIR_ITERATE
+       .iterate = yaffs_iterate,
+#else
        .readdir = yaffs_readdir,
+#endif
        .fsync = yaffs_sync_object,
        .llseek = generic_file_llseek,
 };
@@ -1829,8 +1936,8 @@ static void yaffs_fill_inode_from_obj(struct inode *inode,
 
                inode->i_ino = obj->obj_id;
                inode->i_mode = obj->yst_mode;
-               inode->i_uid = obj->yst_uid;
-               inode->i_gid = obj->yst_gid;
+               inode->i_uid = MAKE_uid(obj->yst_uid);
+               inode->i_gid = MAKE_gid(obj->yst_gid);
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
                inode->i_blksize = inode->i_sb->s_blocksize;
 #endif
@@ -1856,7 +1963,7 @@ static void yaffs_fill_inode_from_obj(struct inode *inode,
 
                yaffs_trace(YAFFS_TRACE_OS,
                        "yaffs_fill_inode mode %x uid %d gid %d size %lld count %d",
-                       inode->i_mode, inode->i_uid, inode->i_gid,
+                       inode->i_mode, obj->yst_uid, obj->yst_gid,
                        inode->i_size, atomic_read(&inode->i_count));
 
                switch (obj->yst_mode & S_IFMT) {
@@ -2670,7 +2777,7 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
 
        /* Get the device */
        mtd = get_mtd_device(NULL, MINOR(sb->s_dev));
-       if (!mtd) {
+       if (IS_ERR(mtd)) {
                yaffs_trace(YAFFS_TRACE_ALWAYS,
                        "yaffs: MTD device %u either not valid or unavailable",
                        MINOR(sb->s_dev));
@@ -2713,15 +2820,11 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
        context = kmalloc(sizeof(struct yaffs_linux_context), GFP_KERNEL);
 
        if (!dev || !context) {
-               if (dev)
-                       kfree(dev);
-               if (context)
-                       kfree(context);
+               kfree(dev);
+               kfree(context);
                dev = NULL;
                context = NULL;
-       }
 
-       if (!dev) {
                /* Deep shit could not allocate device structure */
                yaffs_trace(YAFFS_TRACE_ALWAYS,
                        "yaffs_read_super: Failed trying to allocate struct yaffs_dev."
@@ -3188,7 +3291,7 @@ static struct {
 
 #define MAX_MASK_NAME_LENGTH 40
 static int yaffs_proc_write_trace_options(struct file *file, const char *buf,
-                                         unsigned long count, void *data)
+                                         unsigned long count)
 {
        unsigned rg = 0, mask_bitfield;
        char *end;
@@ -3289,7 +3392,7 @@ static int yaffs_proc_write_trace_options(struct file *file, const char *buf,
  */
 
 static int yaffs_proc_debug_write(struct file *file, const char *buf,
-                                         unsigned long count, void *data)
+                                         unsigned long count)
 {
 
        char str[100];
@@ -3301,7 +3404,7 @@ static int yaffs_proc_debug_write(struct file *file, const char *buf,
        struct list_head *item;
 
        memset(str, 0, sizeof(str));
-       memcpy(str, buf, min(count, sizeof(str) -1));
+       memcpy(str, buf, min((size_t)count, sizeof(str) -1));
 
        cmd = str[1];
 
@@ -3364,12 +3467,18 @@ static int yaffs_proc_debug_write(struct file *file, const char *buf,
        return count;
 }
 
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
 static int yaffs_proc_write(struct file *file, const char *buf,
-                           unsigned long count, void *data)
+                           unsigned long count, void *ppos)
+#else
+static ssize_t yaffs_proc_write(struct file *file, const char __user *buf,
+                           size_t count, loff_t *ppos)
+#endif
 {
        if (buf[0] == '.')
-               return yaffs_proc_debug_write(file, buf, count, data);
-       return yaffs_proc_write_trace_options(file, buf, count, data);
+               return yaffs_proc_debug_write(file, buf, count);
+       return yaffs_proc_write_trace_options(file, buf, count);
 }
 
 /* Stuff to handle installation of file systems */
@@ -3384,16 +3493,52 @@ static struct file_system_to_install fs_to_install[] = {
        {NULL, 0}
 };
 
-static int __init init_yaffs_fs(void)
+
+#ifdef YAFFS_NEW_PROCFS
+static int yaffs_proc_show(struct seq_file *m, void *v)
 {
-       int error = 0;
-       struct file_system_to_install *fsinst;
+       /* FIXME: Unify in a better way? */
+       char buffer[512];
+       char *start;
+       int len;
 
-       yaffs_trace(YAFFS_TRACE_ALWAYS,
-               "yaffs built " __DATE__ " " __TIME__ " Installing.");
+       len = yaffs_proc_read(buffer, &start, 0, sizeof(buffer), NULL, NULL);
+       seq_puts(m, buffer);
+       return 0;
+}
+
+static int yaffs_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, yaffs_proc_show, NULL);
+}
+
+static struct file_operations procfs_ops = {
+       .owner = THIS_MODULE,
+       .open  = yaffs_proc_open,
+       .read  = seq_read,
+       .write = yaffs_proc_write,
+};
+
+static int yaffs_procfs_init(void)
+{
+       /* Install the proc_fs entries */
+       my_proc_entry = proc_create("yaffs",
+                                   S_IRUGO | S_IFREG,
+                                   YPROC_ROOT,
+                                   &procfs_ops);
+
+       if (my_proc_entry) {
+               return 0;
+       } else {
+               return -ENOMEM;
+       }
+}
+
+#else
 
-       mutex_init(&yaffs_context_lock);
 
+static int yaffs_procfs_init(void)
+{
        /* Install the proc_fs entries */
        my_proc_entry = create_proc_entry("yaffs",
                                          S_IRUGO | S_IFREG, YPROC_ROOT);
@@ -3402,9 +3547,28 @@ static int __init init_yaffs_fs(void)
                my_proc_entry->write_proc = yaffs_proc_write;
                my_proc_entry->read_proc = yaffs_proc_read;
                my_proc_entry->data = NULL;
+               return 0;
        } else {
                return -ENOMEM;
-        }
+       }
+}
+
+#endif
+
+
+static int __init init_yaffs_fs(void)
+{
+       int error = 0;
+       struct file_system_to_install *fsinst;
+
+       yaffs_trace(YAFFS_TRACE_ALWAYS,
+               "yaffs built " __DATE__ " " __TIME__ " Installing.");
+
+       mutex_init(&yaffs_context_lock);
+
+       error = yaffs_procfs_init();
+       if (error)
+               return error;
 
        /* Now add the file system entries */
 
index f1dc972276f78091b14a45e4ecfd54d1c406a5b1..8c31a661ff1d756778b25931233efa575f838b28 100644 (file)
@@ -1193,12 +1193,14 @@ static inline int yaffs2_scan_chunk(struct yaffs_dev *dev,
                }
 
                if (!in->valid && in->variant_type !=
-                   (oh ? oh->type : tags.extra_obj_type))
+                   (oh ? oh->type : tags.extra_obj_type)) {
                        yaffs_trace(YAFFS_TRACE_ERROR,
-                               "yaffs tragedy: Bad object type, %d != %d, for object %d at chunk %d during scan",
+                               "yaffs tragedy: Bad type, %d != %d, for object %d at chunk %d during scan",
                                oh ? oh->type : tags.extra_obj_type,
                                in->variant_type, tags.obj_id,
                                chunk);
+                       in = yaffs_retype_obj(in, oh ? oh->type : tags.extra_obj_type);
+               }
 
                if (!in->valid &&
                    (tags.obj_id == YAFFS_OBJECTID_ROOT ||
@@ -1439,7 +1441,7 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev)
                bi++;
        }
 
-       yaffs_trace(YAFFS_TRACE_SCAN, "%d blocks to be sorted...", n_to_scan);
+       yaffs_trace(YAFFS_TRACE_ALWAYS, "%d blocks to be sorted...", n_to_scan);
 
        cond_resched();
 
diff --git a/target/linux/generic/patches-3.14/501-yaffs-3.5-convert-to-use-kuid_t-kgid_t.patch b/target/linux/generic/patches-3.14/501-yaffs-3.5-convert-to-use-kuid_t-kgid_t.patch
deleted file mode 100644 (file)
index c1f7367..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
---- a/fs/yaffs2/yaffs_vfs.c
-+++ b/fs/yaffs2/yaffs_vfs.c
-@@ -329,6 +329,33 @@ static int yaffs_readpage(struct file *f
-       return ret;
- }
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
-+#define YCRED_FSUID() from_kuid(&init_user_ns, current_fsuid())
-+#define YCRED_FSGID() from_kgid(&init_user_ns, current_fsgid())
-+#else
-+#define YCRED_FSUID() YCRED(current)->fsuid
-+#define YCRED_FSGID() YCRED(current)->fsgid
-+
-+static inline uid_t i_uid_read(const struct inode *inode)
-+{
-+      return inode->i_uid;
-+}
-+
-+static inline gid_t i_gid_read(const struct inode *inode)
-+{
-+      return inode->i_gid;
-+}
-+
-+static inline void i_uid_write(struct inode *inode, uid_t uid)
-+{
-+      inode->i_uid = uid;
-+}
-+
-+static inline void i_gid_write(struct inode *inode, gid_t gid)
-+{
-+      inode->i_gid = gid;
-+}
-+#endif
- static void yaffs_set_super_dirty_val(struct yaffs_dev *dev, int val)
- {
-@@ -1225,9 +1252,9 @@ static int yaffs_mknod(struct inode *dir
-       struct yaffs_obj *parent = yaffs_inode_to_obj(dir);
-       int error = -ENOSPC;
--      uid_t uid = YCRED(current)->fsuid;
-+      uid_t uid = YCRED_FSUID();
-       gid_t gid =
--          (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
-+          (dir->i_mode & S_ISGID) ? i_gid_read(dir) : YCRED_FSGID();
-       if ((dir->i_mode & S_ISGID) && S_ISDIR(mode))
-               mode |= S_ISGID;
-@@ -1424,9 +1451,9 @@ static int yaffs_symlink(struct inode *d
- {
-       struct yaffs_obj *obj;
-       struct yaffs_dev *dev;
--      uid_t uid = YCRED(current)->fsuid;
-+      uid_t uid = YCRED_FSUID();
-       gid_t gid =
--          (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
-+          (dir->i_mode & S_ISGID) ? i_gid_read(dir) : YCRED_FSGID();
-       yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink");
-@@ -1829,8 +1856,8 @@ static void yaffs_fill_inode_from_obj(st
-               inode->i_ino = obj->obj_id;
-               inode->i_mode = obj->yst_mode;
--              inode->i_uid = obj->yst_uid;
--              inode->i_gid = obj->yst_gid;
-+              i_uid_write(inode, obj->yst_uid);
-+              i_gid_write(inode, obj->yst_gid);
- #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
-               inode->i_blksize = inode->i_sb->s_blocksize;
- #endif
-@@ -1856,7 +1883,7 @@ static void yaffs_fill_inode_from_obj(st
-               yaffs_trace(YAFFS_TRACE_OS,
-                       "yaffs_fill_inode mode %x uid %d gid %d size %lld count %d",
--                      inode->i_mode, inode->i_uid, inode->i_gid,
-+                      inode->i_mode, i_uid_read(inode), i_gid_read(inode),
-                       inode->i_size, atomic_read(&inode->i_count));
-               switch (obj->yst_mode & S_IFMT) {
---- a/fs/yaffs2/yaffs_attribs.c
-+++ b/fs/yaffs2/yaffs_attribs.c
-@@ -14,6 +14,48 @@
- #include "yaffs_guts.h"
- #include "yaffs_attribs.h"
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
-+static inline uid_t ia_uid_read(const struct iattr *iattr)
-+{
-+      return from_kuid(&init_user_ns, iattr->ia_uid);
-+}
-+
-+static inline gid_t ia_gid_read(const struct iattr *iattr)
-+{
-+      return from_kgid(&init_user_ns, iattr->ia_gid);
-+}
-+
-+static inline void ia_uid_write(struct iattr *iattr, uid_t uid)
-+{
-+      iattr->ia_uid = make_kuid(&init_user_ns, uid);
-+}
-+
-+static inline void ia_gid_write(struct iattr *iattr, gid_t gid)
-+{
-+      iattr->ia_gid = make_kgid(&init_user_ns, gid);
-+}
-+#else
-+static inline uid_t ia_uid_read(const struct iattr *iattr)
-+{
-+      return iattr->ia_uid;
-+}
-+
-+static inline gid_t ia_gid_read(const struct iattr *inode)
-+{
-+      return iattr->ia_gid;
-+}
-+
-+static inline void ia_uid_write(struct iattr *iattr, uid_t uid)
-+{
-+      iattr->ia_uid = uid;
-+}
-+
-+static inline void ia_gid_write(struct iattr *iattr, gid_t gid)
-+{
-+      iattr->ia_gid = gid;
-+}
-+#endif
-+
- void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh)
- {
-       obj->yst_uid = oh->yst_uid;
-@@ -77,9 +119,9 @@ int yaffs_set_attribs(struct yaffs_obj *
-       if (valid & ATTR_MODE)
-               obj->yst_mode = attr->ia_mode;
-       if (valid & ATTR_UID)
--              obj->yst_uid = attr->ia_uid;
-+              obj->yst_uid =  ia_uid_read(attr);
-       if (valid & ATTR_GID)
--              obj->yst_gid = attr->ia_gid;
-+              obj->yst_gid =  ia_gid_read(attr);
-       if (valid & ATTR_ATIME)
-               obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
-@@ -103,9 +145,9 @@ int yaffs_get_attribs(struct yaffs_obj *
-       attr->ia_mode = obj->yst_mode;
-       valid |= ATTR_MODE;
--      attr->ia_uid = obj->yst_uid;
-+      ia_uid_write(attr, obj->yst_uid);
-       valid |= ATTR_UID;
--      attr->ia_gid = obj->yst_gid;
-+      ia_gid_write(attr, obj->yst_gid);
-       valid |= ATTR_GID;
-       Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime;
diff --git a/target/linux/generic/patches-3.14/501-yaffs-add-missing-flush-arguments.patch b/target/linux/generic/patches-3.14/501-yaffs-add-missing-flush-arguments.patch
new file mode 100644 (file)
index 0000000..d5ccc3e
--- /dev/null
@@ -0,0 +1,38 @@
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -738,7 +738,7 @@ static int yaffs_file_flush(struct file
+       yaffs_gross_lock(dev);
+-      yaffs_flush_file(obj, 1, 0);
++      yaffs_flush_file(obj, 1, 0, 1);
+       yaffs_gross_unlock(dev);
+@@ -768,7 +768,7 @@ static int yaffs_sync_object(struct file
+       yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC,
+               "yaffs_sync_object");
+       yaffs_gross_lock(dev);
+-      yaffs_flush_file(obj, 1, datasync);
++      yaffs_flush_file(obj, 1, datasync, 1);
+       yaffs_gross_unlock(dev);
+       return 0;
+ }
+@@ -2187,7 +2187,7 @@ static void yaffs_flush_inodes(struct su
+                       yaffs_trace(YAFFS_TRACE_OS,
+                               "flushing obj %d",
+                               obj->obj_id);
+-                      yaffs_flush_file(obj, 1, 0);
++                      yaffs_flush_file(obj, 1, 0, 1);
+               }
+       }
+ }
+@@ -2200,7 +2200,7 @@ static void yaffs_flush_super(struct sup
+       yaffs_flush_inodes(sb);
+       yaffs_update_dirty_dirs(dev);
+-      yaffs_flush_whole_cache(dev);
++      yaffs_flush_whole_cache(dev, 1);
+       if (do_checkpoint)
+               yaffs_checkpoint_save(dev);
+ }
diff --git a/target/linux/generic/patches-3.14/502-yaffs-3.10-disable-proc-entry.patch b/target/linux/generic/patches-3.14/502-yaffs-3.10-disable-proc-entry.patch
deleted file mode 100644 (file)
index 5b73d38..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
---- a/fs/yaffs2/yaffs_vfs.c
-+++ b/fs/yaffs2/yaffs_vfs.c
-@@ -3025,6 +3025,7 @@ static DECLARE_FSTYPE(yaffs2_fs_type, "y
- #endif
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
- static struct proc_dir_entry *my_proc_entry;
- static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev)
-@@ -3398,6 +3399,7 @@ static int yaffs_proc_write(struct file
-               return yaffs_proc_debug_write(file, buf, count, data);
-       return yaffs_proc_write_trace_options(file, buf, count, data);
- }
-+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)) */
- /* Stuff to handle installation of file systems */
- struct file_system_to_install {
-@@ -3421,6 +3423,7 @@ static int __init init_yaffs_fs(void)
-       mutex_init(&yaffs_context_lock);
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
-       /* Install the proc_fs entries */
-       my_proc_entry = create_proc_entry("yaffs",
-                                         S_IRUGO | S_IFREG, YPROC_ROOT);
-@@ -3432,6 +3435,7 @@ static int __init init_yaffs_fs(void)
-       } else {
-               return -ENOMEM;
-         }
-+#endif
-       /* Now add the file system entries */
-@@ -3468,7 +3472,9 @@ static void __exit exit_yaffs_fs(void)
-       yaffs_trace(YAFFS_TRACE_ALWAYS,
-               "yaffs built " __DATE__ " " __TIME__ " removing.");
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
-       remove_proc_entry("yaffs", YPROC_ROOT);
-+#endif
-       fsinst = fs_to_install;
diff --git a/target/linux/generic/patches-3.14/502-yaffs-fix-compat-tags-handling.patch b/target/linux/generic/patches-3.14/502-yaffs-fix-compat-tags-handling.patch
new file mode 100644 (file)
index 0000000..a18cf6f
--- /dev/null
@@ -0,0 +1,239 @@
+Subject: yaffs: fix compat tags handling
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+--- a/fs/yaffs2/yaffs_tagscompat.c
++++ b/fs/yaffs2/yaffs_tagscompat.c
+@@ -17,7 +17,9 @@
+ #include "yaffs_getblockinfo.h"
+ #include "yaffs_trace.h"
++#if 0
+ static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk);
++#endif
+ /********** Tags ECC calculations  *********/
+@@ -71,6 +73,7 @@ int yaffs_check_tags_ecc(struct yaffs_ta
+       return 0;
+ }
++#if 0
+ /********** Tags **********/
+ static void yaffs_load_tags_to_spare(struct yaffs_spare *spare_ptr,
+@@ -379,3 +382,214 @@ void yaffs_tags_compat_install(struct ya
+       if(!dev->tagger.mark_bad_fn)
+               dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad;
+ }
++#else
++
++#include "yaffs_packedtags1.h"
++
++static int yaffs_tags_compat_write(struct yaffs_dev *dev,
++                                 int nand_chunk,
++                                 const u8 *data,
++                                 const struct yaffs_ext_tags *tags)
++{
++      struct yaffs_packed_tags1 pt1;
++      u8 tag_buf[9];
++      int retval;
++
++      /* we assume that yaffs_packed_tags1 and yaffs_tags are compatible */
++      compile_time_assertion(sizeof(struct yaffs_packed_tags1) == 12);
++      compile_time_assertion(sizeof(struct yaffs_tags) == 8);
++
++      yaffs_pack_tags1(&pt1, tags);
++      yaffs_calc_tags_ecc((struct yaffs_tags *)&pt1);
++
++      /* When deleting a chunk, the upper layer provides only skeletal
++       * tags, one with is_deleted set.  However, we need to update the
++       * tags, not erase them completely.  So we use the NAND write property
++       * that only zeroed-bits stick and set tag bytes to all-ones and
++       * zero just the (not) deleted bit.
++       */
++      if (!dev->param.tags_9bytes) {
++              if (tags->is_deleted) {
++                      memset(&pt1, 0xff, 8);
++                      /* clear delete status bit to indicate deleted */
++                      pt1.deleted = 0;
++              }
++              memcpy(tag_buf, &pt1, 8);
++      } else {
++              if (tags->is_deleted) {
++                      memset(tag_buf, 0xff, 8);
++                      tag_buf[8] = 0;
++              } else {
++                      memcpy(tag_buf, &pt1, 8);
++                      tag_buf[8] = 0xff;
++              }
++      }
++
++      retval = dev->drv.drv_write_chunk_fn(dev, nand_chunk,
++                      data,
++                      (data) ? dev->data_bytes_per_chunk : 0,
++                      tag_buf,
++                      (dev->param.tags_9bytes) ? 9 : 8);
++
++      return retval;
++}
++
++/* Return with empty extended tags but add ecc_result.
++ */
++static int return_empty_tags(struct yaffs_ext_tags *tags,
++                           enum yaffs_ecc_result ecc_result,
++                           int retval)
++{
++      if (tags) {
++              memset(tags, 0, sizeof(*tags));
++              tags->ecc_result = ecc_result;
++      }
++
++      return retval;
++}
++
++static int yaffs_tags_compat_read(struct yaffs_dev *dev,
++                                int nand_chunk,
++                                u8 *data,
++                                struct yaffs_ext_tags *tags)
++{
++      struct yaffs_packed_tags1 pt1;
++      enum yaffs_ecc_result ecc_result;
++      int retval;
++      int deleted;
++      u8 tag_buf[9];
++
++      retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk,
++                      data, dev->param.total_bytes_per_chunk,
++                      tag_buf,
++                      (dev->param.tags_9bytes) ? 9 : 8,
++                      &ecc_result);
++
++      switch (ecc_result) {
++      case YAFFS_ECC_RESULT_NO_ERROR:
++      case YAFFS_ECC_RESULT_FIXED:
++              break;
++
++      case YAFFS_ECC_RESULT_UNFIXED:
++      default:
++              return_empty_tags(tags, YAFFS_ECC_RESULT_UNFIXED, 0);
++              tags->block_bad = dev->drv.drv_check_bad_fn(dev, nand_chunk);
++              return YAFFS_FAIL;
++      }
++
++      /* Check for a blank/erased chunk. */
++      if (yaffs_check_ff(tag_buf, 8)) {
++              /* when blank, upper layers want ecc_result to be <= NO_ERROR */
++              return return_empty_tags(tags, YAFFS_ECC_RESULT_NO_ERROR,
++                                       YAFFS_OK);
++      }
++
++      memcpy(&pt1, tag_buf, 8);
++
++      if (!dev->param.tags_9bytes) {
++              /* Read deleted status (bit) then return it to it's non-deleted
++               * state before performing tags mini-ECC check. pt1.deleted is
++               * inverted.
++               */
++              deleted = !pt1.deleted;
++              pt1.deleted = 1;
++      } else {
++              deleted = (hweight8(tag_buf[8]) < 7) ? 1 : 0;
++      }
++
++      /* Check the packed tags mini-ECC and correct if necessary/possible. */
++      retval = yaffs_check_tags_ecc((struct yaffs_tags *)&pt1);
++      switch (retval) {
++      case 0:
++              /* no tags error, use MTD result */
++              break;
++      case 1:
++              /* recovered tags-ECC error */
++              dev->n_tags_ecc_fixed++;
++              if (ecc_result == YAFFS_ECC_RESULT_NO_ERROR)
++                      ecc_result = YAFFS_ECC_RESULT_FIXED;
++              break;
++      default:
++              /* unrecovered tags-ECC error */
++              dev->n_tags_ecc_unfixed++;
++              return return_empty_tags(tags, YAFFS_ECC_RESULT_UNFIXED,
++                                       YAFFS_FAIL);
++      }
++
++      /* Unpack the tags to extended form and set ECC result.
++       * [set should_be_ff just to keep yaffs_unpack_tags1 happy]
++       */
++      pt1.should_be_ff = 0xffffffff;
++      yaffs_unpack_tags1(tags, &pt1);
++      tags->ecc_result = ecc_result;
++
++      /* Set deleted state */
++      tags->is_deleted = deleted;
++      return YAFFS_OK;
++}
++
++static int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int block_no)
++{
++      return dev->drv.drv_mark_bad_fn(dev, block_no);
++}
++
++static int yaffs_tags_compat_query_block(struct yaffs_dev *dev,
++                                       int block_no,
++                                       enum yaffs_block_state *state,
++                                       u32 *seq_number)
++{
++      struct yaffs_ext_tags tags;
++      int retval;
++
++      yaffs_trace(YAFFS_TRACE_MTD, "%s %d", __func__, block_no);
++
++      *seq_number = 0;
++
++      retval = dev->drv.drv_check_bad_fn(dev, block_no);
++      if (retval == YAFFS_FAIL) {
++              *state = YAFFS_BLOCK_STATE_DEAD;
++              goto out;
++      }
++
++      yaffs_tags_compat_read(dev, block_no * dev->param.chunks_per_block,
++                             NULL, &tags);
++
++      if (tags.ecc_result != YAFFS_ECC_RESULT_NO_ERROR) {
++              yaffs_trace(YAFFS_TRACE_MTD, "block %d is marked bad",
++                          block_no);
++              *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
++      } else if (tags.chunk_used) {
++              *seq_number = tags.seq_number;
++              *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
++      } else {
++              *state = YAFFS_BLOCK_STATE_EMPTY;
++      }
++
++      retval = YAFFS_OK;
++
++out:
++      yaffs_trace(YAFFS_TRACE_MTD,
++                  "block query returns seq %u state %d",
++                  *seq_number, *state);
++
++      return retval;
++}
++
++void yaffs_tags_compat_install(struct yaffs_dev *dev)
++{
++      if (dev->param.is_yaffs2)
++              return;
++
++      if (!dev->tagger.write_chunk_tags_fn)
++              dev->tagger.write_chunk_tags_fn = yaffs_tags_compat_write;
++
++      if (!dev->tagger.read_chunk_tags_fn)
++              dev->tagger.read_chunk_tags_fn = yaffs_tags_compat_read;
++
++      if (!dev->tagger.query_block_fn)
++              dev->tagger.query_block_fn = yaffs_tags_compat_query_block;
++
++      if (!dev->tagger.mark_bad_fn)
++              dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad;
++}
++#endif
diff --git a/target/linux/generic/patches-3.14/503-yaffs-3.12-convert-readdir-to-iterate.patch b/target/linux/generic/patches-3.14/503-yaffs-3.12-convert-readdir-to-iterate.patch
deleted file mode 100644 (file)
index 586c141..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
---- a/fs/yaffs2/yaffs_vfs.c
-+++ b/fs/yaffs2/yaffs_vfs.c
-@@ -1701,6 +1701,110 @@ static void yaffs_remove_obj_callback(st
- /*-----------------------------------------------------------------*/
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
-+static int yaffs_readdir(struct file *file, struct dir_context *ctx)
-+{
-+      struct yaffs_obj *obj;
-+      struct yaffs_dev *dev;
-+      struct yaffs_search_context *sc;
-+      struct inode *inode = file->f_dentry->d_inode;
-+      unsigned long offset, curoffs;
-+      struct yaffs_obj *l;
-+      int ret_val = 0;
-+
-+      char name[YAFFS_MAX_NAME_LENGTH + 1];
-+
-+      obj = yaffs_dentry_to_obj(file->f_dentry);
-+      dev = obj->my_dev;
-+
-+      yaffs_gross_lock(dev);
-+
-+      yaffs_dev_to_lc(dev)->readdir_process = current;
-+
-+      offset = ctx->pos;
-+
-+      sc = yaffs_new_search(obj);
-+      if (!sc) {
-+              ret_val = -ENOMEM;
-+              goto out;
-+      }
-+
-+      yaffs_trace(YAFFS_TRACE_OS,
-+              "yaffs_readdir: starting at %d", (int)offset);
-+
-+      if (offset == 0) {
-+              yaffs_trace(YAFFS_TRACE_OS,
-+                      "yaffs_readdir: entry . ino %d",
-+                      (int)inode->i_ino);
-+              yaffs_gross_unlock(dev);
-+              if (!dir_emit_dot(file, ctx)) {
-+                      yaffs_gross_lock(dev);
-+                      goto out;
-+              }
-+              yaffs_gross_lock(dev);
-+              offset++;
-+              ctx->pos++;
-+      }
-+      if (offset == 1) {
-+              yaffs_trace(YAFFS_TRACE_OS,
-+                      "yaffs_readdir: entry .. ino %d",
-+                      (int)file->f_dentry->d_parent->d_inode->i_ino);
-+              yaffs_gross_unlock(dev);
-+              if (!dir_emit_dotdot(file, ctx)) {
-+                      yaffs_gross_lock(dev);
-+                      goto out;
-+              }
-+              yaffs_gross_lock(dev);
-+              offset++;
-+              ctx->pos++;
-+      }
-+
-+      curoffs = 1;
-+
-+      /* If the directory has changed since the open or last call to
-+         readdir, rewind to after the 2 canned entries. */
-+      if (file->f_version != inode->i_version) {
-+              offset = 2;
-+              ctx->pos = offset;
-+              file->f_version = inode->i_version;
-+      }
-+
-+      while (sc->next_return) {
-+              curoffs++;
-+              l = sc->next_return;
-+              if (curoffs >= offset) {
-+                      int this_inode = yaffs_get_obj_inode(l);
-+                      int this_type = yaffs_get_obj_type(l);
-+
-+                      yaffs_get_obj_name(l, name, YAFFS_MAX_NAME_LENGTH + 1);
-+                      yaffs_trace(YAFFS_TRACE_OS,
-+                              "yaffs_readdir: %s inode %d",
-+                              name, yaffs_get_obj_inode(l));
-+
-+                      yaffs_gross_unlock(dev);
-+
-+                      if (!dir_emit(ctx, name, strlen(name),
-+                                    this_inode, this_type) < 0) {
-+                              yaffs_gross_lock(dev);
-+                              goto out;
-+                      }
-+
-+                      yaffs_gross_lock(dev);
-+
-+                      offset++;
-+                      ctx->pos++;
-+              }
-+              yaffs_search_advance(sc);
-+      }
-+
-+out:
-+      yaffs_search_end(sc);
-+      yaffs_dev_to_lc(dev)->readdir_process = NULL;
-+      yaffs_gross_unlock(dev);
-+
-+      return ret_val;
-+}
-+#else
- static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
- {
-       struct yaffs_obj *obj;
-@@ -1807,10 +1911,15 @@ out:
-       return ret_val;
- }
-+#endif
- static const struct file_operations yaffs_dir_operations = {
-       .read = generic_read_dir,
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
-+      .iterate = yaffs_readdir,
-+#else
-       .readdir = yaffs_readdir,
-+#endif
-       .fsync = yaffs_sync_object,
-       .llseek = generic_file_llseek,
- };
index 4858519ca1465b0e715438b8f51eb52aaa76225d..9ecaa72832238f8a1dca30787e8c48c2e66085dc 100644 (file)
@@ -4,7 +4,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
 ---
 --- a/fs/yaffs2/yaffs_vfs.c
 +++ b/fs/yaffs2/yaffs_vfs.c
-@@ -2634,6 +2634,7 @@ static const struct super_operations yaf
+@@ -2605,6 +2605,7 @@ static const struct super_operations yaf
  
  struct yaffs_options {
        int inband_tags;
@@ -12,7 +12,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
        int skip_checkpoint_read;
        int skip_checkpoint_write;
        int no_cache;
-@@ -2673,6 +2674,8 @@ static int yaffs_parse_options(struct ya
+@@ -2644,6 +2645,8 @@ static int yaffs_parse_options(struct ya
  
                if (!strcmp(cur_opt, "inband-tags")) {
                        options->inband_tags = 1;
@@ -21,7 +21,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
                } else if (!strcmp(cur_opt, "tags-ecc-off")) {
                        options->tags_ecc_on = 0;
                        options->tags_ecc_overridden = 1;
-@@ -2746,7 +2749,6 @@ static struct super_block *yaffs_interna
+@@ -2717,7 +2720,6 @@ static struct super_block *yaffs_interna
        struct yaffs_param *param;
  
        int read_only = 0;
@@ -29,7 +29,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
  
        struct yaffs_options options;
  
-@@ -2786,6 +2788,9 @@ static struct super_block *yaffs_interna
+@@ -2757,6 +2759,9 @@ static struct super_block *yaffs_interna
  
        memset(&options, 0, sizeof(options));
  
@@ -39,7 +39,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
        if (yaffs_parse_options(&options, data_str)) {
                /* Option parsing failed */
                return NULL;
-@@ -2819,17 +2824,22 @@ static struct super_block *yaffs_interna
+@@ -2790,17 +2795,22 @@ static struct super_block *yaffs_interna
        }
  
        /* Added NCB 26/5/2006 for completeness */
@@ -68,7 +68,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
                return NULL;
  
        /* OK, so if we got here, we have an MTD that's NAND and looks
-@@ -2890,7 +2900,8 @@ static struct super_block *yaffs_interna
+@@ -2857,7 +2867,8 @@ static struct super_block *yaffs_interna
  
        param->n_reserved_blocks = 5;
        param->n_caches = (options.no_cache) ? 0 : 10;
@@ -80,15 +80,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
        if (options.lazy_loading_overridden)
 --- a/fs/yaffs2/yaffs_mtdif.c
 +++ b/fs/yaffs2/yaffs_mtdif.c
-@@ -16,6 +16,7 @@
- #include "yaffs_mtdif.h"
- #include "linux/mtd/mtd.h"
-+#include "uapi/linux/major.h"
- #include "linux/types.h"
- #include "linux/time.h"
- #include "linux/mtd/nand.h"
-@@ -276,7 +277,8 @@ struct mtd_info * yaffs_get_mtd_device(d
+@@ -278,7 +278,8 @@ struct mtd_info * yaffs_get_mtd_device(d
        return mtd;
  }
  
@@ -98,7 +90,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
  {
        if (yaffs_version == 2) {
                if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
-@@ -295,6 +297,12 @@ int yaffs_verify_mtd(struct mtd_info *mt
+@@ -297,6 +298,12 @@ int yaffs_verify_mtd(struct mtd_info *mt
                        );
                        return -1;
                }
diff --git a/target/linux/generic/patches-3.14/504-yaffs-3.16-new-fops.patch b/target/linux/generic/patches-3.14/504-yaffs-3.16-new-fops.patch
new file mode 100644 (file)
index 0000000..11c6da0
--- /dev/null
@@ -0,0 +1,25 @@
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -774,7 +774,21 @@ static int yaffs_sync_object(struct file
+ }
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
++static const struct file_operations yaffs_file_operations = {
++      .read = new_sync_read,
++      .read_iter = generic_file_read_iter,
++      .write = new_sync_write,
++      .write_iter = generic_file_write_iter,
++      .mmap = generic_file_mmap,
++      .flush = yaffs_file_flush,
++      .fsync = yaffs_sync_object,
++      .splice_read = generic_file_splice_read,
++      .splice_write = iter_file_splice_write,
++      .llseek = generic_file_llseek,
++};
++
++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
+ static const struct file_operations yaffs_file_operations = {
+       .read = do_sync_read,
+       .write = do_sync_write,
diff --git a/target/linux/generic/patches-3.14/504-yaffs-fix-compat-tags-handling.patch b/target/linux/generic/patches-3.14/504-yaffs-fix-compat-tags-handling.patch
deleted file mode 100644 (file)
index a18cf6f..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-Subject: yaffs: fix compat tags handling
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
---- a/fs/yaffs2/yaffs_tagscompat.c
-+++ b/fs/yaffs2/yaffs_tagscompat.c
-@@ -17,7 +17,9 @@
- #include "yaffs_getblockinfo.h"
- #include "yaffs_trace.h"
-+#if 0
- static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk);
-+#endif
- /********** Tags ECC calculations  *********/
-@@ -71,6 +73,7 @@ int yaffs_check_tags_ecc(struct yaffs_ta
-       return 0;
- }
-+#if 0
- /********** Tags **********/
- static void yaffs_load_tags_to_spare(struct yaffs_spare *spare_ptr,
-@@ -379,3 +382,214 @@ void yaffs_tags_compat_install(struct ya
-       if(!dev->tagger.mark_bad_fn)
-               dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad;
- }
-+#else
-+
-+#include "yaffs_packedtags1.h"
-+
-+static int yaffs_tags_compat_write(struct yaffs_dev *dev,
-+                                 int nand_chunk,
-+                                 const u8 *data,
-+                                 const struct yaffs_ext_tags *tags)
-+{
-+      struct yaffs_packed_tags1 pt1;
-+      u8 tag_buf[9];
-+      int retval;
-+
-+      /* we assume that yaffs_packed_tags1 and yaffs_tags are compatible */
-+      compile_time_assertion(sizeof(struct yaffs_packed_tags1) == 12);
-+      compile_time_assertion(sizeof(struct yaffs_tags) == 8);
-+
-+      yaffs_pack_tags1(&pt1, tags);
-+      yaffs_calc_tags_ecc((struct yaffs_tags *)&pt1);
-+
-+      /* When deleting a chunk, the upper layer provides only skeletal
-+       * tags, one with is_deleted set.  However, we need to update the
-+       * tags, not erase them completely.  So we use the NAND write property
-+       * that only zeroed-bits stick and set tag bytes to all-ones and
-+       * zero just the (not) deleted bit.
-+       */
-+      if (!dev->param.tags_9bytes) {
-+              if (tags->is_deleted) {
-+                      memset(&pt1, 0xff, 8);
-+                      /* clear delete status bit to indicate deleted */
-+                      pt1.deleted = 0;
-+              }
-+              memcpy(tag_buf, &pt1, 8);
-+      } else {
-+              if (tags->is_deleted) {
-+                      memset(tag_buf, 0xff, 8);
-+                      tag_buf[8] = 0;
-+              } else {
-+                      memcpy(tag_buf, &pt1, 8);
-+                      tag_buf[8] = 0xff;
-+              }
-+      }
-+
-+      retval = dev->drv.drv_write_chunk_fn(dev, nand_chunk,
-+                      data,
-+                      (data) ? dev->data_bytes_per_chunk : 0,
-+                      tag_buf,
-+                      (dev->param.tags_9bytes) ? 9 : 8);
-+
-+      return retval;
-+}
-+
-+/* Return with empty extended tags but add ecc_result.
-+ */
-+static int return_empty_tags(struct yaffs_ext_tags *tags,
-+                           enum yaffs_ecc_result ecc_result,
-+                           int retval)
-+{
-+      if (tags) {
-+              memset(tags, 0, sizeof(*tags));
-+              tags->ecc_result = ecc_result;
-+      }
-+
-+      return retval;
-+}
-+
-+static int yaffs_tags_compat_read(struct yaffs_dev *dev,
-+                                int nand_chunk,
-+                                u8 *data,
-+                                struct yaffs_ext_tags *tags)
-+{
-+      struct yaffs_packed_tags1 pt1;
-+      enum yaffs_ecc_result ecc_result;
-+      int retval;
-+      int deleted;
-+      u8 tag_buf[9];
-+
-+      retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk,
-+                      data, dev->param.total_bytes_per_chunk,
-+                      tag_buf,
-+                      (dev->param.tags_9bytes) ? 9 : 8,
-+                      &ecc_result);
-+
-+      switch (ecc_result) {
-+      case YAFFS_ECC_RESULT_NO_ERROR:
-+      case YAFFS_ECC_RESULT_FIXED:
-+              break;
-+
-+      case YAFFS_ECC_RESULT_UNFIXED:
-+      default:
-+              return_empty_tags(tags, YAFFS_ECC_RESULT_UNFIXED, 0);
-+              tags->block_bad = dev->drv.drv_check_bad_fn(dev, nand_chunk);
-+              return YAFFS_FAIL;
-+      }
-+
-+      /* Check for a blank/erased chunk. */
-+      if (yaffs_check_ff(tag_buf, 8)) {
-+              /* when blank, upper layers want ecc_result to be <= NO_ERROR */
-+              return return_empty_tags(tags, YAFFS_ECC_RESULT_NO_ERROR,
-+                                       YAFFS_OK);
-+      }
-+
-+      memcpy(&pt1, tag_buf, 8);
-+
-+      if (!dev->param.tags_9bytes) {
-+              /* Read deleted status (bit) then return it to it's non-deleted
-+               * state before performing tags mini-ECC check. pt1.deleted is
-+               * inverted.
-+               */
-+              deleted = !pt1.deleted;
-+              pt1.deleted = 1;
-+      } else {
-+              deleted = (hweight8(tag_buf[8]) < 7) ? 1 : 0;
-+      }
-+
-+      /* Check the packed tags mini-ECC and correct if necessary/possible. */
-+      retval = yaffs_check_tags_ecc((struct yaffs_tags *)&pt1);
-+      switch (retval) {
-+      case 0:
-+              /* no tags error, use MTD result */
-+              break;
-+      case 1:
-+              /* recovered tags-ECC error */
-+              dev->n_tags_ecc_fixed++;
-+              if (ecc_result == YAFFS_ECC_RESULT_NO_ERROR)
-+                      ecc_result = YAFFS_ECC_RESULT_FIXED;
-+              break;
-+      default:
-+              /* unrecovered tags-ECC error */
-+              dev->n_tags_ecc_unfixed++;
-+              return return_empty_tags(tags, YAFFS_ECC_RESULT_UNFIXED,
-+                                       YAFFS_FAIL);
-+      }
-+
-+      /* Unpack the tags to extended form and set ECC result.
-+       * [set should_be_ff just to keep yaffs_unpack_tags1 happy]
-+       */
-+      pt1.should_be_ff = 0xffffffff;
-+      yaffs_unpack_tags1(tags, &pt1);
-+      tags->ecc_result = ecc_result;
-+
-+      /* Set deleted state */
-+      tags->is_deleted = deleted;
-+      return YAFFS_OK;
-+}
-+
-+static int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int block_no)
-+{
-+      return dev->drv.drv_mark_bad_fn(dev, block_no);
-+}
-+
-+static int yaffs_tags_compat_query_block(struct yaffs_dev *dev,
-+                                       int block_no,
-+                                       enum yaffs_block_state *state,
-+                                       u32 *seq_number)
-+{
-+      struct yaffs_ext_tags tags;
-+      int retval;
-+
-+      yaffs_trace(YAFFS_TRACE_MTD, "%s %d", __func__, block_no);
-+
-+      *seq_number = 0;
-+
-+      retval = dev->drv.drv_check_bad_fn(dev, block_no);
-+      if (retval == YAFFS_FAIL) {
-+              *state = YAFFS_BLOCK_STATE_DEAD;
-+              goto out;
-+      }
-+
-+      yaffs_tags_compat_read(dev, block_no * dev->param.chunks_per_block,
-+                             NULL, &tags);
-+
-+      if (tags.ecc_result != YAFFS_ECC_RESULT_NO_ERROR) {
-+              yaffs_trace(YAFFS_TRACE_MTD, "block %d is marked bad",
-+                          block_no);
-+              *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
-+      } else if (tags.chunk_used) {
-+              *seq_number = tags.seq_number;
-+              *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
-+      } else {
-+              *state = YAFFS_BLOCK_STATE_EMPTY;
-+      }
-+
-+      retval = YAFFS_OK;
-+
-+out:
-+      yaffs_trace(YAFFS_TRACE_MTD,
-+                  "block query returns seq %u state %d",
-+                  *seq_number, *state);
-+
-+      return retval;
-+}
-+
-+void yaffs_tags_compat_install(struct yaffs_dev *dev)
-+{
-+      if (dev->param.is_yaffs2)
-+              return;
-+
-+      if (!dev->tagger.write_chunk_tags_fn)
-+              dev->tagger.write_chunk_tags_fn = yaffs_tags_compat_write;
-+
-+      if (!dev->tagger.read_chunk_tags_fn)
-+              dev->tagger.read_chunk_tags_fn = yaffs_tags_compat_read;
-+
-+      if (!dev->tagger.query_block_fn)
-+              dev->tagger.query_block_fn = yaffs_tags_compat_query_block;
-+
-+      if (!dev->tagger.mark_bad_fn)
-+              dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad;
-+}
-+#endif
diff --git a/target/linux/generic/patches-3.18/501-yaffs-3.5-convert-to-use-kuid_t-kgid_t.patch b/target/linux/generic/patches-3.18/501-yaffs-3.5-convert-to-use-kuid_t-kgid_t.patch
deleted file mode 100644 (file)
index c1f7367..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
---- a/fs/yaffs2/yaffs_vfs.c
-+++ b/fs/yaffs2/yaffs_vfs.c
-@@ -329,6 +329,33 @@ static int yaffs_readpage(struct file *f
-       return ret;
- }
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
-+#define YCRED_FSUID() from_kuid(&init_user_ns, current_fsuid())
-+#define YCRED_FSGID() from_kgid(&init_user_ns, current_fsgid())
-+#else
-+#define YCRED_FSUID() YCRED(current)->fsuid
-+#define YCRED_FSGID() YCRED(current)->fsgid
-+
-+static inline uid_t i_uid_read(const struct inode *inode)
-+{
-+      return inode->i_uid;
-+}
-+
-+static inline gid_t i_gid_read(const struct inode *inode)
-+{
-+      return inode->i_gid;
-+}
-+
-+static inline void i_uid_write(struct inode *inode, uid_t uid)
-+{
-+      inode->i_uid = uid;
-+}
-+
-+static inline void i_gid_write(struct inode *inode, gid_t gid)
-+{
-+      inode->i_gid = gid;
-+}
-+#endif
- static void yaffs_set_super_dirty_val(struct yaffs_dev *dev, int val)
- {
-@@ -1225,9 +1252,9 @@ static int yaffs_mknod(struct inode *dir
-       struct yaffs_obj *parent = yaffs_inode_to_obj(dir);
-       int error = -ENOSPC;
--      uid_t uid = YCRED(current)->fsuid;
-+      uid_t uid = YCRED_FSUID();
-       gid_t gid =
--          (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
-+          (dir->i_mode & S_ISGID) ? i_gid_read(dir) : YCRED_FSGID();
-       if ((dir->i_mode & S_ISGID) && S_ISDIR(mode))
-               mode |= S_ISGID;
-@@ -1424,9 +1451,9 @@ static int yaffs_symlink(struct inode *d
- {
-       struct yaffs_obj *obj;
-       struct yaffs_dev *dev;
--      uid_t uid = YCRED(current)->fsuid;
-+      uid_t uid = YCRED_FSUID();
-       gid_t gid =
--          (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
-+          (dir->i_mode & S_ISGID) ? i_gid_read(dir) : YCRED_FSGID();
-       yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink");
-@@ -1829,8 +1856,8 @@ static void yaffs_fill_inode_from_obj(st
-               inode->i_ino = obj->obj_id;
-               inode->i_mode = obj->yst_mode;
--              inode->i_uid = obj->yst_uid;
--              inode->i_gid = obj->yst_gid;
-+              i_uid_write(inode, obj->yst_uid);
-+              i_gid_write(inode, obj->yst_gid);
- #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
-               inode->i_blksize = inode->i_sb->s_blocksize;
- #endif
-@@ -1856,7 +1883,7 @@ static void yaffs_fill_inode_from_obj(st
-               yaffs_trace(YAFFS_TRACE_OS,
-                       "yaffs_fill_inode mode %x uid %d gid %d size %lld count %d",
--                      inode->i_mode, inode->i_uid, inode->i_gid,
-+                      inode->i_mode, i_uid_read(inode), i_gid_read(inode),
-                       inode->i_size, atomic_read(&inode->i_count));
-               switch (obj->yst_mode & S_IFMT) {
---- a/fs/yaffs2/yaffs_attribs.c
-+++ b/fs/yaffs2/yaffs_attribs.c
-@@ -14,6 +14,48 @@
- #include "yaffs_guts.h"
- #include "yaffs_attribs.h"
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
-+static inline uid_t ia_uid_read(const struct iattr *iattr)
-+{
-+      return from_kuid(&init_user_ns, iattr->ia_uid);
-+}
-+
-+static inline gid_t ia_gid_read(const struct iattr *iattr)
-+{
-+      return from_kgid(&init_user_ns, iattr->ia_gid);
-+}
-+
-+static inline void ia_uid_write(struct iattr *iattr, uid_t uid)
-+{
-+      iattr->ia_uid = make_kuid(&init_user_ns, uid);
-+}
-+
-+static inline void ia_gid_write(struct iattr *iattr, gid_t gid)
-+{
-+      iattr->ia_gid = make_kgid(&init_user_ns, gid);
-+}
-+#else
-+static inline uid_t ia_uid_read(const struct iattr *iattr)
-+{
-+      return iattr->ia_uid;
-+}
-+
-+static inline gid_t ia_gid_read(const struct iattr *inode)
-+{
-+      return iattr->ia_gid;
-+}
-+
-+static inline void ia_uid_write(struct iattr *iattr, uid_t uid)
-+{
-+      iattr->ia_uid = uid;
-+}
-+
-+static inline void ia_gid_write(struct iattr *iattr, gid_t gid)
-+{
-+      iattr->ia_gid = gid;
-+}
-+#endif
-+
- void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh)
- {
-       obj->yst_uid = oh->yst_uid;
-@@ -77,9 +119,9 @@ int yaffs_set_attribs(struct yaffs_obj *
-       if (valid & ATTR_MODE)
-               obj->yst_mode = attr->ia_mode;
-       if (valid & ATTR_UID)
--              obj->yst_uid = attr->ia_uid;
-+              obj->yst_uid =  ia_uid_read(attr);
-       if (valid & ATTR_GID)
--              obj->yst_gid = attr->ia_gid;
-+              obj->yst_gid =  ia_gid_read(attr);
-       if (valid & ATTR_ATIME)
-               obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
-@@ -103,9 +145,9 @@ int yaffs_get_attribs(struct yaffs_obj *
-       attr->ia_mode = obj->yst_mode;
-       valid |= ATTR_MODE;
--      attr->ia_uid = obj->yst_uid;
-+      ia_uid_write(attr, obj->yst_uid);
-       valid |= ATTR_UID;
--      attr->ia_gid = obj->yst_gid;
-+      ia_gid_write(attr, obj->yst_gid);
-       valid |= ATTR_GID;
-       Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime;
diff --git a/target/linux/generic/patches-3.18/501-yaffs-add-missing-flush-arguments.patch b/target/linux/generic/patches-3.18/501-yaffs-add-missing-flush-arguments.patch
new file mode 100644 (file)
index 0000000..d5ccc3e
--- /dev/null
@@ -0,0 +1,38 @@
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -738,7 +738,7 @@ static int yaffs_file_flush(struct file
+       yaffs_gross_lock(dev);
+-      yaffs_flush_file(obj, 1, 0);
++      yaffs_flush_file(obj, 1, 0, 1);
+       yaffs_gross_unlock(dev);
+@@ -768,7 +768,7 @@ static int yaffs_sync_object(struct file
+       yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC,
+               "yaffs_sync_object");
+       yaffs_gross_lock(dev);
+-      yaffs_flush_file(obj, 1, datasync);
++      yaffs_flush_file(obj, 1, datasync, 1);
+       yaffs_gross_unlock(dev);
+       return 0;
+ }
+@@ -2187,7 +2187,7 @@ static void yaffs_flush_inodes(struct su
+                       yaffs_trace(YAFFS_TRACE_OS,
+                               "flushing obj %d",
+                               obj->obj_id);
+-                      yaffs_flush_file(obj, 1, 0);
++                      yaffs_flush_file(obj, 1, 0, 1);
+               }
+       }
+ }
+@@ -2200,7 +2200,7 @@ static void yaffs_flush_super(struct sup
+       yaffs_flush_inodes(sb);
+       yaffs_update_dirty_dirs(dev);
+-      yaffs_flush_whole_cache(dev);
++      yaffs_flush_whole_cache(dev, 1);
+       if (do_checkpoint)
+               yaffs_checkpoint_save(dev);
+ }
diff --git a/target/linux/generic/patches-3.18/502-yaffs-3.10-disable-proc-entry.patch b/target/linux/generic/patches-3.18/502-yaffs-3.10-disable-proc-entry.patch
deleted file mode 100644 (file)
index 5b73d38..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
---- a/fs/yaffs2/yaffs_vfs.c
-+++ b/fs/yaffs2/yaffs_vfs.c
-@@ -3025,6 +3025,7 @@ static DECLARE_FSTYPE(yaffs2_fs_type, "y
- #endif
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
- static struct proc_dir_entry *my_proc_entry;
- static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev)
-@@ -3398,6 +3399,7 @@ static int yaffs_proc_write(struct file
-               return yaffs_proc_debug_write(file, buf, count, data);
-       return yaffs_proc_write_trace_options(file, buf, count, data);
- }
-+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)) */
- /* Stuff to handle installation of file systems */
- struct file_system_to_install {
-@@ -3421,6 +3423,7 @@ static int __init init_yaffs_fs(void)
-       mutex_init(&yaffs_context_lock);
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
-       /* Install the proc_fs entries */
-       my_proc_entry = create_proc_entry("yaffs",
-                                         S_IRUGO | S_IFREG, YPROC_ROOT);
-@@ -3432,6 +3435,7 @@ static int __init init_yaffs_fs(void)
-       } else {
-               return -ENOMEM;
-         }
-+#endif
-       /* Now add the file system entries */
-@@ -3468,7 +3472,9 @@ static void __exit exit_yaffs_fs(void)
-       yaffs_trace(YAFFS_TRACE_ALWAYS,
-               "yaffs built " __DATE__ " " __TIME__ " removing.");
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
-       remove_proc_entry("yaffs", YPROC_ROOT);
-+#endif
-       fsinst = fs_to_install;
diff --git a/target/linux/generic/patches-3.18/502-yaffs-fix-compat-tags-handling.patch b/target/linux/generic/patches-3.18/502-yaffs-fix-compat-tags-handling.patch
new file mode 100644 (file)
index 0000000..a18cf6f
--- /dev/null
@@ -0,0 +1,239 @@
+Subject: yaffs: fix compat tags handling
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+--- a/fs/yaffs2/yaffs_tagscompat.c
++++ b/fs/yaffs2/yaffs_tagscompat.c
+@@ -17,7 +17,9 @@
+ #include "yaffs_getblockinfo.h"
+ #include "yaffs_trace.h"
++#if 0
+ static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk);
++#endif
+ /********** Tags ECC calculations  *********/
+@@ -71,6 +73,7 @@ int yaffs_check_tags_ecc(struct yaffs_ta
+       return 0;
+ }
++#if 0
+ /********** Tags **********/
+ static void yaffs_load_tags_to_spare(struct yaffs_spare *spare_ptr,
+@@ -379,3 +382,214 @@ void yaffs_tags_compat_install(struct ya
+       if(!dev->tagger.mark_bad_fn)
+               dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad;
+ }
++#else
++
++#include "yaffs_packedtags1.h"
++
++static int yaffs_tags_compat_write(struct yaffs_dev *dev,
++                                 int nand_chunk,
++                                 const u8 *data,
++                                 const struct yaffs_ext_tags *tags)
++{
++      struct yaffs_packed_tags1 pt1;
++      u8 tag_buf[9];
++      int retval;
++
++      /* we assume that yaffs_packed_tags1 and yaffs_tags are compatible */
++      compile_time_assertion(sizeof(struct yaffs_packed_tags1) == 12);
++      compile_time_assertion(sizeof(struct yaffs_tags) == 8);
++
++      yaffs_pack_tags1(&pt1, tags);
++      yaffs_calc_tags_ecc((struct yaffs_tags *)&pt1);
++
++      /* When deleting a chunk, the upper layer provides only skeletal
++       * tags, one with is_deleted set.  However, we need to update the
++       * tags, not erase them completely.  So we use the NAND write property
++       * that only zeroed-bits stick and set tag bytes to all-ones and
++       * zero just the (not) deleted bit.
++       */
++      if (!dev->param.tags_9bytes) {
++              if (tags->is_deleted) {
++                      memset(&pt1, 0xff, 8);
++                      /* clear delete status bit to indicate deleted */
++                      pt1.deleted = 0;
++              }
++              memcpy(tag_buf, &pt1, 8);
++      } else {
++              if (tags->is_deleted) {
++                      memset(tag_buf, 0xff, 8);
++                      tag_buf[8] = 0;
++              } else {
++                      memcpy(tag_buf, &pt1, 8);
++                      tag_buf[8] = 0xff;
++              }
++      }
++
++      retval = dev->drv.drv_write_chunk_fn(dev, nand_chunk,
++                      data,
++                      (data) ? dev->data_bytes_per_chunk : 0,
++                      tag_buf,
++                      (dev->param.tags_9bytes) ? 9 : 8);
++
++      return retval;
++}
++
++/* Return with empty extended tags but add ecc_result.
++ */
++static int return_empty_tags(struct yaffs_ext_tags *tags,
++                           enum yaffs_ecc_result ecc_result,
++                           int retval)
++{
++      if (tags) {
++              memset(tags, 0, sizeof(*tags));
++              tags->ecc_result = ecc_result;
++      }
++
++      return retval;
++}
++
++static int yaffs_tags_compat_read(struct yaffs_dev *dev,
++                                int nand_chunk,
++                                u8 *data,
++                                struct yaffs_ext_tags *tags)
++{
++      struct yaffs_packed_tags1 pt1;
++      enum yaffs_ecc_result ecc_result;
++      int retval;
++      int deleted;
++      u8 tag_buf[9];
++
++      retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk,
++                      data, dev->param.total_bytes_per_chunk,
++                      tag_buf,
++                      (dev->param.tags_9bytes) ? 9 : 8,
++                      &ecc_result);
++
++      switch (ecc_result) {
++      case YAFFS_ECC_RESULT_NO_ERROR:
++      case YAFFS_ECC_RESULT_FIXED:
++              break;
++
++      case YAFFS_ECC_RESULT_UNFIXED:
++      default:
++              return_empty_tags(tags, YAFFS_ECC_RESULT_UNFIXED, 0);
++              tags->block_bad = dev->drv.drv_check_bad_fn(dev, nand_chunk);
++              return YAFFS_FAIL;
++      }
++
++      /* Check for a blank/erased chunk. */
++      if (yaffs_check_ff(tag_buf, 8)) {
++              /* when blank, upper layers want ecc_result to be <= NO_ERROR */
++              return return_empty_tags(tags, YAFFS_ECC_RESULT_NO_ERROR,
++                                       YAFFS_OK);
++      }
++
++      memcpy(&pt1, tag_buf, 8);
++
++      if (!dev->param.tags_9bytes) {
++              /* Read deleted status (bit) then return it to it's non-deleted
++               * state before performing tags mini-ECC check. pt1.deleted is
++               * inverted.
++               */
++              deleted = !pt1.deleted;
++              pt1.deleted = 1;
++      } else {
++              deleted = (hweight8(tag_buf[8]) < 7) ? 1 : 0;
++      }
++
++      /* Check the packed tags mini-ECC and correct if necessary/possible. */
++      retval = yaffs_check_tags_ecc((struct yaffs_tags *)&pt1);
++      switch (retval) {
++      case 0:
++              /* no tags error, use MTD result */
++              break;
++      case 1:
++              /* recovered tags-ECC error */
++              dev->n_tags_ecc_fixed++;
++              if (ecc_result == YAFFS_ECC_RESULT_NO_ERROR)
++                      ecc_result = YAFFS_ECC_RESULT_FIXED;
++              break;
++      default:
++              /* unrecovered tags-ECC error */
++              dev->n_tags_ecc_unfixed++;
++              return return_empty_tags(tags, YAFFS_ECC_RESULT_UNFIXED,
++                                       YAFFS_FAIL);
++      }
++
++      /* Unpack the tags to extended form and set ECC result.
++       * [set should_be_ff just to keep yaffs_unpack_tags1 happy]
++       */
++      pt1.should_be_ff = 0xffffffff;
++      yaffs_unpack_tags1(tags, &pt1);
++      tags->ecc_result = ecc_result;
++
++      /* Set deleted state */
++      tags->is_deleted = deleted;
++      return YAFFS_OK;
++}
++
++static int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int block_no)
++{
++      return dev->drv.drv_mark_bad_fn(dev, block_no);
++}
++
++static int yaffs_tags_compat_query_block(struct yaffs_dev *dev,
++                                       int block_no,
++                                       enum yaffs_block_state *state,
++                                       u32 *seq_number)
++{
++      struct yaffs_ext_tags tags;
++      int retval;
++
++      yaffs_trace(YAFFS_TRACE_MTD, "%s %d", __func__, block_no);
++
++      *seq_number = 0;
++
++      retval = dev->drv.drv_check_bad_fn(dev, block_no);
++      if (retval == YAFFS_FAIL) {
++              *state = YAFFS_BLOCK_STATE_DEAD;
++              goto out;
++      }
++
++      yaffs_tags_compat_read(dev, block_no * dev->param.chunks_per_block,
++                             NULL, &tags);
++
++      if (tags.ecc_result != YAFFS_ECC_RESULT_NO_ERROR) {
++              yaffs_trace(YAFFS_TRACE_MTD, "block %d is marked bad",
++                          block_no);
++              *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
++      } else if (tags.chunk_used) {
++              *seq_number = tags.seq_number;
++              *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
++      } else {
++              *state = YAFFS_BLOCK_STATE_EMPTY;
++      }
++
++      retval = YAFFS_OK;
++
++out:
++      yaffs_trace(YAFFS_TRACE_MTD,
++                  "block query returns seq %u state %d",
++                  *seq_number, *state);
++
++      return retval;
++}
++
++void yaffs_tags_compat_install(struct yaffs_dev *dev)
++{
++      if (dev->param.is_yaffs2)
++              return;
++
++      if (!dev->tagger.write_chunk_tags_fn)
++              dev->tagger.write_chunk_tags_fn = yaffs_tags_compat_write;
++
++      if (!dev->tagger.read_chunk_tags_fn)
++              dev->tagger.read_chunk_tags_fn = yaffs_tags_compat_read;
++
++      if (!dev->tagger.query_block_fn)
++              dev->tagger.query_block_fn = yaffs_tags_compat_query_block;
++
++      if (!dev->tagger.mark_bad_fn)
++              dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad;
++}
++#endif
diff --git a/target/linux/generic/patches-3.18/503-yaffs-3.12-convert-readdir-to-iterate.patch b/target/linux/generic/patches-3.18/503-yaffs-3.12-convert-readdir-to-iterate.patch
deleted file mode 100644 (file)
index 586c141..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
---- a/fs/yaffs2/yaffs_vfs.c
-+++ b/fs/yaffs2/yaffs_vfs.c
-@@ -1701,6 +1701,110 @@ static void yaffs_remove_obj_callback(st
- /*-----------------------------------------------------------------*/
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
-+static int yaffs_readdir(struct file *file, struct dir_context *ctx)
-+{
-+      struct yaffs_obj *obj;
-+      struct yaffs_dev *dev;
-+      struct yaffs_search_context *sc;
-+      struct inode *inode = file->f_dentry->d_inode;
-+      unsigned long offset, curoffs;
-+      struct yaffs_obj *l;
-+      int ret_val = 0;
-+
-+      char name[YAFFS_MAX_NAME_LENGTH + 1];
-+
-+      obj = yaffs_dentry_to_obj(file->f_dentry);
-+      dev = obj->my_dev;
-+
-+      yaffs_gross_lock(dev);
-+
-+      yaffs_dev_to_lc(dev)->readdir_process = current;
-+
-+      offset = ctx->pos;
-+
-+      sc = yaffs_new_search(obj);
-+      if (!sc) {
-+              ret_val = -ENOMEM;
-+              goto out;
-+      }
-+
-+      yaffs_trace(YAFFS_TRACE_OS,
-+              "yaffs_readdir: starting at %d", (int)offset);
-+
-+      if (offset == 0) {
-+              yaffs_trace(YAFFS_TRACE_OS,
-+                      "yaffs_readdir: entry . ino %d",
-+                      (int)inode->i_ino);
-+              yaffs_gross_unlock(dev);
-+              if (!dir_emit_dot(file, ctx)) {
-+                      yaffs_gross_lock(dev);
-+                      goto out;
-+              }
-+              yaffs_gross_lock(dev);
-+              offset++;
-+              ctx->pos++;
-+      }
-+      if (offset == 1) {
-+              yaffs_trace(YAFFS_TRACE_OS,
-+                      "yaffs_readdir: entry .. ino %d",
-+                      (int)file->f_dentry->d_parent->d_inode->i_ino);
-+              yaffs_gross_unlock(dev);
-+              if (!dir_emit_dotdot(file, ctx)) {
-+                      yaffs_gross_lock(dev);
-+                      goto out;
-+              }
-+              yaffs_gross_lock(dev);
-+              offset++;
-+              ctx->pos++;
-+      }
-+
-+      curoffs = 1;
-+
-+      /* If the directory has changed since the open or last call to
-+         readdir, rewind to after the 2 canned entries. */
-+      if (file->f_version != inode->i_version) {
-+              offset = 2;
-+              ctx->pos = offset;
-+              file->f_version = inode->i_version;
-+      }
-+
-+      while (sc->next_return) {
-+              curoffs++;
-+              l = sc->next_return;
-+              if (curoffs >= offset) {
-+                      int this_inode = yaffs_get_obj_inode(l);
-+                      int this_type = yaffs_get_obj_type(l);
-+
-+                      yaffs_get_obj_name(l, name, YAFFS_MAX_NAME_LENGTH + 1);
-+                      yaffs_trace(YAFFS_TRACE_OS,
-+                              "yaffs_readdir: %s inode %d",
-+                              name, yaffs_get_obj_inode(l));
-+
-+                      yaffs_gross_unlock(dev);
-+
-+                      if (!dir_emit(ctx, name, strlen(name),
-+                                    this_inode, this_type) < 0) {
-+                              yaffs_gross_lock(dev);
-+                              goto out;
-+                      }
-+
-+                      yaffs_gross_lock(dev);
-+
-+                      offset++;
-+                      ctx->pos++;
-+              }
-+              yaffs_search_advance(sc);
-+      }
-+
-+out:
-+      yaffs_search_end(sc);
-+      yaffs_dev_to_lc(dev)->readdir_process = NULL;
-+      yaffs_gross_unlock(dev);
-+
-+      return ret_val;
-+}
-+#else
- static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
- {
-       struct yaffs_obj *obj;
-@@ -1807,10 +1911,15 @@ out:
-       return ret_val;
- }
-+#endif
- static const struct file_operations yaffs_dir_operations = {
-       .read = generic_read_dir,
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
-+      .iterate = yaffs_readdir,
-+#else
-       .readdir = yaffs_readdir,
-+#endif
-       .fsync = yaffs_sync_object,
-       .llseek = generic_file_llseek,
- };
index 4858519ca1465b0e715438b8f51eb52aaa76225d..9ecaa72832238f8a1dca30787e8c48c2e66085dc 100644 (file)
@@ -4,7 +4,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
 ---
 --- a/fs/yaffs2/yaffs_vfs.c
 +++ b/fs/yaffs2/yaffs_vfs.c
-@@ -2634,6 +2634,7 @@ static const struct super_operations yaf
+@@ -2605,6 +2605,7 @@ static const struct super_operations yaf
  
  struct yaffs_options {
        int inband_tags;
@@ -12,7 +12,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
        int skip_checkpoint_read;
        int skip_checkpoint_write;
        int no_cache;
-@@ -2673,6 +2674,8 @@ static int yaffs_parse_options(struct ya
+@@ -2644,6 +2645,8 @@ static int yaffs_parse_options(struct ya
  
                if (!strcmp(cur_opt, "inband-tags")) {
                        options->inband_tags = 1;
@@ -21,7 +21,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
                } else if (!strcmp(cur_opt, "tags-ecc-off")) {
                        options->tags_ecc_on = 0;
                        options->tags_ecc_overridden = 1;
-@@ -2746,7 +2749,6 @@ static struct super_block *yaffs_interna
+@@ -2717,7 +2720,6 @@ static struct super_block *yaffs_interna
        struct yaffs_param *param;
  
        int read_only = 0;
@@ -29,7 +29,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
  
        struct yaffs_options options;
  
-@@ -2786,6 +2788,9 @@ static struct super_block *yaffs_interna
+@@ -2757,6 +2759,9 @@ static struct super_block *yaffs_interna
  
        memset(&options, 0, sizeof(options));
  
@@ -39,7 +39,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
        if (yaffs_parse_options(&options, data_str)) {
                /* Option parsing failed */
                return NULL;
-@@ -2819,17 +2824,22 @@ static struct super_block *yaffs_interna
+@@ -2790,17 +2795,22 @@ static struct super_block *yaffs_interna
        }
  
        /* Added NCB 26/5/2006 for completeness */
@@ -68,7 +68,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
                return NULL;
  
        /* OK, so if we got here, we have an MTD that's NAND and looks
-@@ -2890,7 +2900,8 @@ static struct super_block *yaffs_interna
+@@ -2857,7 +2867,8 @@ static struct super_block *yaffs_interna
  
        param->n_reserved_blocks = 5;
        param->n_caches = (options.no_cache) ? 0 : 10;
@@ -80,15 +80,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
        if (options.lazy_loading_overridden)
 --- a/fs/yaffs2/yaffs_mtdif.c
 +++ b/fs/yaffs2/yaffs_mtdif.c
-@@ -16,6 +16,7 @@
- #include "yaffs_mtdif.h"
- #include "linux/mtd/mtd.h"
-+#include "uapi/linux/major.h"
- #include "linux/types.h"
- #include "linux/time.h"
- #include "linux/mtd/nand.h"
-@@ -276,7 +277,8 @@ struct mtd_info * yaffs_get_mtd_device(d
+@@ -278,7 +278,8 @@ struct mtd_info * yaffs_get_mtd_device(d
        return mtd;
  }
  
@@ -98,7 +90,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
  {
        if (yaffs_version == 2) {
                if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
-@@ -295,6 +297,12 @@ int yaffs_verify_mtd(struct mtd_info *mt
+@@ -297,6 +298,12 @@ int yaffs_verify_mtd(struct mtd_info *mt
                        );
                        return -1;
                }
diff --git a/target/linux/generic/patches-3.18/504-yaffs-3.16-new-fops.patch b/target/linux/generic/patches-3.18/504-yaffs-3.16-new-fops.patch
new file mode 100644 (file)
index 0000000..11c6da0
--- /dev/null
@@ -0,0 +1,25 @@
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -774,7 +774,21 @@ static int yaffs_sync_object(struct file
+ }
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
++static const struct file_operations yaffs_file_operations = {
++      .read = new_sync_read,
++      .read_iter = generic_file_read_iter,
++      .write = new_sync_write,
++      .write_iter = generic_file_write_iter,
++      .mmap = generic_file_mmap,
++      .flush = yaffs_file_flush,
++      .fsync = yaffs_sync_object,
++      .splice_read = generic_file_splice_read,
++      .splice_write = iter_file_splice_write,
++      .llseek = generic_file_llseek,
++};
++
++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
+ static const struct file_operations yaffs_file_operations = {
+       .read = do_sync_read,
+       .write = do_sync_write,
diff --git a/target/linux/generic/patches-3.18/504-yaffs-fix-compat-tags-handling.patch b/target/linux/generic/patches-3.18/504-yaffs-fix-compat-tags-handling.patch
deleted file mode 100644 (file)
index a18cf6f..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-Subject: yaffs: fix compat tags handling
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
---- a/fs/yaffs2/yaffs_tagscompat.c
-+++ b/fs/yaffs2/yaffs_tagscompat.c
-@@ -17,7 +17,9 @@
- #include "yaffs_getblockinfo.h"
- #include "yaffs_trace.h"
-+#if 0
- static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk);
-+#endif
- /********** Tags ECC calculations  *********/
-@@ -71,6 +73,7 @@ int yaffs_check_tags_ecc(struct yaffs_ta
-       return 0;
- }
-+#if 0
- /********** Tags **********/
- static void yaffs_load_tags_to_spare(struct yaffs_spare *spare_ptr,
-@@ -379,3 +382,214 @@ void yaffs_tags_compat_install(struct ya
-       if(!dev->tagger.mark_bad_fn)
-               dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad;
- }
-+#else
-+
-+#include "yaffs_packedtags1.h"
-+
-+static int yaffs_tags_compat_write(struct yaffs_dev *dev,
-+                                 int nand_chunk,
-+                                 const u8 *data,
-+                                 const struct yaffs_ext_tags *tags)
-+{
-+      struct yaffs_packed_tags1 pt1;
-+      u8 tag_buf[9];
-+      int retval;
-+
-+      /* we assume that yaffs_packed_tags1 and yaffs_tags are compatible */
-+      compile_time_assertion(sizeof(struct yaffs_packed_tags1) == 12);
-+      compile_time_assertion(sizeof(struct yaffs_tags) == 8);
-+
-+      yaffs_pack_tags1(&pt1, tags);
-+      yaffs_calc_tags_ecc((struct yaffs_tags *)&pt1);
-+
-+      /* When deleting a chunk, the upper layer provides only skeletal
-+       * tags, one with is_deleted set.  However, we need to update the
-+       * tags, not erase them completely.  So we use the NAND write property
-+       * that only zeroed-bits stick and set tag bytes to all-ones and
-+       * zero just the (not) deleted bit.
-+       */
-+      if (!dev->param.tags_9bytes) {
-+              if (tags->is_deleted) {
-+                      memset(&pt1, 0xff, 8);
-+                      /* clear delete status bit to indicate deleted */
-+                      pt1.deleted = 0;
-+              }
-+              memcpy(tag_buf, &pt1, 8);
-+      } else {
-+              if (tags->is_deleted) {
-+                      memset(tag_buf, 0xff, 8);
-+                      tag_buf[8] = 0;
-+              } else {
-+                      memcpy(tag_buf, &pt1, 8);
-+                      tag_buf[8] = 0xff;
-+              }
-+      }
-+
-+      retval = dev->drv.drv_write_chunk_fn(dev, nand_chunk,
-+                      data,
-+                      (data) ? dev->data_bytes_per_chunk : 0,
-+                      tag_buf,
-+                      (dev->param.tags_9bytes) ? 9 : 8);
-+
-+      return retval;
-+}
-+
-+/* Return with empty extended tags but add ecc_result.
-+ */
-+static int return_empty_tags(struct yaffs_ext_tags *tags,
-+                           enum yaffs_ecc_result ecc_result,
-+                           int retval)
-+{
-+      if (tags) {
-+              memset(tags, 0, sizeof(*tags));
-+              tags->ecc_result = ecc_result;
-+      }
-+
-+      return retval;
-+}
-+
-+static int yaffs_tags_compat_read(struct yaffs_dev *dev,
-+                                int nand_chunk,
-+                                u8 *data,
-+                                struct yaffs_ext_tags *tags)
-+{
-+      struct yaffs_packed_tags1 pt1;
-+      enum yaffs_ecc_result ecc_result;
-+      int retval;
-+      int deleted;
-+      u8 tag_buf[9];
-+
-+      retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk,
-+                      data, dev->param.total_bytes_per_chunk,
-+                      tag_buf,
-+                      (dev->param.tags_9bytes) ? 9 : 8,
-+                      &ecc_result);
-+
-+      switch (ecc_result) {
-+      case YAFFS_ECC_RESULT_NO_ERROR:
-+      case YAFFS_ECC_RESULT_FIXED:
-+              break;
-+
-+      case YAFFS_ECC_RESULT_UNFIXED:
-+      default:
-+              return_empty_tags(tags, YAFFS_ECC_RESULT_UNFIXED, 0);
-+              tags->block_bad = dev->drv.drv_check_bad_fn(dev, nand_chunk);
-+              return YAFFS_FAIL;
-+      }
-+
-+      /* Check for a blank/erased chunk. */
-+      if (yaffs_check_ff(tag_buf, 8)) {
-+              /* when blank, upper layers want ecc_result to be <= NO_ERROR */
-+              return return_empty_tags(tags, YAFFS_ECC_RESULT_NO_ERROR,
-+                                       YAFFS_OK);
-+      }
-+
-+      memcpy(&pt1, tag_buf, 8);
-+
-+      if (!dev->param.tags_9bytes) {
-+              /* Read deleted status (bit) then return it to it's non-deleted
-+               * state before performing tags mini-ECC check. pt1.deleted is
-+               * inverted.
-+               */
-+              deleted = !pt1.deleted;
-+              pt1.deleted = 1;
-+      } else {
-+              deleted = (hweight8(tag_buf[8]) < 7) ? 1 : 0;
-+      }
-+
-+      /* Check the packed tags mini-ECC and correct if necessary/possible. */
-+      retval = yaffs_check_tags_ecc((struct yaffs_tags *)&pt1);
-+      switch (retval) {
-+      case 0:
-+              /* no tags error, use MTD result */
-+              break;
-+      case 1:
-+              /* recovered tags-ECC error */
-+              dev->n_tags_ecc_fixed++;
-+              if (ecc_result == YAFFS_ECC_RESULT_NO_ERROR)
-+                      ecc_result = YAFFS_ECC_RESULT_FIXED;
-+              break;
-+      default:
-+              /* unrecovered tags-ECC error */
-+              dev->n_tags_ecc_unfixed++;
-+              return return_empty_tags(tags, YAFFS_ECC_RESULT_UNFIXED,
-+                                       YAFFS_FAIL);
-+      }
-+
-+      /* Unpack the tags to extended form and set ECC result.
-+       * [set should_be_ff just to keep yaffs_unpack_tags1 happy]
-+       */
-+      pt1.should_be_ff = 0xffffffff;
-+      yaffs_unpack_tags1(tags, &pt1);
-+      tags->ecc_result = ecc_result;
-+
-+      /* Set deleted state */
-+      tags->is_deleted = deleted;
-+      return YAFFS_OK;
-+}
-+
-+static int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int block_no)
-+{
-+      return dev->drv.drv_mark_bad_fn(dev, block_no);
-+}
-+
-+static int yaffs_tags_compat_query_block(struct yaffs_dev *dev,
-+                                       int block_no,
-+                                       enum yaffs_block_state *state,
-+                                       u32 *seq_number)
-+{
-+      struct yaffs_ext_tags tags;
-+      int retval;
-+
-+      yaffs_trace(YAFFS_TRACE_MTD, "%s %d", __func__, block_no);
-+
-+      *seq_number = 0;
-+
-+      retval = dev->drv.drv_check_bad_fn(dev, block_no);
-+      if (retval == YAFFS_FAIL) {
-+              *state = YAFFS_BLOCK_STATE_DEAD;
-+              goto out;
-+      }
-+
-+      yaffs_tags_compat_read(dev, block_no * dev->param.chunks_per_block,
-+                             NULL, &tags);
-+
-+      if (tags.ecc_result != YAFFS_ECC_RESULT_NO_ERROR) {
-+              yaffs_trace(YAFFS_TRACE_MTD, "block %d is marked bad",
-+                          block_no);
-+              *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
-+      } else if (tags.chunk_used) {
-+              *seq_number = tags.seq_number;
-+              *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
-+      } else {
-+              *state = YAFFS_BLOCK_STATE_EMPTY;
-+      }
-+
-+      retval = YAFFS_OK;
-+
-+out:
-+      yaffs_trace(YAFFS_TRACE_MTD,
-+                  "block query returns seq %u state %d",
-+                  *seq_number, *state);
-+
-+      return retval;
-+}
-+
-+void yaffs_tags_compat_install(struct yaffs_dev *dev)
-+{
-+      if (dev->param.is_yaffs2)
-+              return;
-+
-+      if (!dev->tagger.write_chunk_tags_fn)
-+              dev->tagger.write_chunk_tags_fn = yaffs_tags_compat_write;
-+
-+      if (!dev->tagger.read_chunk_tags_fn)
-+              dev->tagger.read_chunk_tags_fn = yaffs_tags_compat_read;
-+
-+      if (!dev->tagger.query_block_fn)
-+              dev->tagger.query_block_fn = yaffs_tags_compat_query_block;
-+
-+      if (!dev->tagger.mark_bad_fn)
-+              dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad;
-+}
-+#endif
diff --git a/target/linux/generic/patches-3.18/505-yaffs-3.16-new-fops.patch b/target/linux/generic/patches-3.18/505-yaffs-3.16-new-fops.patch
deleted file mode 100644 (file)
index be88ab9..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
---- a/fs/yaffs2/yaffs_vfs.c
-+++ b/fs/yaffs2/yaffs_vfs.c
-@@ -794,15 +794,15 @@ static int yaffs_sync_object(struct file
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
- static const struct file_operations yaffs_file_operations = {
--      .read = do_sync_read,
--      .write = do_sync_write,
--      .aio_read = generic_file_aio_read,
--      .aio_write = generic_file_aio_write,
-+      .read = new_sync_read,
-+      .write = new_sync_write,
-+      .read_iter = generic_file_read_iter,
-+      .write_iter = generic_file_write_iter,
-       .mmap = generic_file_mmap,
-       .flush = yaffs_file_flush,
-       .fsync = yaffs_sync_object,
-       .splice_read = generic_file_splice_read,
--      .splice_write = generic_file_splice_write,
-+      .splice_write = iter_file_splice_write,
-       .llseek = generic_file_llseek,
- };
-@@ -1050,7 +1050,7 @@ static int yaffs_readlink(struct dentry
-       if (!alias)
-               return -ENOMEM;
--      ret = vfs_readlink(dentry, buffer, buflen, alias);
-+      ret = readlink_copy(buffer, buflen, alias);
-       kfree(alias);
-       return ret;
- }
diff --git a/target/linux/generic/patches-4.0/501-yaffs-3.5-convert-to-use-kuid_t-kgid_t.patch b/target/linux/generic/patches-4.0/501-yaffs-3.5-convert-to-use-kuid_t-kgid_t.patch
deleted file mode 100644 (file)
index c1f7367..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
---- a/fs/yaffs2/yaffs_vfs.c
-+++ b/fs/yaffs2/yaffs_vfs.c
-@@ -329,6 +329,33 @@ static int yaffs_readpage(struct file *f
-       return ret;
- }
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
-+#define YCRED_FSUID() from_kuid(&init_user_ns, current_fsuid())
-+#define YCRED_FSGID() from_kgid(&init_user_ns, current_fsgid())
-+#else
-+#define YCRED_FSUID() YCRED(current)->fsuid
-+#define YCRED_FSGID() YCRED(current)->fsgid
-+
-+static inline uid_t i_uid_read(const struct inode *inode)
-+{
-+      return inode->i_uid;
-+}
-+
-+static inline gid_t i_gid_read(const struct inode *inode)
-+{
-+      return inode->i_gid;
-+}
-+
-+static inline void i_uid_write(struct inode *inode, uid_t uid)
-+{
-+      inode->i_uid = uid;
-+}
-+
-+static inline void i_gid_write(struct inode *inode, gid_t gid)
-+{
-+      inode->i_gid = gid;
-+}
-+#endif
- static void yaffs_set_super_dirty_val(struct yaffs_dev *dev, int val)
- {
-@@ -1225,9 +1252,9 @@ static int yaffs_mknod(struct inode *dir
-       struct yaffs_obj *parent = yaffs_inode_to_obj(dir);
-       int error = -ENOSPC;
--      uid_t uid = YCRED(current)->fsuid;
-+      uid_t uid = YCRED_FSUID();
-       gid_t gid =
--          (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
-+          (dir->i_mode & S_ISGID) ? i_gid_read(dir) : YCRED_FSGID();
-       if ((dir->i_mode & S_ISGID) && S_ISDIR(mode))
-               mode |= S_ISGID;
-@@ -1424,9 +1451,9 @@ static int yaffs_symlink(struct inode *d
- {
-       struct yaffs_obj *obj;
-       struct yaffs_dev *dev;
--      uid_t uid = YCRED(current)->fsuid;
-+      uid_t uid = YCRED_FSUID();
-       gid_t gid =
--          (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
-+          (dir->i_mode & S_ISGID) ? i_gid_read(dir) : YCRED_FSGID();
-       yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink");
-@@ -1829,8 +1856,8 @@ static void yaffs_fill_inode_from_obj(st
-               inode->i_ino = obj->obj_id;
-               inode->i_mode = obj->yst_mode;
--              inode->i_uid = obj->yst_uid;
--              inode->i_gid = obj->yst_gid;
-+              i_uid_write(inode, obj->yst_uid);
-+              i_gid_write(inode, obj->yst_gid);
- #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
-               inode->i_blksize = inode->i_sb->s_blocksize;
- #endif
-@@ -1856,7 +1883,7 @@ static void yaffs_fill_inode_from_obj(st
-               yaffs_trace(YAFFS_TRACE_OS,
-                       "yaffs_fill_inode mode %x uid %d gid %d size %lld count %d",
--                      inode->i_mode, inode->i_uid, inode->i_gid,
-+                      inode->i_mode, i_uid_read(inode), i_gid_read(inode),
-                       inode->i_size, atomic_read(&inode->i_count));
-               switch (obj->yst_mode & S_IFMT) {
---- a/fs/yaffs2/yaffs_attribs.c
-+++ b/fs/yaffs2/yaffs_attribs.c
-@@ -14,6 +14,48 @@
- #include "yaffs_guts.h"
- #include "yaffs_attribs.h"
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
-+static inline uid_t ia_uid_read(const struct iattr *iattr)
-+{
-+      return from_kuid(&init_user_ns, iattr->ia_uid);
-+}
-+
-+static inline gid_t ia_gid_read(const struct iattr *iattr)
-+{
-+      return from_kgid(&init_user_ns, iattr->ia_gid);
-+}
-+
-+static inline void ia_uid_write(struct iattr *iattr, uid_t uid)
-+{
-+      iattr->ia_uid = make_kuid(&init_user_ns, uid);
-+}
-+
-+static inline void ia_gid_write(struct iattr *iattr, gid_t gid)
-+{
-+      iattr->ia_gid = make_kgid(&init_user_ns, gid);
-+}
-+#else
-+static inline uid_t ia_uid_read(const struct iattr *iattr)
-+{
-+      return iattr->ia_uid;
-+}
-+
-+static inline gid_t ia_gid_read(const struct iattr *inode)
-+{
-+      return iattr->ia_gid;
-+}
-+
-+static inline void ia_uid_write(struct iattr *iattr, uid_t uid)
-+{
-+      iattr->ia_uid = uid;
-+}
-+
-+static inline void ia_gid_write(struct iattr *iattr, gid_t gid)
-+{
-+      iattr->ia_gid = gid;
-+}
-+#endif
-+
- void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh)
- {
-       obj->yst_uid = oh->yst_uid;
-@@ -77,9 +119,9 @@ int yaffs_set_attribs(struct yaffs_obj *
-       if (valid & ATTR_MODE)
-               obj->yst_mode = attr->ia_mode;
-       if (valid & ATTR_UID)
--              obj->yst_uid = attr->ia_uid;
-+              obj->yst_uid =  ia_uid_read(attr);
-       if (valid & ATTR_GID)
--              obj->yst_gid = attr->ia_gid;
-+              obj->yst_gid =  ia_gid_read(attr);
-       if (valid & ATTR_ATIME)
-               obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
-@@ -103,9 +145,9 @@ int yaffs_get_attribs(struct yaffs_obj *
-       attr->ia_mode = obj->yst_mode;
-       valid |= ATTR_MODE;
--      attr->ia_uid = obj->yst_uid;
-+      ia_uid_write(attr, obj->yst_uid);
-       valid |= ATTR_UID;
--      attr->ia_gid = obj->yst_gid;
-+      ia_gid_write(attr, obj->yst_gid);
-       valid |= ATTR_GID;
-       Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime;
diff --git a/target/linux/generic/patches-4.0/501-yaffs-add-missing-flush-arguments.patch b/target/linux/generic/patches-4.0/501-yaffs-add-missing-flush-arguments.patch
new file mode 100644 (file)
index 0000000..d5ccc3e
--- /dev/null
@@ -0,0 +1,38 @@
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -738,7 +738,7 @@ static int yaffs_file_flush(struct file
+       yaffs_gross_lock(dev);
+-      yaffs_flush_file(obj, 1, 0);
++      yaffs_flush_file(obj, 1, 0, 1);
+       yaffs_gross_unlock(dev);
+@@ -768,7 +768,7 @@ static int yaffs_sync_object(struct file
+       yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC,
+               "yaffs_sync_object");
+       yaffs_gross_lock(dev);
+-      yaffs_flush_file(obj, 1, datasync);
++      yaffs_flush_file(obj, 1, datasync, 1);
+       yaffs_gross_unlock(dev);
+       return 0;
+ }
+@@ -2187,7 +2187,7 @@ static void yaffs_flush_inodes(struct su
+                       yaffs_trace(YAFFS_TRACE_OS,
+                               "flushing obj %d",
+                               obj->obj_id);
+-                      yaffs_flush_file(obj, 1, 0);
++                      yaffs_flush_file(obj, 1, 0, 1);
+               }
+       }
+ }
+@@ -2200,7 +2200,7 @@ static void yaffs_flush_super(struct sup
+       yaffs_flush_inodes(sb);
+       yaffs_update_dirty_dirs(dev);
+-      yaffs_flush_whole_cache(dev);
++      yaffs_flush_whole_cache(dev, 1);
+       if (do_checkpoint)
+               yaffs_checkpoint_save(dev);
+ }
diff --git a/target/linux/generic/patches-4.0/502-yaffs-3.10-disable-proc-entry.patch b/target/linux/generic/patches-4.0/502-yaffs-3.10-disable-proc-entry.patch
deleted file mode 100644 (file)
index 5b73d38..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
---- a/fs/yaffs2/yaffs_vfs.c
-+++ b/fs/yaffs2/yaffs_vfs.c
-@@ -3025,6 +3025,7 @@ static DECLARE_FSTYPE(yaffs2_fs_type, "y
- #endif
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
- static struct proc_dir_entry *my_proc_entry;
- static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev)
-@@ -3398,6 +3399,7 @@ static int yaffs_proc_write(struct file
-               return yaffs_proc_debug_write(file, buf, count, data);
-       return yaffs_proc_write_trace_options(file, buf, count, data);
- }
-+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)) */
- /* Stuff to handle installation of file systems */
- struct file_system_to_install {
-@@ -3421,6 +3423,7 @@ static int __init init_yaffs_fs(void)
-       mutex_init(&yaffs_context_lock);
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
-       /* Install the proc_fs entries */
-       my_proc_entry = create_proc_entry("yaffs",
-                                         S_IRUGO | S_IFREG, YPROC_ROOT);
-@@ -3432,6 +3435,7 @@ static int __init init_yaffs_fs(void)
-       } else {
-               return -ENOMEM;
-         }
-+#endif
-       /* Now add the file system entries */
-@@ -3468,7 +3472,9 @@ static void __exit exit_yaffs_fs(void)
-       yaffs_trace(YAFFS_TRACE_ALWAYS,
-               "yaffs built " __DATE__ " " __TIME__ " removing.");
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
-       remove_proc_entry("yaffs", YPROC_ROOT);
-+#endif
-       fsinst = fs_to_install;
diff --git a/target/linux/generic/patches-4.0/502-yaffs-fix-compat-tags-handling.patch b/target/linux/generic/patches-4.0/502-yaffs-fix-compat-tags-handling.patch
new file mode 100644 (file)
index 0000000..a18cf6f
--- /dev/null
@@ -0,0 +1,239 @@
+Subject: yaffs: fix compat tags handling
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+--- a/fs/yaffs2/yaffs_tagscompat.c
++++ b/fs/yaffs2/yaffs_tagscompat.c
+@@ -17,7 +17,9 @@
+ #include "yaffs_getblockinfo.h"
+ #include "yaffs_trace.h"
++#if 0
+ static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk);
++#endif
+ /********** Tags ECC calculations  *********/
+@@ -71,6 +73,7 @@ int yaffs_check_tags_ecc(struct yaffs_ta
+       return 0;
+ }
++#if 0
+ /********** Tags **********/
+ static void yaffs_load_tags_to_spare(struct yaffs_spare *spare_ptr,
+@@ -379,3 +382,214 @@ void yaffs_tags_compat_install(struct ya
+       if(!dev->tagger.mark_bad_fn)
+               dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad;
+ }
++#else
++
++#include "yaffs_packedtags1.h"
++
++static int yaffs_tags_compat_write(struct yaffs_dev *dev,
++                                 int nand_chunk,
++                                 const u8 *data,
++                                 const struct yaffs_ext_tags *tags)
++{
++      struct yaffs_packed_tags1 pt1;
++      u8 tag_buf[9];
++      int retval;
++
++      /* we assume that yaffs_packed_tags1 and yaffs_tags are compatible */
++      compile_time_assertion(sizeof(struct yaffs_packed_tags1) == 12);
++      compile_time_assertion(sizeof(struct yaffs_tags) == 8);
++
++      yaffs_pack_tags1(&pt1, tags);
++      yaffs_calc_tags_ecc((struct yaffs_tags *)&pt1);
++
++      /* When deleting a chunk, the upper layer provides only skeletal
++       * tags, one with is_deleted set.  However, we need to update the
++       * tags, not erase them completely.  So we use the NAND write property
++       * that only zeroed-bits stick and set tag bytes to all-ones and
++       * zero just the (not) deleted bit.
++       */
++      if (!dev->param.tags_9bytes) {
++              if (tags->is_deleted) {
++                      memset(&pt1, 0xff, 8);
++                      /* clear delete status bit to indicate deleted */
++                      pt1.deleted = 0;
++              }
++              memcpy(tag_buf, &pt1, 8);
++      } else {
++              if (tags->is_deleted) {
++                      memset(tag_buf, 0xff, 8);
++                      tag_buf[8] = 0;
++              } else {
++                      memcpy(tag_buf, &pt1, 8);
++                      tag_buf[8] = 0xff;
++              }
++      }
++
++      retval = dev->drv.drv_write_chunk_fn(dev, nand_chunk,
++                      data,
++                      (data) ? dev->data_bytes_per_chunk : 0,
++                      tag_buf,
++                      (dev->param.tags_9bytes) ? 9 : 8);
++
++      return retval;
++}
++
++/* Return with empty extended tags but add ecc_result.
++ */
++static int return_empty_tags(struct yaffs_ext_tags *tags,
++                           enum yaffs_ecc_result ecc_result,
++                           int retval)
++{
++      if (tags) {
++              memset(tags, 0, sizeof(*tags));
++              tags->ecc_result = ecc_result;
++      }
++
++      return retval;
++}
++
++static int yaffs_tags_compat_read(struct yaffs_dev *dev,
++                                int nand_chunk,
++                                u8 *data,
++                                struct yaffs_ext_tags *tags)
++{
++      struct yaffs_packed_tags1 pt1;
++      enum yaffs_ecc_result ecc_result;
++      int retval;
++      int deleted;
++      u8 tag_buf[9];
++
++      retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk,
++                      data, dev->param.total_bytes_per_chunk,
++                      tag_buf,
++                      (dev->param.tags_9bytes) ? 9 : 8,
++                      &ecc_result);
++
++      switch (ecc_result) {
++      case YAFFS_ECC_RESULT_NO_ERROR:
++      case YAFFS_ECC_RESULT_FIXED:
++              break;
++
++      case YAFFS_ECC_RESULT_UNFIXED:
++      default:
++              return_empty_tags(tags, YAFFS_ECC_RESULT_UNFIXED, 0);
++              tags->block_bad = dev->drv.drv_check_bad_fn(dev, nand_chunk);
++              return YAFFS_FAIL;
++      }
++
++      /* Check for a blank/erased chunk. */
++      if (yaffs_check_ff(tag_buf, 8)) {
++              /* when blank, upper layers want ecc_result to be <= NO_ERROR */
++              return return_empty_tags(tags, YAFFS_ECC_RESULT_NO_ERROR,
++                                       YAFFS_OK);
++      }
++
++      memcpy(&pt1, tag_buf, 8);
++
++      if (!dev->param.tags_9bytes) {
++              /* Read deleted status (bit) then return it to it's non-deleted
++               * state before performing tags mini-ECC check. pt1.deleted is
++               * inverted.
++               */
++              deleted = !pt1.deleted;
++              pt1.deleted = 1;
++      } else {
++              deleted = (hweight8(tag_buf[8]) < 7) ? 1 : 0;
++      }
++
++      /* Check the packed tags mini-ECC and correct if necessary/possible. */
++      retval = yaffs_check_tags_ecc((struct yaffs_tags *)&pt1);
++      switch (retval) {
++      case 0:
++              /* no tags error, use MTD result */
++              break;
++      case 1:
++              /* recovered tags-ECC error */
++              dev->n_tags_ecc_fixed++;
++              if (ecc_result == YAFFS_ECC_RESULT_NO_ERROR)
++                      ecc_result = YAFFS_ECC_RESULT_FIXED;
++              break;
++      default:
++              /* unrecovered tags-ECC error */
++              dev->n_tags_ecc_unfixed++;
++              return return_empty_tags(tags, YAFFS_ECC_RESULT_UNFIXED,
++                                       YAFFS_FAIL);
++      }
++
++      /* Unpack the tags to extended form and set ECC result.
++       * [set should_be_ff just to keep yaffs_unpack_tags1 happy]
++       */
++      pt1.should_be_ff = 0xffffffff;
++      yaffs_unpack_tags1(tags, &pt1);
++      tags->ecc_result = ecc_result;
++
++      /* Set deleted state */
++      tags->is_deleted = deleted;
++      return YAFFS_OK;
++}
++
++static int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int block_no)
++{
++      return dev->drv.drv_mark_bad_fn(dev, block_no);
++}
++
++static int yaffs_tags_compat_query_block(struct yaffs_dev *dev,
++                                       int block_no,
++                                       enum yaffs_block_state *state,
++                                       u32 *seq_number)
++{
++      struct yaffs_ext_tags tags;
++      int retval;
++
++      yaffs_trace(YAFFS_TRACE_MTD, "%s %d", __func__, block_no);
++
++      *seq_number = 0;
++
++      retval = dev->drv.drv_check_bad_fn(dev, block_no);
++      if (retval == YAFFS_FAIL) {
++              *state = YAFFS_BLOCK_STATE_DEAD;
++              goto out;
++      }
++
++      yaffs_tags_compat_read(dev, block_no * dev->param.chunks_per_block,
++                             NULL, &tags);
++
++      if (tags.ecc_result != YAFFS_ECC_RESULT_NO_ERROR) {
++              yaffs_trace(YAFFS_TRACE_MTD, "block %d is marked bad",
++                          block_no);
++              *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
++      } else if (tags.chunk_used) {
++              *seq_number = tags.seq_number;
++              *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
++      } else {
++              *state = YAFFS_BLOCK_STATE_EMPTY;
++      }
++
++      retval = YAFFS_OK;
++
++out:
++      yaffs_trace(YAFFS_TRACE_MTD,
++                  "block query returns seq %u state %d",
++                  *seq_number, *state);
++
++      return retval;
++}
++
++void yaffs_tags_compat_install(struct yaffs_dev *dev)
++{
++      if (dev->param.is_yaffs2)
++              return;
++
++      if (!dev->tagger.write_chunk_tags_fn)
++              dev->tagger.write_chunk_tags_fn = yaffs_tags_compat_write;
++
++      if (!dev->tagger.read_chunk_tags_fn)
++              dev->tagger.read_chunk_tags_fn = yaffs_tags_compat_read;
++
++      if (!dev->tagger.query_block_fn)
++              dev->tagger.query_block_fn = yaffs_tags_compat_query_block;
++
++      if (!dev->tagger.mark_bad_fn)
++              dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad;
++}
++#endif
diff --git a/target/linux/generic/patches-4.0/503-yaffs-3.12-convert-readdir-to-iterate.patch b/target/linux/generic/patches-4.0/503-yaffs-3.12-convert-readdir-to-iterate.patch
deleted file mode 100644 (file)
index 586c141..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
---- a/fs/yaffs2/yaffs_vfs.c
-+++ b/fs/yaffs2/yaffs_vfs.c
-@@ -1701,6 +1701,110 @@ static void yaffs_remove_obj_callback(st
- /*-----------------------------------------------------------------*/
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
-+static int yaffs_readdir(struct file *file, struct dir_context *ctx)
-+{
-+      struct yaffs_obj *obj;
-+      struct yaffs_dev *dev;
-+      struct yaffs_search_context *sc;
-+      struct inode *inode = file->f_dentry->d_inode;
-+      unsigned long offset, curoffs;
-+      struct yaffs_obj *l;
-+      int ret_val = 0;
-+
-+      char name[YAFFS_MAX_NAME_LENGTH + 1];
-+
-+      obj = yaffs_dentry_to_obj(file->f_dentry);
-+      dev = obj->my_dev;
-+
-+      yaffs_gross_lock(dev);
-+
-+      yaffs_dev_to_lc(dev)->readdir_process = current;
-+
-+      offset = ctx->pos;
-+
-+      sc = yaffs_new_search(obj);
-+      if (!sc) {
-+              ret_val = -ENOMEM;
-+              goto out;
-+      }
-+
-+      yaffs_trace(YAFFS_TRACE_OS,
-+              "yaffs_readdir: starting at %d", (int)offset);
-+
-+      if (offset == 0) {
-+              yaffs_trace(YAFFS_TRACE_OS,
-+                      "yaffs_readdir: entry . ino %d",
-+                      (int)inode->i_ino);
-+              yaffs_gross_unlock(dev);
-+              if (!dir_emit_dot(file, ctx)) {
-+                      yaffs_gross_lock(dev);
-+                      goto out;
-+              }
-+              yaffs_gross_lock(dev);
-+              offset++;
-+              ctx->pos++;
-+      }
-+      if (offset == 1) {
-+              yaffs_trace(YAFFS_TRACE_OS,
-+                      "yaffs_readdir: entry .. ino %d",
-+                      (int)file->f_dentry->d_parent->d_inode->i_ino);
-+              yaffs_gross_unlock(dev);
-+              if (!dir_emit_dotdot(file, ctx)) {
-+                      yaffs_gross_lock(dev);
-+                      goto out;
-+              }
-+              yaffs_gross_lock(dev);
-+              offset++;
-+              ctx->pos++;
-+      }
-+
-+      curoffs = 1;
-+
-+      /* If the directory has changed since the open or last call to
-+         readdir, rewind to after the 2 canned entries. */
-+      if (file->f_version != inode->i_version) {
-+              offset = 2;
-+              ctx->pos = offset;
-+              file->f_version = inode->i_version;
-+      }
-+
-+      while (sc->next_return) {
-+              curoffs++;
-+              l = sc->next_return;
-+              if (curoffs >= offset) {
-+                      int this_inode = yaffs_get_obj_inode(l);
-+                      int this_type = yaffs_get_obj_type(l);
-+
-+                      yaffs_get_obj_name(l, name, YAFFS_MAX_NAME_LENGTH + 1);
-+                      yaffs_trace(YAFFS_TRACE_OS,
-+                              "yaffs_readdir: %s inode %d",
-+                              name, yaffs_get_obj_inode(l));
-+
-+                      yaffs_gross_unlock(dev);
-+
-+                      if (!dir_emit(ctx, name, strlen(name),
-+                                    this_inode, this_type) < 0) {
-+                              yaffs_gross_lock(dev);
-+                              goto out;
-+                      }
-+
-+                      yaffs_gross_lock(dev);
-+
-+                      offset++;
-+                      ctx->pos++;
-+              }
-+              yaffs_search_advance(sc);
-+      }
-+
-+out:
-+      yaffs_search_end(sc);
-+      yaffs_dev_to_lc(dev)->readdir_process = NULL;
-+      yaffs_gross_unlock(dev);
-+
-+      return ret_val;
-+}
-+#else
- static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
- {
-       struct yaffs_obj *obj;
-@@ -1807,10 +1911,15 @@ out:
-       return ret_val;
- }
-+#endif
- static const struct file_operations yaffs_dir_operations = {
-       .read = generic_read_dir,
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
-+      .iterate = yaffs_readdir,
-+#else
-       .readdir = yaffs_readdir,
-+#endif
-       .fsync = yaffs_sync_object,
-       .llseek = generic_file_llseek,
- };
index 4858519ca1465b0e715438b8f51eb52aaa76225d..9ecaa72832238f8a1dca30787e8c48c2e66085dc 100644 (file)
@@ -4,7 +4,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
 ---
 --- a/fs/yaffs2/yaffs_vfs.c
 +++ b/fs/yaffs2/yaffs_vfs.c
-@@ -2634,6 +2634,7 @@ static const struct super_operations yaf
+@@ -2605,6 +2605,7 @@ static const struct super_operations yaf
  
  struct yaffs_options {
        int inband_tags;
@@ -12,7 +12,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
        int skip_checkpoint_read;
        int skip_checkpoint_write;
        int no_cache;
-@@ -2673,6 +2674,8 @@ static int yaffs_parse_options(struct ya
+@@ -2644,6 +2645,8 @@ static int yaffs_parse_options(struct ya
  
                if (!strcmp(cur_opt, "inband-tags")) {
                        options->inband_tags = 1;
@@ -21,7 +21,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
                } else if (!strcmp(cur_opt, "tags-ecc-off")) {
                        options->tags_ecc_on = 0;
                        options->tags_ecc_overridden = 1;
-@@ -2746,7 +2749,6 @@ static struct super_block *yaffs_interna
+@@ -2717,7 +2720,6 @@ static struct super_block *yaffs_interna
        struct yaffs_param *param;
  
        int read_only = 0;
@@ -29,7 +29,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
  
        struct yaffs_options options;
  
-@@ -2786,6 +2788,9 @@ static struct super_block *yaffs_interna
+@@ -2757,6 +2759,9 @@ static struct super_block *yaffs_interna
  
        memset(&options, 0, sizeof(options));
  
@@ -39,7 +39,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
        if (yaffs_parse_options(&options, data_str)) {
                /* Option parsing failed */
                return NULL;
-@@ -2819,17 +2824,22 @@ static struct super_block *yaffs_interna
+@@ -2790,17 +2795,22 @@ static struct super_block *yaffs_interna
        }
  
        /* Added NCB 26/5/2006 for completeness */
@@ -68,7 +68,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
                return NULL;
  
        /* OK, so if we got here, we have an MTD that's NAND and looks
-@@ -2890,7 +2900,8 @@ static struct super_block *yaffs_interna
+@@ -2857,7 +2867,8 @@ static struct super_block *yaffs_interna
  
        param->n_reserved_blocks = 5;
        param->n_caches = (options.no_cache) ? 0 : 10;
@@ -80,15 +80,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
        if (options.lazy_loading_overridden)
 --- a/fs/yaffs2/yaffs_mtdif.c
 +++ b/fs/yaffs2/yaffs_mtdif.c
-@@ -16,6 +16,7 @@
- #include "yaffs_mtdif.h"
- #include "linux/mtd/mtd.h"
-+#include "uapi/linux/major.h"
- #include "linux/types.h"
- #include "linux/time.h"
- #include "linux/mtd/nand.h"
-@@ -276,7 +277,8 @@ struct mtd_info * yaffs_get_mtd_device(d
+@@ -278,7 +278,8 @@ struct mtd_info * yaffs_get_mtd_device(d
        return mtd;
  }
  
@@ -98,7 +90,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
  {
        if (yaffs_version == 2) {
                if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
-@@ -295,6 +297,12 @@ int yaffs_verify_mtd(struct mtd_info *mt
+@@ -297,6 +298,12 @@ int yaffs_verify_mtd(struct mtd_info *mt
                        );
                        return -1;
                }
diff --git a/target/linux/generic/patches-4.0/504-yaffs-3.16-new-fops.patch b/target/linux/generic/patches-4.0/504-yaffs-3.16-new-fops.patch
new file mode 100644 (file)
index 0000000..11c6da0
--- /dev/null
@@ -0,0 +1,25 @@
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -774,7 +774,21 @@ static int yaffs_sync_object(struct file
+ }
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
++static const struct file_operations yaffs_file_operations = {
++      .read = new_sync_read,
++      .read_iter = generic_file_read_iter,
++      .write = new_sync_write,
++      .write_iter = generic_file_write_iter,
++      .mmap = generic_file_mmap,
++      .flush = yaffs_file_flush,
++      .fsync = yaffs_sync_object,
++      .splice_read = generic_file_splice_read,
++      .splice_write = iter_file_splice_write,
++      .llseek = generic_file_llseek,
++};
++
++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
+ static const struct file_operations yaffs_file_operations = {
+       .read = do_sync_read,
+       .write = do_sync_write,
diff --git a/target/linux/generic/patches-4.0/504-yaffs-fix-compat-tags-handling.patch b/target/linux/generic/patches-4.0/504-yaffs-fix-compat-tags-handling.patch
deleted file mode 100644 (file)
index a18cf6f..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-Subject: yaffs: fix compat tags handling
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
---- a/fs/yaffs2/yaffs_tagscompat.c
-+++ b/fs/yaffs2/yaffs_tagscompat.c
-@@ -17,7 +17,9 @@
- #include "yaffs_getblockinfo.h"
- #include "yaffs_trace.h"
-+#if 0
- static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk);
-+#endif
- /********** Tags ECC calculations  *********/
-@@ -71,6 +73,7 @@ int yaffs_check_tags_ecc(struct yaffs_ta
-       return 0;
- }
-+#if 0
- /********** Tags **********/
- static void yaffs_load_tags_to_spare(struct yaffs_spare *spare_ptr,
-@@ -379,3 +382,214 @@ void yaffs_tags_compat_install(struct ya
-       if(!dev->tagger.mark_bad_fn)
-               dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad;
- }
-+#else
-+
-+#include "yaffs_packedtags1.h"
-+
-+static int yaffs_tags_compat_write(struct yaffs_dev *dev,
-+                                 int nand_chunk,
-+                                 const u8 *data,
-+                                 const struct yaffs_ext_tags *tags)
-+{
-+      struct yaffs_packed_tags1 pt1;
-+      u8 tag_buf[9];
-+      int retval;
-+
-+      /* we assume that yaffs_packed_tags1 and yaffs_tags are compatible */
-+      compile_time_assertion(sizeof(struct yaffs_packed_tags1) == 12);
-+      compile_time_assertion(sizeof(struct yaffs_tags) == 8);
-+
-+      yaffs_pack_tags1(&pt1, tags);
-+      yaffs_calc_tags_ecc((struct yaffs_tags *)&pt1);
-+
-+      /* When deleting a chunk, the upper layer provides only skeletal
-+       * tags, one with is_deleted set.  However, we need to update the
-+       * tags, not erase them completely.  So we use the NAND write property
-+       * that only zeroed-bits stick and set tag bytes to all-ones and
-+       * zero just the (not) deleted bit.
-+       */
-+      if (!dev->param.tags_9bytes) {
-+              if (tags->is_deleted) {
-+                      memset(&pt1, 0xff, 8);
-+                      /* clear delete status bit to indicate deleted */
-+                      pt1.deleted = 0;
-+              }
-+              memcpy(tag_buf, &pt1, 8);
-+      } else {
-+              if (tags->is_deleted) {
-+                      memset(tag_buf, 0xff, 8);
-+                      tag_buf[8] = 0;
-+              } else {
-+                      memcpy(tag_buf, &pt1, 8);
-+                      tag_buf[8] = 0xff;
-+              }
-+      }
-+
-+      retval = dev->drv.drv_write_chunk_fn(dev, nand_chunk,
-+                      data,
-+                      (data) ? dev->data_bytes_per_chunk : 0,
-+                      tag_buf,
-+                      (dev->param.tags_9bytes) ? 9 : 8);
-+
-+      return retval;
-+}
-+
-+/* Return with empty extended tags but add ecc_result.
-+ */
-+static int return_empty_tags(struct yaffs_ext_tags *tags,
-+                           enum yaffs_ecc_result ecc_result,
-+                           int retval)
-+{
-+      if (tags) {
-+              memset(tags, 0, sizeof(*tags));
-+              tags->ecc_result = ecc_result;
-+      }
-+
-+      return retval;
-+}
-+
-+static int yaffs_tags_compat_read(struct yaffs_dev *dev,
-+                                int nand_chunk,
-+                                u8 *data,
-+                                struct yaffs_ext_tags *tags)
-+{
-+      struct yaffs_packed_tags1 pt1;
-+      enum yaffs_ecc_result ecc_result;
-+      int retval;
-+      int deleted;
-+      u8 tag_buf[9];
-+
-+      retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk,
-+                      data, dev->param.total_bytes_per_chunk,
-+                      tag_buf,
-+                      (dev->param.tags_9bytes) ? 9 : 8,
-+                      &ecc_result);
-+
-+      switch (ecc_result) {
-+      case YAFFS_ECC_RESULT_NO_ERROR:
-+      case YAFFS_ECC_RESULT_FIXED:
-+              break;
-+
-+      case YAFFS_ECC_RESULT_UNFIXED:
-+      default:
-+              return_empty_tags(tags, YAFFS_ECC_RESULT_UNFIXED, 0);
-+              tags->block_bad = dev->drv.drv_check_bad_fn(dev, nand_chunk);
-+              return YAFFS_FAIL;
-+      }
-+
-+      /* Check for a blank/erased chunk. */
-+      if (yaffs_check_ff(tag_buf, 8)) {
-+              /* when blank, upper layers want ecc_result to be <= NO_ERROR */
-+              return return_empty_tags(tags, YAFFS_ECC_RESULT_NO_ERROR,
-+                                       YAFFS_OK);
-+      }
-+
-+      memcpy(&pt1, tag_buf, 8);
-+
-+      if (!dev->param.tags_9bytes) {
-+              /* Read deleted status (bit) then return it to it's non-deleted
-+               * state before performing tags mini-ECC check. pt1.deleted is
-+               * inverted.
-+               */
-+              deleted = !pt1.deleted;
-+              pt1.deleted = 1;
-+      } else {
-+              deleted = (hweight8(tag_buf[8]) < 7) ? 1 : 0;
-+      }
-+
-+      /* Check the packed tags mini-ECC and correct if necessary/possible. */
-+      retval = yaffs_check_tags_ecc((struct yaffs_tags *)&pt1);
-+      switch (retval) {
-+      case 0:
-+              /* no tags error, use MTD result */
-+              break;
-+      case 1:
-+              /* recovered tags-ECC error */
-+              dev->n_tags_ecc_fixed++;
-+              if (ecc_result == YAFFS_ECC_RESULT_NO_ERROR)
-+                      ecc_result = YAFFS_ECC_RESULT_FIXED;
-+              break;
-+      default:
-+              /* unrecovered tags-ECC error */
-+              dev->n_tags_ecc_unfixed++;
-+              return return_empty_tags(tags, YAFFS_ECC_RESULT_UNFIXED,
-+                                       YAFFS_FAIL);
-+      }
-+
-+      /* Unpack the tags to extended form and set ECC result.
-+       * [set should_be_ff just to keep yaffs_unpack_tags1 happy]
-+       */
-+      pt1.should_be_ff = 0xffffffff;
-+      yaffs_unpack_tags1(tags, &pt1);
-+      tags->ecc_result = ecc_result;
-+
-+      /* Set deleted state */
-+      tags->is_deleted = deleted;
-+      return YAFFS_OK;
-+}
-+
-+static int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int block_no)
-+{
-+      return dev->drv.drv_mark_bad_fn(dev, block_no);
-+}
-+
-+static int yaffs_tags_compat_query_block(struct yaffs_dev *dev,
-+                                       int block_no,
-+                                       enum yaffs_block_state *state,
-+                                       u32 *seq_number)
-+{
-+      struct yaffs_ext_tags tags;
-+      int retval;
-+
-+      yaffs_trace(YAFFS_TRACE_MTD, "%s %d", __func__, block_no);
-+
-+      *seq_number = 0;
-+
-+      retval = dev->drv.drv_check_bad_fn(dev, block_no);
-+      if (retval == YAFFS_FAIL) {
-+              *state = YAFFS_BLOCK_STATE_DEAD;
-+              goto out;
-+      }
-+
-+      yaffs_tags_compat_read(dev, block_no * dev->param.chunks_per_block,
-+                             NULL, &tags);
-+
-+      if (tags.ecc_result != YAFFS_ECC_RESULT_NO_ERROR) {
-+              yaffs_trace(YAFFS_TRACE_MTD, "block %d is marked bad",
-+                          block_no);
-+              *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
-+      } else if (tags.chunk_used) {
-+              *seq_number = tags.seq_number;
-+              *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
-+      } else {
-+              *state = YAFFS_BLOCK_STATE_EMPTY;
-+      }
-+
-+      retval = YAFFS_OK;
-+
-+out:
-+      yaffs_trace(YAFFS_TRACE_MTD,
-+                  "block query returns seq %u state %d",
-+                  *seq_number, *state);
-+
-+      return retval;
-+}
-+
-+void yaffs_tags_compat_install(struct yaffs_dev *dev)
-+{
-+      if (dev->param.is_yaffs2)
-+              return;
-+
-+      if (!dev->tagger.write_chunk_tags_fn)
-+              dev->tagger.write_chunk_tags_fn = yaffs_tags_compat_write;
-+
-+      if (!dev->tagger.read_chunk_tags_fn)
-+              dev->tagger.read_chunk_tags_fn = yaffs_tags_compat_read;
-+
-+      if (!dev->tagger.query_block_fn)
-+              dev->tagger.query_block_fn = yaffs_tags_compat_query_block;
-+
-+      if (!dev->tagger.mark_bad_fn)
-+              dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad;
-+}
-+#endif
diff --git a/target/linux/generic/patches-4.0/505-yaffs-3.16-new-fops.patch b/target/linux/generic/patches-4.0/505-yaffs-3.16-new-fops.patch
deleted file mode 100644 (file)
index be88ab9..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
---- a/fs/yaffs2/yaffs_vfs.c
-+++ b/fs/yaffs2/yaffs_vfs.c
-@@ -794,15 +794,15 @@ static int yaffs_sync_object(struct file
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
- static const struct file_operations yaffs_file_operations = {
--      .read = do_sync_read,
--      .write = do_sync_write,
--      .aio_read = generic_file_aio_read,
--      .aio_write = generic_file_aio_write,
-+      .read = new_sync_read,
-+      .write = new_sync_write,
-+      .read_iter = generic_file_read_iter,
-+      .write_iter = generic_file_write_iter,
-       .mmap = generic_file_mmap,
-       .flush = yaffs_file_flush,
-       .fsync = yaffs_sync_object,
-       .splice_read = generic_file_splice_read,
--      .splice_write = generic_file_splice_write,
-+      .splice_write = iter_file_splice_write,
-       .llseek = generic_file_llseek,
- };
-@@ -1050,7 +1050,7 @@ static int yaffs_readlink(struct dentry
-       if (!alias)
-               return -ENOMEM;
--      ret = vfs_readlink(dentry, buffer, buflen, alias);
-+      ret = readlink_copy(buffer, buflen, alias);
-       kfree(alias);
-       return ret;
- }