From 472f5abe113e59628501827db7a189f1c61a084e Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 31 Mar 2015 15:31:57 +0000 Subject: 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 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 Signed-off-by: Gabor Juhos git-svn-id: svn://svn.openwrt.org/openwrt/trunk@45188 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- ...01-yaffs-3.5-convert-to-use-kuid_t-kgid_t.patch | 155 ------------- .../501-yaffs-add-missing-flush-arguments.patch | 38 ++++ .../502-yaffs-3.10-disable-proc-entry.patch | 44 ---- .../502-yaffs-fix-compat-tags-handling.patch | 239 +++++++++++++++++++++ ...503-yaffs-3.12-convert-readdir-to-iterate.patch | 129 ----------- .../503-yaffs-add-tags-9bytes-mount-option.patch | 24 +-- .../patches-4.0/504-yaffs-3.16-new-fops.patch | 25 +++ .../504-yaffs-fix-compat-tags-handling.patch | 239 --------------------- .../patches-4.0/505-yaffs-3.16-new-fops.patch | 32 --- 9 files changed, 310 insertions(+), 615 deletions(-) delete mode 100644 target/linux/generic/patches-4.0/501-yaffs-3.5-convert-to-use-kuid_t-kgid_t.patch create mode 100644 target/linux/generic/patches-4.0/501-yaffs-add-missing-flush-arguments.patch delete mode 100644 target/linux/generic/patches-4.0/502-yaffs-3.10-disable-proc-entry.patch create mode 100644 target/linux/generic/patches-4.0/502-yaffs-fix-compat-tags-handling.patch delete mode 100644 target/linux/generic/patches-4.0/503-yaffs-3.12-convert-readdir-to-iterate.patch create mode 100644 target/linux/generic/patches-4.0/504-yaffs-3.16-new-fops.patch delete mode 100644 target/linux/generic/patches-4.0/504-yaffs-fix-compat-tags-handling.patch delete mode 100644 target/linux/generic/patches-4.0/505-yaffs-3.16-new-fops.patch (limited to 'target/linux/generic/patches-4.0') 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/502-yaffs-fix-compat-tags-handling.patch b/target/linux/generic/patches-4.0/502-yaffs-fix-compat-tags-handling.patch new file mode 100644 index 0000000000..a18cf6fd7b --- /dev/null +++ b/target/linux/generic/patches-4.0/502-yaffs-fix-compat-tags-handling.patch @@ -0,0 +1,239 @@ +Subject: yaffs: fix compat tags handling + +Signed-off-by: Gabor Juhos +--- +--- a/fs/yaffs2/yaffs_tagscompat.c ++++ b/fs/yaffs2/yaffs_tagscompat.c +@@ -17,7 +17,9 @@ + #include "yaffs_getblockinfo.h" + #include "yaffs_trace.h" + ++#if 0 + static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk); ++#endif + + + /********** Tags ECC calculations *********/ +@@ -71,6 +73,7 @@ int yaffs_check_tags_ecc(struct yaffs_ta + return 0; + } + ++#if 0 + /********** Tags **********/ + + static void yaffs_load_tags_to_spare(struct yaffs_spare *spare_ptr, +@@ -379,3 +382,214 @@ void yaffs_tags_compat_install(struct ya + if(!dev->tagger.mark_bad_fn) + dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad; + } ++#else ++ ++#include "yaffs_packedtags1.h" ++ ++static int yaffs_tags_compat_write(struct yaffs_dev *dev, ++ int nand_chunk, ++ const u8 *data, ++ const struct yaffs_ext_tags *tags) ++{ ++ struct yaffs_packed_tags1 pt1; ++ u8 tag_buf[9]; ++ int retval; ++ ++ /* we assume that yaffs_packed_tags1 and yaffs_tags are compatible */ ++ compile_time_assertion(sizeof(struct yaffs_packed_tags1) == 12); ++ compile_time_assertion(sizeof(struct yaffs_tags) == 8); ++ ++ yaffs_pack_tags1(&pt1, tags); ++ yaffs_calc_tags_ecc((struct yaffs_tags *)&pt1); ++ ++ /* When deleting a chunk, the upper layer provides only skeletal ++ * tags, one with is_deleted set. However, we need to update the ++ * tags, not erase them completely. So we use the NAND write property ++ * that only zeroed-bits stick and set tag bytes to all-ones and ++ * zero just the (not) deleted bit. ++ */ ++ if (!dev->param.tags_9bytes) { ++ if (tags->is_deleted) { ++ memset(&pt1, 0xff, 8); ++ /* clear delete status bit to indicate deleted */ ++ pt1.deleted = 0; ++ } ++ memcpy(tag_buf, &pt1, 8); ++ } else { ++ if (tags->is_deleted) { ++ memset(tag_buf, 0xff, 8); ++ tag_buf[8] = 0; ++ } else { ++ memcpy(tag_buf, &pt1, 8); ++ tag_buf[8] = 0xff; ++ } ++ } ++ ++ retval = dev->drv.drv_write_chunk_fn(dev, nand_chunk, ++ data, ++ (data) ? dev->data_bytes_per_chunk : 0, ++ tag_buf, ++ (dev->param.tags_9bytes) ? 9 : 8); ++ ++ return retval; ++} ++ ++/* Return with empty extended tags but add ecc_result. ++ */ ++static int return_empty_tags(struct yaffs_ext_tags *tags, ++ enum yaffs_ecc_result ecc_result, ++ int retval) ++{ ++ if (tags) { ++ memset(tags, 0, sizeof(*tags)); ++ tags->ecc_result = ecc_result; ++ } ++ ++ return retval; ++} ++ ++static int yaffs_tags_compat_read(struct yaffs_dev *dev, ++ int nand_chunk, ++ u8 *data, ++ struct yaffs_ext_tags *tags) ++{ ++ struct yaffs_packed_tags1 pt1; ++ enum yaffs_ecc_result ecc_result; ++ int retval; ++ int deleted; ++ u8 tag_buf[9]; ++ ++ retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk, ++ data, dev->param.total_bytes_per_chunk, ++ tag_buf, ++ (dev->param.tags_9bytes) ? 9 : 8, ++ &ecc_result); ++ ++ switch (ecc_result) { ++ case YAFFS_ECC_RESULT_NO_ERROR: ++ case YAFFS_ECC_RESULT_FIXED: ++ break; ++ ++ case YAFFS_ECC_RESULT_UNFIXED: ++ default: ++ return_empty_tags(tags, YAFFS_ECC_RESULT_UNFIXED, 0); ++ tags->block_bad = dev->drv.drv_check_bad_fn(dev, nand_chunk); ++ return YAFFS_FAIL; ++ } ++ ++ /* Check for a blank/erased chunk. */ ++ if (yaffs_check_ff(tag_buf, 8)) { ++ /* when blank, upper layers want ecc_result to be <= NO_ERROR */ ++ return return_empty_tags(tags, YAFFS_ECC_RESULT_NO_ERROR, ++ YAFFS_OK); ++ } ++ ++ memcpy(&pt1, tag_buf, 8); ++ ++ if (!dev->param.tags_9bytes) { ++ /* Read deleted status (bit) then return it to it's non-deleted ++ * state before performing tags mini-ECC check. pt1.deleted is ++ * inverted. ++ */ ++ deleted = !pt1.deleted; ++ pt1.deleted = 1; ++ } else { ++ deleted = (hweight8(tag_buf[8]) < 7) ? 1 : 0; ++ } ++ ++ /* Check the packed tags mini-ECC and correct if necessary/possible. */ ++ retval = yaffs_check_tags_ecc((struct yaffs_tags *)&pt1); ++ switch (retval) { ++ case 0: ++ /* no tags error, use MTD result */ ++ break; ++ case 1: ++ /* recovered tags-ECC error */ ++ dev->n_tags_ecc_fixed++; ++ if (ecc_result == YAFFS_ECC_RESULT_NO_ERROR) ++ ecc_result = YAFFS_ECC_RESULT_FIXED; ++ break; ++ default: ++ /* unrecovered tags-ECC error */ ++ dev->n_tags_ecc_unfixed++; ++ return return_empty_tags(tags, YAFFS_ECC_RESULT_UNFIXED, ++ YAFFS_FAIL); ++ } ++ ++ /* Unpack the tags to extended form and set ECC result. ++ * [set should_be_ff just to keep yaffs_unpack_tags1 happy] ++ */ ++ pt1.should_be_ff = 0xffffffff; ++ yaffs_unpack_tags1(tags, &pt1); ++ tags->ecc_result = ecc_result; ++ ++ /* Set deleted state */ ++ tags->is_deleted = deleted; ++ return YAFFS_OK; ++} ++ ++static int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int block_no) ++{ ++ return dev->drv.drv_mark_bad_fn(dev, block_no); ++} ++ ++static int yaffs_tags_compat_query_block(struct yaffs_dev *dev, ++ int block_no, ++ enum yaffs_block_state *state, ++ u32 *seq_number) ++{ ++ struct yaffs_ext_tags tags; ++ int retval; ++ ++ yaffs_trace(YAFFS_TRACE_MTD, "%s %d", __func__, block_no); ++ ++ *seq_number = 0; ++ ++ retval = dev->drv.drv_check_bad_fn(dev, block_no); ++ if (retval == YAFFS_FAIL) { ++ *state = YAFFS_BLOCK_STATE_DEAD; ++ goto out; ++ } ++ ++ yaffs_tags_compat_read(dev, block_no * dev->param.chunks_per_block, ++ NULL, &tags); ++ ++ if (tags.ecc_result != YAFFS_ECC_RESULT_NO_ERROR) { ++ yaffs_trace(YAFFS_TRACE_MTD, "block %d is marked bad", ++ block_no); ++ *state = YAFFS_BLOCK_STATE_NEEDS_SCAN; ++ } else if (tags.chunk_used) { ++ *seq_number = tags.seq_number; ++ *state = YAFFS_BLOCK_STATE_NEEDS_SCAN; ++ } else { ++ *state = YAFFS_BLOCK_STATE_EMPTY; ++ } ++ ++ retval = YAFFS_OK; ++ ++out: ++ yaffs_trace(YAFFS_TRACE_MTD, ++ "block query returns seq %u state %d", ++ *seq_number, *state); ++ ++ return retval; ++} ++ ++void yaffs_tags_compat_install(struct yaffs_dev *dev) ++{ ++ if (dev->param.is_yaffs2) ++ return; ++ ++ if (!dev->tagger.write_chunk_tags_fn) ++ dev->tagger.write_chunk_tags_fn = yaffs_tags_compat_write; ++ ++ if (!dev->tagger.read_chunk_tags_fn) ++ dev->tagger.read_chunk_tags_fn = yaffs_tags_compat_read; ++ ++ if (!dev->tagger.query_block_fn) ++ dev->tagger.query_block_fn = yaffs_tags_compat_query_block; ++ ++ if (!dev->tagger.mark_bad_fn) ++ dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad; ++} ++#endif diff --git a/target/linux/generic/patches-4.0/503-yaffs-3.12-convert-readdir-to-iterate.patch b/target/linux/generic/patches-4.0/503-yaffs-3.12-convert-readdir-to-iterate.patch deleted file mode 100644 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 --- --- 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 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 } 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 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 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 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 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 { 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/504-yaffs-fix-compat-tags-handling.patch b/target/linux/generic/patches-4.0/504-yaffs-fix-compat-tags-handling.patch deleted file mode 100644 index a18cf6fd7b..0000000000 --- a/target/linux/generic/patches-4.0/504-yaffs-fix-compat-tags-handling.patch +++ /dev/null @@ -1,239 +0,0 @@ -Subject: yaffs: fix compat tags handling - -Signed-off-by: Gabor Juhos ---- ---- a/fs/yaffs2/yaffs_tagscompat.c -+++ b/fs/yaffs2/yaffs_tagscompat.c -@@ -17,7 +17,9 @@ - #include "yaffs_getblockinfo.h" - #include "yaffs_trace.h" - -+#if 0 - static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk); -+#endif - - - /********** Tags ECC calculations *********/ -@@ -71,6 +73,7 @@ int yaffs_check_tags_ecc(struct yaffs_ta - return 0; - } - -+#if 0 - /********** Tags **********/ - - static void yaffs_load_tags_to_spare(struct yaffs_spare *spare_ptr, -@@ -379,3 +382,214 @@ void yaffs_tags_compat_install(struct ya - if(!dev->tagger.mark_bad_fn) - dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad; - } -+#else -+ -+#include "yaffs_packedtags1.h" -+ -+static int yaffs_tags_compat_write(struct yaffs_dev *dev, -+ int nand_chunk, -+ const u8 *data, -+ const struct yaffs_ext_tags *tags) -+{ -+ struct yaffs_packed_tags1 pt1; -+ u8 tag_buf[9]; -+ int retval; -+ -+ /* we assume that yaffs_packed_tags1 and yaffs_tags are compatible */ -+ compile_time_assertion(sizeof(struct yaffs_packed_tags1) == 12); -+ compile_time_assertion(sizeof(struct yaffs_tags) == 8); -+ -+ yaffs_pack_tags1(&pt1, tags); -+ yaffs_calc_tags_ecc((struct yaffs_tags *)&pt1); -+ -+ /* When deleting a chunk, the upper layer provides only skeletal -+ * tags, one with is_deleted set. However, we need to update the -+ * tags, not erase them completely. So we use the NAND write property -+ * that only zeroed-bits stick and set tag bytes to all-ones and -+ * zero just the (not) deleted bit. -+ */ -+ if (!dev->param.tags_9bytes) { -+ if (tags->is_deleted) { -+ memset(&pt1, 0xff, 8); -+ /* clear delete status bit to indicate deleted */ -+ pt1.deleted = 0; -+ } -+ memcpy(tag_buf, &pt1, 8); -+ } else { -+ if (tags->is_deleted) { -+ memset(tag_buf, 0xff, 8); -+ tag_buf[8] = 0; -+ } else { -+ memcpy(tag_buf, &pt1, 8); -+ tag_buf[8] = 0xff; -+ } -+ } -+ -+ retval = dev->drv.drv_write_chunk_fn(dev, nand_chunk, -+ data, -+ (data) ? dev->data_bytes_per_chunk : 0, -+ tag_buf, -+ (dev->param.tags_9bytes) ? 9 : 8); -+ -+ return retval; -+} -+ -+/* Return with empty extended tags but add ecc_result. -+ */ -+static int return_empty_tags(struct yaffs_ext_tags *tags, -+ enum yaffs_ecc_result ecc_result, -+ int retval) -+{ -+ if (tags) { -+ memset(tags, 0, sizeof(*tags)); -+ tags->ecc_result = ecc_result; -+ } -+ -+ return retval; -+} -+ -+static int yaffs_tags_compat_read(struct yaffs_dev *dev, -+ int nand_chunk, -+ u8 *data, -+ struct yaffs_ext_tags *tags) -+{ -+ struct yaffs_packed_tags1 pt1; -+ enum yaffs_ecc_result ecc_result; -+ int retval; -+ int deleted; -+ u8 tag_buf[9]; -+ -+ retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk, -+ data, dev->param.total_bytes_per_chunk, -+ tag_buf, -+ (dev->param.tags_9bytes) ? 9 : 8, -+ &ecc_result); -+ -+ switch (ecc_result) { -+ case YAFFS_ECC_RESULT_NO_ERROR: -+ case YAFFS_ECC_RESULT_FIXED: -+ break; -+ -+ case YAFFS_ECC_RESULT_UNFIXED: -+ default: -+ return_empty_tags(tags, YAFFS_ECC_RESULT_UNFIXED, 0); -+ tags->block_bad = dev->drv.drv_check_bad_fn(dev, nand_chunk); -+ return YAFFS_FAIL; -+ } -+ -+ /* Check for a blank/erased chunk. */ -+ if (yaffs_check_ff(tag_buf, 8)) { -+ /* when blank, upper layers want ecc_result to be <= NO_ERROR */ -+ return return_empty_tags(tags, YAFFS_ECC_RESULT_NO_ERROR, -+ YAFFS_OK); -+ } -+ -+ memcpy(&pt1, tag_buf, 8); -+ -+ if (!dev->param.tags_9bytes) { -+ /* Read deleted status (bit) then return it to it's non-deleted -+ * state before performing tags mini-ECC check. pt1.deleted is -+ * inverted. -+ */ -+ deleted = !pt1.deleted; -+ pt1.deleted = 1; -+ } else { -+ deleted = (hweight8(tag_buf[8]) < 7) ? 1 : 0; -+ } -+ -+ /* Check the packed tags mini-ECC and correct if necessary/possible. */ -+ retval = yaffs_check_tags_ecc((struct yaffs_tags *)&pt1); -+ switch (retval) { -+ case 0: -+ /* no tags error, use MTD result */ -+ break; -+ case 1: -+ /* recovered tags-ECC error */ -+ dev->n_tags_ecc_fixed++; -+ if (ecc_result == YAFFS_ECC_RESULT_NO_ERROR) -+ ecc_result = YAFFS_ECC_RESULT_FIXED; -+ break; -+ default: -+ /* unrecovered tags-ECC error */ -+ dev->n_tags_ecc_unfixed++; -+ return return_empty_tags(tags, YAFFS_ECC_RESULT_UNFIXED, -+ YAFFS_FAIL); -+ } -+ -+ /* Unpack the tags to extended form and set ECC result. -+ * [set should_be_ff just to keep yaffs_unpack_tags1 happy] -+ */ -+ pt1.should_be_ff = 0xffffffff; -+ yaffs_unpack_tags1(tags, &pt1); -+ tags->ecc_result = ecc_result; -+ -+ /* Set deleted state */ -+ tags->is_deleted = deleted; -+ return YAFFS_OK; -+} -+ -+static int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int block_no) -+{ -+ return dev->drv.drv_mark_bad_fn(dev, block_no); -+} -+ -+static int yaffs_tags_compat_query_block(struct yaffs_dev *dev, -+ int block_no, -+ enum yaffs_block_state *state, -+ u32 *seq_number) -+{ -+ struct yaffs_ext_tags tags; -+ int retval; -+ -+ yaffs_trace(YAFFS_TRACE_MTD, "%s %d", __func__, block_no); -+ -+ *seq_number = 0; -+ -+ retval = dev->drv.drv_check_bad_fn(dev, block_no); -+ if (retval == YAFFS_FAIL) { -+ *state = YAFFS_BLOCK_STATE_DEAD; -+ goto out; -+ } -+ -+ yaffs_tags_compat_read(dev, block_no * dev->param.chunks_per_block, -+ NULL, &tags); -+ -+ if (tags.ecc_result != YAFFS_ECC_RESULT_NO_ERROR) { -+ yaffs_trace(YAFFS_TRACE_MTD, "block %d is marked bad", -+ block_no); -+ *state = YAFFS_BLOCK_STATE_NEEDS_SCAN; -+ } else if (tags.chunk_used) { -+ *seq_number = tags.seq_number; -+ *state = YAFFS_BLOCK_STATE_NEEDS_SCAN; -+ } else { -+ *state = YAFFS_BLOCK_STATE_EMPTY; -+ } -+ -+ retval = YAFFS_OK; -+ -+out: -+ yaffs_trace(YAFFS_TRACE_MTD, -+ "block query returns seq %u state %d", -+ *seq_number, *state); -+ -+ return retval; -+} -+ -+void yaffs_tags_compat_install(struct yaffs_dev *dev) -+{ -+ if (dev->param.is_yaffs2) -+ return; -+ -+ if (!dev->tagger.write_chunk_tags_fn) -+ dev->tagger.write_chunk_tags_fn = yaffs_tags_compat_write; -+ -+ if (!dev->tagger.read_chunk_tags_fn) -+ dev->tagger.read_chunk_tags_fn = yaffs_tags_compat_read; -+ -+ if (!dev->tagger.query_block_fn) -+ dev->tagger.query_block_fn = yaffs_tags_compat_query_block; -+ -+ if (!dev->tagger.mark_bad_fn) -+ dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad; -+} -+#endif diff --git a/target/linux/generic/patches-4.0/505-yaffs-3.16-new-fops.patch b/target/linux/generic/patches-4.0/505-yaffs-3.16-new-fops.patch deleted file mode 100644 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; - } -- cgit v1.2.3