From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sat, 15 Aug 2015 17:16:03 +0000 (+0000)
Subject: kernel: yaffs2: update to version from 2015-06-02
X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=b1bd85c40eb5d22253fcc09c441abb50308ecd40;p=openwrt%2Fstaging%2Fnbd.git

kernel: yaffs2: update to version from 2015-06-02

In addition to the update this also fixes compile problems with kernel 4.1.

This closes #20323.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>

SVN-Revision: 46609
---

diff --git a/target/linux/generic/files/fs/yaffs2/NOTE.openwrt b/target/linux/generic/files/fs/yaffs2/NOTE.openwrt
index ad807bdc09..e84fbe6fc6 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: 7e5cf0fa1b694f835cdc184a8395b229fa29f9ae (2014-08-07)
+Version: 583dbd9cc2668870cb013f051ba59f7d3e513dae (2015-06-02)
diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_checkptrw.c b/target/linux/generic/files/fs/yaffs2/yaffs_checkptrw.c
index e739fb4a10..16ee1e0695 100644
--- a/target/linux/generic/files/fs/yaffs2/yaffs_checkptrw.c
+++ b/target/linux/generic/files/fs/yaffs2/yaffs_checkptrw.c
@@ -237,8 +237,9 @@ int yaffs2_checkpt_open(struct yaffs_dev *dev, int writing)
 	dev->blocks_in_checkpt = 0;
 	dev->checkpt_max_blocks =
 	    (dev->internal_end_block - dev->internal_start_block) / 16 + 2;
-	dev->checkpt_block_list =
-	    kmalloc(sizeof(int) * dev->checkpt_max_blocks, GFP_NOFS);
+	if (!dev->checkpt_block_list)
+		dev->checkpt_block_list =
+		      kmalloc(sizeof(int) * dev->checkpt_max_blocks, GFP_NOFS);
 
 	if (!dev->checkpt_block_list)
 		return 0;
@@ -348,7 +349,6 @@ int yaffs2_checkpt_wr(struct yaffs_dev *dev, const void *data, int n_bytes)
 int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes)
 {
 	int i = 0;
-	int ok = 1;
 	struct yaffs_ext_tags tags;
 	int chunk;
 	int offset_chunk;
@@ -360,7 +360,7 @@ int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes)
 	if (dev->checkpt_open_write)
 		return -1;
 
-	while (i < n_bytes && ok) {
+	while (i < n_bytes) {
 
 		if (dev->checkpt_byte_offs < 0 ||
 		    dev->checkpt_byte_offs >= dev->data_bytes_per_chunk) {
@@ -370,10 +370,9 @@ int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes)
 				dev->checkpt_cur_chunk = 0;
 			}
 
-			if (dev->checkpt_cur_block < 0) {
-				ok = 0;
+			/* Bail out if we can't find a checpoint block */
+			if (dev->checkpt_cur_block < 0)
 				break;
-			}
 
 			chunk = dev->checkpt_cur_block *
 			    dev->param.chunks_per_block +
@@ -382,22 +381,21 @@ int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes)
 			offset_chunk = apply_chunk_offset(dev, chunk);
 			dev->n_page_reads++;
 
-			/* read in the next chunk */
+			/* Read in the next chunk */
 			dev->tagger.read_chunk_tags_fn(dev,
 						offset_chunk,
 						dev->checkpt_buffer,
 						&tags);
 
+			/* Bail out if the chunk is corrupted. */
 			if (tags.chunk_id != (dev->checkpt_page_seq + 1) ||
 			    tags.ecc_result > YAFFS_ECC_RESULT_FIXED ||
-			    tags.seq_number != YAFFS_SEQUENCE_CHECKPOINT_DATA) {
-				ok = 0;
+			    tags.seq_number != YAFFS_SEQUENCE_CHECKPOINT_DATA)
 				break;
-			}
-			if(!yaffs2_checkpt_check_chunk_hdr(dev)) {
-				ok = 0;
+
+			/* Bail out if it is not a checkpoint chunk. */
+			if(!yaffs2_checkpt_check_chunk_hdr(dev))
 				break;
-			}
 
 			dev->checkpt_page_seq++;
 			dev->checkpt_cur_chunk++;
@@ -417,7 +415,7 @@ int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes)
 		dev->checkpt_byte_count++;
 	}
 
-	return i;
+	return i; /* Number of bytes read */
 }
 
 int yaffs_checkpt_close(struct yaffs_dev *dev)
