*/
const char *yaffs_fs_c_version =
- "$Id: yaffs_fs.c,v 1.47 2006-05-17 09:36:06 charles Exp $";
+ "$Id: yaffs_fs.c,v 1.54 2006-10-24 18:09:15 charles Exp $";
extern const char *yaffs_guts_c_version;
#include <linux/config.h>
#define BDEVNAME_SIZE 0
#define yaffs_devname(sb, buf) kdevname(sb->s_dev)
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+/* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */
+#define __user
+#endif
+
#endif
#include <asm/uaccess.h>
static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
loff_t * pos);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+static int yaffs_file_flush(struct file *file, fl_owner_t id);
+#else
static int yaffs_file_flush(struct file *file);
+#endif
static int yaffs_sync_object(struct file *file, struct dentry *dentry,
int datasync);
struct inode *new_dir, struct dentry *new_dentry);
static int yaffs_setattr(struct dentry *dentry, struct iattr *attr);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+static int yaffs_sync_fs(struct super_block *sb, int wait);
+static void yaffs_write_super(struct super_block *sb);
+#else
static int yaffs_sync_fs(struct super_block *sb);
static int yaffs_write_super(struct super_block *sb);
+#endif
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf);
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf);
#else
static int yaffs_statfs(struct super_block *sb, struct statfs *buf);
clear_inode(inode);
}
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+static int yaffs_file_flush(struct file *file, fl_owner_t id)
+#else
static int yaffs_file_flush(struct file *file)
+#endif
{
yaffs_Object *obj = yaffs_DentryToObject(file->f_dentry);
static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object * obj)
{
if (inode && obj) {
+
+
+ /* Check mode against the variant type and attempt to repair if broken. */
+ __u32 mode = obj->yst_mode;
+ switch( obj->variantType ){
+ case YAFFS_OBJECT_TYPE_FILE :
+ if( ! S_ISREG(mode) ){
+ obj->yst_mode &= ~S_IFMT;
+ obj->yst_mode |= S_IFREG;
+ }
+
+ break;
+ case YAFFS_OBJECT_TYPE_SYMLINK :
+ if( ! S_ISLNK(mode) ){
+ obj->yst_mode &= ~S_IFMT;
+ obj->yst_mode |= S_IFLNK;
+ }
+
+ break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY :
+ if( ! S_ISDIR(mode) ){
+ obj->yst_mode &= ~S_IFMT;
+ obj->yst_mode |= S_IFDIR;
+ }
+
+ break;
+ case YAFFS_OBJECT_TYPE_UNKNOWN :
+ case YAFFS_OBJECT_TYPE_HARDLINK :
+ case YAFFS_OBJECT_TYPE_SPECIAL :
+ default:
+ /* TODO? */
+ break;
+ }
+
inode->i_ino = obj->objectId;
inode->i_mode = obj->yst_mode;
inode->i_uid = obj->yst_uid;
int error = -ENOSPC;
uid_t uid = current->fsuid;
gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
+
+ if((dir->i_mode & S_ISGID) && S_ISDIR(mode))
+ mode |= S_ISGID;
if (parent) {
T(YAFFS_TRACE_OS,
return error;
}
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+ yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev;
+ struct super_block *sb = dentry->d_sb;
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf)
+{
+ yaffs_Device *dev = yaffs_SuperToDevice(sb);
#else
static int yaffs_statfs(struct super_block *sb, struct statfs *buf)
-#endif
{
-
yaffs_Device *dev = yaffs_SuperToDevice(sb);
+#endif
+
T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_statfs\n"));
yaffs_GrossLock(dev);
buf->f_type = YAFFS_MAGIC;
buf->f_bsize = sb->s_blocksize;
buf->f_namelen = 255;
- if (sb->s_blocksize > dev->nBytesPerChunk) {
+ if (sb->s_blocksize > dev->nDataBytesPerChunk) {
buf->f_blocks =
(dev->endBlock - dev->startBlock +
1) * dev->nChunksPerBlock / (sb->s_blocksize /
- dev->nBytesPerChunk);
+ dev->nDataBytesPerChunk);
buf->f_bfree =
yaffs_GetNumberOfFreeChunks(dev) / (sb->s_blocksize /
- dev->nBytesPerChunk);
+ dev->nDataBytesPerChunk);
} else {
buf->f_blocks =
(dev->endBlock - dev->startBlock +
- 1) * dev->nChunksPerBlock * (dev->nBytesPerChunk /
+ 1) * dev->nChunksPerBlock * (dev->nDataBytesPerChunk /
sb->s_blocksize);
buf->f_bfree =
- yaffs_GetNumberOfFreeChunks(dev) * (dev->nBytesPerChunk /
+ yaffs_GetNumberOfFreeChunks(dev) * (dev->nDataBytesPerChunk /
sb->s_blocksize);
}
buf->f_files = 0;
}
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+static void yaffs_write_super(struct super_block *sb)
+#else
static int yaffs_write_super(struct super_block *sb)
+#endif
{
T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_write_super\n"));
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
return 0; /* yaffs_do_sync_fs(sb);*/
-
+#endif
}
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+static int yaffs_sync_fs(struct super_block *sb, int wait)
+#else
static int yaffs_sync_fs(struct super_block *sb)
+#endif
{
T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_fs\n"));
T(YAFFS_TRACE_OS, (" writeoob %p\n", mtd->write_oob));
T(YAFFS_TRACE_OS, (" block_isbad %p\n", mtd->block_isbad));
T(YAFFS_TRACE_OS, (" block_markbad %p\n", mtd->block_markbad));
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ T(YAFFS_TRACE_OS, (" writesize %d\n", mtd->writesize));
+#else
T(YAFFS_TRACE_OS, (" oobblock %d\n", mtd->oobblock));
+#endif
T(YAFFS_TRACE_OS, (" oobsize %d\n", mtd->oobsize));
T(YAFFS_TRACE_OS, (" erasesize %d\n", mtd->erasesize));
T(YAFFS_TRACE_OS, (" size %d\n", mtd->size));
#ifdef CONFIG_YAFFS_AUTO_YAFFS2
if (yaffsVersion == 1 &&
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ mtd->writesize >= 2048) {
+#else
mtd->oobblock >= 2048) {
+#endif
T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n"));
yaffsVersion = 2;
}
+
+ /* Added NCB 26/5/2006 for completeness */
+ if (yaffsVersion == 2 &&
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ mtd->writesize == 512) {
+#else
+ mtd->oobblock == 512) {
+#endif
+ T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs1\n"));
+ yaffsVersion = 1;
+ }
+
#endif
if (yaffsVersion == 2) {
!mtd->block_markbad ||
!mtd->read ||
!mtd->write ||
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ !mtd->read_oob || !mtd->write_oob) {
+#else
!mtd->write_ecc ||
!mtd->read_ecc || !mtd->read_oob || !mtd->write_oob) {
+#endif
T(YAFFS_TRACE_ALWAYS,
("yaffs: MTD device does not support required "
"functions\n"));;
return NULL;
}
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ if (mtd->writesize < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
+#else
if (mtd->oobblock < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
+#endif
mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) {
T(YAFFS_TRACE_ALWAYS,
("yaffs: MTD device does not have the "
if (!mtd->erase ||
!mtd->read ||
!mtd->write ||
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ !mtd->read_oob || !mtd->write_oob) {
+#else
!mtd->write_ecc ||
!mtd->read_ecc || !mtd->read_oob || !mtd->write_oob) {
+#endif
T(YAFFS_TRACE_ALWAYS,
("yaffs: MTD device does not support required "
"functions\n"));;
return NULL;
}
- if (mtd->oobblock != YAFFS_BYTES_PER_CHUNK ||
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ if (mtd->writesize < YAFFS_BYTES_PER_CHUNK ||
+#else
+ if (mtd->oobblock < YAFFS_BYTES_PER_CHUNK ||
+#endif
mtd->oobsize != YAFFS_BYTES_PER_SPARE) {
T(YAFFS_TRACE_ALWAYS,
("yaffs: MTD device does not support have the "
dev->startBlock = 0;
dev->endBlock = nBlocks - 1;
dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
- dev->nBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
+ dev->nDataBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
dev->nReservedBlocks = 5;
dev->nShortOpCaches = 10; /* Enable short op caching */
dev->queryNANDBlock = nandmtd2_QueryNANDBlock;
dev->spareBuffer = YMALLOC(mtd->oobsize);
dev->isYaffs2 = 1;
- dev->nBytesPerChunk = mtd->oobblock;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ dev->nDataBytesPerChunk = mtd->writesize;
+ dev->nChunksPerBlock = mtd->erasesize / mtd->writesize;
+#else
+ dev->nDataBytesPerChunk = mtd->oobblock;
dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock;
+#endif
nBlocks = mtd->size / mtd->erasesize;
+
+ dev->nCheckpointReservedBlocks = 10;
dev->startBlock = 0;
dev->endBlock = nBlocks - 1;
} else {
return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL;
}
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+static int yaffs_read_super(struct file_system_type *fs,
+ int flags, const char *dev_name,
+ void *data, struct vfsmount *mnt)
+{
+
+ return get_sb_bdev(fs, flags, dev_name, data,
+ yaffs_internal_read_super_mtd, mnt);
+}
+#else
static struct super_block *yaffs_read_super(struct file_system_type *fs,
int flags, const char *dev_name,
void *data)
return get_sb_bdev(fs, flags, dev_name, data,
yaffs_internal_read_super_mtd);
}
+#endif
static struct file_system_type yaffs_fs_type = {
.owner = THIS_MODULE,
return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL;
}
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+static int yaffs2_read_super(struct file_system_type *fs,
+ int flags, const char *dev_name, void *data,
+ struct vfsmount *mnt)
+{
+ return get_sb_bdev(fs, flags, dev_name, data,
+ yaffs2_internal_read_super_mtd, mnt);
+}
+#else
static struct super_block *yaffs2_read_super(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);
}
+#endif
static struct file_system_type yaffs2_fs_type = {
.owner = THIS_MODULE,