*** empty log message ***
[yaffs/.git] / yaffs_fs.c
index de7ee00f00b2d869c9f80a00187ca4acdb73c150..418f378bf2487a69abac6037c52e419e83a4891d 100644 (file)
  * Acknowledgements:
  * * Luc van OostenRyck for numerous patches.
  * * Nick Bane for numerous patches.
+ * * Nick Bane for 2.5/2.6 integration.
  * * Andras Toth for mknod rdev issue.
  * * Some code bodily lifted from JFFS2.
  */
 
 
-const char *yaffs_fs_c_version = "$Id: yaffs_fs.c,v 1.23 2003-01-17 04:19:08 charles Exp $";
+const char *yaffs_fs_c_version = "$Id: yaffs_fs.c,v 1.30 2003-09-20 01:13:48 charles Exp $";
 extern const char *yaffs_guts_c_version;
 
 
@@ -44,7 +45,18 @@ extern const char *yaffs_guts_c_version;
 #include <linux/mtd/mtd.h>
 #include <linux/interrupt.h>
 #include <linux/string.h>
+
+
+#if defined(CONFIG_KERNEL_2_5)
+#include <linux/statfs.h>      /* Added NCB 15-8-2003 */
+#include <asm/statfs.h>
+#define UnlockPage(p) unlock_page(p)
+#define Page_Uptodate(page)    test_bit(PG_uptodate, &(page)->flags)
+#define kdevname(x) cdevname(to_kdev_t(x))
+#else
 #include <linux/locks.h>
+#endif
+
 
 #include <asm/uaccess.h>
 
@@ -73,8 +85,13 @@ unsigned yaffs_traceMask = YAFFS_TRACE_ALWAYS | YAFFS_TRACE_BAD_BLOCKS;
 
 #define yaffs_InodeToObject(iptr) ((yaffs_Object *)((iptr)->u.generic_ip))
 #define yaffs_DentryToObject(dptr) yaffs_InodeToObject((dptr)->d_inode)
-#define yaffs_SuperToDevice(sb)        ((yaffs_Device *)sb->u.generic_sbp)
+//NCB #define yaffs_SuperToDevice(sb)  ((yaffs_Device *)sb->u.generic_sbp)
 
+#if defined(CONFIG_KERNEL_2_5)
+#define yaffs_SuperToDevice(sb)        ((yaffs_Device *)sb->s_fs_info)
+#else
+#define yaffs_SuperToDevice(sb)        ((yaffs_Device *)sb->u.generic_sbp)
+#endif
 
 
 static void yaffs_put_super(struct super_block *sb);
@@ -87,19 +104,39 @@ static int yaffs_sync_object(struct file * file, struct dentry *dentry, int data
 
 static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir);
 
+#if defined(CONFIG_KERNEL_2_5) /* Added NCB 185-8-2003 */
+static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *n);
+static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *n);
+#else
 static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode);
 static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry);
+#endif
 static int yaffs_link(struct dentry *old_dentry, struct inode * dir, struct dentry * dentry);
 static int yaffs_unlink(struct inode * dir, struct dentry *dentry);
 static int yaffs_symlink(struct inode * dir, struct dentry *dentry, const char * symname);
 static int yaffs_mkdir(struct inode * dir, struct dentry * dentry, int mode);
+
+#if defined(CONFIG_KERNEL_2_5)
+static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
+#else
 static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev);
+#endif
 static int yaffs_rename(struct inode * old_dir, struct dentry *old_dentry, struct inode * new_dir,struct dentry *new_dentry);
 static int yaffs_setattr(struct dentry *dentry, struct iattr *attr);
 
+#if defined(CONFIG_KERNEL_2_5) /* Added NCB 185-8-2003 */
+static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf);
+#else
 static int yaffs_statfs(struct super_block *sb, struct statfs *buf);
+#endif
 static void yaffs_read_inode (struct inode *inode);
+
+#if defined(CONFIG_KERNEL_2_5)
+static struct super_block *yaffs_read_super(struct file_system_type * fs, int flags, const char *dev_name, void *data);
+#else
 static struct super_block *yaffs_read_super(struct super_block * sb, void * data, int silent);
+#endif
+
 static void yaffs_put_inode (struct inode *inode);
 static void yaffs_delete_inode(struct inode *);
 static void yaffs_clear_inode(struct inode *);
@@ -243,10 +280,14 @@ struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,yaffs_Ob
 /*
  * Lookup is used to find objects in the fs
  */
+#if defined(CONFIG_KERNEL_2_5) /* Added NCB 185-8-2003 */
+static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *n)
+#else
 static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry)
+#endif
 {
        yaffs_Object *obj;
-       struct inode *inode;
+       struct inode *inode = NULL; // NCB 2.5/2.6 needs NULL here
        
        yaffs_Device *dev = yaffs_InodeToObject(dir)->myDev;
 
@@ -271,6 +312,8 @@ static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry)
                if(inode)
                {
                        T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_loookup dentry \n"));
+/* #if 0 asserted by NCB for 2.5/6 compatability - falls through to d_add even if NULL inode */        
+#if 0
                        //dget(dentry); // try to solve directory bug
                        d_add(dentry,inode);
                        
@@ -278,6 +321,7 @@ static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry)
 
                        // return dentry;
                        return NULL;
