Initial revision
[yaffs/.git] / yaffs_fs.c
1 /*
2  * YAFFS: Yet another FFS. A NAND-flash specific file system.
3  * yaffs_fs.c
4  *
5  * Copyright (C) 2002 Aleph One Ltd.
6  *   for Toby Churchill Ltd and Brightstar Engineering
7  *
8  * Created by Charles Manning <charles@aleph1.co.uk>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  *
14  * This is the file system front-end to YAFFS that hooks it up to
15  * the VFS.
16  *
17  * Special notes:
18  * >> sb->u.generic_sbp points to the yaffs_Device associated with this superblock
19  * >> inode->u.generic_ip points to the associated yaffs_Object.
20  */
21
22
23 #include <linux/config.h>
24 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <linux/version.h>
27 #include <linux/slab.h>
28 #include <linux/init.h>
29 #include <linux/list.h>
30 #include <linux/fs.h>
31 #include <linux/proc_fs.h>
32 #include <linux/pagemap.h>
33 #include <linux/mtd/mtd.h>
34 #include <linux/interrupt.h>
35 #include <linux/string.h>
36 #include <linux/locks.h>
37
38 #include <asm/uaccess.h>
39
40 #include "yaffs_guts.h"
41
42 #ifdef YAFFS_RAM_ENABLED
43 #include "yaffs_nandemul.h"
44 // 2 MB of RAM for emulation
45 #define YAFFS_RAM_EMULATION_SIZE  0x200000
46 #endif // YAFFS_RAM_ENABLED
47
48 #ifdef YAFFS_MTD_ENABLED
49 #include <linux/mtd/mtd.h>
50 #include "yaffs_mtdif.h"
51 #endif //YAFFS_MTD_ENABLED
52
53 #define T(x) printk x
54
55
56
57 #define yaffs_InodeToObject(iptr) ((yaffs_Object *)((iptr)->u.generic_ip))
58 #define yaffs_DentryToObject(dptr) yaffs_InodeToObject((dptr)->d_inode)
59 #define yaffs_SuperToDevice(sb) ((yaffs_Device *)sb->u.generic_sbp)
60
61
62
63 static ssize_t yaffs_file_read(struct file *f, char *buf, size_t n, loff_t *pos);
64 static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, loff_t *pos);
65
66 static int yaffs_sync_object(struct file * file, struct dentry *dentry, int datasync);
67
68 static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir);
69
70 static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode);
71 static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry);
72 static int yaffs_link(struct dentry *old_dentry, struct inode * dir, struct dentry * dentry);
73 static int yaffs_unlink(struct inode * dir, struct dentry *dentry);
74 static int yaffs_symlink(struct inode * dir, struct dentry *dentry, const char * symname);
75 static int yaffs_mkdir(struct inode * dir, struct dentry * dentry, int mode);
76 static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev);
77 static int yaffs_rename(struct inode * old_dir, struct dentry *old_dentry, struct inode * new_dir,struct dentry *new_dentry);
78 static int yaffs_setattr(struct dentry *dentry, struct iattr *attr);
79
80 static int yaffs_statfs(struct super_block *sb, struct statfs *buf);
81 static void yaffs_read_inode (struct inode *inode);
82 static struct super_block *yaffs_read_super(struct super_block * sb, void * data, int silent);
83 static void yaffs_put_inode (struct inode *inode);
84
85 //static int yaffs_readpage(struct file*,struct page *
86
87 static struct address_space_operations yaffs_address_ops = {
88 //      readpage:               yaffs_readpage,
89 //      prepare_write:  yaffs_prepare_write,
90 //      commit_write:   yaffs_commit_write
91 };
92
93
94 static struct file_operations yaffs_file_operations = {
95         read:           yaffs_file_read,
96         write:          yaffs_file_write,
97 //      mmap:           generic_file_mmap,
98         fsync:          yaffs_sync_object,
99 };
100
101
102 static struct inode_operations yaffs_file_inode_operations = {
103         setattr:        yaffs_setattr,
104 };
105
106
107
108 static struct file_operations yaffs_dir_operations = {
109         read:           generic_read_dir,
110         readdir:        yaffs_readdir,
111         fsync:          yaffs_sync_object,
112 };
113
114 static struct inode_operations yaffs_dir_inode_operations = {
115         create:         yaffs_create,
116         lookup:         yaffs_lookup,
117         link:           yaffs_link,
118         unlink:         yaffs_unlink,
119         symlink:        yaffs_symlink,
120         mkdir:          yaffs_mkdir,
121         rmdir:          yaffs_unlink,
122         mknod:          yaffs_mknod,
123         rename:         yaffs_rename,
124         setattr:        yaffs_setattr,
125 };
126
127 static struct super_operations yaffs_super_ops = {
128         statfs:                 yaffs_statfs,
129         read_inode:             yaffs_read_inode,
130         put_inode:              yaffs_put_inode,
131 //      read_inode:
132 //      remount_fs:
133 //      clear_inode:
134 };
135
136
137 struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,yaffs_Object *obj);
138
139 /*
140  * Lookup is used to find objects in the fs
141  */
142 static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry)
143 {
144         yaffs_Object *obj;
145         struct inode *inode;
146
147
148         T((KERN_DEBUG"yaffs_lookup for %d:%s\n",yaffs_InodeToObject(dir)->objectId,dentry->d_name.name));
149
150         obj = yaffs_FindObjectByName(yaffs_InodeToObject(dir),dentry->d_name.name);
151
152         if(obj)
153         {
154                 T((KERN_DEBUG"yaffs_lookup found %d\n",obj->objectId));
155
156                 inode = yaffs_get_inode(dir->i_sb, obj->st_mode,0,obj);
157
158                 if(inode)
159                 {
160                         T((KERN_DEBUG"yaffs_loookup looks good\n"));
161                         dget(dentry); // try to solve directory bug
162                         d_add(dentry,inode);
163                         return dentry;
164                 }
165
166         }
167         else
168         {
169                 T((KERN_DEBUG"yaffs_lookup not found\n"));
170
171         }
172         return NULL;
173
174 }
175
176 // For now put inode is just for debugging
177 static void yaffs_put_inode(struct inode *inode)
178 {
179         T(("yaffs_put_inode: ino %d, count %d\n",(int)inode->i_ino, atomic_read(&inode->i_count)));
180 }
181
182 #ifdef YAFFS_ADDRESS_OPS
183 static int yaffs_readpage(struct file *file, struct page * page)
184 {
185         T((KERN_DEBUG"yaffs_readpage\n"));
186
187         // TODO
188         return 0;
189 }
190
191 static int yaffs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
192 {
193         T((KERN_DEBUG"yaffs_prepare_write\n"));
194
195         //TODO
196         return 0;
197 }
198
199 static int yaffs_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
200 {
201
202         struct inode *inode = page->mapping->host;
203         loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
204
205         T((KERN_DEBUG"yaffs_commit_write\n"));
206
207         return 0;
208 }
209
210 #endif //YAFFS_ADDRESS_OPS
211
212
213 static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object *obj)
214 {
215         if (inode && obj)
216         {
217                 inode->i_ino = obj->objectId;
218                 inode->i_mode = obj->st_mode;
219                 inode->i_uid = obj->st_uid;
220                 inode->i_gid = obj->st_gid;
221                 inode->i_blksize = YAFFS_BYTES_PER_CHUNK;
222                 inode->i_blocks = 0;
223                 inode->i_rdev = NODEV;
224                 inode->i_mapping->a_ops = &yaffs_address_ops;
225                 inode->i_atime = obj->st_atime;
226                 inode->i_mtime = obj->st_mtime;
227                 inode->i_ctime = obj->st_ctime;
228                 inode->i_size = yaffs_GetObjectFileLength(obj);
229                 inode->i_nlink = yaffs_GetObjectLinkCount(obj);
230
231                 T((KERN_DEBUG"yaffs_FillInode mode %x uid %d gid %d size %d count %d\n",
232                                 inode->i_mode, inode->i_uid, inode->i_gid, (int)inode->i_size, atomic_read(&inode->i_count)));
233
234                 switch (obj->st_mode & S_IFMT)
235                 {
236                         default:
237                         //      init_special_inode(inode, mode, dev);
238                                 break;
239                         case S_IFREG:   // file
240                                 inode->i_op = &yaffs_file_inode_operations;
241                                 inode->i_fop = &yaffs_file_operations;
242                                 break;
243                         case S_IFDIR:   // directory
244                                 inode->i_op = &yaffs_dir_inode_operations;
245                                 inode->i_fop = &yaffs_dir_operations;
246                                 break;
247                         case S_IFLNK:   // symlink
248                                 inode->i_op = &page_symlink_inode_operations;
249                                 break;
250                 }
251
252
253                 inode->u.generic_ip = obj;
254
255         }
256         else
257         {
258                 T((KERN_DEBUG"yaffs_FileInode invalid parameters\n"));
259         }
260
261 }
262
263 struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,yaffs_Object *obj)
264 {
265         struct inode * inode;
266
267         T((KERN_DEBUG"yaffs_get_inode for object %d\n",obj->objectId));
268
269         inode = iget(sb,obj->objectId);
270
271         // No need to call this since iget calls it via the read_inode callback
272         // yaffs_FillInodeFromObject(inode,obj);
273
274         return inode;
275 }
276
277 static ssize_t yaffs_file_read(struct file *f, char *buf, size_t n, loff_t *pos)
278 {
279         yaffs_Object *obj;
280         int nRead,ipos;
281         struct inode *inode;
282
283         T((KERN_DEBUG"yaffs_file_read\n"));
284
285         obj  = yaffs_DentryToObject(f->f_dentry);
286         inode = f->f_dentry->d_inode;
287
288         if (*pos < inode->i_size)
289         {
290                         if (*pos + n > inode->i_size)
291                         {
292                                 n = inode->i_size - *pos;
293                         }
294         }
295         else
296         {
297                 n = 0;
298         }
299
300         nRead = yaffs_ReadDataFromFile(obj,buf,*pos,n);
301         if(nRead > 0)
302         {
303                 f->f_pos += nRead;
304         }
305         ipos = *pos;
306         T((KERN_DEBUG"yaffs_file_read read %d bytes, %d read at %d\n",n,nRead,ipos));
307         return nRead;
308
309 }
310
311 static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, loff_t *pos)
312 {
313         yaffs_Object *obj;
314         int nWritten,ipos;
315         struct inode *inode;
316
317         obj  = yaffs_DentryToObject(f->f_dentry);
318         inode = f->f_dentry->d_inode;
319         nWritten = yaffs_WriteDataToFile(obj,buf,*pos,n);
320         ipos = *pos;
321         T((KERN_DEBUG"yaffs_file_write writing %d bytes, %d written at %d\n",n,nWritten,ipos));
322         if(nWritten > 0)
323         {
324                 *pos += nWritten;
325                 ipos = *pos;
326                 if(*pos > inode->i_size)
327                 {
328                         inode->i_size = *pos;
329                         T((KERN_DEBUG"yaffs_file_write size updated to %d\n",ipos));
330                 }
331
332         }
333         return nWritten;
334 }
335
336
337 static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
338 {
339         yaffs_Object *obj;
340         struct inode *inode = f->f_dentry->d_inode;
341         unsigned long offset, curoffs;
342         struct list_head *i;
343         yaffs_Object *l;
344
345         char name[YAFFS_MAX_NAME_LENGTH +1];
346
347         obj =  yaffs_DentryToObject(f->f_dentry);
348
349         offset = f->f_pos;
350
351         T(("yaffs_readdir: starting at %d\n",(int)offset));
352
353         if(offset == 0)
354         {
355         T((KERN_DEBUG"yaffs_readdir: entry . ino %d \n",(int)inode->i_ino));
356                 if(filldir(dirent,".",1,offset,inode->i_ino,DT_DIR) < 0)
357                 {
358                         goto out;
359                 }
360                 offset++;
361                 f->f_pos++;
362         }
363         if(offset == 1)
364         {
365                 T((KERN_DEBUG"yaffs_readdir: entry .. ino %d \n",(int)f->f_dentry->d_parent->d_inode->i_ino));
366                 if(filldir(dirent,"..",2,offset,f->f_dentry->d_parent->d_inode->i_ino,DT_DIR) < 0)
367                 {
368                         goto out;
369                 }
370                 offset++;
371                 f->f_pos++;
372         }
373
374         curoffs = 1;
375
376         //down(&obj->sem);
377
378
379         list_for_each(i,&obj->variant.directoryVariant.children)
380         {
381                 curoffs++;
382                 if(curoffs >= offset)
383                 {
384                         l = list_entry(i, yaffs_Object,siblings);
385
386                         yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);
387                         T((KERN_DEBUG"yaffs_readdir: %s inode %d\n",name,yaffs_GetObjectInode(l)));
388
389                         if(filldir(dirent,
390                                            name,
391                                            strlen(name),
392                                            offset,
393                                            yaffs_GetObjectInode(l),
394                                            yaffs_GetObjectType(l))
395                                            < 0)
396                         {
397                                 goto up_and_out;
398                         }
399
400                         offset++;
401                         f->f_pos++;
402                 }
403         }
404
405   up_and_out:
406
407         //up(&obj->sem);
408
409   out:
410         return 0;
411 }
412
413
414 /*
415  * File creation. Allocate an inode, and we're done..
416  */
417 static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev)
418 {
419         struct inode *inode;
420
421         yaffs_Object *obj = NULL;
422         yaffs_Object *parent = yaffs_InodeToObject(dir);
423
424         int error = -ENOSPC;
425
426         if(parent)
427         {
428                 T((KERN_DEBUG"yaffs_mknod: parent object %d type %d\n",
429                                          parent->objectId,parent->variantType));
430         }
431         else
432         {
433                 T((KERN_DEBUG"yaffs_mknod: could not get parent object\n"));
434                 return -EPERM;
435         }
436
437         T(("yaffs_mknod: making oject for %s, mode %x\n",
438                                 dentry->d_name.name, mode));
439
440         switch (mode & S_IFMT)
441         {
442                 default:
443
444                         break;
445                 case S_IFREG:   // file
446                         T((KERN_DEBUG"yaffs_mknod: making file\n"));
447                         obj = yaffs_MknodFile(parent,dentry->d_name.name,mode,current->uid, current->gid);
448                         break;
449                 case S_IFDIR:   // directory
450                         T((KERN_DEBUG"yaffs_mknod: making directory\n"));
451                         obj = yaffs_MknodDirectory(parent,dentry->d_name.name,mode,current->uid, current->gid);
452                         break;
453                 case S_IFLNK:   // symlink
454                         T((KERN_DEBUG"yaffs_mknod: making file\n"));
455                         obj = NULL; // Todo
456                         break;
457         }
458
459         if(obj)
460         {
461                 inode = yaffs_get_inode(dir->i_sb, mode, dev, obj);
462
463 // did not fix dir bug          if((mode & S_IFMT) == S_IFDIR)  atomic_inc(&inode->i_count);
464
465                 d_instantiate(dentry, inode);
466                 T((KERN_DEBUG"yaffs_mknod created object %d count = %d\n",obj->objectId,atomic_read(&inode->i_count)));
467                 error = 0;
468         }
469         else
470         {
471                 T((KERN_DEBUG"yaffs_mknod failed making object\n"));
472                 error = -ENOMEM;
473         }
474
475
476         return error;
477 }
478
479 static int yaffs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
480 {
481         int retVal;
482         T((KERN_DEBUG"yaffs_mkdir\n"));
483         retVal =  yaffs_mknod(dir, dentry, mode | S_IFDIR, 0);
484 #if 0
485  // attempt to fix dir bug - didn't work
486         if(!retVal)
487         {
488                 dget(dentry);
489         }
490 #endif
491         return retVal;
492 }
493
494 static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode)
495 {
496         T((KERN_DEBUG"yaffs_create\n"));
497         return yaffs_mknod(dir, dentry, mode | S_IFREG, 0);
498 }
499
500
501 static int yaffs_unlink(struct inode * dir, struct dentry *dentry)
502 {
503
504         T((KERN_DEBUG"yaffs_unlink\n"));
505
506         if(yaffs_Unlink(yaffs_InodeToObject(dir),dentry->d_name.name) == YAFFS_OK)
507         {
508                 return 0;
509         }
510         else
511         {
512                 return -ENOTEMPTY;
513         }
514 }
515
516
517 /*
518  * Link a file..
519  */
520 static int yaffs_link(struct dentry *old_dentry, struct inode * dir, struct dentry * dentry)
521 {
522         struct inode *inode = old_dentry->d_inode;
523
524         T((KERN_DEBUG"yaffs_link\n"));
525
526         return -EPERM; //Todo
527
528
529         if (S_ISDIR(inode->i_mode))
530                 return -EPERM;
531
532
533         return 0;
534 }
535
536
537 static int yaffs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
538 {
539         int error;
540
541         T((KERN_DEBUG"yaffs_symlink\n"));
542
543
544         return -ENOMEM; //Todo
545
546         error = yaffs_mknod(dir, dentry, S_IFLNK | S_IRWXUGO, 0);
547         return error;
548 }
549
550 static int yaffs_sync_object(struct file * file, struct dentry *dentry, int datasync)
551 {
552
553         T((KERN_DEBUG"yaffs_sync_object\n"));
554         yaffs_FlushFile(yaffs_DentryToObject(dentry));
555         return 0;
556 }
557
558 /*
559  * The VFS layer already does all the dentry stuff for rename.
560  */
561 static int yaffs_rename(struct inode * old_dir, struct dentry *old_dentry, struct inode * new_dir,struct dentry *new_dentry)
562 {
563
564
565         if( yaffs_RenameObject(yaffs_InodeToObject(old_dir),old_dentry->d_name.name,
566                                yaffs_InodeToObject(new_dir),new_dentry->d_name.name) == YAFFS_OK)
567         {
568                 return 0;
569         }
570         else
571         {
572                 return -ENOTEMPTY;
573         }
574
575
576 }
577
578 static int yaffs_setattr(struct dentry *dentry, struct iattr *attr)
579 {
580         struct inode *inode = dentry->d_inode;
581         int error;
582
583         T((KERN_DEBUG"yaffs_setattr\n"));
584
585         if((error = inode_change_ok(inode,attr)) == 0)
586         {
587
588                 if(yaffs_SetAttributes(yaffs_InodeToObject(inode),attr) == YAFFS_OK)
589                 {
590                         error = 0;
591                 }
592                 else
593                 {
594                         error = -EPERM;
595                 }
596
597                 inode_setattr(inode,attr);
598         }
599         return error;
600 }
601
602 static int yaffs_statfs(struct super_block *sb, struct statfs *buf)
603 {
604         T((KERN_DEBUG"yaffs_statfs\n"));
605
606         buf->f_type = YAFFS_MAGIC;
607         buf->f_bsize = YAFFS_BYTES_PER_CHUNK;
608         buf->f_namelen = 255;
609         buf->f_blocks = yaffs_SuperToDevice(sb)->nBlocks * YAFFS_CHUNKS_PER_BLOCK;
610         buf->f_files = 0;
611         buf->f_ffree = 0;
612         buf->f_bavail = yaffs_GetNumberOfFreeChunks(yaffs_SuperToDevice(sb));
613         return 0;
614 }
615
616 static void yaffs_read_inode (struct inode *inode)
617 {
618
619         yaffs_Object *obj ;
620
621         T((KERN_DEBUG"yaffs_read_inode for %d\n",(int)inode->i_ino));
622
623         obj  = yaffs_FindObjectByNumber(yaffs_SuperToDevice(inode->i_sb),inode->i_ino);
624
625         yaffs_FillInodeFromObject(inode,obj);
626 }
627
628
629 static struct super_block *yaffs_internal_read_super(int useRam, struct super_block * sb, void * data, int silent)
630 {
631         struct inode * inode;
632         struct dentry * root;
633         yaffs_Device *dev;
634
635
636         T(("yaffs_read_super:\n"));
637         sb->s_blocksize = YAFFS_BYTES_PER_CHUNK;
638         sb->s_blocksize_bits = YAFFS_CHUNK_SIZE_SHIFT;
639         sb->s_magic = YAFFS_MAGIC;
640         sb->s_op = &yaffs_super_ops;
641
642         if(!sb)
643                 printk(KERN_INFO"sb is NULL\n");
644         else if(!sb->s_dev)
645                 printk(KERN_INFO"sb->s_dev is NULL\n");
646         else if(! kdevname(sb->s_dev))
647                 printk(KERN_INFO"kdevname is NULL\n");
648         else
649                 printk(KERN_INFO"dev is %d name is \"%s\"\n", sb->s_dev, kdevname(sb->s_dev));
650
651
652         if(useRam)
653         {
654
655 #if YAFFS_RAM_ENABLED
656                 // Set the yaffs_Device up for ram emulation
657
658                 sb->u.generic_sbp =     dev = kmalloc(sizeof(yaffs_Device),GFP_KERNEL);
659                 if(!dev)
660                 {
661                         // Deep shit could not allocate device structure
662                         printk(KERN_DEBUG"yaffs_read_super: Failed trying to allocate yaffs_Device. Terminating debug.\n");
663                         return NULL;
664                 }
665
666                 memset(dev,0,sizeof(yaffs_Device));
667                 dev->genericDevice = NULL; // Not used for RAM emulation.
668
669                 dev->nBlocks = YAFFS_RAM_EMULATION_SIZE / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK);
670                 dev->startBlock = 1;  // Don't use block 0
671                 dev->endBlock = dev->nBlocks - 1;
672
673                 dev->writeChunkToNAND = nandemul_WriteChunkToNAND;
674                 dev->readChunkFromNAND = nandemul_ReadChunkFromNAND;
675                 dev->eraseBlockInNAND = nandemul_EraseBlockInNAND;
676                 dev->initialiseNAND = nandemul_InitialiseNAND;
677 #endif
678
679         }
680         else
681         {
682 #ifdef YAFFS_MTD_ENABLED
683                 struct mtd_info *mtd;
684
685                 // Hope it's a NAND mtd
686                 mtd = get_mtd_device(NULL, MINOR(sb->s_dev));
687                 if (!mtd)
688                 {
689                         printk(KERN_DEBUG "yaffs: MTD device #%u doesn't appear to exist\n", MINOR(sb->s_dev));
690                         return NULL;
691                 }
692                 if(mtd->type != MTD_NANDFLASH)
693                 {
694                         printk(KERN_DEBUG "yaffs: MTD device is not NAND it's type %d\n", mtd->type);
695                         return NULL;
696                 }
697
698                 if(!mtd->erase ||
699                    !mtd->read  ||
700                    !mtd->write ||
701                    !mtd->read_oob ||
702                    !mtd->write_oob)
703                 {
704                         printk(KERN_DEBUG "yaffs: MTD device does not support required functions\n");
705                         return NULL;
706                 }
707
708                 if(mtd->oobblock != YAFFS_BYTES_PER_CHUNK ||
709                    mtd->oobsize != YAFFS_BYTES_PER_SPARE)
710                 {
711                         printk(KERN_DEBUG "yaffs: MTD device does not support have the right page sizes\n");
712                         return NULL;
713                 }
714
715
716                 // OK, so if we got here, we have an MTD that's NAND and looks
717                 // like it has the right capabilities
718                 // Set the yaffs_Device up for ram emulation
719
720                 sb->u.generic_sbp =     dev = kmalloc(sizeof(yaffs_Device),GFP_KERNEL);
721                 if(!dev)
722                 {
723                         // Deep shit could not allocate device structure
724                         printk(KERN_DEBUG"yaffs_read_super: Failed trying to allocate yaffs_Device. Terminating debug.\n");
725                         return NULL;
726                 }
727
728                 memset(dev,0,sizeof(yaffs_Device));
729                 dev->genericDevice = mtd;
730
731                 // Set up the memory size parameters....
732
733                 dev->nBlocks = mtd->size / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK);
734                 dev->startBlock = 1;  // Don't use block 0
735                 dev->endBlock = dev->nBlocks - 1;
736
737                 // ... and the functions.
738                 dev->writeChunkToNAND = nandmtd_WriteChunkToNAND;
739                 dev->readChunkFromNAND = nandmtd_ReadChunkFromNAND;
740                 dev->eraseBlockInNAND = nandmtd_EraseBlockInNAND;
741                 dev->initialiseNAND = nandmtd_InitialiseNAND;
742
743 #endif
744         }
745
746
747
748         yaffs_GutsInitialise(yaffs_SuperToDevice(sb));
749         T(("yaffs_read_super: guts initialised\n"));
750
751         // Create root inode
752         inode = yaffs_get_inode(sb, S_IFDIR | 0755, 0,yaffs_Root(yaffs_SuperToDevice(sb)));
753         if (!inode)
754                 return NULL;
755
756         T(("yaffs_read_super: got root inode\n"));
757
758
759         root = d_alloc_root(inode);
760
761         T(("yaffs_read_super: d_alloc_root done\n"));
762
763         if (!root) {
764                 iput(inode);
765                 return NULL;
766         }
767         sb->s_root = root;
768
769         T(("yaffs_read_super: done\n"));
770         return sb;
771 }
772
773 #ifdef YAFFS_MTD_ENABLED
774 static struct super_block *yaffs_read_super(struct super_block * sb, void * data, int silent)
775 {
776         return yaffs_internal_read_super(0,sb,data,silent);
777 }
778
779 static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super, FS_REQUIRES_DEV);
780 #endif
781
782 #ifdef YAFFS_RAM_ENABLED
783
784 static struct super_block *yaffs_ram_read_super(struct super_block * sb, void * data, int silent)
785 {
786         return yaffs_internal_read_super(1,sb,data,silent);
787 }
788
789 static DECLARE_FSTYPE(yaffs_ram_fs_type, "yaffsram", yaffs_ram_read_super, FS_SINGLE);
790 #endif // YAFFS_RAM_ENABLED
791
792
793 static struct proc_dir_entry *my_proc_entry;
794
795
796 static int  yaffs_proc_read(
797         char *page,
798         char **start,
799         off_t offset,
800         int count,
801         int *eof,
802         void *data
803         )
804 {
805
806         static char my_buffer[1000];
807
808         if (offset > 0) return 0;
809
810         /* Fill the buffer and get its length */
811         sprintf( my_buffer,
812                 "YAFFS built:"__DATE__ " "__TIME__"\n"
813
814         );
815
816         strcpy(page,my_buffer);
817         return strlen(my_buffer);
818 }
819
820 static int __init init_yaffs_fs(void)
821 {
822         int error = 0;
823
824         printk(KERN_DEBUG "yaffs " __DATE__ " " __TIME__ " Initialisation\n");
825     /* Install the proc_fs entry */
826     my_proc_entry = create_proc_read_entry("yaffs",
827                                            S_IRUGO | S_IFREG,
828                                            &proc_root,
829                                            yaffs_proc_read,
830                                            NULL);
831     if(!my_proc_entry)
832     {
833        return -ENOMEM;
834     }
835
836 #ifdef YAFFS_RAM_ENABLED
837
838     error = register_filesystem(&yaffs_ram_fs_type);
839     if(error)
840     {
841         return error;
842     }
843 #endif //YAFFS_RAM_ENABLED
844
845 #ifdef YAFFS_MTD_ENABLED
846         error = register_filesystem(&yaffs_fs_type);
847         if(error)
848         {
849 #ifdef YAFFS_RAM_ENABLED
850                 unregister_filesystem(&yaffs_ram_fs_type);
851 #endif //YAFFS_RAM_ENABLED
852         }
853 #endif // YAFFS_MTD_ENABLED
854
855         return error;
856 }
857
858 static void __exit exit_yaffs_fs(void)
859 {
860         printk(KERN_DEBUG "yaffs " __DATE__ " " __TIME__ " Clean up\n");
861
862     remove_proc_entry("yaffs",&proc_root);
863
864 #ifdef YAFFS_RAM_ENABLED
865         unregister_filesystem(&yaffs_ram_fs_type);
866 #endif
867 #ifdef YAFFS_MTD_ENABLED
868         unregister_filesystem(&yaffs_fs_type);
869 #endif
870
871 }
872
873 module_init(init_yaffs_fs)
874 module_exit(exit_yaffs_fs)
875
876 MODULE_DESCRIPTION("YAFFS - a NAND specific flash file system");
877 MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002");
878 MODULE_LICENSE("GPL");
879