summaryrefslogtreecommitdiffstats
path: root/target
diff options
context:
space:
mode:
authorGabor Juhos <juhosg@openwrt.org>2015-03-31 15:31:57 +0000
committerGabor Juhos <juhosg@openwrt.org>2015-03-31 15:31:57 +0000
commit82f0308be91d572df10dadfe59f196e14760dc3d (patch)
tree06f81e98d755d3b1d9a199b9b78a277ce3577b03 /target
parent640318e62090821c1778dc9e3dfc5608bdcd7f0b (diff)
downloadmaster-31e0f0ae-82f0308be91d572df10dadfe59f196e14760dc3d.tar.gz
master-31e0f0ae-82f0308be91d572df10dadfe59f196e14760dc3d.tar.bz2
master-31e0f0ae-82f0308be91d572df10dadfe59f196e14760dc3d.zip
kernel: update yaffs code to the latest version
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
Diffstat (limited to 'target')
-rw-r--r--target/linux/generic/files/fs/yaffs2/NOTE.openwrt2
-rw-r--r--target/linux/generic/files/fs/yaffs2/yaffs_attribs.c16
-rw-r--r--target/linux/generic/files/fs/yaffs2/yaffs_guts.c342
-rw-r--r--target/linux/generic/files/fs/yaffs2/yaffs_guts.h35
-rw-r--r--target/linux/generic/files/fs/yaffs2/yaffs_mtdif.c4
-rw-r--r--target/linux/generic/files/fs/yaffs2/yaffs_packedtags1.h14
-rw-r--r--target/linux/generic/files/fs/yaffs2/yaffs_summary.c1
-rw-r--r--target/linux/generic/files/fs/yaffs2/yaffs_vfs.c218
-rw-r--r--target/linux/generic/files/fs/yaffs2/yaffs_yaffs2.c8
-rw-r--r--target/linux/generic/patches-3.14/501-yaffs-3.5-convert-to-use-kuid_t-kgid_t.patch155
-rw-r--r--target/linux/generic/patches-3.14/501-yaffs-add-missing-flush-arguments.patch38
-rw-r--r--target/linux/generic/patches-3.14/502-yaffs-3.10-disable-proc-entry.patch44
-rw-r--r--target/linux/generic/patches-3.14/502-yaffs-fix-compat-tags-handling.patch (renamed from target/linux/generic/patches-3.14/504-yaffs-fix-compat-tags-handling.patch)0
-rw-r--r--target/linux/generic/patches-3.14/503-yaffs-3.12-convert-readdir-to-iterate.patch129
-rw-r--r--target/linux/generic/patches-3.14/503-yaffs-add-tags-9bytes-mount-option.patch24
-rw-r--r--target/linux/generic/patches-3.14/504-yaffs-3.16-new-fops.patch25
-rw-r--r--target/linux/generic/patches-3.18/501-yaffs-3.5-convert-to-use-kuid_t-kgid_t.patch155
-rw-r--r--target/linux/generic/patches-3.18/501-yaffs-add-missing-flush-arguments.patch38
-rw-r--r--target/linux/generic/patches-3.18/502-yaffs-3.10-disable-proc-entry.patch44
-rw-r--r--target/linux/generic/patches-3.18/502-yaffs-fix-compat-tags-handling.patch (renamed from target/linux/generic/patches-3.18/504-yaffs-fix-compat-tags-handling.patch)0
-rw-r--r--target/linux/generic/patches-3.18/503-yaffs-3.12-convert-readdir-to-iterate.patch129
-rw-r--r--target/linux/generic/patches-3.18/503-yaffs-add-tags-9bytes-mount-option.patch24
-rw-r--r--target/linux/generic/patches-3.18/504-yaffs-3.16-new-fops.patch25
-rw-r--r--target/linux/generic/patches-3.18/505-yaffs-3.16-new-fops.patch32
-rw-r--r--target/linux/generic/patches-4.0/501-yaffs-3.5-convert-to-use-kuid_t-kgid_t.patch155
-rw-r--r--target/linux/generic/patches-4.0/501-yaffs-add-missing-flush-arguments.patch38
-rw-r--r--target/linux/generic/patches-4.0/502-yaffs-3.10-disable-proc-entry.patch44
-rw-r--r--target/linux/generic/patches-4.0/502-yaffs-fix-compat-tags-handling.patch (renamed from target/linux/generic/patches-4.0/504-yaffs-fix-compat-tags-handling.patch)0
-rw-r--r--target/linux/generic/patches-4.0/503-yaffs-3.12-convert-readdir-to-iterate.patch129
-rw-r--r--target/linux/generic/patches-4.0/503-yaffs-add-tags-9bytes-mount-option.patch24
-rw-r--r--target/linux/generic/patches-4.0/504-yaffs-3.16-new-fops.patch25
-rw-r--r--target/linux/generic/patches-4.0/505-yaffs-3.16-new-fops.patch32
32 files changed, 651 insertions, 1298 deletions
diff --git a/target/linux/generic/files/fs/yaffs2/NOTE.openwrt b/target/linux/generic/files/fs/yaffs2/NOTE.openwrt
index 0be479d66c..ad807bdc09 100644
--- a/target/linux/generic/files/fs/yaffs2/NOTE.openwrt
+++ b/target/linux/generic/files/fs/yaffs2/NOTE.openwrt
@@ -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)
diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_attribs.c b/target/linux/generic/files/fs/yaffs2/yaffs_attribs.c
index 3d778f2266..711941f137 100644
--- a/target/linux/generic/files/fs/yaffs2/yaffs_attribs.c
+++ b/target/linux/generic/files/fs/yaffs2/yaffs_attribs.c
@@ -14,6 +14,14 @@
#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;
diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_guts.c b/target/linux/generic/files/fs/yaffs2/yaffs_guts.c
index 1fd464d68a..1c0ae71320 100644
--- a/target/linux/generic/files/fs/yaffs2/yaffs_guts.c
+++ b/target/linux/generic/files/fs/yaffs2/yaffs_guts.c
@@ -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;
diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_guts.h b/target/linux/generic/files/fs/yaffs2/yaffs_guts.h
index 05785367cb..231f8ac567 100644
--- a/target/linux/generic/files/fs/yaffs2/yaffs_guts.h
+++ b/target/linux/generic/files/fs/yaffs2/yaffs_guts.h
@@ -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);
diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_mtdif.c b/target/linux/generic/files/fs/yaffs2/yaffs_mtdif.c
index 7ae63c54a9..7c01461ab9 100644
--- a/target/linux/generic/files/fs/yaffs2/yaffs_mtdif.c
+++ b/target/linux/generic/files/fs/yaffs2/yaffs_mtdif.c
@@ -22,12 +22,14 @@
#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
diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_packedtags1.h b/target/linux/generic/files/fs/yaffs2/yaffs_packedtags1.h
index b80f0a5b15..3015d58a07 100644
--- a/target/linux/generic/files/fs/yaffs2/yaffs_packedtags1.h
+++ b/target/linux/generic/files/fs/yaffs2/yaffs_packedtags1.h
@@ -21,13 +21,13 @@
#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;
};
diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_summary.c b/target/linux/generic/files/fs/yaffs2/yaffs_summary.c
index 6f3c7839fa..3c9e72321e 100644
--- a/target/linux/generic/files/fs/yaffs2/yaffs_summary.c
+++ b/target/linux/generic/files/fs/yaffs2/yaffs_summary.c
@@ -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;
diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_vfs.c b/target/linux/generic/files/fs/yaffs2/yaffs_vfs.c
index 67050d4e3d..76bc1db59f 100644
--- a/target/linux/generic/files/fs/yaffs2/yaffs_vfs.c
+++ b/target/linux/generic/files/fs/yaffs2/yaffs_vfs.c
@@ -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 */
diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_yaffs2.c b/target/linux/generic/files/fs/yaffs2/yaffs_yaffs2.c
index f1dc972276..8c31a661ff 100644
--- a/target/linux/generic/files/fs/yaffs2/yaffs_yaffs2.c
+++ b/target/linux/generic/files/fs/yaffs2/yaffs_yaffs2.c
@@ -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
index c1f7367dd8..0000000000
--- a/target/linux/generic/patches-3.14/501-yaffs-3.5-convert-to-use-kuid_t-kgid_t.patch
+++ /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
index 0000000000..d5ccc3e81e
--- /dev/null
+++ b/target/linux/generic/patches-3.14/501-yaffs-add-missing-flush-arguments.patch
@@ -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
index 5b73d3898b..0000000000
--- a/target/linux/generic/patches-3.14/502-yaffs-3.10-disable-proc-entry.patch
+++ /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/504-yaffs-fix-compat-tags-handling.patch b/target/linux/generic/patches-3.14/502-yaffs-fix-compat-tags-handling.patch
index a18cf6fd7b..a18cf6fd7b 100644
--- a/target/linux/generic/patches-3.14/504-yaffs-fix-compat-tags-handling.patch
+++ b/target/linux/generic/patches-3.14/502-yaffs-fix-compat-tags-handling.patch
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
index 586c141e0a..0000000000
--- a/target/linux/generic/patches-3.14/503-yaffs-3.12-convert-readdir-to-iterate.patch
+++ /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,
- };
diff --git a/target/linux/generic/patches-3.14/503-yaffs-add-tags-9bytes-mount-option.patch b/target/linux/generic/patches-3.14/503-yaffs-add-tags-9bytes-mount-option.patch
index 4858519ca1..9ecaa72832 100644
--- a/target/linux/generic/patches-3.14/503-yaffs-add-tags-9bytes-mount-option.patch
+++ b/target/linux/generic/patches-3.14/503-yaffs-add-tags-9bytes-mount-option.patch
@@ -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
index 0000000000..11c6da0516
--- /dev/null
+++ b/target/linux/generic/patches-3.14/504-yaffs-3.16-new-fops.patch
@@ -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/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
index c1f7367dd8..0000000000
--- a/target/linux/generic/patches-3.18/501-yaffs-3.5-convert-to-use-kuid_t-kgid_t.patch
+++ /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
index 0000000000..d5ccc3e81e
--- /dev/null
+++ b/target/linux/generic/patches-3.18/501-yaffs-add-missing-flush-arguments.patch
@@ -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
index 5b73d3898b..0000000000
--- a/target/linux/generic/patches-3.18/502-yaffs-3.10-disable-proc-entry.patch
+++ /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/504-yaffs-fix-compat-tags-handling.patch b/target/linux/generic/patches-3.18/502-yaffs-fix-compat-tags-handling.patch
index a18cf6fd7b..a18cf6fd7b 100644
--- a/target/linux/generic/patches-3.18/504-yaffs-fix-compat-tags-handling.patch
+++ b/target/linux/generic/patches-3.18/502-yaffs-fix-compat-tags-handling.patch
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
index 586c141e0a..0000000000
--- a/target/linux/generic/patches-3.18/503-yaffs-3.12-convert-readdir-to-iterate.patch
+++ /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,
- };
diff --git a/target/linux/generic/patches-3.18/503-yaffs-add-tags-9bytes-mount-option.patch b/target/linux/generic/patches-3.18/503-yaffs-add-tags-9bytes-mount-option.patch
index 4858519ca1..9ecaa72832 100644
--- a/target/linux/generic/patches-3.18/503-yaffs-add-tags-9bytes-mount-option.patch
+++ b/target/linux/generic/patches-3.18/503-yaffs-add-tags-9bytes-mount-option.patch
@@ -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
index 0000000000..11c6da0516
--- /dev/null
+++ b/target/linux/generic/patches-3.18/504-yaffs-3.16-new-fops.patch
@@ -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/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
index be88ab9525..0000000000
--- a/target/linux/generic/patches-3.18/505-yaffs-3.16-new-fops.patch
+++ /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
index c1f7367dd8..0000000000
--- a/target/linux/generic/patches-4.0/501-yaffs-3.5-convert-to-use-kuid_t-kgid_t.patch
+++ /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
index 0000000000..d5ccc3e81e
--- /dev/null
+++ b/target/linux/generic/patches-4.0/501-yaffs-add-missing-flush-arguments.patch
@@ -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
index 5b73d3898b..0000000000
--- a/target/linux/generic/patches-4.0/502-yaffs-3.10-disable-proc-entry.patch
+++ /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/504-yaffs-fix-compat-tags-handling.patch b/target/linux/generic/patches-4.0/502-yaffs-fix-compat-tags-handling.patch
index a18cf6fd7b..a18cf6fd7b 100644
--- a/target/linux/generic/patches-4.0/504-yaffs-fix-compat-tags-handling.patch
+++ b/target/linux/generic/patches-4.0/502-yaffs-fix-compat-tags-handling.patch
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
index 586c141e0a..0000000000
--- a/target/linux/generic/patches-4.0/503-yaffs-3.12-convert-readdir-to-iterate.patch
+++ /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,
- };
diff --git a/target/linux/generic/patches-4.0/503-yaffs-add-tags-9bytes-mount-option.patch b/target/linux/generic/patches-4.0/503-yaffs-add-tags-9bytes-mount-option.patch
index 4858519ca1..9ecaa72832 100644
--- a/target/linux/generic/patches-4.0/503-yaffs-add-tags-9bytes-mount-option.patch
+++ b/target/linux/generic/patches-4.0/503-yaffs-add-tags-9bytes-mount-option.patch
@@ -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
index 0000000000..11c6da0516
--- /dev/null
+++ b/target/linux/generic/patches-4.0/504-yaffs-3.16-new-fops.patch
@@ -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/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
index be88ab9525..0000000000
--- a/target/linux/generic/patches-4.0/505-yaffs-3.16-new-fops.patch
+++ /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;
- }