+#endif
                }
 
        }
@@ -287,6 +331,9 @@ static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry)
                
        }
        yaffs_GrossUnlock(dev);
+
+/* added NCB for 2.5/6 compatability - forces add even if inode is NULL which creates dentry hash*/    
+       d_add(dentry,inode);
        
        return NULL;
        //      return (ERR_PTR(-EIO));
@@ -476,12 +523,23 @@ static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object *obj)
                inode->i_uid = obj->st_uid;
                inode->i_gid = obj->st_gid;
                inode->i_blksize = inode->i_sb->s_blocksize;
-               inode->i_blocks = 0;
-               inode->i_rdev = obj->st_rdev;;
+#if defined(CONFIG_KERNEL_2_5)
+               inode->i_rdev = to_kdev_t(obj->st_rdev);
+               inode->i_atime.tv_sec = (time_t)(obj->st_atime);
+               inode->i_atime.tv_nsec = 0;
+               inode->i_mtime.tv_sec = (time_t)obj->st_mtime;
+               inode->i_mtime.tv_nsec =0;
+               inode->i_ctime.tv_sec = (time_t)obj->st_ctime;
+               inode->i_ctime.tv_nsec = 0;
+#else
+               inode->i_rdev = obj->st_rdev;
                inode->i_atime = obj->st_atime;
                inode->i_mtime = obj->st_mtime;
                inode->i_ctime = obj->st_ctime;
+#endif
                inode->i_size = yaffs_GetObjectFileLength(obj);
+               inode->i_blocks = (inode->i_size + 511) >> 9;
+
                inode->i_nlink = yaffs_GetObjectLinkCount(obj);
                
                T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_FillInode mode %x uid %d gid %d size %d count %d\n",
@@ -490,7 +548,7 @@ static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object *obj)
                switch (obj->st_mode & S_IFMT) 
                {
                        default: // fifo, device or socket
-                               init_special_inode(inode, obj->st_mode, obj->st_rdev);
+                               init_special_inode(inode, obj->st_mode,(dev_t)(obj->st_rdev));
                                break;
                        case S_IFREG:   // file         
                                inode->i_op = &yaffs_file_inode_operations;
@@ -622,7 +680,7 @@ static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, loff_
                if(ipos > inode->i_size)
                {
                        inode->i_size = ipos;
-                       inode->i_blocks = (ipos + inode->i_blksize - 1)/ inode->i_blksize;
+                       inode->i_blocks = (ipos + 511)>>9;
                        
                        T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_file_write size updated to %d bytes, %d blocks\n",ipos,(int)(inode->i_blocks)));
                }
@@ -715,7 +773,11 @@ static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
 /*
  * File creation. Allocate an inode, and we're done..
  */
+#if defined(CONFIG_KERNEL_2_5)
+static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
+#else
 static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev)
+#endif
 {
        struct inode *inode;
        
@@ -798,7 +860,11 @@ static int yaffs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
        return retVal;
 }
 
+#if defined(CONFIG_KERNEL_2_5) /* Added NCB 185-8-2003 */
+static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *n)
+#else
 static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode)
+#endif
 {
        T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_create\n"));
        return yaffs_mknod(dir, dentry, mode | S_IFREG, 0);
@@ -1017,7 +1083,11 @@ static int yaffs_setattr(struct dentry *dentry, struct iattr *attr)
        return error;
 }
 
+#if defined(CONFIG_KERNEL_2_5) /* Added NCB 185-8-2003 */
+static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf)
+#else
 static int yaffs_statfs(struct super_block *sb, struct statfs *buf)
