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