@@ -441,8 +439,6 @@ int yaffs_checkpt_close(struct yaffs_dev *dev)
 			if (bi && bi->block_state == YAFFS_BLOCK_STATE_EMPTY)
 				bi->block_state = YAFFS_BLOCK_STATE_CHECKPOINT;
 		}
-		kfree(dev->checkpt_block_list);
-		dev->checkpt_block_list = NULL;
 	}
 
 	dev->n_free_chunks -=
@@ -452,14 +448,10 @@ int yaffs_checkpt_close(struct yaffs_dev *dev)
 	yaffs_trace(YAFFS_TRACE_CHECKPOINT, "checkpoint byte count %d",
 		dev->checkpt_byte_count);
 
-	if (dev->checkpt_buffer) {
-		/* free the buffer */
-		kfree(dev->checkpt_buffer);
-		dev->checkpt_buffer = NULL;
+	if (dev->checkpt_buffer)
 		return 1;
-	} else {
+	else
 		return 0;
-	}
 }
 
 int yaffs2_checkpt_invalidate_stream(struct yaffs_dev *dev)
diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_guts.c b/target/linux/generic/files/fs/yaffs2/yaffs_guts.c
index 1c0ae71320..89fb2a9bba 100644
--- a/target/linux/generic/files/fs/yaffs2/yaffs_guts.c
+++ b/target/linux/generic/files/fs/yaffs2/yaffs_guts.c
@@ -1922,21 +1922,18 @@ static int yaffs_new_obj_id(struct yaffs_dev *dev)
 	struct list_head *i;
 	u32 n = (u32) bucket;
 
-	/* Now find an object value that has not already been taken
-	 * by scanning the list.
+	/*
+	 * Now find an object value that has not already been taken
+	 * by scanning the list, incrementing each time by number of buckets.
 	 */
-
 	while (!found) {
 		found = 1;
 		n += YAFFS_NOBJECT_BUCKETS;
-		if (1 || dev->obj_bucket[bucket].count > 0) {
-			list_for_each(i, &dev->obj_bucket[bucket].list) {
-				/* If there is already one in the list */
-				if (i && list_entry(i, struct yaffs_obj,
-						    hash_link)->obj_id == n) {
-					found = 0;
-				}
-			}
+		list_for_each(i, &dev->obj_bucket[bucket].list) {
+			/* Check if this value is already taken. */
+			if (i && list_entry(i, struct yaffs_obj,
+					    hash_link)->obj_id == n)
+				found = 0;
 		}
 	}
 	return n;
@@ -5022,8 +5019,15 @@ void yaffs_deinitialise(struct yaffs_dev *dev)
 
 		kfree(dev->gc_cleanup_list);
 
-		for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++)
+		for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
 			kfree(dev->temp_buffer[i].buffer);
+			dev->temp_buffer[i].buffer = NULL;
+		}
+
+		kfree(dev->checkpt_buffer);
+		dev->checkpt_buffer = NULL;
+		kfree(dev->checkpt_block_list);
+		dev->checkpt_block_list = NULL;
 
 		dev->is_mounted = 0;
 
diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_vfs.c b/target/linux/generic/files/fs/yaffs2/yaffs_vfs.c
index 76bc1db59f..6540434371 100644
--- a/target/linux/generic/files/fs/yaffs2/yaffs_vfs.c
+++ b/target/linux/generic/files/fs/yaffs2/yaffs_vfs.c
@@ -738,7 +738,7 @@ static int yaffs_file_flush(struct file *file)
 
 	yaffs_gross_lock(dev);
 
-	yaffs_flush_file(obj, 1, 0);
+	yaffs_flush_file(obj, 1, 0, 0);
 
 	yaffs_gross_unlock(dev);
 
@@ -768,7 +768,7 @@ static int yaffs_sync_object(struct file *file, struct dentry *dentry,
 	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, 0);
 	yaffs_gross_unlock(dev);
 	return 0;
 }
@@ -2187,7 +2187,7 @@ static void yaffs_flush_inodes(struct super_block *sb)
 			yaffs_trace(YAFFS_TRACE_OS,
 				"flushing obj %d",
 				obj->obj_id);
-			yaffs_flush_file(obj, 1, 0);
+			yaffs_flush_file(obj, 1, 0, 0);
 		}
 	}
 }