+#endif
 {
        yaffs_Device *dev = yaffs_SuperToDevice(sb);
        T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_statfs\n"));
@@ -1130,7 +1200,7 @@ static struct super_block *yaffs_internal_read_super(int useRam, struct super_bl
        T(YAFFS_TRACE_OS,("yaffs_read_super: %s block size %d\n", useRam ? "RAM" : "MTD",(int)(sb->s_blocksize)));
 
 #ifdef CONFIG_YAFFS_DISABLE_WRITE_VERIFY
-       T(YAFFS_TRACE_OS,("yaffs: Write verification disabled. All guarantees null and void\n");
+       T(YAFFS_TRACE_OS,("yaffs: Write verification disabled. All guarantees null and void\n"));
 #endif
 
 
@@ -1157,6 +1227,7 @@ static struct super_block *yaffs_internal_read_super(int useRam, struct super_bl
                dev->endBlock = nBlocks - 1;
                dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
                dev->nBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
+               dev->nReservedBlocks = 5;
 
                dev->writeChunkToNAND = nandemul_WriteChunkToNAND;
                dev->readChunkFromNAND = nandemul_ReadChunkFromNAND;
@@ -1176,7 +1247,13 @@ static struct super_block *yaffs_internal_read_super(int useRam, struct super_bl
                printk(KERN_DEBUG "yaffs: Attempting MTD mount on %u.%u, \"%s\"\n",
                 MAJOR(sb->s_dev),MINOR(sb->s_dev),kdevname(sb->s_dev));
                        
-               // Hope it's a NAND mtd
+               // Check it's an mtd device.....
+               if(MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR)
+               {
+                       return NULL; // This isn't an mtd device
+               } 
+               
+               // Get the device
                mtd = get_mtd_device(NULL, MINOR(sb->s_dev));
                if (!mtd) 
                {
@@ -1184,6 +1261,7 @@ static struct super_block *yaffs_internal_read_super(int useRam, struct super_bl
                        return NULL;
                }
                
+               // Check it's NAND
                if(mtd->type != MTD_NANDFLASH)
                {
                        printk(KERN_DEBUG "yaffs: MTD device is not NAND it's type %d\n", mtd->type);
@@ -1225,7 +1303,11 @@ static struct super_block *yaffs_internal_read_super(int useRam, struct super_bl
                // like it has the right capabilities
                // Set the yaffs_Device up for ram emulation
 
+#if defined(CONFIG_KERNEL_2_5)
+               sb->s_fs_info = dev = kmalloc(sizeof(yaffs_Device),GFP_KERNEL);
+#else
                sb->u.generic_sbp =     dev = kmalloc(sizeof(yaffs_Device),GFP_KERNEL);
+#endif
                if(!dev)
                {
                        // Deep shit could not allocate device structure
@@ -1243,6 +1325,8 @@ static struct super_block *yaffs_internal_read_super(int useRam, struct super_bl
                dev->endBlock = nBlocks - 1;
                dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
                dev->nBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
+               dev->nReservedBlocks = 5;
+               dev->nShortOpCaches = 10; // Enable short op caching
                
 
                // ... and the functions.
@@ -1277,6 +1361,10 @@ static struct super_block *yaffs_internal_read_super(int useRam, struct super_bl
 
        if (!inode)
                return NULL;
+               
+// added NCB
+       inode->i_op = & yaffs_dir_inode_operations;
+       inode->i_fop = & yaffs_dir_operations;
 
        T(YAFFS_TRACE_OS,("yaffs_read_super: got root inode\n"));
                
@@ -1295,7 +1383,35 @@ static struct super_block *yaffs_internal_read_super(int useRam, struct super_bl
        return sb;
 }
 
+static int yaffs_internal_read_super_ram(struct super_block * sb, void * data, int silent)
+{
+        return yaffs_internal_read_super(1,sb,data,silent) ? 0 : -1;
+}
+static int yaffs_internal_read_super_mtd(struct super_block * sb, void * data, int silent)
+{
+        return yaffs_internal_read_super(0,sb,data,silent) ? 0 : -1;
+}
+
+
 #ifdef CONFIG_YAFFS_MTD_ENABLED
+#if defined(CONFIG_KERNEL_2_5)
+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);
+}
+
+/* changes NCB 2.5.70 */
+//static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super, FS_REQUIRES_DEV);
+static struct file_system_type yaffs_fs_type = {
+       .owner          = THIS_MODULE,
+       .name           = "yaffs",
+       .get_sb         = yaffs_read_super,
+//     .kill_sb        = kill_block_super,
+       .kill_sb        = kill_litter_super,
+       .fs_flags       = FS_REQUIRES_DEV,
+};
+#else
 static struct super_block *yaffs_read_super(struct super_block * sb, void * data, int silent)
 {
        return yaffs_internal_read_super(0,sb,data,silent);
@@ -1303,15 +1419,35 @@ static struct super_block *yaffs_read_super(struct super_block * sb, void * data
 
 static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super, FS_REQUIRES_DEV);
 #endif
+#endif
 
 #ifdef CONFIG_YAFFS_RAM_ENABLED
 
+#if defined(CONFIG_KERNEL_2_5)
+static struct super_block *yaffs_ram_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_ram);
+}
+
+/* changes NCB 2.5.70 */
+//static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super, FS_REQUIRES_DEV);
+static struct file_system_type yaffs_fs_type = {
+       .owner          = THIS_MODULE,
+       .name           = "yaffsram",
+       .get_sb         = yaffs_ram_read_super,
+//     .kill_sb        = kill_block_super,
+       .kill_sb        = kill_litter_super,
+       .fs_flags       = FS_SINGLE,
+};
+#else
 static struct super_block *yaffs_ram_read_super(struct super_block * sb, void * data, int silent)
 {
        return yaffs_internal_read_super(1,sb,data,silent);
 }
 
 static DECLARE_FSTYPE(yaffs_ram_fs_type, "yaffsram", yaffs_ram_read_super, FS_SINGLE);
+#endif
 #endif // CONFIG_YAFFS_RAM_ENABLED