*** empty log message ***
[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  * Acknowledgements:
23  * * Luc van OostenRyck for numerous patches.
24  * * Nick Bane for numerous patches.
25  * * Andras Toth for mknod rdev issue.
26  * * Some code bodily lifted from JFFS2.
27  */
28
29
30 const char *yaffs_fs_c_version = "$Id: yaffs_fs.c,v 1.19 2002-11-22 00:12:23 charles Exp $";
31 extern const char *yaffs_guts_c_version;
32
33
34 #include <linux/config.h>
35 #include <linux/kernel.h>
36 #include <linux/module.h>
37 #include <linux/version.h>
38 #include <linux/slab.h>
39 #include <linux/init.h>
40 #include <linux/list.h>
41 #include <linux/fs.h>
42 #include <linux/proc_fs.h>
43 #include <linux/pagemap.h>
44 #include <linux/mtd/mtd.h>
45 #include <linux/interrupt.h>
46 #include <linux/string.h>
47 #include <linux/locks.h>
48
49 #include <asm/uaccess.h>
50
51 #include "yportenv.h"
52 #include "yaffs_guts.h"
53
54
55
56
57 unsigned yaffs_traceMask = YAFFS_TRACE_ALWAYS | YAFFS_TRACE_BAD_BLOCKS;
58
59 #ifdef CONFIG_YAFFS_RAM_ENABLED
60 #include "yaffs_nandemul.h" 
61 // 2 MB of RAM for emulation
62 #define YAFFS_RAM_EMULATION_SIZE  0x200000
63 #endif //CONFIG_YAFFS_RAM_ENABLED
64
65 #ifdef CONFIG_YAFFS_MTD_ENABLED
66 #include <linux/mtd/mtd.h>
67 #include "yaffs_mtdif.h"
68 #endif //CONFIG_YAFFS_MTD_ENABLED
69
70 #define T(x) printk x
71
72
73
74 #define yaffs_InodeToObject(iptr) ((yaffs_Object *)((iptr)->u.generic_ip))
75 #define yaffs_DentryToObject(dptr) yaffs_InodeToObject((dptr)->d_inode)
76 #define yaffs_SuperToDevice(sb) ((yaffs_Device *)sb->u.generic_sbp)
77
78
79
80 static void yaffs_put_super(struct super_block *sb);
81
82 static ssize_t yaffs_file_read(struct file *f, char *buf, size_t n, loff_t *pos);
83 static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, loff_t *pos);
84 static int yaffs_file_flush(struct file* file);
85
86 static int yaffs_sync_object(struct file * file, struct dentry *dentry, int datasync);
87
88 static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir);
89
90 static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode);
91 static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry);
92 static int yaffs_link(struct dentry *old_dentry, struct inode * dir, struct dentry * dentry);
93 static int yaffs_unlink(struct inode * dir, struct dentry *dentry);
94 static int yaffs_symlink(struct inode * dir, struct dentry *dentry, const char * symname);
95 static int yaffs_mkdir(struct inode * dir, struct dentry * dentry, int mode);
96 static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev);
97 static int yaffs_rename(struct inode * old_dir, struct dentry *old_dentry, struct inode * new_dir,struct dentry *new_dentry);
98 static int yaffs_setattr(struct dentry *dentry, struct iattr *attr);
99
100 static int yaffs_statfs(struct super_block *sb, struct statfs *buf);
101 static void yaffs_read_inode (struct inode *inode);
102 static struct super_block *yaffs_read_super(struct super_block * sb, void * data, int silent);
103 static void yaffs_put_inode (struct inode *inode);
104 static void yaffs_delete_inode(struct inode *);
105 static void yaffs_clear_inode(struct inode *);
106
107 static int yaffs_readpage(struct file *file, struct page * page);
108
109 static int yaffs_prepare_write(struct file *f, struct page *pg, unsigned offset, unsigned to);
110 static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, unsigned to);
111
112 static int yaffs_readlink(struct dentry *dentry, char *buffer, int buflen);
113 static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd);
114
115
116
117
118 static struct address_space_operations yaffs_file_address_operations = {
119         readpage:               yaffs_readpage,
120         prepare_write:  yaffs_prepare_write,
121         commit_write:   yaffs_commit_write
122 };
123
124
125 static struct file_operations yaffs_file_operations = {
126 #ifdef CONFIG_YAFFS_USE_GENERIC_RW
127         read:           generic_file_read,
128         write:          generic_file_write,
129 #else
130         read:           yaffs_file_read,
131         write:          yaffs_file_write,
132 #endif
133         mmap:           generic_file_mmap,
134         flush:          yaffs_file_flush,
135         fsync:          yaffs_sync_object,
136 };
137
138
139 static struct inode_operations yaffs_file_inode_operations = {
140         setattr:        yaffs_setattr,
141 };
142
143
144 struct inode_operations yaffs_symlink_inode_operations =
145 {       
146         readlink:       yaffs_readlink,
147         follow_link:    yaffs_follow_link,
148         setattr:        yaffs_setattr
149 };
150
151 static struct inode_operations yaffs_dir_inode_operations = {
152         create:         yaffs_create,
153         lookup:         yaffs_lookup,
154         link:           yaffs_link,
155         unlink:         yaffs_unlink,   
156         symlink:        yaffs_symlink,
157         mkdir:          yaffs_mkdir,
158         rmdir:          yaffs_unlink,
159         mknod:          yaffs_mknod,
160         rename:         yaffs_rename,
161         setattr:        yaffs_setattr,
162 };
163
164 static struct file_operations yaffs_dir_operations = {
165         read:           generic_read_dir,
166         readdir:        yaffs_readdir,
167         fsync:          yaffs_sync_object,
168 };
169
170
171 static struct super_operations yaffs_super_ops = {
172         statfs:                 yaffs_statfs,
173         read_inode:             yaffs_read_inode,
174         put_inode:              yaffs_put_inode,
175         put_super:              yaffs_put_super,
176 //      remount_fs:
177         delete_inode:           yaffs_delete_inode,
178         clear_inode:            yaffs_clear_inode,
179 };
180
181
182
183 static void yaffs_GrossLock(yaffs_Device *dev)
184 {
185         T((KERN_DEBUG"yaffs locking\n"));
186
187         down(&dev->grossLock);
188 }
189
190 static void yaffs_GrossUnlock(yaffs_Device *dev)
191 {
192         T((KERN_DEBUG"yaffs unlocking\n"));
193         up(&dev->grossLock);
194
195 }
196
197 static int yaffs_readlink(struct dentry *dentry, char *buffer, int buflen)
198 {
199         unsigned char *alias;
200         int ret;
201
202         yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev;
203
204
205         yaffs_GrossLock(dev);
206         
207         alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry));
208         
209         yaffs_GrossUnlock(dev);
210         
211         if(!alias)
212                 return -ENOMEM;
213
214         ret = vfs_readlink(dentry, buffer, buflen, alias);
215         kfree(alias);
216         return ret;
217 }
218
219 static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
220 {
221         unsigned char *alias;
222         int ret;
223         yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev;
224
225
226         yaffs_GrossLock(dev);
227
228         alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry));
229         
230         yaffs_GrossUnlock(dev);
231         
232         if(!alias)
233                 return -ENOMEM;
234
235         ret = vfs_follow_link(nd,alias);
236         kfree(alias);
237         return ret;
238 }
239
240
241 struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,yaffs_Object *obj);
242
243 /*
244  * Lookup is used to find objects in the fs
245  */
246 static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry)
247 {
248         yaffs_Object *obj;
249         struct inode *inode;
250         
251         yaffs_Device *dev = yaffs_InodeToObject(dir)->myDev;
252
253
254         yaffs_GrossLock(dev);
255
256         
257         T((KERN_DEBUG"yaffs_lookup for %d:%s\n",yaffs_InodeToObject(dir)->objectId,dentry->d_name.name));
258         
259         obj = yaffs_FindObjectByName(yaffs_InodeToObject(dir),dentry->d_name.name);
260         
261         obj = yaffs_GetEquivalentObject(obj); // in case it was a hardlink
262         
263
264         
265         if(obj)
266         {
267                 T((KERN_DEBUG"yaffs_lookup found %d\n",obj->objectId));
268                 
269                 inode = yaffs_get_inode(dir->i_sb, obj->st_mode,0,obj);
270                 
271                 if(inode)
272                 {
273                         T((KERN_DEBUG"yaffs_loookup dentry \n"));
274                         //dget(dentry); // try to solve directory bug
275                         d_add(dentry,inode);
276                         
277                         yaffs_GrossUnlock(dev);
278
279                         // return dentry;
280                         return NULL;
281                 }
282
283         }
284         else
285         {
286                 T((KERN_DEBUG"yaffs_lookup not found\n"));
287                 
288         }
289         yaffs_GrossUnlock(dev);
290         
291         return NULL;
292         //      return (ERR_PTR(-EIO));
293         
294 }
295
296 // For now put inode is just for debugging
297 // Put inode is called when the inode **structure** is put.
298 static void yaffs_put_inode(struct inode *inode)
299 {
300         T(("yaffs_put_inode: ino %d, count %d\n",(int)inode->i_ino, atomic_read(&inode->i_count)));
301         
302 }
303
304 // clear is called to tell the fs to release any per-inode data it holds
305 static void yaffs_clear_inode(struct inode *inode)
306 {
307         yaffs_Object *obj = yaffs_InodeToObject(inode);
308         
309         T(("yaffs_clear_inode: ino %d, count %d %s\n",(int)inode->i_ino, atomic_read(&inode->i_count),
310                 obj ? "object exists" : "null object"));        
311
312         if(obj)
313         {
314                 obj->myInode = NULL;
315                 inode->u.generic_ip = NULL;     
316         }
317         
318         
319 }
320
321 // delete is called when the link count is zero and the inode
322 // is put (ie. nobody wants to know about it anymore, time to
323 // delete the file).
324 // NB Must call clear_inode()
325 static void yaffs_delete_inode(struct inode *inode)
326 {
327         yaffs_Object *obj = yaffs_InodeToObject(inode);
328         yaffs_Device *dev;
329
330         T(("yaffs_delete_inode: ino %d, count %d %s\n",(int)inode->i_ino, atomic_read(&inode->i_count),
331                 obj ? "object exists" : "null object"));
332         
333         if(obj)
334         {
335                 dev = obj->myDev;
336                 yaffs_GrossLock(dev);
337                 yaffs_DeleteFile(obj);
338                 yaffs_GrossUnlock(dev);
339         }
340         clear_inode(inode);
341 }
342
343
344 static int yaffs_file_flush(struct file* file)
345 {
346         yaffs_Object *obj = yaffs_DentryToObject(file->f_dentry);
347         
348         yaffs_Device *dev = obj->myDev;
349         
350         T((KERN_DEBUG"yaffs_file_flush object %d (%s)\n",obj->objectId,
351                                 obj->dirty ? "dirty" : "clean"));
352
353         yaffs_GrossLock(dev);
354         
355     yaffs_FlushFile(obj);
356
357         yaffs_GrossUnlock(dev);
358
359     return 0;
360 }
361
362
363
364 static int yaffs_readpage_nolock(struct file *f, struct page * pg)
365 {
366         // Lifted from jffs2
367         
368         yaffs_Object *obj;
369         unsigned char *pg_buf;  
370         int ret;
371         
372         yaffs_Device *dev;
373         
374         T((KERN_DEBUG"yaffs_readpage at %08x, size %08x\n", 
375                       (unsigned)(pg->index << PAGE_CACHE_SHIFT), (unsigned)PAGE_CACHE_SIZE));
376
377         obj  = yaffs_DentryToObject(f->f_dentry);
378
379         dev = obj->myDev;
380         
381         
382         if (!PageLocked(pg))
383                 PAGE_BUG(pg);
384
385         pg_buf = kmap(pg);
386         /* FIXME: Can kmap fail? */
387
388         yaffs_GrossLock(dev);
389         
390         ret = yaffs_ReadDataFromFile(obj, pg_buf, pg->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE);
391
392         yaffs_GrossUnlock(dev);
393         
394         if(ret >= 0) ret = 0;
395
396         if (ret) {
397                 ClearPageUptodate(pg);
398                 SetPageError(pg);
399         } else {
400                 SetPageUptodate(pg);
401                 ClearPageError(pg);
402         }
403
404         flush_dcache_page(pg);
405         kunmap(pg);
406
407
408         T((KERN_DEBUG"yaffs_readpage done\n"));
409         return ret;
410 }
411
412 static int yaffs_readpage_unlock(struct file *f, struct page *pg)
413 {
414         int ret = yaffs_readpage_nolock(f,pg);
415         UnlockPage(pg);
416         return ret;
417 }
418
419 static int yaffs_readpage(struct file *f, struct page * pg)
420 {
421         return yaffs_readpage_unlock(f,pg);
422 }
423
424
425 static int yaffs_prepare_write(struct file *f, struct page *pg, unsigned offset, unsigned to)
426 {
427
428         T((KERN_DEBUG"yaffs_prepair_write\n"));
429         if(!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE))
430                 return  yaffs_readpage_nolock(f,pg);    
431
432         return 0;
433         
434 }
435
436 static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, unsigned to)
437 {
438
439         void *addr = page_address(pg) + offset;
440         loff_t pos = (((loff_t)pg->index) << PAGE_CACHE_SHIFT) + offset;
441         int nBytes = to - offset;
442         int nWritten;
443         
444         unsigned spos = pos;
445         unsigned saddr = (unsigned)addr;
446
447         T((KERN_DEBUG"yaffs_commit_write addr %x pos %x nBytes %d\n",saddr,spos,nBytes));
448         
449         nWritten = yaffs_file_write(f,addr, nBytes, &pos);
450         
451         if(nWritten != nBytes)
452         {
453                 T((KERN_DEBUG"yaffs_commit_write not same size nWritten %d  nBytes %d\n",nWritten,nBytes));
454                 SetPageError(pg);
455                 ClearPageUptodate(pg);
456         }
457         else
458         {
459                 SetPageUptodate(pg);
460         }
461
462         T((KERN_DEBUG"yaffs_commit_write returning %d\n",nWritten));
463         
464         return nWritten;
465
466 }
467
468
469
470 static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object *obj)
471 {
472         if (inode && obj) 
473         {
474                 inode->i_ino = obj->objectId;
475                 inode->i_mode = obj->st_mode;
476                 inode->i_uid = obj->st_uid;
477                 inode->i_gid = obj->st_gid;
478                 inode->i_blksize = inode->i_sb->s_blocksize;
479                 inode->i_blocks = 0;
480                 inode->i_rdev = obj->st_rdev;;
481                 inode->i_atime = obj->st_atime;
482                 inode->i_mtime = obj->st_mtime;
483                 inode->i_ctime = obj->st_ctime;
484                 inode->i_size = yaffs_GetObjectFileLength(obj);
485                 inode->i_nlink = yaffs_GetObjectLinkCount(obj);
486                 
487                 T((KERN_DEBUG"yaffs_FillInode mode %x uid %d gid %d size %d count %d\n",
488                                 inode->i_mode, inode->i_uid, inode->i_gid, (int)inode->i_size, atomic_read(&inode->i_count)));
489                 
490                 switch (obj->st_mode & S_IFMT) 
491                 {
492                         default: // fifo, device or socket
493                                 init_special_inode(inode, obj->st_mode, obj->st_rdev);
494                                 break;
495                         case S_IFREG:   // file         
496                                 inode->i_op = &yaffs_file_inode_operations;
497                                 inode->i_fop = &yaffs_file_operations;
498                                 inode->i_mapping->a_ops = &yaffs_file_address_operations;
499                                 break;
500                         case S_IFDIR:   // directory
501                                 inode->i_op = &yaffs_dir_inode_operations;
502                                 inode->i_fop = &yaffs_dir_operations;
503                                 break;
504                         case S_IFLNK:   // symlink
505                                 inode->i_op = &yaffs_symlink_inode_operations;
506                                 break;
507                 }
508                 
509                 
510                 inode->u.generic_ip = obj;
511                 obj->myInode = inode;
512                 
513         }
514         else
515         {
516                 T((KERN_DEBUG"yaffs_FileInode invalid parameters\n"));
517         }
518
519 }
520
521 struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,yaffs_Object *obj)
522 {
523         struct inode * inode;
524         
525         T((KERN_DEBUG"yaffs_get_inode for object %d\n",obj->objectId));
526
527         inode = iget(sb,obj->objectId);
528
529         // NB Side effect: iget calls back to yaffs_read_inode().
530         // iget also increments the inode's i_count
531         
532         return inode;
533 }
534
535 static ssize_t yaffs_file_read(struct file *f, char *buf, size_t n, loff_t *pos)
536 {
537         yaffs_Object *obj;
538         int nRead,ipos;
539         struct inode *inode;
540         yaffs_Device *dev;
541         
542         T((KERN_DEBUG"yaffs_file_read\n"));
543
544         obj  = yaffs_DentryToObject(f->f_dentry);
545         
546         dev = obj->myDev;
547         
548         yaffs_GrossLock(dev);
549         
550         inode = f->f_dentry->d_inode;
551         
552         if (*pos < inode->i_size) 
553         {
554                         if (*pos + n > inode->i_size)
555                         {
556                                 n = inode->i_size - *pos;
557                         }
558         }
559         else
560         {
561                 n = 0;
562         }
563         
564         nRead = yaffs_ReadDataFromFile(obj,buf,*pos,n);
565         if(nRead > 0)
566         {
567                 f->f_pos += nRead;
568         }
569         
570         yaffs_GrossUnlock(dev);
571         
572         ipos = *pos;
573         
574         T((KERN_DEBUG"yaffs_file_read read %d bytes, %d read at %d\n",n,nRead,ipos));
575         return nRead;
576         
577 }
578
579
580 static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, loff_t *pos)
581 {
582         yaffs_Object *obj;
583         int nWritten,ipos;
584         struct inode *inode;
585         yaffs_Device *dev;
586         
587         
588         obj  = yaffs_DentryToObject(f->f_dentry);
589         
590         dev = obj->myDev;
591         
592         yaffs_GrossLock(dev);
593         
594         inode = f->f_dentry->d_inode;
595
596         if(!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND)
597         {
598                 ipos = inode->i_size;
599         }
600         else
601         {
602                 ipos = *pos;
603         }
604         
605         
606         if(!obj)
607         {
608                 T((KERN_DEBUG"yaffs_file_write: hey obj is null!\n"));
609         }
610         else
611         {
612                 T((KERN_DEBUG"yaffs_file_write about to write writing %d bytes to object %d at %d\n",n,obj->objectId,ipos));
613         }
614
615         nWritten = yaffs_WriteDataToFile(obj,buf,ipos,n);
616
617         T((KERN_DEBUG"yaffs_file_write writing %d bytes, %d written at %d\n",n,nWritten,ipos));
618         if(nWritten > 0)
619         {
620                 ipos += nWritten;
621                 *pos = ipos;
622                 if(ipos > inode->i_size)
623                 {
624                         inode->i_size = ipos;
625                         inode->i_blocks = (ipos + inode->i_blksize - 1)/ inode->i_blksize;
626                         
627                         T((KERN_DEBUG"yaffs_file_write size updated to %d bytes, %d blocks\n",ipos,(int)(inode->i_blocks)));
628                 }
629                 
630         }
631         yaffs_GrossUnlock(dev);
632         
633         return nWritten != n ? -ENOSPC : nWritten;      
634 }
635
636
637 static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
638 {
639         yaffs_Object *obj;
640         yaffs_Device *dev;
641         struct inode *inode = f->f_dentry->d_inode;
642         unsigned long offset, curoffs;
643         struct list_head *i;    
644         yaffs_Object *l;
645         
646         char name[YAFFS_MAX_NAME_LENGTH +1];
647                 
648         obj =  yaffs_DentryToObject(f->f_dentry);
649         dev = obj->myDev;
650         
651         yaffs_GrossLock(dev);
652         
653         offset = f->f_pos;
654         
655         T(("yaffs_readdir: starting at %d\n",(int)offset));
656         
657         if(offset == 0)
658         {
659         T((KERN_DEBUG"yaffs_readdir: entry . ino %d \n",(int)inode->i_ino));
660                 if(filldir(dirent,".",1,offset,inode->i_ino,DT_DIR) < 0)
661                 {
662                         goto out;
663                 }
664                 offset++;
665                 f->f_pos++;
666         }
667         if(offset == 1)
668         {
669                 T((KERN_DEBUG"yaffs_readdir: entry .. ino %d \n",(int)f->f_dentry->d_parent->d_inode->i_ino));
670                 if(filldir(dirent,"..",2,offset,f->f_dentry->d_parent->d_inode->i_ino,DT_DIR) < 0)
671                 {
672                         goto out;
673                 }
674                 offset++;
675                 f->f_pos++;
676         }
677         
678         curoffs = 1;
679         
680         list_for_each(i,&obj->variant.directoryVariant.children)
681         {
682                 curoffs++;
683                 if(curoffs >= offset)
684                 {               
685                         l = list_entry(i, yaffs_Object,siblings);
686                         
687                         yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1); 
688                         T((KERN_DEBUG"yaffs_readdir: %s inode %d\n",name,yaffs_GetObjectInode(l)));
689                         
690                         if(filldir(dirent,
691                                            name,
692                                            strlen(name),
693                                            offset,
694                                            yaffs_GetObjectInode(l),
695                                            yaffs_GetObjectType(l))
696                                            < 0)
697                         {
698                                 goto up_and_out;
699                         }
700                         
701                         offset++;
702                         f->f_pos++;        
703                 }
704         }
705
706   up_and_out:
707   out:
708   
709     yaffs_GrossUnlock(dev);
710     
711         return 0;
712 }
713
714
715 /*
716  * File creation. Allocate an inode, and we're done..
717  */
718 static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev)
719 {
720         struct inode *inode;
721         
722         yaffs_Object *obj = NULL;
723         yaffs_Device *dev;
724         
725         yaffs_Object *parent = yaffs_InodeToObject(dir);
726         
727         int error = -ENOSPC;
728
729         if(parent)
730         {
731                 T((KERN_DEBUG"yaffs_mknod: parent object %d type %d\n",
732                                          parent->objectId,parent->variantType));
733         }
734         else
735         {
736                 T((KERN_DEBUG"yaffs_mknod: could not get parent object\n"));
737                 return -EPERM;
738         }
739         
740         T(("yaffs_mknod: making oject for %s, mode %x dev %x\n",
741                                         dentry->d_name.name, mode,rdev));
742
743         dev = parent->myDev;
744         
745         yaffs_GrossLock(dev);
746
747         switch (mode & S_IFMT) 
748         {
749                 default:
750                         // Special (socket, fifo, device...)
751                         T((KERN_DEBUG"yaffs_mknod: making special\n"));
752                         obj = yaffs_MknodSpecial(parent,dentry->d_name.name,mode,current->uid, current->gid,rdev);
753                         break;
754                 case S_IFREG:   // file         
755                         T((KERN_DEBUG"yaffs_mknod: making file\n"));
756                         obj = yaffs_MknodFile(parent,dentry->d_name.name,mode,current->uid, current->gid);
757                         break;
758                 case S_IFDIR:   // directory
759                         T((KERN_DEBUG"yaffs_mknod: making directory\n"));
760                         obj = yaffs_MknodDirectory(parent,dentry->d_name.name,mode,current->uid, current->gid);
761                         break;
762                 case S_IFLNK:   // symlink
763                         T((KERN_DEBUG"yaffs_mknod: making file\n"));
764                         obj = NULL; // Do we ever get here?
765                         break;
766         }
767         
768         if(obj)
769         {
770                 inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj);
771                 d_instantiate(dentry, inode);
772                 T((KERN_DEBUG"yaffs_mknod created object %d count = %d\n",obj->objectId,atomic_read(&inode->i_count)));
773                 error = 0;
774         }
775         else
776         {
777                 T((KERN_DEBUG"yaffs_mknod failed making object\n"));
778                 error = -ENOMEM;
779         }
780
781         yaffs_GrossUnlock(dev);
782
783         return error;
784 }
785
786 static int yaffs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
787 {
788         int retVal;
789         T((KERN_DEBUG"yaffs_mkdir\n"));
790         retVal =  yaffs_mknod(dir, dentry, mode | S_IFDIR, 0);
791 #if 0
792  // attempt to fix dir bug - didn't work
793         if(!retVal)
794         {
795                 dget(dentry);
796         }
797 #endif
798         return retVal;
799 }
800
801 static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode)
802 {
803         T((KERN_DEBUG"yaffs_create\n"));
804         return yaffs_mknod(dir, dentry, mode | S_IFREG, 0);
805 }
806
807
808 static int yaffs_unlink(struct inode * dir, struct dentry *dentry)
809 {
810         int retVal;
811         int nlinks;
812         
813         yaffs_Device *dev;
814         
815         
816         T((KERN_DEBUG"yaffs_unlink %d:%s\n",(int)(dir->i_ino),dentry->d_name.name));
817         
818         dev = yaffs_InodeToObject(dir)->myDev;
819         
820         yaffs_GrossLock(dev);
821         
822         
823         retVal = yaffs_Unlink(yaffs_InodeToObject(dir),dentry->d_name.name);
824         
825         
826         yaffs_GrossUnlock(dev);
827         
828         if( retVal == YAFFS_OK)
829         {
830                 dentry->d_inode->i_nlink--;
831                 mark_inode_dirty(dentry->d_inode);
832                 return 0;
833         }
834         else
835         {
836                 return -ENOTEMPTY;
837         }
838 }
839
840
841 /*
842  * Create a link...
843  */
844 static int yaffs_link(struct dentry *old_dentry, struct inode * dir, struct dentry * dentry)
845 {
846         struct inode *inode = old_dentry->d_inode;
847         yaffs_Object *obj = NULL;
848         yaffs_Object *link=NULL;
849         yaffs_Device *dev;
850         
851         T((KERN_DEBUG"yaffs_link\n"));
852         
853         obj = yaffs_InodeToObject(inode);
854         dev = obj->myDev;
855         
856         yaffs_GrossLock(dev);
857         
858         link = yaffs_Link(yaffs_InodeToObject(dir),dentry->d_name.name,obj);
859         
860
861         if(link)
862         {
863                 old_dentry->d_inode->i_nlink =  yaffs_GetObjectLinkCount(obj);
864                 d_instantiate(dentry, old_dentry->d_inode);
865                 atomic_inc(&old_dentry->d_inode->i_count);
866                 T((KERN_DEBUG"yaffs_link link count %d i_count %d\n",   
867                         old_dentry->d_inode->i_nlink,atomic_read(&old_dentry->d_inode->i_count)));
868         
869         }
870         
871         yaffs_GrossUnlock(dev);
872         
873
874         if(link)
875         {
876         
877                 return 0;
878         }
879         
880         
881         return -EPERM; 
882 }
883
884
885 static int yaffs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
886 {
887         yaffs_Object *obj;
888         yaffs_Device *dev;
889         
890         T((KERN_DEBUG"yaffs_symlink\n"));
891         
892         dev = yaffs_InodeToObject(dir)->myDev;
893         yaffs_GrossLock(dev);
894         obj = yaffs_MknodSymLink(yaffs_InodeToObject(dir), dentry->d_name.name, 
895                                                          S_IFLNK | S_IRWXUGO, current->uid, current->gid,
896                                                          symname);
897         yaffs_GrossUnlock(dev);
898
899         if(obj)
900         {
901
902                 struct inode* inode;
903         
904                 inode = yaffs_get_inode(dir->i_sb, obj->st_mode, 0, obj);
905                 d_instantiate(dentry, inode);
906                 T((KERN_DEBUG"symlink created OK\n"));
907                 return 0;
908         }
909         else
910         {
911                 T((KERN_DEBUG"symlink not created\n"));
912
913         }
914         
915         return -ENOMEM;
916 }
917
918 static int yaffs_sync_object(struct file * file, struct dentry *dentry, int datasync)
919 {
920
921         yaffs_Object *obj;
922         yaffs_Device *dev;
923         
924         obj = yaffs_DentryToObject(dentry);
925
926         dev = obj->myDev;
927         
928         T((KERN_DEBUG"yaffs_sync_object\n"));
929         yaffs_GrossLock(dev);
930         yaffs_FlushFile(obj);
931         yaffs_GrossUnlock(dev);
932         return 0;
933 }
934
935 /*
936  * The VFS layer already does all the dentry stuff for rename.
937  *
938  * NB: POSIX says you can rename an object over an old object of the same name
939  */
940 static int yaffs_rename(struct inode * old_dir, struct dentry *old_dentry, struct inode * new_dir,struct dentry *new_dentry)
941 {
942         yaffs_Device *dev;
943         int retVal;
944         
945         dev = yaffs_InodeToObject(old_dir)->myDev;
946
947         yaffs_GrossLock(dev);
948         
949         // Unlink the target if it exists
950         yaffs_Unlink(yaffs_InodeToObject(new_dir),new_dentry->d_name.name);
951
952         
953         retVal =  yaffs_RenameObject(yaffs_InodeToObject(old_dir),old_dentry->d_name.name,
954                                          yaffs_InodeToObject(new_dir),new_dentry->d_name.name);
955         yaffs_GrossUnlock(dev);
956         
957         if(retVal == YAFFS_OK)
958         {
959                 return 0;
960         }
961         else
962         {
963                 return -ENOTEMPTY;
964         }
965         
966
967 }
968
969 static int yaffs_setattr(struct dentry *dentry, struct iattr *attr)
970 {
971         struct inode *inode = dentry->d_inode;
972         int error;
973         yaffs_Device *dev;
974         
975         T((KERN_DEBUG"yaffs_setattr of object %d\n",yaffs_InodeToObject(inode)->objectId));
976         
977         if((error = inode_change_ok(inode,attr)) == 0)
978         {
979         
980                 dev = yaffs_InodeToObject(inode)->myDev;
981                 yaffs_GrossLock(dev);
982                 if(yaffs_SetAttributes(yaffs_InodeToObject(inode),attr) == YAFFS_OK)
983                 {
984                         error = 0;
985                 }
986                 else
987                 {
988                         error = -EPERM;
989                 }
990                 yaffs_GrossUnlock(dev);
991                 inode_setattr(inode,attr);
992         }
993         return error;
994 }
995
996 static int yaffs_statfs(struct super_block *sb, struct statfs *buf)
997 {
998         yaffs_Device *dev = yaffs_SuperToDevice(sb);
999         T((KERN_DEBUG"yaffs_statfs\n"));
1000
1001         yaffs_GrossLock(dev);
1002         
1003         buf->f_type = YAFFS_MAGIC;
1004         buf->f_bsize = sb->s_blocksize;
1005         buf->f_namelen = 255;
1006         buf->f_blocks = (dev->endBlock - dev->startBlock + 1) * YAFFS_CHUNKS_PER_BLOCK/
1007                                                 (sb->s_blocksize/YAFFS_BYTES_PER_CHUNK);
1008         buf->f_files = 0;
1009         buf->f_ffree = 0;
1010         buf->f_bfree = yaffs_GetNumberOfFreeChunks(dev)/
1011                                                 (sb->s_blocksize/YAFFS_BYTES_PER_CHUNK);
1012         buf->f_bavail =  buf->f_bfree;
1013         
1014         yaffs_GrossUnlock(dev);
1015         return 0;
1016 }
1017
1018 static void yaffs_read_inode (struct inode *inode)
1019 {
1020         // NB This is called as a side effect of other functions and
1021         // thus gross locking should always be in place already.
1022         
1023         yaffs_Object *obj ; 
1024         yaffs_Device *dev = yaffs_SuperToDevice(inode->i_sb);
1025         
1026         T((KERN_DEBUG"yaffs_read_inode for %d\n",(int)inode->i_ino));
1027
1028         obj  = yaffs_FindObjectByNumber(dev,inode->i_ino);
1029         
1030         yaffs_FillInodeFromObject(inode,obj);
1031
1032 }
1033
1034
1035
1036 static yaffs_Device *yaffs_dev;
1037 static yaffs_Device *yaffsram_dev;
1038
1039
1040
1041 static void yaffs_put_super(struct super_block *sb)
1042 {
1043         yaffs_Device *dev = yaffs_SuperToDevice(sb);
1044         
1045         yaffs_GrossLock(dev);
1046         if(dev->putSuperFunc)
1047         {
1048                  dev->putSuperFunc(sb);
1049         }
1050         yaffs_Deinitialise(dev);
1051         yaffs_GrossUnlock(dev);
1052
1053         if(dev == yaffs_dev) yaffs_dev = NULL;
1054         if(dev == yaffsram_dev) yaffsram_dev = NULL;
1055                 
1056         kfree(dev);
1057 }
1058
1059
1060 #ifdef CONFIG_YAFFS_MTD_ENABLED
1061
1062 static void  yaffs_MTDPutSuper(struct super_block *sb)
1063 {
1064         
1065         struct mtd_info *mtd = yaffs_SuperToDevice(sb)->genericDevice;
1066         
1067         if(mtd->sync)
1068         {
1069                 mtd->sync(mtd);
1070         }
1071         
1072         put_mtd_device(mtd);
1073 }
1074
1075 #endif
1076
1077
1078 static struct super_block *yaffs_internal_read_super(int useRam, struct super_block * sb, void * data, int silent)
1079 {
1080         int nBlocks;
1081         struct inode * inode;
1082         struct dentry * root;
1083         yaffs_Device *dev;
1084         
1085         sb->s_magic = YAFFS_MAGIC;
1086         sb->s_op = &yaffs_super_ops;
1087         
1088         if(!sb)
1089                 printk(KERN_INFO"yaffs: sb is NULL\n");
1090         else if(!sb->s_dev)
1091                 printk(KERN_INFO"yaffs: sb->s_dev is NULL\n");
1092         else if(! kdevname(sb->s_dev))
1093                 printk(KERN_INFO"yaffs: kdevname is NULL\n");
1094         else
1095                 printk(KERN_INFO"yaffs: dev is %d name is \"%s\"\n", sb->s_dev, kdevname(sb->s_dev));
1096
1097         
1098
1099 #ifdef CONFIG_YAFFS_USE_CHUNK_SIZE
1100         sb->s_blocksize = YAFFS_BYTES_PER_CHUNK;
1101         sb->s_blocksize_bits = YAFFS_CHUNK_SIZE_SHIFT;
1102 #else
1103         sb->s_blocksize = PAGE_CACHE_SIZE;
1104         sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
1105 #endif
1106         T(("yaffs_read_super: %s block size %d\n", useRam ? "RAM" : "MTD",(int)(sb->s_blocksize)));
1107
1108 #ifdef CONFIG_YAFFS_DISABLE_WRITE_VERIFY
1109         T(("yaffs: Write verification disabled. All guarantees null and void\n");
1110 #endif
1111
1112
1113         
1114         if(useRam)
1115         {
1116
1117 #ifdef CONFIG_YAFFS_RAM_ENABLED
1118                 // Set the yaffs_Device up for ram emulation
1119
1120                 sb->u.generic_sbp =     dev = kmalloc(sizeof(yaffs_Device),GFP_KERNEL);
1121                 if(!dev)
1122                 {
1123                         // Deep shit could not allocate device structure
1124                         printk(KERN_DEBUG"yaffs_read_super: Failed trying to allocate yaffs_Device. Terminating debug.\n");
1125                         return NULL;
1126                 }
1127
1128                 memset(dev,0,sizeof(yaffs_Device));
1129                 dev->genericDevice = NULL; // Not used for RAM emulation.
1130
1131                 nBlocks = YAFFS_RAM_EMULATION_SIZE / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK);
1132                 dev->startBlock = 1;  // Don't use block 0
1133                 dev->endBlock = nBlocks - 1;
1134
1135                 dev->writeChunkToNAND = nandemul_WriteChunkToNAND;
1136                 dev->readChunkFromNAND = nandemul_ReadChunkFromNAND;
1137                 dev->eraseBlockInNAND = nandemul_EraseBlockInNAND;
1138                 dev->initialiseNAND = nandemul_InitialiseNAND;
1139
1140                 yaffsram_dev = dev;
1141                 
1142 #endif
1143
1144         }
1145         else
1146         {       
1147 #ifdef CONFIG_YAFFS_MTD_ENABLED
1148                 struct mtd_info *mtd;
1149                 
1150                 printk(KERN_DEBUG "yaffs: Attempting MTD mount on %u.%u, \"%s\"\n",
1151                  MAJOR(sb->s_dev),MINOR(sb->s_dev),kdevname(sb->s_dev));
1152                         
1153                 // Hope it's a NAND mtd
1154                 mtd = get_mtd_device(NULL, MINOR(sb->s_dev));
1155                 if (!mtd) 
1156                 {
1157                         printk(KERN_DEBUG "yaffs: MTD device #%u doesn't appear to exist\n", MINOR(sb->s_dev));
1158                         return NULL;
1159                 }
1160                 
1161                 if(mtd->type != MTD_NANDFLASH)
1162                 {
1163                         printk(KERN_DEBUG "yaffs: MTD device is not NAND it's type %d\n", mtd->type);
1164                         return NULL;
1165                 }
1166
1167                 //printk(KERN_DEBUG" erase %x\n",mtd->erase);
1168                 //printk(KERN_DEBUG" read %x\n",mtd->read);
1169                 //printk(KERN_DEBUG" write %x\n",mtd->write);
1170                 //printk(KERN_DEBUG" readoob %x\n",mtd->read_oob);
1171                 //printk(KERN_DEBUG" writeoob %x\n",mtd->write_oob);
1172                 //printk(KERN_DEBUG" oobblock %x\n",mtd->oobblock);
1173                 //printk(KERN_DEBUG" oobsize %x\n",mtd->oobsize);
1174
1175
1176                 if(!mtd->erase ||
1177                    !mtd->read  ||
1178                    !mtd->write ||
1179                    !mtd->read_oob ||
1180                    !mtd->write_oob)
1181                 {
1182                         printk(KERN_DEBUG "yaffs: MTD device does not support required functions\n");
1183                         return NULL;
1184                 }
1185                 
1186                 if(mtd->oobblock != YAFFS_BYTES_PER_CHUNK ||
1187                    mtd->oobsize != YAFFS_BYTES_PER_SPARE)
1188                 {
1189                         printk(KERN_DEBUG "yaffs: MTD device does not support have the right page sizes\n");
1190                         return NULL;
1191                 }
1192                    
1193
1194                 // OK, so if we got here, we have an MTD that's NAND and looks 
1195                 // like it has the right capabilities
1196                 // Set the yaffs_Device up for ram emulation
1197
1198                 sb->u.generic_sbp =     dev = kmalloc(sizeof(yaffs_Device),GFP_KERNEL);
1199                 if(!dev)
1200                 {
1201                         // Deep shit could not allocate device structure
1202                         printk(KERN_DEBUG"yaffs_read_super: Failed trying to allocate yaffs_Device. Terminating debug.\n");
1203                         return NULL;
1204                 }
1205
1206                 memset(dev,0,sizeof(yaffs_Device));
1207                 dev->genericDevice = mtd; 
1208
1209                 // Set up the memory size parameters....
1210                 
1211                 nBlocks = mtd->size / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK);
1212                 dev->startBlock = 1;  // Don't use block 0
1213                 dev->endBlock = nBlocks - 1;
1214
1215                 // ... and the functions.
1216                 dev->writeChunkToNAND = nandmtd_WriteChunkToNAND;
1217                 dev->readChunkFromNAND = nandmtd_ReadChunkFromNAND;
1218                 dev->eraseBlockInNAND = nandmtd_EraseBlockInNAND;
1219                 dev->initialiseNAND = nandmtd_InitialiseNAND;
1220                                 
1221                 dev->putSuperFunc = yaffs_MTDPutSuper;
1222
1223                 yaffs_dev = dev;
1224                 
1225 #endif
1226         }
1227
1228         init_MUTEX(&dev->grossLock);
1229         
1230         
1231         yaffs_GrossLock(dev);
1232         yaffs_GutsInitialise(yaffs_SuperToDevice(sb));
1233
1234         T(("yaffs_read_super: guts initialised\n"));
1235
1236         // Create root inode
1237         inode = yaffs_get_inode(sb, S_IFDIR | 0755, 0,yaffs_Root(yaffs_SuperToDevice(sb)));
1238
1239         yaffs_GrossUnlock(dev);
1240
1241         if (!inode)
1242                 return NULL;
1243
1244         T(("yaffs_read_super: got root inode\n"));
1245                 
1246
1247         root = d_alloc_root(inode);
1248
1249         T(("yaffs_read_super: d_alloc_root done\n"));
1250
1251         if (!root) {
1252                 iput(inode);
1253                 return NULL;
1254         }
1255         sb->s_root = root;
1256
1257         T(("yaffs_read_super: done\n"));
1258         return sb;
1259 }
1260
1261 #ifdef CONFIG_YAFFS_MTD_ENABLED
1262 static struct super_block *yaffs_read_super(struct super_block * sb, void * data, int silent)
1263 {
1264         return yaffs_internal_read_super(0,sb,data,silent);
1265 }
1266
1267 static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super, FS_REQUIRES_DEV);
1268 #endif
1269
1270 #ifdef CONFIG_YAFFS_RAM_ENABLED
1271
1272 static struct super_block *yaffs_ram_read_super(struct super_block * sb, void * data, int silent)
1273 {
1274         return yaffs_internal_read_super(1,sb,data,silent);
1275 }
1276
1277 static DECLARE_FSTYPE(yaffs_ram_fs_type, "yaffsram", yaffs_ram_read_super, FS_SINGLE);
1278 #endif // CONFIG_YAFFS_RAM_ENABLED
1279
1280
1281 static struct proc_dir_entry *my_proc_entry;
1282 static struct proc_dir_entry *my_proc_ram_write_entry;
1283
1284 static char * yaffs_dump_dev(char *buf,yaffs_Device *dev,char *name)
1285 {
1286         buf +=sprintf(buf,"\nDevice %s\n",name);
1287         buf +=sprintf(buf,"startBlock......... %d\n",dev->startBlock);
1288         buf +=sprintf(buf,"endBlock........... %d\n",dev->endBlock);
1289         buf +=sprintf(buf,"chunkGroupBits..... %d\n",dev->chunkGroupBits);
1290         buf +=sprintf(buf,"chunkGroupSize..... %d\n",dev->chunkGroupSize);
1291         buf +=sprintf(buf,"nErasedBlocks...... %d\n",dev->nErasedBlocks);
1292         buf +=sprintf(buf,"nTnodesCreated..... %d\n",dev->nTnodesCreated);
1293         buf +=sprintf(buf,"nFreeTnodes........ %d\n",dev->nFreeTnodes);
1294         buf +=sprintf(buf,"nObjectsCreated.... %d\n",dev->nObjectsCreated);
1295         buf +=sprintf(buf,"nFreeObjects....... %d\n",dev->nFreeObjects);
1296         buf +=sprintf(buf,"nFreeChunks........ %d\n",dev->nFreeChunks);
1297         buf +=sprintf(buf,"nPageWrites........ %d\n",dev->nPageWrites);
1298         buf +=sprintf(buf,"nPageReads......... %d\n",dev->nPageReads);
1299         buf +=sprintf(buf,"nBlockErasures..... %d\n",dev->nBlockErasures);
1300         buf +=sprintf(buf,"nGCCopies.......... %d\n",dev->nGCCopies);
1301         buf +=sprintf(buf,"garbageCollections. %d\n",dev->garbageCollections);
1302         buf +=sprintf(buf,"nRetriedWrites..... %d\n",dev->nRetriedWrites);
1303         buf +=sprintf(buf,"nRetireBlocks...... %d\n",dev->nRetiredBlocks);
1304         buf +=sprintf(buf,"eccFixed........... %d\n",dev->eccFixed);
1305         buf +=sprintf(buf,"eccUnfixed......... %d\n",dev->eccUnfixed);
1306         buf +=sprintf(buf,"tagsEccFixed....... %d\n",dev->tagsEccFixed);
1307         buf +=sprintf(buf,"tagsEccUnfixed..... %d\n",dev->tagsEccUnfixed);
1308         buf +=sprintf(buf,"cacheHits.......... %d\n",dev->cacheHits);
1309         buf +=sprintf(buf,"nDeletedFiles...... %d\n",dev->nDeletedFiles);
1310         buf +=sprintf(buf,"nUnlinkedFiles..... %d\n",dev->nUnlinkedFiles);
1311         buf +=sprintf(buf,"nBackgroudDeletions %d\n",dev->nBackgroundDeletions);
1312         
1313         return buf;     
1314 }
1315
1316 static int  yaffs_proc_read(
1317         char *page,
1318         char **start,
1319         off_t offset,
1320         int count,
1321         int *eof,
1322         void *data
1323         )
1324 {
1325
1326         char my_buffer[3000];
1327         char *buf;
1328         buf = my_buffer;
1329
1330         if (offset > 0) return 0;
1331
1332         /* Fill the buffer and get its length */
1333         buf +=sprintf(buf,"YAFFS built:"__DATE__ " "__TIME__"\n%s\n%s\n", yaffs_fs_c_version,yaffs_guts_c_version);
1334         
1335         if(yaffs_dev) buf = yaffs_dump_dev(buf,yaffs_dev,"yaffs");
1336         if(yaffsram_dev) buf = yaffs_dump_dev(buf,yaffsram_dev,"yaffsram");
1337         
1338
1339         strcpy(page,my_buffer);
1340         return strlen(my_buffer);
1341 }
1342
1343
1344 static int  yaffs_proc_ram_write(
1345         char *page,
1346         char **start,
1347         off_t offset,
1348         int count,
1349         int *eof,
1350         void *data
1351         )
1352 {
1353
1354         printk(KERN_DEBUG "yaffs write size %d\n",count);
1355         return count;
1356 }
1357
1358 static int __init init_yaffs_fs(void)
1359 {
1360         int error = 0;
1361         
1362         yaffs_dev = yaffsram_dev = NULL;
1363         
1364         printk(KERN_DEBUG "yaffs " __DATE__ " " __TIME__ " Initialisation\n");
1365 #ifdef CONFIG_YAFFS_USE_GENERIC_RW
1366         printk(KERN_DEBUG "yaffs is using generic read/write (caching)\n");
1367 #else
1368         printk(KERN_DEBUG "yaffs is using direct read/write (uncached)\n");
1369 #endif
1370
1371
1372     /* Install the proc_fs entry */
1373     my_proc_entry = create_proc_read_entry("yaffs",
1374                                            S_IRUGO | S_IFREG,
1375                                            &proc_root,
1376                                            yaffs_proc_read,
1377                                            NULL);
1378     if(!my_proc_entry)
1379     {
1380        return -ENOMEM;
1381     }
1382
1383 #ifdef CONFIG_YAFFS_RAM_ENABLED
1384 #if 0
1385     my_proc_ram_write_entry = create_proc_entry("yaffs_ram",
1386                                            S_IRUGO | S_IFREG,
1387                                            &proc_root);
1388  
1389     if(!my_proc_ram_write_entry)
1390     {
1391        return -ENOMEM;
1392     }
1393     else
1394     {
1395         my_proc_ram_write_entry->write_proc = yaffs_proc_ram_write;
1396     }
1397 #endif
1398
1399     error = register_filesystem(&yaffs_ram_fs_type);
1400     if(error)
1401     {
1402         return error;
1403     }
1404 #endif //CONFIG_YAFFS_RAM_ENABLED
1405
1406 #ifdef CONFIG_YAFFS_MTD_ENABLED
1407         error = register_filesystem(&yaffs_fs_type);
1408         if(error)
1409         {
1410 #ifdef CONFIG_YAFFS_RAM_ENABLED
1411                 unregister_filesystem(&yaffs_ram_fs_type);
1412 #endif //CONFIG_YAFFS_RAM_ENABLED
1413         }
1414 #endif // CONFIG_YAFFS_MTD_ENABLED
1415
1416         return error;
1417 }
1418
1419 static void __exit exit_yaffs_fs(void)
1420 {
1421         printk(KERN_DEBUG "yaffs " __DATE__ " " __TIME__ " Clean up\n");
1422
1423     remove_proc_entry("yaffs",&proc_root);
1424     
1425 #ifdef CONFIG_YAFFS_RAM_ENABLED
1426         unregister_filesystem(&yaffs_ram_fs_type);
1427 #endif
1428 #ifdef CONFIG_YAFFS_MTD_ENABLED
1429         unregister_filesystem(&yaffs_fs_type);
1430 #endif
1431
1432 }
1433
1434 module_init(init_yaffs_fs)
1435 module_exit(exit_yaffs_fs)
1436
1437 MODULE_DESCRIPTION("YAFFS - a NAND specific flash file system");
1438 MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002");
1439 MODULE_LICENSE("GPL");
1440