@@ -2200,7 +2200,7 @@ static void yaffs_flush_super(struct super_block *sb, int do_checkpoint)
 
 	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);
 }
@@ -2579,7 +2579,45 @@ static int yaffs_sync_fs(struct super_block *sb)
 	return 0;
 }
 
+/* the function only is used to change dev->read_only when this file system
+ * is remounted.
+ */
+static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data)
+{
+	int read_only = 0;
+	struct mtd_info *mtd;
+	struct yaffs_dev *dev = 0;
 
+	/* Get the device */
+	mtd = get_mtd_device(NULL, MINOR(sb->s_dev));
+	if (!mtd) {
+		yaffs_trace(YAFFS_TRACE_ALWAYS,
+			"MTD device #%u doesn't appear to exist",
+			MINOR(sb->s_dev));
+		return 1;
+	}
+
+	/* Check it's NAND */
+	if (mtd->type != MTD_NANDFLASH) {
+		yaffs_trace(YAFFS_TRACE_ALWAYS,
+			"MTD device is not NAND it's type %d",
+			mtd->type);
+		return 1;
+	}
+
+	read_only = ((*flags & MS_RDONLY) != 0);
+	if (!read_only && !(mtd->flags & MTD_WRITEABLE)) {
+		read_only = 1;
+		printk(KERN_INFO
+			"yaffs: mtd is read only, setting superblock read only");
+		*flags |= MS_RDONLY;
+	}
+
+	dev = sb->s_fs_info;
+	dev->read_only = read_only;
+
+	return 0;
+}
 
 static const struct super_operations yaffs_super_ops = {
 	.statfs = yaffs_statfs,
@@ -2601,6 +2639,7 @@ static const struct super_operations yaffs_super_ops = {
 #ifdef YAFFS_HAS_WRITE_SUPER
 	.write_super = yaffs_write_super,
 #endif
+	.remount_fs = yaffs_remount_fs,
 };
 
 struct yaffs_options {
diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_yaffs2.c b/target/linux/generic/files/fs/yaffs2/yaffs_yaffs2.c
index 8c31a661ff..9fb7c944ca 100644
--- a/target/linux/generic/files/fs/yaffs2/yaffs_yaffs2.c
+++ b/target/linux/generic/files/fs/yaffs2/yaffs_yaffs2.c
@@ -1351,7 +1351,6 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev)
 	int n_to_scan = 0;
 	enum yaffs_block_state state;
 	int c;
-	int deleted;
 	LIST_HEAD(hard_list);
 	struct yaffs_block_info *bi;
 	u32 seq_number;
@@ -1469,7 +1468,6 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev)
 		/* get the block to scan in the correct order */
 		blk = block_index[block_iter].block;
 		bi = yaffs_get_block_info(dev, blk);
