From 80d031a7c6cbfc952e9646c5cc3c838ddb4d073f Mon Sep 17 00:00:00 2001 From: Charles Manning Date: Mon, 13 Feb 2012 15:30:01 +1300 Subject: [PATCH 1/1] Add Waldemar's patches for Linux 3.2 Also rolled in some suggestions for the multi-version code. Signed-off-by: Charles Manning --- .gitignore | 8 ++++++++ Makefile | 1 + yaffs_mtdif1_multi.c | 9 +++++++-- yaffs_mtdif1_single.c | 10 +++++----- yaffs_mtdif2_multi.c | 10 ++++++++-- yaffs_mtdif2_single.c | 5 +++-- yaffs_vfs_multi.c | 27 +++++++++++++++++-------- yaffs_vfs_single.c | 46 ++++++++++++++++++++++--------------------- yportenv.h | 20 +++++++++++++++++++ 9 files changed, 95 insertions(+), 41 deletions(-) create mode 100644 yportenv.h diff --git a/.gitignore b/.gitignore index 97f1da3..d4f60ef 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,12 @@ *.pyc DEADJOE *.mod.c +*.order +/Module.symvers +/.tmp_versions + +# +# cscope files +# +cscope.* diff --git a/Makefile b/Makefile index db1b5c2..6722182 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,7 @@ ifdef YAFFS_CURRENT YAFFS_O := yaffs2.o + EXTRA_CFLAGS += -DYAFFS_CURRENT else YAFFS_O := yaffs2multi.o endif diff --git a/yaffs_mtdif1_multi.c b/yaffs_mtdif1_multi.c index 3673891..14d5c6f 100644 --- a/yaffs_mtdif1_multi.c +++ b/yaffs_mtdif1_multi.c @@ -36,6 +36,11 @@ #include "linux/types.h" #include "linux/mtd/mtd.h" +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) +#define MTD_OPS_AUTO_OOB MTD_OOB_AUTO +#endif + + /* Don't compile this module if we don't have MTD's mtd_oob_ops interface */ #if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17)) @@ -124,7 +129,7 @@ int nandmtd1_write_chunk_tags(struct yaffs_dev *dev, } memset(&ops, 0, sizeof(ops)); - ops.mode = MTD_OOB_AUTO; + ops.mode = MTD_OPS_AUTO_OOB; ops.len = (data) ? chunk_bytes : 0; ops.ooblen = dev->param.tags_9bytes ? 9 : 8; ops.datbuf = (u8 *) data; @@ -177,7 +182,7 @@ int nandmtd1_read_chunk_tags(struct yaffs_dev *dev, int deleted; memset(&ops, 0, sizeof(ops)); - ops.mode = MTD_OOB_AUTO; + ops.mode = MTD_OPS_AUTO_OOB; ops.len = (data) ? chunk_bytes : 0; ops.ooblen = dev->param.tags_9bytes ? 9 : 8; ops.datbuf = data; diff --git a/yaffs_mtdif1_single.c b/yaffs_mtdif1_single.c index 467a031..a6907bf 100644 --- a/yaffs_mtdif1_single.c +++ b/yaffs_mtdif1_single.c @@ -97,7 +97,7 @@ int nandmtd1_write_chunk_tags(struct yaffs_dev *dev, } memset(&ops, 0, sizeof(ops)); - ops.mode = MTD_OOB_AUTO; + ops.mode = MTD_OPS_AUTO_OOB; ops.len = (data) ? chunk_bytes : 0; ops.ooblen = dev->param.tags_9bytes ? 9 : 8; ops.datbuf = (u8 *) data; @@ -150,7 +150,7 @@ int nandmtd1_read_chunk_tags(struct yaffs_dev *dev, int deleted; memset(&ops, 0, sizeof(ops)); - ops.mode = MTD_OOB_AUTO; + ops.mode = MTD_OPS_AUTO_OOB; ops.len = (data) ? chunk_bytes : 0; ops.ooblen = dev->param.tags_9bytes ? 9 : 8; ops.datbuf = data; @@ -259,7 +259,7 @@ int nandmtd1_mark_block_bad(struct yaffs_dev *dev, int block_no) * * Returns YAFFS_OK or YAFFS_FAIL. */ -static int nandmtd1_test_prerequists(struct mtd_info *mtd) +static int nandmtd1_test_prerequists(struct yaffs_dev *dev, struct mtd_info *mtd) { /* 2.6.18 has mtd->ecclayout->oobavail */ /* 2.6.21 has mtd->ecclayout->oobavail and mtd->oobavail */ @@ -268,7 +268,7 @@ static int nandmtd1_test_prerequists(struct mtd_info *mtd) if (oobavail < (dev->param.tags_9bytes ? 9 : 8)) { yaffs_trace(YAFFS_TRACE_ERROR, "mtd device has only %d bytes for tags, need %d", - oobavail, (dev->param.tags_9bytes ? 9 : 8); + oobavail, (dev->param.tags_9bytes ? 9 : 8)); return YAFFS_FAIL; } return YAFFS_OK; @@ -297,7 +297,7 @@ int nandmtd1_query_block(struct yaffs_dev *dev, int block_no, /* We don't yet have a good place to test for MTD config prerequists. * Do it here as we are called during the initial scan. */ - if (nandmtd1_test_prerequists(mtd) != YAFFS_OK) + if (nandmtd1_test_prerequists(dev, mtd) != YAFFS_OK) return YAFFS_FAIL; retval = nandmtd1_read_chunk_tags(dev, chunk_num, NULL, &etags); diff --git a/yaffs_mtdif2_multi.c b/yaffs_mtdif2_multi.c index 684ed2a..18ac992 100644 --- a/yaffs_mtdif2_multi.c +++ b/yaffs_mtdif2_multi.c @@ -26,6 +26,12 @@ #include "yaffs_linux.h" +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) +#define MTD_OPS_AUTO_OOB MTD_OOB_AUTO +#endif + + + /* NB For use with inband tags.... * We assume that the data buffer is of size total_bytes_per_chunk so * that we can also use it to load the tags. @@ -75,7 +81,7 @@ int nandmtd2_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk, } #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) - ops.mode = MTD_OOB_AUTO; + ops.mode = MTD_OPS_AUTO_OOB; ops.ooblen = (dev->param.inband_tags) ? 0 : packed_tags_size; ops.len = dev->param.total_bytes_per_chunk; ops.ooboffs = 0; @@ -139,7 +145,7 @@ int nandmtd2_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk, retval = mtd->read(mtd, addr, dev->param.total_bytes_per_chunk, &dummy, data); else if (tags) { - ops.mode = MTD_OOB_AUTO; + ops.mode = MTD_OPS_AUTO_OOB; ops.ooblen = packed_tags_size; ops.len = data ? dev->data_bytes_per_chunk : packed_tags_size; ops.ooboffs = 0; diff --git a/yaffs_mtdif2_single.c b/yaffs_mtdif2_single.c index c013232..f92c49f 100644 --- a/yaffs_mtdif2_single.c +++ b/yaffs_mtdif2_single.c @@ -21,6 +21,7 @@ #include "linux/mtd/mtd.h" #include "linux/types.h" #include "linux/time.h" +#include "mtd/mtd-abi.h" /* NB For use with inband tags.... @@ -64,7 +65,7 @@ int nandmtd2_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk, yaffs_pack_tags2(&pt, tags, !dev->param.no_tags_ecc); } - ops.mode = MTD_OOB_AUTO; + ops.mode = MTD_OPS_AUTO_OOB; ops.ooblen = (dev->param.inband_tags) ? 0 : packed_tags_size; ops.len = dev->param.total_bytes_per_chunk; ops.ooboffs = 0; @@ -106,7 +107,7 @@ int nandmtd2_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk, retval = mtd->read(mtd, addr, dev->param.total_bytes_per_chunk, &dummy, data); } else if (tags) { - ops.mode = MTD_OOB_AUTO; + ops.mode = MTD_OPS_AUTO_OOB; ops.ooblen = packed_tags_size; ops.len = data ? dev->data_bytes_per_chunk : packed_tags_size; ops.ooboffs = 0; diff --git a/yaffs_vfs_multi.c b/yaffs_vfs_multi.c index b8e5124..fdb0137 100644 --- a/yaffs_vfs_multi.c +++ b/yaffs_vfs_multi.c @@ -148,6 +148,12 @@ #define YAFFS_USE_WRITE_BEGIN_END 0 #endif + + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) +#define set_nlink(inode, count) do { (inode)->i_nlink = (count); } while(0) +#endif + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28)) static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size) { @@ -1330,7 +1336,7 @@ static void yaffs_fill_inode_from_obj(struct inode *inode, inode->i_size = yaffs_get_obj_length(obj); inode->i_blocks = (inode->i_size + 511) >> 9; - inode->i_nlink = yaffs_get_obj_link_count(obj); + set_nlink(inode, yaffs_get_obj_link_count(obj)); yaffs_trace(YAFFS_TRACE_OS, "yaffs_fill_inode mode %x uid %d gid %d size %d count %d", @@ -1744,10 +1750,9 @@ static int yaffs_unlink(struct inode *dir, struct dentry *dentry) ret_val = yaffs_unlinker(obj, dentry->d_name.name); if (ret_val == YAFFS_OK) { - dentry->d_inode->i_nlink--; + inode_dec_link_count(dentry->d_inode); dir->i_version++; yaffs_gross_unlock(dev); - mark_inode_dirty(dentry->d_inode); update_dir_time(dir); return 0; } @@ -1779,7 +1784,7 @@ static int yaffs_link(struct dentry *old_dentry, struct inode *dir, obj); if (link) { - old_dentry->d_inode->i_nlink = yaffs_get_obj_link_count(obj); + set_nlink(old_dentry->d_inode, yaffs_get_obj_link_count(obj)); d_instantiate(dentry, old_dentry->d_inode); atomic_inc(&old_dentry->d_inode->i_count); yaffs_trace(YAFFS_TRACE_OS, @@ -1809,6 +1814,14 @@ static int yaffs_symlink(struct inode *dir, struct dentry *dentry, yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink"); + if (strnlen(dentry->d_name.name, YAFFS_MAX_NAME_LENGTH + 1) > + YAFFS_MAX_NAME_LENGTH) + return -ENAMETOOLONG; + + if (strnlen(symname, YAFFS_MAX_ALIAS_LENGTH + 1) > + YAFFS_MAX_ALIAS_LENGTH) + return -ENAMETOOLONG; + dev = yaffs_inode_to_obj(dir)->my_dev; yaffs_gross_lock(dev); obj = yaffs_create_symlink(yaffs_inode_to_obj(dir), dentry->d_name.name, @@ -1897,10 +1910,8 @@ static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry, yaffs_gross_unlock(dev); if (ret_val == YAFFS_OK) { - if (target) { - new_dentry->d_inode->i_nlink--; - mark_inode_dirty(new_dentry->d_inode); - } + if (target) + inode_dec_link_count(new_dentry->d_inode); update_dir_time(old_dir); if (old_dir != new_dir) diff --git a/yaffs_vfs_single.c b/yaffs_vfs_single.c index f822845..d8379d4 100644 --- a/yaffs_vfs_single.c +++ b/yaffs_vfs_single.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include @@ -307,7 +306,7 @@ static int yaffs_link(struct dentry *old_dentry, struct inode *dir, obj); if (link) { - old_dentry->d_inode->i_nlink = yaffs_get_obj_link_count(obj); + set_nlink(old_dentry->d_inode, yaffs_get_obj_link_count(obj)); d_instantiate(dentry, old_dentry->d_inode); atomic_inc(&old_dentry->d_inode->i_count); yaffs_trace(YAFFS_TRACE_OS, @@ -338,6 +337,14 @@ static int yaffs_symlink(struct inode *dir, struct dentry *dentry, yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink"); + if (strnlen(dentry->d_name.name, YAFFS_MAX_NAME_LENGTH + 1) > + YAFFS_MAX_NAME_LENGTH) + return -ENAMETOOLONG; + + if (strnlen(symname, YAFFS_MAX_ALIAS_LENGTH + 1) > + YAFFS_MAX_ALIAS_LENGTH) + return -ENAMETOOLONG; + dev = yaffs_inode_to_obj(dir)->my_dev; yaffs_gross_lock(dev); obj = yaffs_create_symlink(yaffs_inode_to_obj(dir), dentry->d_name.name, @@ -419,10 +426,9 @@ static int yaffs_unlink(struct inode *dir, struct dentry *dentry) ret_val = yaffs_unlinker(obj, dentry->d_name.name); if (ret_val == YAFFS_OK) { - dentry->d_inode->i_nlink--; + inode_dec_link_count(dentry->d_inode); dir->i_version++; yaffs_gross_unlock(dev); - mark_inode_dirty(dentry->d_inode); update_dir_time(dir); return 0; } @@ -430,7 +436,7 @@ static int yaffs_unlink(struct inode *dir, struct dentry *dentry) return -ENOTEMPTY; } -static int yaffs_sync_object(struct file *file, int datasync) +static int yaffs_sync_object(struct file *file, loff_t start, loff_t end, int datasync) { struct yaffs_obj *obj; @@ -486,10 +492,8 @@ static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry, yaffs_gross_unlock(dev); if (ret_val == YAFFS_OK) { - if (target) { - new_dentry->d_inode->i_nlink--; - mark_inode_dirty(new_dentry->d_inode); - } + if (target) + inode_dec_link_count(new_dentry->d_inode); update_dir_time(old_dir); if (old_dir != new_dir) @@ -1873,7 +1877,7 @@ static void yaffs_fill_inode_from_obj(struct inode *inode, inode->i_ctime.tv_nsec = 0; inode->i_size = yaffs_get_obj_length(obj); inode->i_blocks = (inode->i_size + 511) >> 9; - inode->i_nlink = yaffs_get_obj_link_count(obj); + set_nlink(inode, yaffs_get_obj_link_count(obj)); yaffs_trace(YAFFS_TRACE_OS, "yaffs_fill_inode mode %x uid %d gid %d size %d count %d", inode->i_mode, inode->i_uid, inode->i_gid, @@ -2292,19 +2296,18 @@ static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data, return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL; } -static int yaffs_read_super(struct file_system_type *fs, +static struct dentry *yaffs_mount(struct file_system_type *fs, int flags, const char *dev_name, - void *data, struct vfsmount *mnt) + void *data) { - - return get_sb_bdev(fs, flags, dev_name, data, - yaffs_internal_read_super_mtd, mnt); + return mount_bdev(fs, flags, dev_name, data, + yaffs_internal_read_super_mtd); } static struct file_system_type yaffs_fs_type = { .owner = THIS_MODULE, .name = "yaffs", - .get_sb = yaffs_read_super, + .mount = yaffs_mount, .kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV, }; @@ -2315,18 +2318,17 @@ static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data, return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL; } -static int yaffs2_read_super(struct file_system_type *fs, - int flags, const char *dev_name, void *data, - struct vfsmount *mnt) +static struct dentry *yaffs2_mount(struct file_system_type *fs, + int flags, const char *dev_name, void *data) { - return get_sb_bdev(fs, flags, dev_name, data, - yaffs2_internal_read_super_mtd, mnt); + return mount_bdev(fs, flags, dev_name, data, + yaffs2_internal_read_super_mtd); } static struct file_system_type yaffs2_fs_type = { .owner = THIS_MODULE, .name = "yaffs2", - .get_sb = yaffs2_read_super, + .mount = yaffs2_mount, .kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV, }; diff --git a/yportenv.h b/yportenv.h new file mode 100644 index 0000000..d4a9178 --- /dev/null +++ b/yportenv.h @@ -0,0 +1,20 @@ +/* + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. + * + * Copyright (C) 2002-2011 Aleph One Ltd. + * for Toby Churchill Ltd and Brightstar Engineering + * + * Created by Waldemar Rymarkiewicz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. + */ + +#ifdef YAFFS_CURRENT + #include "yportenv_single.h" +#else + #include "yportenv_multi.h" +#endif -- 2.30.2