]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/fs/jffs2/v2_0/src/fs-ecos.c
Initial revision
[karo-tx-redboot.git] / packages / fs / jffs2 / v2_0 / src / fs-ecos.c
1 /*
2  * JFFS2 -- Journalling Flash File System, Version 2.
3  *
4  * Copyright (C) 2001-2003 Red Hat, Inc.
5  *
6  * Created by Dominic Ostrowski <dominic.ostrowski@3glab.com>
7  * Contributors: David Woodhouse, Nick Garnett, Richard Panton.
8  *
9  * For licensing information, see the file 'LICENCE' in this directory.
10  *
11  * $Id$
12  *
13  */
14
15 #include <linux/kernel.h>
16 #include "nodelist.h"
17 #include <linux/pagemap.h>
18 #include <linux/crc32.h>
19 #include "compr.h"
20 #include <errno.h>
21 #include <string.h>
22 #include <cyg/io/config_keys.h>
23
24 #if (__GNUC__ == 3) && (__GNUC_MINOR__ == 2) && defined (__ARM_ARCH_4__)
25 #error This compiler is known to be broken. Please see:
26 #error http://ecos.sourceware.org/ml/ecos-patches/2003-08/msg00006.html
27 #endif
28
29 //==========================================================================
30 // Forward definitions
31
32 // Filesystem operations
33 static int jffs2_mount(cyg_fstab_entry * fste, cyg_mtab_entry * mte);
34 static int jffs2_umount(cyg_mtab_entry * mte);
35 static int jffs2_open(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
36                       int mode, cyg_file * fte);
37 #ifdef CYGOPT_FS_JFFS2_WRITE
38 static int jffs2_ops_unlink(cyg_mtab_entry * mte, cyg_dir dir,
39                             const char *name);
40 static int jffs2_ops_mkdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name);
41 static int jffs2_ops_rmdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name);
42 static int jffs2_ops_rename(cyg_mtab_entry * mte, cyg_dir dir1,
43                             const char *name1, cyg_dir dir2, const char *name2);
44 static int jffs2_ops_link(cyg_mtab_entry * mte, cyg_dir dir1, const char *name1,
45                           cyg_dir dir2, const char *name2, int type);
46 #endif
47 static int jffs2_opendir(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
48                          cyg_file * fte);
49 static int jffs2_chdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
50                        cyg_dir * dir_out);
51 static int jffs2_stat(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
52                       struct stat *buf);
53 static int jffs2_getinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
54                          int key, void *buf, int len);
55 static int jffs2_setinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
56                          int key, void *buf, int len);
57
58 // File operations
59 static int jffs2_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
60 #ifdef CYGOPT_FS_JFFS2_WRITE
61 static int jffs2_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
62 #endif
63 static int jffs2_fo_lseek(struct CYG_FILE_TAG *fp, off_t * pos, int whence);
64 static int jffs2_fo_ioctl(struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
65                           CYG_ADDRWORD data);
66 static int jffs2_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
67 static int jffs2_fo_close(struct CYG_FILE_TAG *fp);
68 static int jffs2_fo_fstat(struct CYG_FILE_TAG *fp, struct stat *buf);
69 static int jffs2_fo_getinfo(struct CYG_FILE_TAG *fp, int key, void *buf,
70                             int len);
71 static int jffs2_fo_setinfo(struct CYG_FILE_TAG *fp, int key, void *buf,
72                             int len);
73
74 // Directory operations
75 static int jffs2_fo_dirread(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
76 static int jffs2_fo_dirlseek(struct CYG_FILE_TAG *fp, off_t * pos, int whence);
77
78
79 static int jffs2_read_inode (struct _inode *inode);
80 static void jffs2_clear_inode (struct _inode *inode);
81 static int jffs2_truncate_file (struct _inode *inode);
82
83 //==========================================================================
84 // Filesystem table entries
85
86 // -------------------------------------------------------------------------
87 // Fstab entry.
88 // This defines the entry in the filesystem table.
89 // For simplicity we use _FILESYSTEM synchronization for all accesses since
90 // we should never block in any filesystem operations.
91
92 #ifdef CYGOPT_FS_JFFS2_WRITE
93 FSTAB_ENTRY(jffs2_fste, "jffs2", 0,
94             CYG_SYNCMODE_FILE_FILESYSTEM | CYG_SYNCMODE_IO_FILESYSTEM,
95             jffs2_mount,
96             jffs2_umount,
97             jffs2_open,
98             jffs2_ops_unlink,
99             jffs2_ops_mkdir,
100             jffs2_ops_rmdir,
101             jffs2_ops_rename,
102             jffs2_ops_link,
103             jffs2_opendir,
104             jffs2_chdir, jffs2_stat, jffs2_getinfo, jffs2_setinfo);
105 #else
106 FSTAB_ENTRY(jffs2_fste, "jffs2", 0,
107             CYG_SYNCMODE_FILE_FILESYSTEM | CYG_SYNCMODE_IO_FILESYSTEM,
108             jffs2_mount,
109             jffs2_umount,
110             jffs2_open,
111             (cyg_fsop_unlink *)cyg_fileio_erofs,
112             (cyg_fsop_mkdir *)cyg_fileio_erofs,
113             (cyg_fsop_rmdir *)cyg_fileio_erofs,
114             (cyg_fsop_rename *)cyg_fileio_erofs,
115             (cyg_fsop_link *)cyg_fileio_erofs,
116             jffs2_opendir,
117             jffs2_chdir, jffs2_stat, jffs2_getinfo, jffs2_setinfo);
118 #endif
119
120 // -------------------------------------------------------------------------
121 // File operations.
122 // This set of file operations are used for normal open files.
123
124 static cyg_fileops jffs2_fileops = {
125         jffs2_fo_read,
126 #ifdef CYGOPT_FS_JFFS2_WRITE
127         jffs2_fo_write,
128 #else
129         (cyg_fileop_write *) cyg_fileio_erofs,
130 #endif
131         jffs2_fo_lseek,
132         jffs2_fo_ioctl,
133         cyg_fileio_seltrue,
134         jffs2_fo_fsync,
135         jffs2_fo_close,
136         jffs2_fo_fstat,
137         jffs2_fo_getinfo,
138         jffs2_fo_setinfo
139 };
140
141 // -------------------------------------------------------------------------
142 // Directory file operations.
143 // This set of operations are used for open directories. Most entries
144 // point to error-returning stub functions. Only the read, lseek and
145 // close entries are functional.
146
147 static cyg_fileops jffs2_dirops = {
148         jffs2_fo_dirread,
149         (cyg_fileop_write *) cyg_fileio_enosys,
150         jffs2_fo_dirlseek,
151         (cyg_fileop_ioctl *) cyg_fileio_enosys,
152         cyg_fileio_seltrue,
153         (cyg_fileop_fsync *) cyg_fileio_enosys,
154         jffs2_fo_close,
155         (cyg_fileop_fstat *) cyg_fileio_enosys,
156         (cyg_fileop_getinfo *) cyg_fileio_enosys,
157         (cyg_fileop_setinfo *) cyg_fileio_enosys
158 };
159
160 //==========================================================================
161 // STATIC VARIABLES !!!
162
163 static unsigned char gc_buffer[PAGE_CACHE_SIZE];        //avoids malloc when user may be under memory pressure
164 static unsigned char n_fs_mounted = 0;  // a counter to track the number of jffs2 instances mounted
165
166 //==========================================================================
167 // Directory operations
168
169 struct jffs2_dirsearch {
170         struct _inode *dir;         // directory to search
171         const unsigned char *path;  // path to follow
172         struct _inode *node;        // Node found
173         const unsigned char *name;  // last name fragment used
174         int namelen;                // name fragment length
175         cyg_bool last;              // last name in path?
176 };
177
178 typedef struct jffs2_dirsearch jffs2_dirsearch;
179
180 //==========================================================================
181 // Ref count and nlink management
182
183
184 // FIXME: This seems like real cruft. Wouldn't it be better just to do the
185 // right thing?
186 static void icache_evict(struct _inode *root_i, struct _inode *i)
187 {
188         struct _inode *this = root_i, *next;
189
190  restart:
191         D2(printf("icache_evict\n"));
192         // If this is an absolute search path from the root,
193         // remove all cached inodes with i_count of zero (these are only 
194         // held where needed for dotdot filepaths)
195         while (this) {
196                 next = this->i_cache_next;
197                 if (this != i && this->i_count == 0) {
198                         struct _inode *parent = this->i_parent;
199                         if (this->i_cache_next)
200                                 this->i_cache_next->i_cache_prev = this->i_cache_prev;
201                         if (this->i_cache_prev)
202                                 this->i_cache_prev->i_cache_next = this->i_cache_next;
203                         jffs2_clear_inode(this);
204                         memset(this, 0x5a, sizeof(*this));
205                         free(this);
206                         if (parent && parent != this) {
207                                 parent->i_count--;
208                                 this = root_i;
209                                 goto restart;
210                         }
211                 }
212                 this = next;
213         }
214 }
215
216 //==========================================================================
217 // Directory search
218
219 // -------------------------------------------------------------------------
220 // init_dirsearch()
221 // Initialize a dirsearch object to start a search
222
223 static void init_dirsearch(jffs2_dirsearch * ds,
224                            struct _inode *dir, const unsigned char *name)
225 {
226         D2(printf("init_dirsearch name = %s\n", name));
227         D2(printf("init_dirsearch dir = %x\n", dir));
228
229         dir->i_count++;
230         ds->dir = dir;
231         ds->path = name;
232         ds->node = dir;
233         ds->name = name;
234         ds->namelen = 0;
235         ds->last = false;
236 }
237
238 // -------------------------------------------------------------------------
239 // find_entry()
240 // Search a single directory for the next name in a path and update the
241 // dirsearch object appropriately.
242
243 static int find_entry(jffs2_dirsearch * ds)
244 {
245         struct _inode *dir = ds->dir;
246         const unsigned char *name = ds->path;
247         const unsigned char *n = name;
248         char namelen = 0;
249         struct _inode *d;
250
251         D2(printf("find_entry\n"));
252
253         // check that we really have a directory
254         if (!S_ISDIR(dir->i_mode))
255                 return ENOTDIR;
256
257         // Isolate the next element of the path name. 
258         while (*n != '\0' && *n != '/')
259                 n++, namelen++;
260
261         // Check if this is the last path element.
262         while( *n == '/') n++;
263         if (*n == '\0')
264                 ds->last = true;
265
266         // update name in dirsearch object
267         ds->name = name;
268         ds->namelen = namelen;
269
270         if (name[0] == '.')
271                 switch (namelen) {
272                 default:
273                         break;
274                 case 2:
275                         // Dot followed by not Dot, treat as any other name 
276                         if (name[1] != '.')
277                                 break;
278                         // Dot Dot 
279                         // Move back up the search path
280                         D2(printf("find_entry found ..\n"));
281                         ds->dir = ds->node;
282                         ds->node = ds->dir->i_parent;
283                         ds->node->i_count++;
284                         return ENOERR;
285                 case 1:
286                         // Dot is consumed
287                         D2(printf("find_entry found .\n"));
288                         ds->node = ds->dir;
289                         ds->dir->i_count++;
290                         return ENOERR;
291                 }
292
293         // Here we have the name and its length set up.
294         // Search the directory for a matching entry
295
296         D2(printf("find_entry for name = %s\n", ds->path));
297         d = jffs2_lookup(dir, name, namelen);
298         D2(printf("find_entry got dir = %x\n", d));
299
300         if (d == NULL)
301                 return ENOENT;
302         if (IS_ERR(d))
303                 return -PTR_ERR(d);
304
305         // If it's a new directory inode, increase refcount on its parent
306         if (S_ISDIR(d->i_mode) && !d->i_parent) {
307                 d->i_parent = dir;
308                 dir->i_count++;
309         }
310
311         // pass back the node we have found
312         ds->node = d;
313         return ENOERR;
314
315 }
316
317 // -------------------------------------------------------------------------
318 // jffs2_find()
319 // Main interface to directory search code. This is used in all file
320 // level operations to locate the object named by the pathname.
321
322 // Returns with use count incremented on both the sought object and 
323 // the directory it was found in
324 static int jffs2_find(jffs2_dirsearch * d)
325 {
326         int err;
327
328         D2(printf("jffs2_find for path =%s\n", d->path));
329
330         // Short circuit empty paths
331         if (*(d->path) == '\0') {
332                 d->node->i_count++;
333                 return ENOERR;
334         }
335
336         // iterate down directory tree until we find the object
337         // we want.
338         for (;;) {
339                 err = find_entry(d);
340
341                 if (err != ENOERR)
342                         return err;
343
344                 if (d->last)
345                         return ENOERR;
346
347                 /* We're done with it, although it we found a subdir that
348                    will have caused the refcount to have been increased */
349                 jffs2_iput(d->dir);
350
351                 // Update dirsearch object to search next directory.
352                 d->dir = d->node;
353                 d->path += d->namelen;
354                 while (*(d->path) == '/')
355                         d->path++;      // skip dirname separators
356         }
357 }
358
359 //==========================================================================
360 // Pathconf support
361 // This function provides support for pathconf() and fpathconf().
362
363 static int jffs2_pathconf(struct _inode *node, struct cyg_pathconf_info *info)
364 {
365         int err = ENOERR;
366         D2(printf("jffs2_pathconf\n"));
367
368         switch (info->name) {
369         case _PC_LINK_MAX:
370                 info->value = LINK_MAX;
371                 break;
372
373         case _PC_MAX_CANON:
374                 info->value = -1;       // not supported
375                 err = EINVAL;
376                 break;
377
378         case _PC_MAX_INPUT:
379                 info->value = -1;       // not supported
380                 err = EINVAL;
381                 break;
382
383         case _PC_NAME_MAX:
384                 info->value = NAME_MAX;
385                 break;
386
387         case _PC_PATH_MAX:
388                 info->value = PATH_MAX;
389                 break;
390
391         case _PC_PIPE_BUF:
392                 info->value = -1;       // not supported
393                 err = EINVAL;
394                 break;
395
396         case _PC_ASYNC_IO:
397                 info->value = -1;       // not supported
398                 err = EINVAL;
399                 break;
400
401         case _PC_CHOWN_RESTRICTED:
402                 info->value = -1;       // not supported
403                 err = EINVAL;
404                 break;
405
406         case _PC_NO_TRUNC:
407                 info->value = 0;
408                 break;
409
410         case _PC_PRIO_IO:
411                 info->value = 0;
412                 break;
413
414         case _PC_SYNC_IO:
415                 info->value = 0;
416                 break;
417
418         case _PC_VDISABLE:
419                 info->value = -1;       // not supported
420                 err = EINVAL;
421                 break;
422
423         default:
424                 err = EINVAL;
425                 break;
426         }
427
428         return err;
429 }
430
431 //==========================================================================
432 // Filesystem operations
433
434 // -------------------------------------------------------------------------
435 // jffs2_mount()
436 // Process a mount request. This mainly creates a root for the
437 // filesystem.
438 static int jffs2_read_super(struct super_block *sb)
439 {
440         struct jffs2_sb_info *c;
441         Cyg_ErrNo err;
442         cyg_uint32 len;
443         cyg_io_flash_getconfig_devsize_t ds;
444         cyg_io_flash_getconfig_blocksize_t bs;
445
446         D1(printk(KERN_DEBUG "jffs2: read_super\n"));
447
448         c = JFFS2_SB_INFO(sb);
449
450         len = sizeof (ds);
451         err = cyg_io_get_config(sb->s_dev,
452                                 CYG_IO_GET_CONFIG_FLASH_DEVSIZE, &ds, &len);
453         if (err != ENOERR) {
454                 D1(printf
455                    ("jffs2: cyg_io_get_config failed to get dev size: %d\n",
456                     err));
457                 return err;
458         }
459         len = sizeof (bs);
460         bs.offset = 0;
461         err = cyg_io_get_config(sb->s_dev,
462                                 CYG_IO_GET_CONFIG_FLASH_BLOCKSIZE, &bs, &len);
463         if (err != ENOERR) {
464                 D1(printf
465                    ("jffs2: cyg_io_get_config failed to get block size: %d\n",
466                     err));
467                 return err;
468         }
469
470         c->sector_size = bs.block_size;
471         c->flash_size = ds.dev_size;
472         c->cleanmarker_size = sizeof(struct jffs2_unknown_node);
473
474         err = jffs2_do_mount_fs(c);
475         if (err)
476                 return -err;
477
478         D1(printk(KERN_DEBUG "jffs2_read_super(): Getting root inode\n"));
479         sb->s_root = jffs2_iget(sb, 1);
480         if (IS_ERR(sb->s_root)) {
481                 D1(printk(KERN_WARNING "get root inode failed\n"));
482                 err = PTR_ERR(sb->s_root);
483                 sb->s_root = NULL;
484                 goto out_nodes;
485         }
486
487         return 0;
488
489       out_nodes:
490         jffs2_free_ino_caches(c);
491         jffs2_free_raw_node_refs(c);
492         free(c->blocks);
493
494         return err;
495 }
496
497 static int jffs2_mount(cyg_fstab_entry * fste, cyg_mtab_entry * mte)
498 {
499         extern cyg_mtab_entry cyg_mtab[], cyg_mtab_end;
500         struct super_block *jffs2_sb = NULL;
501         struct jffs2_sb_info *c;
502         cyg_mtab_entry *m;
503         cyg_io_handle_t t;
504         Cyg_ErrNo err;
505
506         D2(printf("jffs2_mount\n"));
507
508         err = cyg_io_lookup(mte->devname, &t);
509         if (err != ENOERR)
510                 return -err;
511
512         // Iterate through the mount table to see if we're mounted
513         // FIXME: this should be done better - perhaps if the superblock
514         // can be stored as an inode in the icache.
515         for (m = &cyg_mtab[0]; m != &cyg_mtab_end; m++) {
516                 // stop if there are more than the configured maximum
517                 if (m - &cyg_mtab[0] >= CYGNUM_FILEIO_MTAB_MAX) {
518                         m = &cyg_mtab_end;
519                         break;
520                 }
521                 if (m->valid && strcmp(m->fsname, "jffs2") == 0 &&
522                     strcmp(m->devname, mte->devname) == 0) {
523                         jffs2_sb = (struct super_block *) m->data;
524                 }
525         }
526
527         if (jffs2_sb == NULL) {
528                 jffs2_sb = malloc(sizeof (struct super_block));
529
530                 if (jffs2_sb == NULL)
531                         return ENOMEM;
532
533                 c = JFFS2_SB_INFO(jffs2_sb);
534                 memset(jffs2_sb, 0, sizeof (struct super_block));
535                 jffs2_sb->s_dev = t;
536
537                 c->inocache_list = malloc(sizeof(struct jffs2_inode_cache *) * INOCACHE_HASHSIZE);
538                 if (!c->inocache_list) {
539                         free(jffs2_sb);
540                         return ENOMEM;
541                 }
542                 memset(c->inocache_list, 0, sizeof(struct jffs2_inode_cache *) * INOCACHE_HASHSIZE);
543                 if (n_fs_mounted++ == 0) {
544                         jffs2_create_slab_caches(); // No error check, cannot fail
545                         jffs2_compressors_init(); 
546                 }
547
548                 err = jffs2_read_super(jffs2_sb);
549
550                 if (err) {
551                         if (--n_fs_mounted == 0) {
552                                 jffs2_destroy_slab_caches();
553                                 jffs2_compressors_exit();
554                         }
555                         
556                         free(jffs2_sb);
557                         free(c->inocache_list);
558                         return err;
559                 }
560
561                 jffs2_sb->s_root->i_parent = jffs2_sb->s_root;  // points to itself, no dotdot paths above mountpoint
562                 jffs2_sb->s_root->i_cache_prev = NULL;  // root inode, so always null
563                 jffs2_sb->s_root->i_cache_next = NULL;
564                 jffs2_sb->s_root->i_count = 1;  // Ensures the root inode is always in ram until umount
565
566                 D2(printf("jffs2_mount erasing pending blocks\n"));
567 #ifdef CYGOPT_FS_JFFS2_WRITE
568                 if (!jffs2_is_readonly(c))
569                     jffs2_erase_pending_blocks(c,0);
570 #endif
571 #ifdef CYGOPT_FS_JFFS2_GCTHREAD
572                 jffs2_start_garbage_collect_thread(c);
573 #endif
574         }
575         mte->data = (CYG_ADDRWORD) jffs2_sb;
576
577         jffs2_sb->s_mount_count++;
578         mte->root = (cyg_dir) jffs2_sb->s_root;
579         D2(printf("jffs2_mounted superblock at %x\n", mte->root));
580
581         return ENOERR;
582 }
583
584 extern cyg_dir cyg_cdir_dir;
585 extern cyg_mtab_entry *cyg_cdir_mtab_entry;
586
587 // -------------------------------------------------------------------------
588 // jffs2_umount()
589 // Unmount the filesystem. 
590
591 static int jffs2_umount(cyg_mtab_entry * mte)
592 {
593         struct _inode *root = (struct _inode *) mte->root;
594         struct super_block *jffs2_sb = root->i_sb;
595         struct jffs2_sb_info *c = JFFS2_SB_INFO(jffs2_sb);
596         struct jffs2_full_dirent *fd, *next;
597
598         D2(printf("jffs2_umount\n"));
599
600         // Only really umount if this is the only mount
601         if (jffs2_sb->s_mount_count == 1) {
602                 icache_evict(root, NULL);
603                 if (root->i_cache_next != NULL) {
604                         struct _inode *inode = root;
605                         printf("Refuse to unmount.\n");
606                         while (inode) {
607                                 printf("Ino #%u has use count %d\n",
608                                        inode->i_ino, inode->i_count);
609                                 inode = inode->i_cache_next;
610                         }
611                         // root icount was set to 1 on mount
612                         return EBUSY;
613                 }
614                 if (root->i_count == 2 &&
615                     cyg_cdir_mtab_entry == mte &&
616                     cyg_cdir_dir == (cyg_dir)root &&
617                     !strcmp(mte->name, "/")) {
618                         /* If we were mounted on root, there's no
619                            way for the cwd to change out and free 
620                            the file system for unmounting. So we hack
621                            it -- if cwd is '/' we unset it. Perhaps
622                            we should allow chdir(NULL) to unset
623                            cyg_cdir_dir? */
624                         cyg_cdir_dir = CYG_DIR_NULL;
625                         jffs2_iput(root);
626                 }
627                 /* Argh. The fileio code sets this; never clears it */
628                 if (cyg_cdir_mtab_entry == mte)
629                         cyg_cdir_mtab_entry = NULL;
630
631                 if (root->i_count != 1) {
632                         printf("Ino #1 has use count %d\n",
633                                root->i_count);
634                         return EBUSY;
635                 }
636 #ifdef CYGOPT_FS_JFFS2_GCTHREAD
637                 jffs2_stop_garbage_collect_thread(c);
638 #endif
639                 jffs2_iput(root);       // Time to free the root inode
640
641                 // free directory entries
642                 for (fd = root->jffs2_i.dents; fd; fd = next) {
643                   next=fd->next;
644                   jffs2_free_full_dirent(fd);
645                 }
646
647                 free(root);
648                 //Clear root inode
649                 //root_i = NULL;
650
651                 // Clean up the super block and root inode
652                 jffs2_free_ino_caches(c);
653                 jffs2_free_raw_node_refs(c);
654                 free(c->blocks);
655                 free(c->inocache_list);
656                 free(jffs2_sb);
657                 // Clear superblock & root pointer
658                 mte->root = CYG_DIR_NULL;
659                 mte->data = 0;
660                 mte->fs->data = 0;      // fstab entry, visible to all mounts. No current mount
661                 // That's all folks.
662                 D2(printf("jffs2_umount No current mounts\n"));
663         } else {
664                 jffs2_sb->s_mount_count--;
665         }
666         if (--n_fs_mounted == 0) {
667                 jffs2_destroy_slab_caches();        
668                 jffs2_compressors_exit();
669         }
670         return ENOERR;
671 }
672
673 // -------------------------------------------------------------------------
674 // jffs2_open()
675 // Open a file for reading or writing.
676
677 static int jffs2_open(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
678                       int mode, cyg_file * file)
679 {
680
681         jffs2_dirsearch ds;
682         struct _inode *node = NULL;
683         int err;
684
685         D2(printf("jffs2_open\n"));
686
687         /* If no chdir has been called and we were the first file system
688            mounted, we get called with dir == NULL. Deal with it */
689         if (!dir)
690                 dir = mte->root;
691
692 #ifndef CYGOPT_FS_JFFS2_WRITE
693         if (mode & (O_CREAT|O_TRUNC|O_WRONLY))
694                 return EROFS;
695 #endif
696         init_dirsearch(&ds, (struct _inode *) dir, 
697                        (const unsigned char *) name);
698
699         err = jffs2_find(&ds);
700
701         if (err == ENOENT) {
702 #ifdef CYGOPT_FS_JFFS2_WRITE
703                 if (ds.last && (mode & O_CREAT)) {
704
705                         // No node there, if the O_CREAT bit is set then we must
706                         // create a new one. The dir and name fields of the dirsearch
707                         // object will have been updated so we know where to put it.
708
709                         err = jffs2_create(ds.dir, ds.name, S_IRUGO|S_IXUGO|S_IWUSR|S_IFREG, &node);
710
711                         if (err != 0) {
712                                 //Possible orphaned inode on the flash - but will be gc'd
713                                 jffs2_iput(ds.dir);
714                                 return -err;
715                         }
716
717                         err = ENOERR;
718                 }
719 #endif
720         } else if (err == ENOERR) {
721                 // The node exists. If the O_CREAT and O_EXCL bits are set, we
722                 // must fail the open.
723
724                 if ((mode & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
725                         jffs2_iput(ds.node);
726                         err = EEXIST;
727                 } else
728                         node = ds.node;
729         }
730
731         // Finished with the directory now 
732         jffs2_iput(ds.dir);
733
734         if (err != ENOERR)
735                 return err;
736
737         // Check that we actually have a file here
738         if (S_ISDIR(node->i_mode)) {
739                 jffs2_iput(node);
740                 return EISDIR;
741         }
742
743              // If the O_TRUNC bit is set we must clean out the file data.
744         if (mode & O_TRUNC) {
745 #ifdef CYGOPT_FS_JFFS2_WRITE
746              err = jffs2_truncate_file(node);
747              if (err) {
748                   jffs2_iput(node);
749                   return err;
750              }
751 #else
752              jffs2_iput(node);
753              return EROFS;
754 #endif
755         }
756         
757         // Initialise the file object
758         file->f_flag |= mode & CYG_FILE_MODE_MASK;
759         file->f_type = CYG_FILE_TYPE_FILE;
760         file->f_ops = &jffs2_fileops;
761         file->f_offset = (mode & O_APPEND) ? node->i_size : 0;
762         file->f_data = (CYG_ADDRWORD) node;
763         file->f_xops = 0;
764
765         return ENOERR;
766 }
767
768 #ifdef CYGOPT_FS_JFFS2_WRITE
769 // -------------------------------------------------------------------------
770 // jffs2_ops_unlink()
771 // Remove a file link from its directory.
772
773 static int jffs2_ops_unlink(cyg_mtab_entry * mte, cyg_dir dir, const char *name)
774 {
775         jffs2_dirsearch ds;
776         int err;
777
778         D2(printf("jffs2_ops_unlink\n"));
779
780         init_dirsearch(&ds, (struct _inode *) dir, 
781                        (const unsigned char *)name);
782
783         err = jffs2_find(&ds);
784
785         if (err != ENOERR) {
786                 jffs2_iput(ds.dir);
787                 return err;
788         }
789
790         // Cannot unlink directories, use rmdir() instead
791         if (S_ISDIR(ds.node->i_mode)) {
792                 jffs2_iput(ds.dir);
793                 jffs2_iput(ds.node);
794                 return EPERM;
795         }
796
797         // Delete it from its directory
798
799         err = jffs2_unlink(ds.dir, ds.node, ds.name);
800         jffs2_iput(ds.dir);
801         jffs2_iput(ds.node);
802
803         return -err;
804 }
805
806 // -------------------------------------------------------------------------
807 // jffs2_ops_mkdir()
808 // Create a new directory.
809
810 static int jffs2_ops_mkdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name)
811 {
812         jffs2_dirsearch ds;
813         int err;
814
815         D2(printf("jffs2_ops_mkdir\n"));
816
817         init_dirsearch(&ds, (struct _inode *) dir, 
818                        (const unsigned char *)name);
819
820         err = jffs2_find(&ds);
821
822         if (err == ENOENT) {
823                 if (ds.last) {
824                         // The entry does not exist, and it is the last element in
825                         // the pathname, so we can create it here.
826
827                         err = -jffs2_mkdir(ds.dir, ds.name, S_IRUGO|S_IXUGO|S_IWUSR);
828                 }
829                 // If this was not the last element, then an intermediate
830                 // directory does not exist.
831         } else {
832                 // If there we no error, something already exists with that
833                 // name, so we cannot create another one.
834                if (err == ENOERR) {
835                         jffs2_iput(ds.node);
836                         err = EEXIST;
837                }
838         }
839         jffs2_iput(ds.dir);
840         return err;
841 }
842
843 // -------------------------------------------------------------------------
844 // jffs2_ops_rmdir()
845 // Remove a directory.
846
847 static int jffs2_ops_rmdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name)
848 {
849         jffs2_dirsearch ds;
850         int err;
851
852         D2(printf("jffs2_ops_rmdir\n"));
853
854         init_dirsearch(&ds, (struct _inode *) dir, 
855                        (const unsigned char *)name);
856
857         err = jffs2_find(&ds);
858
859         if (err != ENOERR) {
860                 jffs2_iput(ds.dir);
861                 return err;
862         }
863
864         // Check that this is actually a directory.
865         if (!S_ISDIR(ds.node->i_mode)) {
866                 jffs2_iput(ds.dir);
867                 jffs2_iput(ds.node);
868                 return EPERM;
869         }
870
871         err = jffs2_rmdir(ds.dir, ds.node, ds.name);
872
873         jffs2_iput(ds.dir);
874         jffs2_iput(ds.node);
875         return -err;
876 }
877
878 // -------------------------------------------------------------------------
879 // jffs2_ops_rename()
880 // Rename a file/dir.
881
882 static int jffs2_ops_rename(cyg_mtab_entry * mte, cyg_dir dir1,
883                             const char *name1, cyg_dir dir2, const char *name2)
884 {
885         jffs2_dirsearch ds1, ds2;
886         int err;
887
888         D2(printf("jffs2_ops_rename\n"));
889
890         init_dirsearch(&ds1, (struct _inode *) dir1, 
891                        (const unsigned char *)name1);
892
893         err = jffs2_find(&ds1);
894
895         if (err != ENOERR) {
896                 jffs2_iput(ds1.dir);
897                 return err;
898         }
899
900         init_dirsearch(&ds2, (struct _inode *) dir2, 
901                        (const unsigned char *)name2);
902
903         err = jffs2_find(&ds2);
904
905         // Allow through renames to non-existent objects.
906         if (ds2.last && err == ENOENT) {
907                 ds2.node = NULL;
908                 err = ENOERR;
909         }
910
911         if (err != ENOERR) {
912                 jffs2_iput(ds1.dir);
913                 jffs2_iput(ds1.node);
914                 jffs2_iput(ds2.dir);
915                 return err;
916         }
917
918         // Null rename, just return
919         if (ds1.node == ds2.node) {
920                 err = ENOERR;
921                 goto out;
922         }
923
924         // First deal with any entry that is at the destination
925         if (ds2.node) {
926                 // Check that we are renaming like-for-like
927
928                 if (!S_ISDIR(ds1.node->i_mode) && S_ISDIR(ds2.node->i_mode)) {
929                         err = EISDIR;
930                         goto out;
931                 }
932
933                 if (S_ISDIR(ds1.node->i_mode) && !S_ISDIR(ds2.node->i_mode)) {
934                         err = ENOTDIR;
935                         goto out;
936                 }
937
938                 // Now delete the destination directory entry
939                 /* Er, what happened to atomicity of rename()? */
940                 err = -jffs2_unlink(ds2.dir, ds2.node, ds2.name);
941
942                 if (err != 0)
943                         goto out;
944
945         }
946         // Now we know that there is no clashing node at the destination,
947         // make a new direntry at the destination and delete the old entry
948         // at the source.
949
950         err = -jffs2_rename(ds1.dir, ds1.node, ds1.name, ds2.dir, ds2.name);
951
952         // Update directory times
953         if (!err)
954                 ds1.dir->i_ctime =
955                     ds1.dir->i_mtime =
956                     ds2.dir->i_ctime = ds2.dir->i_mtime = cyg_timestamp();
957  out:
958         jffs2_iput(ds1.dir);
959         if (S_ISDIR(ds1.node->i_mode)) {
960                 /* Renamed a directory to elsewhere... so fix up its
961                    i_parent pointer and the i_counts of its old and
962                    new parents. */
963                 jffs2_iput(ds1.node->i_parent);
964                 ds1.node->i_parent = ds2.dir;
965                 /* We effectively increase its use count by not... */
966         } else {
967                 jffs2_iput(ds2.dir); /* ... doing this */
968         }
969         jffs2_iput(ds1.node);
970         if (ds2.node)
971                 jffs2_iput(ds2.node);
972  
973         return err;
974 }
975
976 // -------------------------------------------------------------------------
977 // jffs2_ops_link()
978 // Make a new directory entry for a file.
979
980 static int jffs2_ops_link(cyg_mtab_entry * mte, cyg_dir dir1, const char *name1,
981                           cyg_dir dir2, const char *name2, int type)
982 {
983         jffs2_dirsearch ds1, ds2;
984         int err;
985
986         D2(printf("jffs2_ops_link\n"));
987
988         // Only do hard links for now in this filesystem
989         if (type != CYG_FSLINK_HARD)
990                 return EINVAL;
991
992         init_dirsearch(&ds1, (struct _inode *) dir1, 
993                        (const unsigned char *) name1);
994
995         err = jffs2_find(&ds1);
996
997         if (err != ENOERR) {
998                 jffs2_iput(ds1.dir);
999                 return err;
1000         }
1001
1002         init_dirsearch(&ds2, (struct _inode *) dir2, 
1003                        (const unsigned char *) name2);
1004
1005         err = jffs2_find(&ds2);
1006
1007         // Don't allow links to existing objects
1008         if (err == ENOERR) {
1009                 jffs2_iput(ds1.dir);
1010                 jffs2_iput(ds1.node);
1011                 jffs2_iput(ds2.dir);
1012                 jffs2_iput(ds2.node);
1013                 return EEXIST;
1014         }
1015
1016         // Allow through links to non-existing terminal objects
1017         if (ds2.last && err == ENOENT) {
1018                 ds2.node = NULL;
1019                 err = ENOERR;
1020         }
1021
1022         if (err != ENOERR) {
1023                 jffs2_iput(ds1.dir);
1024                 jffs2_iput(ds1.node);
1025                 jffs2_iput(ds2.dir);
1026                 return err;
1027         }
1028
1029         // Now we know that there is no existing node at the destination,
1030         // make a new direntry at the destination.
1031
1032         err = jffs2_link(ds1.node, ds2.dir, ds2.name);
1033
1034         if (err == 0)
1035                 ds1.node->i_ctime =
1036                     ds2.dir->i_ctime = ds2.dir->i_mtime = cyg_timestamp();
1037
1038         jffs2_iput(ds1.dir);
1039         jffs2_iput(ds1.node);
1040         jffs2_iput(ds2.dir);
1041
1042         return -err;
1043 }
1044 #endif /* CYGOPT_FS_JFFS2_WRITE */
1045 // -------------------------------------------------------------------------
1046 // jffs2_opendir()
1047 // Open a directory for reading.
1048
1049 static int jffs2_opendir(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
1050                          cyg_file * file)
1051 {
1052         jffs2_dirsearch ds;
1053         int err;
1054
1055         D2(printf("jffs2_opendir\n"));
1056
1057         init_dirsearch(&ds, (struct _inode *) dir, 
1058                        (const unsigned char *) name);
1059
1060         err = jffs2_find(&ds);
1061
1062         jffs2_iput(ds.dir);
1063
1064         if (err != ENOERR)
1065                 return err;
1066
1067         // check it is really a directory.
1068         if (!S_ISDIR(ds.node->i_mode)) {
1069                 jffs2_iput(ds.node);
1070                 return ENOTDIR;
1071         }
1072
1073         // Initialize the file object, setting the f_ops field to a
1074         // special set of file ops.
1075
1076         file->f_type = CYG_FILE_TYPE_FILE;
1077         file->f_ops = &jffs2_dirops;
1078         file->f_offset = 0;
1079         file->f_data = (CYG_ADDRWORD) ds.node;
1080         file->f_xops = 0;
1081
1082         return ENOERR;
1083
1084 }
1085
1086 // -------------------------------------------------------------------------
1087 // jffs2_chdir()
1088 // Change directory support.
1089
1090 static int jffs2_chdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
1091                        cyg_dir * dir_out)
1092 {
1093         D2(printf("jffs2_chdir\n"));
1094
1095         if (dir_out != NULL) {
1096                 // This is a request to get a new directory pointer in
1097                 // *dir_out.
1098
1099                 jffs2_dirsearch ds;
1100                 int err;
1101
1102                 init_dirsearch(&ds, (struct _inode *) dir, 
1103                                (const unsigned char *) name);
1104
1105                 err = jffs2_find(&ds);
1106                 jffs2_iput(ds.dir);
1107
1108                 if (err != ENOERR)
1109                         return err;
1110
1111                 // check it is a directory
1112                 if (!S_ISDIR(ds.node->i_mode)) {
1113                         jffs2_iput(ds.node);
1114                         return ENOTDIR;
1115                 }
1116                 
1117                 // Pass it out
1118                 *dir_out = (cyg_dir) ds.node;
1119         } else {
1120                 // If no output dir is required, this means that the mte and
1121                 // dir arguments are the current cdir setting and we should
1122                 // forget this fact.
1123
1124                 struct _inode *node = (struct _inode *) dir;
1125
1126                 // Just decrement directory reference count.
1127                 jffs2_iput(node);
1128         }
1129
1130         return ENOERR;
1131 }
1132
1133 // -------------------------------------------------------------------------
1134 // jffs2_stat()
1135 // Get struct stat info for named object.
1136
1137 static int jffs2_stat(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
1138                       struct stat *buf)
1139 {
1140         jffs2_dirsearch ds;
1141         int err;
1142
1143         D2(printf("jffs2_stat\n"));
1144
1145         init_dirsearch(&ds, (struct _inode *) dir, 
1146                        (const unsigned char *) name);
1147
1148         err = jffs2_find(&ds);
1149         jffs2_iput(ds.dir);
1150
1151         if (err != ENOERR)
1152                 return err;
1153
1154         // Fill in the status
1155         buf->st_mode = ds.node->i_mode;
1156         buf->st_ino = ds.node->i_ino;
1157         buf->st_dev = 0;
1158         buf->st_nlink = ds.node->i_nlink;
1159         buf->st_uid = ds.node->i_uid;
1160         buf->st_gid = ds.node->i_gid;
1161         buf->st_size = ds.node->i_size;
1162         buf->st_atime = ds.node->i_atime;
1163         buf->st_mtime = ds.node->i_mtime;
1164         buf->st_ctime = ds.node->i_ctime;
1165
1166         jffs2_iput(ds.node);
1167
1168         return ENOERR;
1169 }
1170
1171 // -------------------------------------------------------------------------
1172 // jffs2_getinfo()
1173 // Getinfo. Currently only support pathconf().
1174
1175 static int jffs2_getinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
1176                          int key, void *buf, int len)
1177 {
1178         jffs2_dirsearch ds;
1179         int err;
1180
1181         D2(printf("jffs2_getinfo\n"));
1182
1183         init_dirsearch(&ds, (struct _inode *) dir, 
1184                        (const unsigned char *) name);
1185
1186         err = jffs2_find(&ds);
1187         jffs2_iput(ds.dir);
1188
1189         if (err != ENOERR)
1190                 return err;
1191
1192         switch (key) {
1193         case FS_INFO_CONF:
1194                 err = jffs2_pathconf(ds.node, (struct cyg_pathconf_info *) buf);
1195                 break;
1196
1197         default:
1198                 err = EINVAL;
1199         }
1200
1201         jffs2_iput(ds.node);
1202         return err;
1203 }
1204
1205 // -------------------------------------------------------------------------
1206 // jffs2_setinfo()
1207 // Setinfo. Nothing to support here at present.
1208
1209 static int jffs2_setinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name,
1210                          int key, void *buf, int len)
1211 {
1212         // No setinfo keys supported at present
1213
1214         D2(printf("jffs2_setinfo\n"));
1215
1216         return EINVAL;
1217 }
1218
1219 //==========================================================================
1220 // File operations
1221
1222 // -------------------------------------------------------------------------
1223 // jffs2_fo_read()
1224 // Read data from the file.
1225
1226 static int jffs2_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1227 {
1228         struct _inode *inode = (struct _inode *) fp->f_data;
1229         struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
1230         struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
1231         int i;
1232         ssize_t resid = uio->uio_resid;
1233         off_t pos = fp->f_offset;
1234
1235         down(&f->sem);
1236
1237         // Loop over the io vectors until there are none left
1238         for (i = 0; i < uio->uio_iovcnt && pos < inode->i_size; i++) {
1239                 int ret;
1240                 cyg_iovec *iov = &uio->uio_iov[i];
1241                 off_t len = min(iov->iov_len, inode->i_size - pos);
1242
1243                 D2(printf("jffs2_fo_read inode size %d\n", inode->i_size));
1244
1245                 ret =
1246                     jffs2_read_inode_range(c, f,
1247                                            (unsigned char *) iov->iov_base, pos,
1248                                            len);
1249                 if (ret) {
1250                         D1(printf
1251                            ("jffs2_fo_read(): read_inode_range failed %d\n",
1252                             ret));
1253                         uio->uio_resid = resid;
1254                         up(&f->sem);
1255                         return -ret;
1256                 }
1257                 resid -= len;
1258                 pos += len;
1259         }
1260
1261         // We successfully read some data, update the node's access time
1262         // and update the file offset and transfer residue.
1263
1264         inode->i_atime = cyg_timestamp();
1265
1266         uio->uio_resid = resid;
1267         fp->f_offset = pos;
1268
1269         up(&f->sem);
1270
1271         return ENOERR;
1272 }
1273
1274
1275 #ifdef CYGOPT_FS_JFFS2_WRITE
1276 // -------------------------------------------------------------------------
1277 // jffs2_fo_write()
1278 // Write data to file.
1279 static int jffs2_extend_file (struct _inode *inode, struct jffs2_raw_inode *ri,
1280                        unsigned long offset)
1281 {
1282         struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
1283         struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
1284         struct jffs2_full_dnode *fn;
1285         uint32_t phys_ofs, alloc_len;
1286         int ret = 0;
1287
1288         /* Make new hole frag from old EOF to new page */
1289         D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",
1290                   (unsigned int)inode->i_size, offset));
1291
1292         ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloc_len, ALLOC_NORMAL);
1293         if (ret)
1294                 return ret;
1295
1296         down(&f->sem);
1297
1298         ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
1299         ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
1300         ri->totlen = cpu_to_je32(sizeof(*ri));
1301         ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
1302
1303         ri->version = cpu_to_je32(++f->highest_version);
1304         ri->isize = cpu_to_je32(max((uint32_t)inode->i_size, offset));
1305
1306         ri->offset = cpu_to_je32(inode->i_size);
1307         ri->dsize = cpu_to_je32(offset - inode->i_size);
1308         ri->csize = cpu_to_je32(0);
1309         ri->compr = JFFS2_COMPR_ZERO;
1310         ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
1311         ri->data_crc = cpu_to_je32(0);
1312                 
1313         fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL);
1314         jffs2_complete_reservation(c);
1315         if (IS_ERR(fn)) {
1316                 ret = PTR_ERR(fn);
1317                 up(&f->sem);
1318                 return ret;
1319         }
1320         ret = jffs2_add_full_dnode_to_inode(c, f, fn);
1321         if (f->metadata) {
1322                 jffs2_mark_node_obsolete(c, f->metadata->raw);
1323                 jffs2_free_full_dnode(f->metadata);
1324                 f->metadata = NULL;
1325         }
1326         if (ret) {
1327                 D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in prepare_write, returned %d\n", ret));
1328                 jffs2_mark_node_obsolete(c, fn->raw);
1329                 jffs2_free_full_dnode(fn);
1330                 up(&f->sem);
1331                 return ret;
1332         }
1333         inode->i_size = offset;
1334         up(&f->sem);
1335         return 0;
1336 }
1337
1338 // jffs2_fo_open()
1339 // Truncate a file
1340 static int jffs2_truncate_file (struct _inode *inode)
1341 {
1342      struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
1343      struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
1344      struct jffs2_full_dnode *new_metadata, * old_metadata;
1345      struct jffs2_raw_inode *ri;
1346      uint32_t phys_ofs, alloclen;
1347      int err;
1348      
1349      ri = jffs2_alloc_raw_inode();
1350      if (!ri) {
1351           return ENOMEM;
1352      }
1353      err = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL);
1354      
1355      if (err) {
1356           jffs2_free_raw_inode(ri);
1357           return err;
1358      }
1359      down(&f->sem);
1360      ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
1361      ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
1362      ri->totlen = cpu_to_je32(sizeof(*ri));
1363      ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
1364      
1365      ri->ino = cpu_to_je32(inode->i_ino);
1366      ri->version = cpu_to_je32(++f->highest_version);
1367      
1368      ri->uid = cpu_to_je16(inode->i_uid);
1369      ri->gid = cpu_to_je16(inode->i_gid);
1370      ri->mode = cpu_to_jemode(inode->i_mode);
1371      ri->isize = cpu_to_je32(0);
1372      ri->atime = cpu_to_je32(inode->i_atime);
1373      ri->mtime = cpu_to_je32(cyg_timestamp());
1374      ri->offset = cpu_to_je32(0);
1375      ri->csize = ri->dsize = cpu_to_je32(0);
1376      ri->compr = JFFS2_COMPR_NONE;
1377      ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
1378      ri->data_crc = cpu_to_je32(0);
1379      new_metadata = jffs2_write_dnode(c, f, ri, NULL, 0, 
1380                                       phys_ofs, ALLOC_NORMAL);
1381      if (IS_ERR(new_metadata)) {
1382           jffs2_complete_reservation(c);
1383           jffs2_free_raw_inode(ri);
1384           up(&f->sem);
1385           return PTR_ERR(new_metadata);
1386      }
1387      
1388      /* It worked. Update the inode */
1389      inode->i_mtime = cyg_timestamp();
1390      inode->i_size = 0;
1391      old_metadata = f->metadata;
1392      jffs2_truncate_fragtree (c, &f->fragtree, 0);
1393      f->metadata = new_metadata;
1394      if (old_metadata) {
1395           jffs2_mark_node_obsolete(c, old_metadata->raw);
1396           jffs2_free_full_dnode(old_metadata);
1397      }
1398      jffs2_free_raw_inode(ri);
1399      
1400      up(&f->sem);
1401      jffs2_complete_reservation(c);
1402      
1403      return 0;
1404 }
1405
1406 static int jffs2_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1407 {
1408         struct _inode *inode = (struct _inode *) fp->f_data;
1409         off_t pos = fp->f_offset;
1410         ssize_t resid = uio->uio_resid;
1411         struct jffs2_raw_inode ri;
1412         struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
1413         struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
1414         int i;
1415
1416         // If the APPEND mode bit was supplied, force all writes to
1417         // the end of the file.
1418         if (fp->f_flag & CYG_FAPPEND)
1419                 pos = fp->f_offset = inode->i_size;
1420
1421         if (pos < 0)
1422                 return EINVAL;
1423
1424         memset(&ri, 0, sizeof(ri));
1425
1426         ri.ino = cpu_to_je32(f->inocache->ino);
1427         ri.mode = cpu_to_jemode(inode->i_mode);
1428         ri.uid = cpu_to_je16(inode->i_uid);
1429         ri.gid = cpu_to_je16(inode->i_gid);
1430         ri.atime = ri.ctime = ri.mtime = cpu_to_je32(cyg_timestamp());
1431
1432         if (pos > inode->i_size) {
1433                 int err;
1434                 ri.version = cpu_to_je32(++f->highest_version);
1435                 err = jffs2_extend_file(inode, &ri, pos);
1436                 if (err)
1437                         return -err;
1438         }
1439         ri.isize = cpu_to_je32(inode->i_size);
1440
1441         // Now loop over the iovecs until they are all done, or
1442         // we get an error.
1443         for (i = 0; i < uio->uio_iovcnt; i++) {
1444                 cyg_iovec *iov = &uio->uio_iov[i];
1445                 unsigned char *buf = iov->iov_base;
1446                 off_t len = iov->iov_len;
1447
1448                 uint32_t writtenlen;
1449                 int err;
1450
1451                 D2(printf("jffs2_fo_write page_start_pos %d\n", pos));
1452                 D2(printf("jffs2_fo_write transfer size %d\n", len));
1453
1454                 err = jffs2_write_inode_range(c, f, &ri, buf,
1455                                               pos, len, &writtenlen);
1456                 if (err)
1457                         return -err;
1458                 
1459                 if (writtenlen != len)
1460                         return ENOSPC;
1461
1462                 pos += len;
1463                 resid -= len;
1464         }
1465
1466         // We wrote some data successfully, update the modified and access
1467         // times of the inode, increase its size appropriately, and update
1468         // the file offset and transfer residue.
1469         inode->i_mtime = inode->i_ctime = je32_to_cpu(ri.mtime);
1470         if (pos > inode->i_size)
1471                 inode->i_size = pos;
1472
1473         uio->uio_resid = resid;
1474         fp->f_offset = pos;
1475
1476         return ENOERR;
1477 }
1478 #endif /* CYGOPT_FS_JFFS2_WRITE */
1479
1480 // -------------------------------------------------------------------------
1481 // jffs2_fo_lseek()
1482 // Seek to a new file position.
1483
1484 static int jffs2_fo_lseek(struct CYG_FILE_TAG *fp, off_t * apos, int whence)
1485 {
1486         struct _inode *node = (struct _inode *) fp->f_data;
1487         off_t pos = *apos;
1488
1489         D2(printf("jffs2_fo_lseek\n"));
1490
1491         switch (whence) {
1492         case SEEK_SET:
1493                 // Pos is already where we want to be.
1494                 break;
1495
1496         case SEEK_CUR:
1497                 // Add pos to current offset.
1498                 pos += fp->f_offset;
1499                 break;
1500
1501         case SEEK_END:
1502                 // Add pos to file size.
1503                 pos += node->i_size;
1504                 break;
1505
1506         default:
1507                 return EINVAL;
1508         }
1509
1510         if (pos < 0 )
1511                 return EINVAL;
1512
1513         // All OK, set fp offset and return new position.
1514         *apos = fp->f_offset = pos;
1515
1516         return ENOERR;
1517 }
1518
1519 // -------------------------------------------------------------------------
1520 // jffs2_fo_ioctl()
1521 // Handle ioctls. Currently none are defined.
1522
1523 static int jffs2_fo_ioctl(struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
1524                           CYG_ADDRWORD data)
1525 {
1526         // No Ioctls currenly defined.
1527
1528         D2(printf("jffs2_fo_ioctl\n"));
1529
1530         return EINVAL;
1531 }
1532
1533 // -------------------------------------------------------------------------
1534 // jffs2_fo_fsync().
1535 // Force the file out to data storage.
1536
1537 static int jffs2_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
1538 {
1539         // Data is always permanently where it belongs, nothing to do
1540         // here.
1541
1542         D2(printf("jffs2_fo_fsync\n"));
1543
1544         return ENOERR;
1545 }
1546
1547 // -------------------------------------------------------------------------
1548 // jffs2_fo_close()
1549 // Close a file. We just decrement the refcnt and let it go away if
1550 // that is all that is keeping it here.
1551
1552 static int jffs2_fo_close(struct CYG_FILE_TAG *fp)
1553 {
1554         struct _inode *node = (struct _inode *) fp->f_data;
1555
1556         D2(printf("jffs2_fo_close\n"));
1557
1558         jffs2_iput(node);
1559
1560         fp->f_data = 0;         // zero data pointer
1561
1562         return ENOERR;
1563 }
1564
1565 // -------------------------------------------------------------------------
1566 //jffs2_fo_fstat()
1567 // Get file status.
1568
1569 static int jffs2_fo_fstat(struct CYG_FILE_TAG *fp, struct stat *buf)
1570 {
1571         struct _inode *node = (struct _inode *) fp->f_data;
1572
1573         D2(printf("jffs2_fo_fstat\n"));
1574
1575         // Fill in the status
1576         buf->st_mode = node->i_mode;
1577         buf->st_ino = node->i_ino;
1578         buf->st_dev = 0;
1579         buf->st_nlink = node->i_nlink;
1580         buf->st_uid = node->i_uid;
1581         buf->st_gid = node->i_gid;
1582         buf->st_size = node->i_size;
1583         buf->st_atime = node->i_atime;
1584         buf->st_mtime = node->i_mtime;
1585         buf->st_ctime = node->i_ctime;
1586
1587         return ENOERR;
1588 }
1589
1590 // -------------------------------------------------------------------------
1591 // jffs2_fo_getinfo()
1592 // Get info. Currently only supports fpathconf().
1593
1594 static int jffs2_fo_getinfo(struct CYG_FILE_TAG *fp, int key, void *buf,
1595                             int len)
1596 {
1597         struct _inode *node = (struct _inode *) fp->f_data;
1598         int err;
1599
1600         D2(printf("jffs2_fo_getinfo\n"));
1601
1602         switch (key) {
1603         case FS_INFO_CONF:
1604                 err = jffs2_pathconf(node, (struct cyg_pathconf_info *) buf);
1605                 break;
1606
1607         default:
1608                 err = EINVAL;
1609         }
1610         return err;
1611
1612         return ENOERR;
1613 }
1614
1615 // -------------------------------------------------------------------------
1616 // jffs2_fo_setinfo()
1617 // Set info. Nothing supported here.
1618
1619 static int jffs2_fo_setinfo(struct CYG_FILE_TAG *fp, int key, void *buf,
1620                             int len)
1621 {
1622         // No setinfo key supported at present
1623
1624         D2(printf("jffs2_fo_setinfo\n"));
1625
1626         return ENOERR;
1627 }
1628
1629 //==========================================================================
1630 // Directory operations
1631
1632 // -------------------------------------------------------------------------
1633 // jffs2_fo_dirread()
1634 // Read a single directory entry from a file.
1635
1636 static __inline void filldir(char *nbuf, int nlen, const unsigned char *name, int namlen)
1637 {
1638         int len = nlen < namlen ? nlen : namlen;
1639         memcpy(nbuf, name, len);
1640         nbuf[len] = '\0';
1641 }
1642
1643 static int jffs2_fo_dirread(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1644 {
1645         struct _inode *d_inode = (struct _inode *) fp->f_data;
1646         struct dirent *ent = (struct dirent *) uio->uio_iov[0].iov_base;
1647         char *nbuf = ent->d_name;
1648         int nlen = sizeof (ent->d_name) - 1;
1649         off_t len = uio->uio_iov[0].iov_len;
1650         struct jffs2_inode_info *f;
1651         struct jffs2_sb_info *c;
1652         struct _inode *inode = d_inode;
1653         struct jffs2_full_dirent *fd;
1654         unsigned long offset, curofs;
1655         int found = 1;
1656
1657         if (len < sizeof (struct dirent))
1658                 return EINVAL;
1659
1660         D1(printk
1661            (KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", d_inode->i_ino));
1662
1663         f = JFFS2_INODE_INFO(inode);
1664         c = JFFS2_SB_INFO(inode->i_sb);
1665
1666         offset = fp->f_offset;
1667
1668         if (offset == 0) {
1669                 D1(printk
1670                    (KERN_DEBUG "Dirent 0: \".\", ino #%lu\n", inode->i_ino));
1671                 filldir(nbuf, nlen, (const unsigned char *) ".", 1);
1672                 goto out;
1673         }
1674         if (offset == 1) {
1675                 filldir(nbuf, nlen, (const unsigned char *) "..", 2);
1676                 goto out;
1677         }
1678
1679         curofs = 1;
1680         down(&f->sem);
1681         for (fd = f->dents; fd; fd = fd->next) {
1682
1683                 curofs++;
1684                 /* First loop: curofs = 2; offset = 2 */
1685                 if (curofs < offset) {
1686                         D2(printk
1687                            (KERN_DEBUG
1688                             "Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld\n",
1689                             fd->name, fd->ino, fd->type, curofs, offset));
1690                         continue;
1691                 }
1692                 if (!fd->ino) {
1693                         D2(printk
1694                            (KERN_DEBUG "Skipping deletion dirent \"%s\"\n",
1695                             fd->name));
1696                         offset++;
1697                         continue;
1698                 }
1699                 D2(printk
1700                    (KERN_DEBUG "Dirent %ld: \"%s\", ino #%u, type %d\n", offset,
1701                     fd->name, fd->ino, fd->type));
1702                 filldir(nbuf, nlen, fd->name, strlen((char *)fd->name));
1703                 goto out_sem;
1704         }
1705         /* Reached the end of the directory */
1706         found = 0;
1707       out_sem:
1708         up(&f->sem);
1709       out:
1710         fp->f_offset = ++offset;
1711         if (found) {
1712                 uio->uio_resid -= sizeof (struct dirent);
1713         }
1714         return ENOERR;
1715 }
1716
1717 // -------------------------------------------------------------------------
1718 // jffs2_fo_dirlseek()
1719 // Seek directory to start.
1720
1721 static int jffs2_fo_dirlseek(struct CYG_FILE_TAG *fp, off_t * pos, int whence)
1722 {
1723         // Only allow SEEK_SET to zero
1724
1725         D2(printf("jffs2_fo_dirlseek\n"));
1726
1727         if (whence != SEEK_SET || *pos != 0)
1728                 return EINVAL;
1729
1730         *pos = fp->f_offset = 0;
1731
1732         return ENOERR;
1733 }
1734
1735 //==========================================================================
1736 // 
1737 // Called by JFFS2
1738 // ===============
1739 // 
1740 //
1741 //==========================================================================
1742
1743 unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, 
1744                                    struct jffs2_inode_info *f, 
1745                                    unsigned long offset,
1746                                    unsigned long *priv)
1747 {
1748         /* FIXME: This works only with one file system mounted at a time */
1749         int ret;
1750
1751         ret = jffs2_read_inode_range(c, f, gc_buffer, 
1752                                      offset & ~(PAGE_CACHE_SIZE-1), PAGE_CACHE_SIZE);
1753         if (ret)
1754                 return ERR_PTR(ret);
1755
1756         return gc_buffer;
1757 }
1758
1759 void jffs2_gc_release_page(struct jffs2_sb_info *c,
1760                            unsigned char *ptr,
1761                            unsigned long *priv)
1762 {
1763         /* Do nothing */
1764 }
1765
1766 static struct _inode *new_inode(struct super_block *sb)
1767 {
1768
1769         // Only called in write.c jffs2_new_inode
1770         // Always adds itself to inode cache
1771
1772         struct _inode *inode;
1773         struct _inode *cached_inode;
1774
1775         inode = malloc(sizeof (struct _inode));
1776         if (inode == NULL)
1777                 return 0;
1778
1779         D2(printf
1780            ("malloc new_inode %x ####################################\n",
1781             inode));
1782
1783         memset(inode, 0, sizeof (struct _inode));
1784         inode->i_sb = sb;
1785         inode->i_ino = 1;
1786         inode->i_count = 1;
1787         inode->i_nlink = 1;     // Let JFFS2 manage the link count
1788         inode->i_size = 0;
1789
1790         inode->i_cache_next = NULL;     // Newest inode, about to be cached
1791
1792         // Add to the icache
1793         for (cached_inode = sb->s_root; cached_inode != NULL;
1794              cached_inode = cached_inode->i_cache_next) {
1795                 if (cached_inode->i_cache_next == NULL) {
1796                         cached_inode->i_cache_next = inode;     // Current last in cache points to newcomer
1797                         inode->i_cache_prev = cached_inode;     // Newcomer points back to last
1798                         break;
1799                 }
1800         }
1801         return inode;
1802 }
1803
1804 static struct _inode *ilookup(struct super_block *sb, cyg_uint32 ino)
1805 {
1806         struct _inode *inode = NULL;
1807
1808         D2(printf("ilookup\n"));
1809         // Check for this inode in the cache
1810         for (inode = sb->s_root; inode != NULL; inode = inode->i_cache_next) {
1811                 if (inode->i_ino == ino) {
1812                         inode->i_count++;
1813                         break;
1814                 }
1815         }
1816         return inode;
1817 }
1818
1819 struct _inode *jffs2_iget(struct super_block *sb, cyg_uint32 ino)
1820 {
1821         // Called in super.c jffs2_read_super, dir.c jffs2_lookup,
1822         // and gc.c jffs2_garbage_collect_pass
1823
1824         // Must first check for cached inode 
1825         // If this fails let new_inode create one
1826
1827         struct _inode *inode;
1828         int err;
1829
1830         D2(printf("jffs2_iget\n"));
1831
1832         inode = ilookup(sb, ino);
1833         if (inode)
1834                 return inode;
1835
1836         // Not cached, so malloc it
1837         inode = new_inode(sb);
1838         if (inode == NULL)
1839                 return ERR_PTR(-ENOMEM);
1840
1841         inode->i_ino = ino;
1842
1843         err = jffs2_read_inode(inode);
1844         if (err) {
1845                 printf("jffs2_read_inode() failed\n");
1846                 inode->i_nlink = 0; // free _this_ bad inode right now
1847                 jffs2_iput(inode);
1848                 inode = NULL;
1849                 return ERR_PTR(err);
1850         }
1851         return inode;
1852 }
1853
1854 // -------------------------------------------------------------------------
1855 // Decrement the reference count on an inode. If this makes the ref count
1856 // zero, then this inode can be freed.
1857
1858 void jffs2_iput(struct _inode *i)
1859 {
1860         // Called in jffs2_find 
1861         // (and jffs2_open and jffs2_ops_mkdir?)
1862         // super.c jffs2_read_super,
1863         // and gc.c jffs2_garbage_collect_pass
1864  recurse:
1865         if (!i) {
1866                 printf("jffs2_iput() called with NULL inode\n");
1867                 // and let it fault... 
1868         }
1869
1870         i->i_count--;
1871
1872         if (i->i_count < 0)
1873                 BUG();
1874
1875         if (i->i_count)
1876                 return;
1877         
1878         if (!i->i_nlink) {
1879                 struct _inode *parent;
1880
1881                 // Remove from the icache linked list and free immediately
1882                 if (i->i_cache_prev)
1883                         i->i_cache_prev->i_cache_next = i->i_cache_next;
1884                 if (i->i_cache_next)
1885                         i->i_cache_next->i_cache_prev = i->i_cache_prev;
1886
1887                 parent = i->i_parent;
1888                 jffs2_clear_inode(i);
1889                 memset(i, 0x5a, sizeof(*i));
1890                 free(i);
1891
1892                 if (parent && parent != i) {
1893                         i = parent;
1894                         goto recurse;
1895                 }
1896
1897         } else {
1898                 // Evict some _other_ inode with i_count zero, leaving
1899                 // this latest one in the cache for a while 
1900                 icache_evict(i->i_sb->s_root, i);
1901         }
1902 }
1903
1904
1905 // -------------------------------------------------------------------------
1906 // EOF jffs2.c
1907
1908
1909 static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
1910 {
1911         memset(f, 0, sizeof(*f));
1912         init_MUTEX_LOCKED(&f->sem);
1913 }
1914
1915 static void jffs2_clear_inode (struct _inode *inode)
1916 {
1917         /* We can forget about this inode for now - drop all
1918          *  the nodelists associated with it, etc.
1919          */
1920         struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
1921         struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
1922
1923         D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode));
1924
1925         jffs2_do_clear_inode(c, f);
1926 }
1927
1928
1929 /* jffs2_new_inode: allocate a new inode and inocache, add it to the hash,
1930    fill in the raw_inode while you're at it. */
1931 struct _inode *jffs2_new_inode (struct _inode *dir_i, int mode, struct jffs2_raw_inode *ri)
1932 {
1933         struct _inode *inode;
1934         struct super_block *sb = dir_i->i_sb;
1935         struct jffs2_sb_info *c;
1936         struct jffs2_inode_info *f;
1937         int ret;
1938
1939         D1(printk(KERN_DEBUG "jffs2_new_inode(): dir_i %ld, mode 0x%x\n", dir_i->i_ino, mode));
1940
1941         c = JFFS2_SB_INFO(sb);
1942         
1943         inode = new_inode(sb);
1944         
1945         if (!inode)
1946                 return ERR_PTR(-ENOMEM);
1947
1948         f = JFFS2_INODE_INFO(inode);
1949         jffs2_init_inode_info(f);
1950
1951         memset(ri, 0, sizeof(*ri));
1952         /* Set OS-specific defaults for new inodes */
1953         ri->uid = ri->gid = cpu_to_je16(0);
1954         ri->mode =  cpu_to_jemode(mode);
1955         ret = jffs2_do_new_inode (c, f, mode, ri);
1956         if (ret) {
1957                 // forceful evict: f->sem is locked already, and the
1958                 // inode is bad.
1959                 if (inode->i_cache_prev)
1960                        inode->i_cache_prev->i_cache_next = inode->i_cache_next;
1961                 if (inode->i_cache_next)
1962                        inode->i_cache_next->i_cache_prev = inode->i_cache_prev; 
1963                 up(&(f->sem));
1964                 jffs2_clear_inode(inode);
1965                 memset(inode, 0x6a, sizeof(*inode));
1966                 free(inode);
1967                 return ERR_PTR(ret);
1968         }
1969         inode->i_nlink = 1;
1970         inode->i_ino = je32_to_cpu(ri->ino);
1971         inode->i_mode = jemode_to_cpu(ri->mode);
1972         inode->i_gid = je16_to_cpu(ri->gid);
1973         inode->i_uid = je16_to_cpu(ri->uid);
1974         inode->i_atime = inode->i_ctime = inode->i_mtime = cyg_timestamp();
1975         ri->atime = ri->mtime = ri->ctime = cpu_to_je32(inode->i_mtime);
1976
1977         inode->i_size = 0;
1978
1979         return inode;
1980 }
1981
1982
1983 static int jffs2_read_inode (struct _inode *inode)
1984 {
1985         struct jffs2_inode_info *f;
1986         struct jffs2_sb_info *c;
1987         struct jffs2_raw_inode latest_node;
1988         int ret;
1989
1990         D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino));
1991
1992         f = JFFS2_INODE_INFO(inode);
1993         c = JFFS2_SB_INFO(inode->i_sb);
1994
1995         jffs2_init_inode_info(f);
1996         
1997         ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node);
1998
1999         if (ret) {
2000                 up(&f->sem);
2001                 return ret;
2002         }
2003         inode->i_mode = jemode_to_cpu(latest_node.mode);
2004         inode->i_uid = je16_to_cpu(latest_node.uid);
2005         inode->i_gid = je16_to_cpu(latest_node.gid);
2006         inode->i_size = je32_to_cpu(latest_node.isize);
2007         inode->i_atime = je32_to_cpu(latest_node.atime);
2008         inode->i_mtime = je32_to_cpu(latest_node.mtime);
2009         inode->i_ctime = je32_to_cpu(latest_node.ctime);
2010
2011         inode->i_nlink = f->inocache->nlink;
2012         up(&f->sem);
2013
2014         D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n"));
2015         return 0;
2016 }
2017
2018
2019 void jffs2_gc_release_inode(struct jffs2_sb_info *c,
2020                                    struct jffs2_inode_info *f)
2021 {
2022         jffs2_iput(OFNI_EDONI_2SFFJ(f));
2023 }
2024
2025 struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
2026                                                      int inum, int nlink)
2027 {
2028         struct _inode *inode;
2029         struct jffs2_inode_cache *ic;
2030         if (!nlink) {
2031                 /* The inode has zero nlink but its nodes weren't yet marked
2032                    obsolete. This has to be because we're still waiting for 
2033                    the final (close() and) jffs2_iput() to happen.
2034
2035                    There's a possibility that the final jffs2_iput() could have 
2036                    happened while we were contemplating. In order to ensure
2037                    that we don't cause a new read_inode() (which would fail)
2038                    for the inode in question, we use ilookup() in this case
2039                    instead of jffs2_iget().
2040
2041                    The nlink can't _become_ zero at this point because we're 
2042                    holding the alloc_sem, and jffs2_do_unlink() would also
2043                    need that while decrementing nlink on any inode.
2044                 */
2045                 inode = ilookup(OFNI_BS_2SFFJ(c), inum);
2046                 if (!inode) {
2047                         D1(printk(KERN_DEBUG "ilookup() failed for ino #%u; inode is probably deleted.\n",
2048                                   inum));
2049
2050                         spin_lock(&c->inocache_lock);
2051                         ic = jffs2_get_ino_cache(c, inum);
2052                         if (!ic) {
2053                                 D1(printk(KERN_DEBUG "Inode cache for ino #%u is gone.\n", inum));
2054                                 spin_unlock(&c->inocache_lock);
2055                                 return NULL;
2056                         }
2057                         if (ic->state != INO_STATE_CHECKEDABSENT) {
2058                                 /* Wait for progress. Don't just loop */
2059                                 D1(printk(KERN_DEBUG "Waiting for ino #%u in state %d\n",
2060                                           ic->ino, ic->state));
2061                                 sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
2062                         } else {
2063                                 spin_unlock(&c->inocache_lock);
2064                         }
2065
2066                         return NULL;
2067                 }
2068         } else {
2069                 /* Inode has links to it still; they're not going away because
2070                    jffs2_do_unlink() would need the alloc_sem and we have it.
2071                    Just jffs2_iget() it, and if read_inode() is necessary that's OK.
2072                 */
2073                 inode = jffs2_iget(OFNI_BS_2SFFJ(c), inum);
2074                 if (IS_ERR(inode))
2075                         return (void *)inode;
2076         }
2077
2078         return JFFS2_INODE_INFO(inode);
2079 }
2080
2081
2082
2083 uint32_t jffs2_from_os_mode(uint32_t osmode)
2084 {
2085         uint32_t jmode = ((osmode & S_IRUSR)?00400:0) |
2086                 ((osmode & S_IWUSR)?00200:0) |
2087                 ((osmode & S_IXUSR)?00100:0) |
2088                 ((osmode & S_IRGRP)?00040:0) |
2089                 ((osmode & S_IWGRP)?00020:0) |
2090                 ((osmode & S_IXGRP)?00010:0) |
2091                 ((osmode & S_IROTH)?00004:0) |
2092                 ((osmode & S_IWOTH)?00002:0) |
2093                 ((osmode & S_IXOTH)?00001:0);
2094
2095         switch (osmode & S_IFMT) {
2096         case S_IFSOCK:
2097                 return jmode | 0140000;
2098         case S_IFLNK:
2099                 return jmode | 0120000;
2100         case S_IFREG:
2101                 return jmode | 0100000;
2102         case S_IFBLK:
2103                 return jmode | 0060000;
2104         case S_IFDIR:
2105                 return jmode | 0040000;
2106         case S_IFCHR:
2107                 return jmode | 0020000;
2108         case S_IFIFO:
2109                 return jmode | 0010000;
2110         case S_ISUID:
2111                 return jmode | 0004000;
2112         case S_ISGID:
2113                 return jmode | 0002000;
2114 #ifdef S_ISVTX
2115         case S_ISVTX:
2116                 return jmode | 0001000;
2117 #endif
2118         }
2119         printf("os_to_jffs2_mode() cannot convert 0x%x\n", osmode);
2120         BUG();
2121         return 0;
2122 }
2123
2124 uint32_t jffs2_to_os_mode (uint32_t jmode)
2125 {
2126         uint32_t osmode = ((jmode & 00400)?S_IRUSR:0) |
2127                 ((jmode & 00200)?S_IWUSR:0) |
2128                 ((jmode & 00100)?S_IXUSR:0) |
2129                 ((jmode & 00040)?S_IRGRP:0) |
2130                 ((jmode & 00020)?S_IWGRP:0) |
2131                 ((jmode & 00010)?S_IXGRP:0) |
2132                 ((jmode & 00004)?S_IROTH:0) |
2133                 ((jmode & 00002)?S_IWOTH:0) |
2134                 ((jmode & 00001)?S_IXOTH:0);
2135
2136         switch(jmode & 00170000) {
2137         case 0140000:
2138                 return osmode | S_IFSOCK;
2139         case 0120000:
2140                 return osmode | S_IFLNK;
2141         case 0100000:
2142                 return osmode | S_IFREG;
2143         case 0060000:
2144                 return osmode | S_IFBLK;
2145         case 0040000:
2146                 return osmode | S_IFDIR;
2147         case 0020000:
2148                 return osmode | S_IFCHR;
2149         case 0010000:
2150                 return osmode | S_IFIFO;
2151         case 0004000:
2152                 return osmode | S_ISUID;
2153         case 0002000:
2154                 return osmode | S_ISGID;
2155 #ifdef S_ISVTX
2156         case 0001000:
2157                 return osmode | S_ISVTX;
2158 #endif
2159         }
2160         printf("jffs2_to_os_mode() cannot convert 0x%x\n", osmode);
2161         BUG();
2162         return 0;
2163 }