-		deleted = 0;
 
 		summary_available = yaffs_summary_read(dev, dev->sum_tags, blk);
 
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
deleted file mode 100644
index d5ccc3e81e..0000000000
--- a/target/linux/generic/patches-3.18/501-yaffs-add-missing-flush-arguments.patch
+++ /dev/null
@@ -1,38 +0,0 @@
---- 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/503-yaffs-add-tags-9bytes-mount-option.patch b/target/linux/generic/patches-3.18/503-yaffs-add-tags-9bytes-mount-option.patch
index 9ecaa72832..3f51bafc11 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
-@@ -2605,6 +2605,7 @@ static const struct super_operations yaf
+@@ -2644,6 +2644,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;
-@@ -2644,6 +2645,8 @@ static int yaffs_parse_options(struct ya
+@@ -2683,6 +2684,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;
-@@ -2717,7 +2720,6 @@ static struct super_block *yaffs_interna
+@@ -2756,7 +2759,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;
  
-@@ -2757,6 +2759,9 @@ static struct super_block *yaffs_interna
+@@ -2796,6 +2798,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;
-@@ -2790,17 +2795,22 @@ static struct super_block *yaffs_interna
+@@ -2829,17 +2834,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
-@@ -2857,7 +2867,8 @@ static struct super_block *yaffs_interna
+@@ -2896,7 +2906,8 @@ static struct super_block *yaffs_interna
  
  	param->n_reserved_blocks = 5;
  	param->n_caches = (options.no_cache) ? 0 : 10;
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
deleted file mode 100644
index d5ccc3e81e..0000000000
--- a/target/linux/generic/patches-4.0/501-yaffs-add-missing-flush-arguments.patch
+++ /dev/null
@@ -1,38 +0,0 @@
---- 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/503-yaffs-add-tags-9bytes-mount-option.patch b/target/linux/generic/patches-4.0/503-yaffs-add-tags-9bytes-mount-option.patch
index 9ecaa72832..3f51bafc11 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
-@@ -2605,6 +2605,7 @@ static const struct super_operations yaf
+@@ -2644,6 +2644,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;
-@@ -2644,6 +2645,8 @@ static int yaffs_parse_options(struct ya
+@@ -2683,6 +2684,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;
-@@ -2717,7 +2720,6 @@ static struct super_block *yaffs_interna
+@@ -2756,7 +2759,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;
  
-@@ -2757,6 +2759,9 @@ static struct super_block *yaffs_interna
+@@ -2796,6 +2798,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;
-@@ -2790,17 +2795,22 @@ static struct super_block *yaffs_interna
+@@ -2829,17 +2834,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
-@@ -2857,7 +2867,8 @@ static struct super_block *yaffs_interna
+@@ -2896,7 +2906,8 @@ static struct super_block *yaffs_interna
  
  	param->n_reserved_blocks = 5;
  	param->n_caches = (options.no_cache) ? 0 : 10;
diff --git a/target/linux/generic/patches-4.0/505-yaffs-3.19-f_dentry-remove.patch b/target/linux/generic/patches-4.0/505-yaffs-3.19-f_dentry-remove.patch
new file mode 100644
index 0000000000..4dd2afe992
--- /dev/null
+++ b/target/linux/generic/patches-4.0/505-yaffs-3.19-f_dentry-remove.patch
@@ -0,0 +1,95 @@
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -283,7 +283,7 @@ static int yaffs_readpage_nolock(struct
+ 		(long long)pos,
+ 		(unsigned)PAGE_CACHE_SIZE);
+ 
+-	obj = yaffs_dentry_to_obj(f->f_dentry);
++	obj = yaffs_dentry_to_obj(f->f_path.dentry);
+ 
+ 	dev = obj->my_dev;
+ 
+@@ -481,7 +481,7 @@ static ssize_t yaffs_hold_space(struct f
+ 
+ 	int n_free_chunks;
+ 
+-	obj = yaffs_dentry_to_obj(f->f_dentry);
++	obj = yaffs_dentry_to_obj(f->f_path.dentry);
+ 
+ 	dev = obj->my_dev;
+ 
+@@ -499,7 +499,7 @@ static void yaffs_release_space(struct f
+ 	struct yaffs_obj *obj;
+ 	struct yaffs_dev *dev;
+ 
+-	obj = yaffs_dentry_to_obj(f->f_dentry);
++	obj = yaffs_dentry_to_obj(f->f_path.dentry);
+ 
+ 	dev = obj->my_dev;
+ 
+@@ -591,7 +591,7 @@ static ssize_t yaffs_file_write(struct f
+ 	struct inode *inode;
+ 	struct yaffs_dev *dev;
+ 
+-	obj = yaffs_dentry_to_obj(f->f_dentry);
++	obj = yaffs_dentry_to_obj(f->f_path.dentry);
+ 
+ 	if (!obj) {
+ 		yaffs_trace(YAFFS_TRACE_OS,
+@@ -603,7 +603,7 @@ static ssize_t yaffs_file_write(struct f
+ 
+ 	yaffs_gross_lock(dev);
+ 
+-	inode = f->f_dentry->d_inode;
++	inode = f->f_path.dentry->d_inode;
+ 
+ 	if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND)
+ 		ipos = inode->i_size;
+@@ -727,7 +727,7 @@ static int yaffs_file_flush(struct file
+ static int yaffs_file_flush(struct file *file)
+ #endif
+ {
+-	struct yaffs_obj *obj = yaffs_dentry_to_obj(file->f_dentry);
++	struct yaffs_obj *obj = yaffs_dentry_to_obj(file->f_path.dentry);
+ 
+ 	struct yaffs_dev *dev = obj->my_dev;
+ 
+@@ -1730,7 +1730,7 @@ static int yaffs_iterate(struct file *f,
+ 
+ 	char name[YAFFS_MAX_NAME_LENGTH + 1];
+ 
+-	obj = yaffs_dentry_to_obj(f->f_dentry);
++	obj = yaffs_dentry_to_obj(f->f_path.dentry);
+ 	dev = obj->my_dev;
+ 
+ 	yaffs_gross_lock(dev);
+@@ -1794,14 +1794,14 @@ static int yaffs_readdir(struct file *f,
+ 	struct yaffs_obj *obj;
+ 	struct yaffs_dev *dev;
+ 	struct yaffs_search_context *sc;
+-	struct inode *inode = f->f_dentry->d_inode;
++	struct inode *inode = f->f_path.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(f->f_dentry);
++	obj = yaffs_dentry_to_obj(f->f_path.dentry);
+ 	dev = obj->my_dev;
+ 
+ 	yaffs_gross_lock(dev);
+@@ -1835,10 +1835,10 @@ static int yaffs_readdir(struct file *f,
+ 	if (offset == 1) {
+ 		yaffs_trace(YAFFS_TRACE_OS,
+ 			"yaffs_readdir: entry .. ino %d",
+-			(int)f->f_dentry->d_parent->d_inode->i_ino);
++			(int)f->f_path.dentry->d_parent->d_inode->i_ino);
+ 		yaffs_gross_unlock(dev);
+ 		if (filldir(dirent, "..", 2, offset,
+-			    f->f_dentry->d_parent->d_inode->i_ino,
++			    f->f_path.dentry->d_parent->d_inode->i_ino,
+ 			    DT_DIR) < 0) {
+ 			yaffs_gross_lock(dev);
+ 			goto out;
diff --git a/target/linux/generic/patches-4.1/501-yaffs-add-missing-flush-arguments.patch b/target/linux/generic/patches-4.1/501-yaffs-add-missing-flush-arguments.patch
deleted file mode 100644
index d5ccc3e81e..0000000000
--- a/target/linux/generic/patches-4.1/501-yaffs-add-missing-flush-arguments.patch
+++ /dev/null
@@ -1,38 +0,0 @@
---- 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.1/503-yaffs-add-tags-9bytes-mount-option.patch b/target/linux/generic/patches-4.1/503-yaffs-add-tags-9bytes-mount-option.patch
index 9ecaa72832..3f51bafc11 100644
--- a/target/linux/generic/patches-4.1/503-yaffs-add-tags-9bytes-mount-option.patch
+++ b/target/linux/generic/patches-4.1/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
-@@ -2605,6 +2605,7 @@ static const struct super_operations yaf
+@@ -2644,6 +2644,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;
-@@ -2644,6 +2645,8 @@ static int yaffs_parse_options(struct ya
+@@ -2683,6 +2684,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;
-@@ -2717,7 +2720,6 @@ static struct super_block *yaffs_interna
+@@ -2756,7 +2759,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;
  
-@@ -2757,6 +2759,9 @@ static struct super_block *yaffs_interna
+@@ -2796,6 +2798,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;
-@@ -2790,17 +2795,22 @@ static struct super_block *yaffs_interna
+@@ -2829,17 +2834,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
-@@ -2857,7 +2867,8 @@ static struct super_block *yaffs_interna
+@@ -2896,7 +2906,8 @@ static struct super_block *yaffs_interna
  
  	param->n_reserved_blocks = 5;
  	param->n_caches = (options.no_cache) ? 0 : 10;
diff --git a/target/linux/generic/patches-4.1/504-yaffs-3.16-new-fops.patch b/target/linux/generic/patches-4.1/504-yaffs-3.16-new-fops.patch
index 11c6da0516..32b4fdfa39 100644
--- a/target/linux/generic/patches-4.1/504-yaffs-3.16-new-fops.patch
+++ b/target/linux/generic/patches-4.1/504-yaffs-3.16-new-fops.patch
@@ -1,15 +1,19 @@
 --- a/fs/yaffs2/yaffs_vfs.c
 +++ b/fs/yaffs2/yaffs_vfs.c
-@@ -774,7 +774,21 @@ static int yaffs_sync_object(struct file
+@@ -774,7 +774,25 @@ 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 = {
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0))
 +	.read = new_sync_read,
++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) */
 +	.read_iter = generic_file_read_iter,
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0))
 +	.write = new_sync_write,
++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) */
 +	.write_iter = generic_file_write_iter,
 +	.mmap = generic_file_mmap,
 +	.flush = yaffs_file_flush,
diff --git a/target/linux/generic/patches-4.1/505-yaffs-3.19-f_dentry-remove.patch b/target/linux/generic/patches-4.1/505-yaffs-3.19-f_dentry-remove.patch
new file mode 100644
index 0000000000..0d4b6bf04f
--- /dev/null
+++ b/target/linux/generic/patches-4.1/505-yaffs-3.19-f_dentry-remove.patch
@@ -0,0 +1,95 @@
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -283,7 +283,7 @@ static int yaffs_readpage_nolock(struct
+ 		(long long)pos,
+ 		(unsigned)PAGE_CACHE_SIZE);
+ 
+-	obj = yaffs_dentry_to_obj(f->f_dentry);
++	obj = yaffs_dentry_to_obj(f->f_path.dentry);
+ 
+ 	dev = obj->my_dev;
+ 
+@@ -481,7 +481,7 @@ static ssize_t yaffs_hold_space(struct f
+ 
+ 	int n_free_chunks;
+ 
+-	obj = yaffs_dentry_to_obj(f->f_dentry);
++	obj = yaffs_dentry_to_obj(f->f_path.dentry);
+ 
+ 	dev = obj->my_dev;
+ 
+@@ -499,7 +499,7 @@ static void yaffs_release_space(struct f
+ 	struct yaffs_obj *obj;
+ 	struct yaffs_dev *dev;
+ 
+-	obj = yaffs_dentry_to_obj(f->f_dentry);
++	obj = yaffs_dentry_to_obj(f->f_path.dentry);
+ 
+ 	dev = obj->my_dev;
+ 
+@@ -591,7 +591,7 @@ static ssize_t yaffs_file_write(struct f
+ 	struct inode *inode;
+ 	struct yaffs_dev *dev;
+ 
+-	obj = yaffs_dentry_to_obj(f->f_dentry);
++	obj = yaffs_dentry_to_obj(f->f_path.dentry);
+ 
+ 	if (!obj) {
+ 		yaffs_trace(YAFFS_TRACE_OS,
+@@ -603,7 +603,7 @@ static ssize_t yaffs_file_write(struct f
+ 
+ 	yaffs_gross_lock(dev);
+ 
+-	inode = f->f_dentry->d_inode;
++	inode = f->f_path.dentry->d_inode;
+ 
+ 	if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND)
+ 		ipos = inode->i_size;
+@@ -727,7 +727,7 @@ static int yaffs_file_flush(struct file
+ static int yaffs_file_flush(struct file *file)
+ #endif
+ {
+-	struct yaffs_obj *obj = yaffs_dentry_to_obj(file->f_dentry);
++	struct yaffs_obj *obj = yaffs_dentry_to_obj(file->f_path.dentry);
+ 
+ 	struct yaffs_dev *dev = obj->my_dev;
+ 
+@@ -1734,7 +1734,7 @@ static int yaffs_iterate(struct file *f,
+ 
+ 	char name[YAFFS_MAX_NAME_LENGTH + 1];
+ 
+-	obj = yaffs_dentry_to_obj(f->f_dentry);
++	obj = yaffs_dentry_to_obj(f->f_path.dentry);
+ 	dev = obj->my_dev;
+ 
+ 	yaffs_gross_lock(dev);
+@@ -1798,14 +1798,14 @@ static int yaffs_readdir(struct file *f,
+ 	struct yaffs_obj *obj;
+ 	struct yaffs_dev *dev;
+ 	struct yaffs_search_context *sc;
+-	struct inode *inode = f->f_dentry->d_inode;
++	struct inode *inode = f->f_path.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(f->f_dentry);
++	obj = yaffs_dentry_to_obj(f->f_path.dentry);
+ 	dev = obj->my_dev;
+ 
+ 	yaffs_gross_lock(dev);
+@@ -1839,10 +1839,10 @@ static int yaffs_readdir(struct file *f,
+ 	if (offset == 1) {
+ 		yaffs_trace(YAFFS_TRACE_OS,
+ 			"yaffs_readdir: entry .. ino %d",
+-			(int)f->f_dentry->d_parent->d_inode->i_ino);
++			(int)f->f_path.dentry->d_parent->d_inode->i_ino);
+ 		yaffs_gross_unlock(dev);
+ 		if (filldir(dirent, "..", 2, offset,
+-			    f->f_dentry->d_parent->d_inode->i_ino,
++			    f->f_path.dentry->d_parent->d_inode->i_ino,
+ 			    DT_DIR) < 0) {
+ 			yaffs_gross_lock(dev);
+ 			goto out;