comparison packages/fs/jffs2/current/src/jffs2.c @ 208:e0c0827131d1 ecos

Merge from eCos master repository on 2002-05-20-20:11:54-BST
author jlarmour
date Mon, 20 May 2002 22:19:26 +0000
parents
children d2c90368aeef
comparison
equal deleted inserted replaced
207:74c807ddde34 208:e0c0827131d1
1 //==========================================================================
2 //
3 // jffs2.c
4 //
5 // JFFS2 file system
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s): dominic.ostrowski@3glab.com
44 // Contributors: nickg, richard.panton@3glab.com
45 // Date: 2000-07-25
46 // Purpose: JFFS2 file system
47 // Description: This is the JFFS2 flash filesystem for eCos.
48 //
49 //####DESCRIPTIONEND####
50 //
51 //==========================================================================
52 //
53 // General Description
54 // ===================
55 //
56 //
57 //==========================================================================
58
59 #include "jffs2port.h"
60 #include "jffs2.h"
61 #include "jffs2_fs_sb.h"
62 #include "jffs2_fs_i.h"
63 #include "nodelist.h"
64
65 #include <errno.h>
66 #include <string.h>
67 #include <cyg/io/io.h>
68 #include <cyg/io/config_keys.h>
69 #include <cyg/io/flash.h>
70
71 //==========================================================================
72 // Forward definitions
73
74 // Filesystem operations
75 static int jffs2_mount ( cyg_fstab_entry *fste, cyg_mtab_entry *mte );
76 static int jffs2_umount ( cyg_mtab_entry *mte );
77 static int jffs2_open ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
78 int mode, cyg_file *fte );
79 static int jffs2_ops_unlink ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );
80 static int jffs2_ops_mkdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );
81 static int jffs2_ops_rmdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );
82 static int jffs2_ops_rename ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
83 cyg_dir dir2, const char *name2 );
84 static int jffs2_ops_link ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
85 cyg_dir dir2, const char *name2, int type );
86 static int jffs2_opendir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
87 cyg_file *fte );
88 static int jffs2_chdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
89 cyg_dir *dir_out );
90 static int jffs2_stat ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
91 struct stat *buf);
92 static int jffs2_getinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
93 int key, void *buf, int len );
94 static int jffs2_setinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
95 int key, void *buf, int len );
96
97 // File operations
98 static int jffs2_fo_read (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
99 static int jffs2_fo_write (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
100 static int jffs2_fo_lseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence );
101 static int jffs2_fo_ioctl (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
102 CYG_ADDRWORD data);
103 static int jffs2_fo_fsync (struct CYG_FILE_TAG *fp, int mode );
104 static int jffs2_fo_close (struct CYG_FILE_TAG *fp);
105 static int jffs2_fo_fstat (struct CYG_FILE_TAG *fp, struct stat *buf );
106 static int jffs2_fo_getinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len );
107 static int jffs2_fo_setinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len );
108
109 // Directory operations
110 static int jffs2_fo_dirread (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
111 static int jffs2_fo_dirlseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence );
112
113
114 //==========================================================================
115 // Filesystem table entries
116
117 // -------------------------------------------------------------------------
118 // Fstab entry.
119 // This defines the entry in the filesystem table.
120 // For simplicity we use _FILESYSTEM synchronization for all accesses since
121 // we should never block in any filesystem operations.
122
123 FSTAB_ENTRY( jffs2_fste, "jffs2", 0,
124 CYG_SYNCMODE_FILE_FILESYSTEM|CYG_SYNCMODE_IO_FILESYSTEM,
125 jffs2_mount,
126 jffs2_umount,
127 jffs2_open,
128 jffs2_ops_unlink,
129 jffs2_ops_mkdir,
130 jffs2_ops_rmdir,
131 jffs2_ops_rename,
132 jffs2_ops_link,
133 jffs2_opendir,
134 jffs2_chdir,
135 jffs2_stat,
136 jffs2_getinfo,
137 jffs2_setinfo);
138
139 // -------------------------------------------------------------------------
140 // File operations.
141 // This set of file operations are used for normal open files.
142
143 static cyg_fileops jffs2_fileops =
144 {
145 jffs2_fo_read,
146 jffs2_fo_write,
147 jffs2_fo_lseek,
148 jffs2_fo_ioctl,
149 cyg_fileio_seltrue,
150 jffs2_fo_fsync,
151 jffs2_fo_close,
152 jffs2_fo_fstat,
153 jffs2_fo_getinfo,
154 jffs2_fo_setinfo
155 };
156
157 // -------------------------------------------------------------------------
158 // Directory file operations.
159 // This set of operations are used for open directories. Most entries
160 // point to error-returning stub functions. Only the read, lseek and
161 // close entries are functional.
162
163 static cyg_fileops jffs2_dirops =
164 {
165 jffs2_fo_dirread,
166 (cyg_fileop_write *)cyg_fileio_enosys,
167 jffs2_fo_dirlseek,
168 (cyg_fileop_ioctl *)cyg_fileio_enosys,
169 cyg_fileio_seltrue,
170 (cyg_fileop_fsync *)cyg_fileio_enosys,
171 jffs2_fo_close,
172 (cyg_fileop_fstat *)cyg_fileio_enosys,
173 (cyg_fileop_getinfo *)cyg_fileio_enosys,
174 (cyg_fileop_setinfo *)cyg_fileio_enosys
175 };
176
177
178 //==========================================================================
179 // STATIC VARIABLES !!!
180
181 static char read_write_buffer[PAGE_CACHE_SIZE]; //avoids malloc when user may be under memory pressure
182 static char gc_buffer[PAGE_CACHE_SIZE]; //avoids malloc when user may be under memory pressure
183
184 //==========================================================================
185 // Directory operations
186
187 struct jffs2_dirsearch
188 {
189 struct inode *dir; // directory to search
190 const char *path; // path to follow
191 struct inode *node; // Node found
192 const char *name; // last name fragment used
193 int namelen; // name fragment length
194 cyg_bool last; // last name in path?
195 };
196
197 typedef struct jffs2_dirsearch jffs2_dirsearch;
198
199 //==========================================================================
200 // Ref count and nlink management
201
202 // -------------------------------------------------------------------------
203 // dec_refcnt()
204 // Decrment the reference count on an inode. If this makes the ref count
205 // zero, then this inode can be freed.
206
207 static int dec_refcnt( struct inode *node )
208 {
209 int err = ENOERR;
210 node->i_count--;
211
212 // In JFFS2 inode's are temporary in ram structures that are free'd when the usage i_count drops to 0
213 // The i_nlink however is managed by JFFS2 and is unrelated to usage
214 if( node->i_count == 0)
215 {
216 // This inode is not in use, so delete it.
217 iput(node);
218 }
219
220 return err;
221 }
222
223 // FIXME: This seems like real cruft. Wouldn't it be better just to do the
224 // right thing?
225 static void icache_evict(struct inode *root_i, struct inode *i) {
226 struct inode *cached_inode;
227 struct inode *next_inode;
228
229 D2(printf("icache_evict\n"));
230 // If this is an absolute search path from the root,
231 // remove all cached inodes with i_count of zero (these are only
232 // held where needed for dotdot filepaths)
233 if(i == root_i) {
234 for(cached_inode = root_i; cached_inode != NULL; cached_inode = next_inode) {
235 next_inode = cached_inode->i_cache_next;
236 if (cached_inode->i_count == 0) {
237 cached_inode->i_cache_prev->i_cache_next = cached_inode->i_cache_next; // Prveious entry points ahead of us
238 if (cached_inode->i_cache_next != NULL)
239 cached_inode->i_cache_next->i_cache_prev = cached_inode->i_cache_prev; // Next entry points behind us
240 jffs2_clear_inode(cached_inode);
241 D2(printf("free icache_evict inode %x $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n", cached_inode));
242 free(cached_inode);
243 }
244 }
245 }
246 }
247
248 //==========================================================================
249 // Directory search
250
251 // -------------------------------------------------------------------------
252 // init_dirsearch()
253 // Initialize a dirsearch object to start a search
254
255 static void init_dirsearch( jffs2_dirsearch *ds,
256 struct inode *dir,
257 const char *name)
258 {
259 D2(printf("init_dirsearch name = %s\n", name));
260 D2(printf("init_dirsearch dir = %x\n", dir));
261 ds->dir = dir;
262 ds->path = name;
263 ds->node = dir;
264 ds->name = name;
265 ds->namelen = 0;
266 ds->last = false;
267 }
268
269
270 // -------------------------------------------------------------------------
271 // find_entry()
272 // Search a single directory for the next name in a path and update the
273 // dirsearch object appropriately.
274
275 static int find_entry( jffs2_dirsearch *ds )
276 {
277 unsigned long hash;
278 struct qstr this;
279 unsigned int c;
280 const char * hashname;
281
282 struct inode *dir = ds->dir;
283 const char *name = ds->path;
284 const char *n = name;
285 char namelen = 0;
286 struct inode *d;
287
288 D2(printf("find_entry\n"));
289
290 // check that we really have a directory
291 if( !S_ISDIR(dir->i_mode) )
292 return ENOTDIR;
293
294 // Isolate the next element of the path name.
295 while( *n != '\0' && *n != '/' )
296 n++, namelen++;
297
298 // If we terminated on a NUL, set last flag.
299 if( *n == '\0' )
300 ds->last = true;
301
302 // update name in dirsearch object
303 ds->name = name;
304 ds->namelen = namelen;
305
306 if (name[0] == '.') switch (namelen) {
307 default:
308 break;
309 case 2:
310 // Dot followed by not Dot, treat as any other name
311 if (name[1] != '.')
312 break;
313 // Dot Dot
314 // Move back up the search path
315 D2(printf("find_entry found ..\n"));
316 ds->node = ds->dir->i_parent;
317 if(ds->dir->i_count == 0) {
318 iput(ds->dir); // This inode may be evicted
319 ds->dir = NULL;
320 }
321 return ENOERR;
322 case 1:
323 // Dot is consumed
324 D2(printf("find_entry found .\n"));
325 ds->node = ds->dir;
326 return ENOERR;
327 }
328
329 // Here we have the name and its length set up.
330 // Search the directory for a matching entry
331
332 hashname = name;
333 this.name = hashname;
334 c = *(const unsigned char *)hashname;
335
336 hash = init_name_hash();
337 do {
338 hashname++;
339 hash = partial_name_hash(c, hash);
340 c = *(const unsigned char *)hashname;
341 } while (c && (c != '/'));
342 this.len = hashname - (const char *) this.name;
343 this.hash = end_name_hash(hash);
344
345 D2(printf("find_entry for name = %s\n", ds->path));
346 d = jffs2_lookup(dir, &this);
347 D2(printf("find_entry got dir = %x\n", d));
348
349 if( d == NULL )
350 return ENOENT;
351
352 // The back path for dotdot to follow
353 d->i_parent = dir;
354 // pass back the node we have found
355 ds->node = d;
356
357 return ENOERR;
358
359 }
360
361 // -------------------------------------------------------------------------
362 // jffs2_find()
363 // Main interface to directory search code. This is used in all file
364 // level operations to locate the object named by the pathname.
365
366 static int jffs2_find( jffs2_dirsearch *d )
367 {
368 int err;
369
370 D2(printf("jffs2_find for path =%s\n", d->path));
371 // Short circuit empty paths
372 if( *(d->path) == '\0' )
373 return ENOERR;
374
375 // iterate down directory tree until we find the object
376 // we want.
377 for(;;)
378 {
379 err = find_entry( d );
380
381 if( err != ENOERR )
382 return err;
383
384 if( d->last )
385 return ENOERR;
386
387 // every inode traversed in the find is temporary and should be free'd
388 //iput(d->dir);
389
390 // Update dirsearch object to search next directory.
391 d->dir = d->node;
392 d->path += d->namelen;
393 if( *(d->path) == '/' ) d->path++; // skip dirname separators
394 }
395 }
396
397 //==========================================================================
398 // Pathconf support
399 // This function provides support for pathconf() and fpathconf().
400
401 static int jffs2_pathconf( struct inode *node, struct cyg_pathconf_info *info )
402 {
403 int err = ENOERR;
404 D2(printf("jffs2_pathconf\n"));
405
406 switch( info->name )
407 {
408 case _PC_LINK_MAX:
409 info->value = LINK_MAX;
410 break;
411
412 case _PC_MAX_CANON:
413 info->value = -1; // not supported
414 err = EINVAL;
415 break;
416
417 case _PC_MAX_INPUT:
418 info->value = -1; // not supported
419 err = EINVAL;
420 break;
421
422 case _PC_NAME_MAX:
423 info->value = NAME_MAX;
424 break;
425
426 case _PC_PATH_MAX:
427 info->value = PATH_MAX;
428 break;
429
430 case _PC_PIPE_BUF:
431 info->value = -1; // not supported
432 err = EINVAL;
433 break;
434
435
436 case _PC_ASYNC_IO:
437 info->value = -1; // not supported
438 err = EINVAL;
439 break;
440
441 case _PC_CHOWN_RESTRICTED:
442 info->value = -1; // not supported
443 err = EINVAL;
444 break;
445
446 case _PC_NO_TRUNC:
447 info->value = 0;
448 break;
449
450 case _PC_PRIO_IO:
451 info->value = 0;
452 break;
453
454 case _PC_SYNC_IO:
455 info->value = 0;
456 break;
457
458 case _PC_VDISABLE:
459 info->value = -1; // not supported
460 err = EINVAL;
461 break;
462
463 default:
464 err = EINVAL;
465 break;
466 }
467
468 return err;
469 }
470
471 //==========================================================================
472 // Filesystem operations
473
474 // -------------------------------------------------------------------------
475 // jffs2_mount()
476 // Process a mount request. This mainly creates a root for the
477 // filesystem.
478 static int jffs2_read_super(struct super_block *sb)
479 {
480 struct jffs2_sb_info *c;
481 struct inode *root_i;
482 Cyg_ErrNo err;
483 cyg_uint32 len;
484 cyg_io_flash_getconfig_devsize_t ds;
485 cyg_io_flash_getconfig_blocksize_t bs;
486
487 D1(printk(KERN_DEBUG "jffs2: read_super\n"));
488
489 c = JFFS2_SB_INFO(sb);
490 memset(c, 0, sizeof(*c));
491
492 len = sizeof(ds);
493 err = cyg_io_get_config( sb->s_dev,
494 CYG_IO_GET_CONFIG_FLASH_DEVSIZE,
495 &ds, &len );
496 if ( err != ENOERR ) {
497 D1(printf("jffs2: cyg_io_get_config failed to get dev size: %d\n",
498 err));
499 return err;
500 }
501 len = sizeof(bs);
502 bs.offset = 0;
503 err = cyg_io_get_config( sb->s_dev,
504 CYG_IO_GET_CONFIG_FLASH_BLOCKSIZE,
505 &bs, &len );
506 if ( err != ENOERR ) {
507 D1(printf("jffs2: cyg_io_get_config failed to get block size: %d\n",
508 err));
509 return err;
510 }
511
512 c->sector_size = bs.block_size;
513 c->flash_size = ds.dev_size;
514
515 err = jffs2_do_mount_fs(c);
516 if (err)
517 return -err;
518
519 D1(printk(KERN_DEBUG "jffs2_read_super(): Getting root inode\n"));
520 root_i = iget(sb, 1);
521 if (is_bad_inode(root_i)) {
522 D1(printk(KERN_WARNING "get root inode failed\n"));
523 err = EIO;
524 goto out_nodes;
525 }
526
527 D1(printk(KERN_DEBUG "jffs2_read_super(): d_alloc_root()\n"));
528 sb->s_root = d_alloc_root(root_i);
529 if (!sb->s_root) {
530 err = ENOMEM;
531 goto out_root_i;
532 }
533 sb->s_blocksize = PAGE_CACHE_SIZE;
534 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
535 sb->s_magic = JFFS2_SUPER_MAGIC;
536
537 return 0;
538
539 out_root_i:
540 iput(root_i);
541 out_nodes:
542 jffs2_free_ino_caches(c);
543 jffs2_free_raw_node_refs(c);
544 free(c->blocks);
545
546 return err;
547 }
548
549 static int jffs2_mount ( cyg_fstab_entry *fste, cyg_mtab_entry *mte )
550 {
551 extern cyg_mtab_entry mtab[], mtab_end;
552 struct super_block *jffs2_sb = NULL;
553 struct jffs2_sb_info *c;
554 cyg_mtab_entry *m;
555 cyg_io_handle_t t;
556 Cyg_ErrNo err;
557
558 D2(printf("jffs2_mount\n"));
559
560 err = cyg_io_lookup( mte->devname, &t );
561 if( err != ENOERR )
562 return -err;
563
564 // Iterate through the mount table to see if we're mounted
565 // FIXME: this should be done better - perhaps if the superblock
566 // can be stored as an inode in the icache.
567 for( m = &mtab[0]; m != &mtab_end; m++ )
568 {
569 // stop if there are more than the configured maximum
570 if( m-&mtab[0] >= CYGNUM_FILEIO_MTAB_MAX )
571 {
572 m = &mtab_end;
573 break;
574 }
575 if ( m->valid && strcmp( m->fsname, "jffs2" ) == 0 &&
576 strcmp( m->devname, mte->devname) == 0 ) {
577 jffs2_sb = (struct super_block *)m->data;
578 }
579 }
580
581 if ( jffs2_sb == NULL) {
582 jffs2_sb = malloc(sizeof(struct super_block));
583
584 if(jffs2_sb == NULL)
585 return ENOSPC;
586
587 c = JFFS2_SB_INFO(jffs2_sb);
588 memset(jffs2_sb, 0, sizeof(struct super_block));
589 jffs2_sb->s_dev = t;
590
591 err = jffs2_read_super(jffs2_sb);
592
593 if (err) {
594 free(jffs2_sb);
595 return err;
596 }
597
598 jffs2_sb->s_root->i_parent = jffs2_sb->s_root; // points to itself, no dotdot paths above mountpoint
599 jffs2_sb->s_root->i_cache_prev = NULL; // root inode, so always null
600 jffs2_sb->s_root->i_cache_next = NULL;
601 jffs2_sb->s_root->i_count = 1; // Ensures the root inode is always in ram until umount
602
603 D2(printf("jffs2_mount erasing pending blocks\n"));
604 jffs2_erase_pending_blocks(c);
605 jffs2_mark_erased_blocks(c);
606 }
607 mte->data = (CYG_ADDRWORD)jffs2_sb;
608
609 jffs2_sb->s_mount_count++;
610 mte->root = (cyg_dir)jffs2_sb->s_root;
611 D2(printf("jffs2_mounted superblock at %x\n", mte->root));
612
613 return ENOERR;
614 }
615
616 // -------------------------------------------------------------------------
617 // jffs2_umount()
618 // Unmount the filesystem.
619
620 static int jffs2_umount ( cyg_mtab_entry *mte )
621 {
622 struct inode *root = (struct inode *)mte->root;
623 struct super_block *jffs2_sb = root->i_sb;
624 struct jffs2_sb_info *c = JFFS2_SB_INFO(jffs2_sb);
625
626 D2(printf("jffs2_umount\n"));
627
628 // Decrement the mount count
629 jffs2_sb->s_mount_count--;
630
631 // Only really umount if this is the only mount
632 if (jffs2_sb->s_mount_count == 0) {
633
634 // Check for open/inuse root or any cached inodes
635 //if( root->i_count != 1 || root->i_cache_next != NULL) // root icount was set to 1 on mount
636 if( root->i_cache_next != NULL) // root icount was set to 1 on mount
637 return EBUSY;
638
639 dec_refcnt(root); // Time to free the root inode
640
641 //Clear root inode
642 //root_i = NULL;
643
644 // Clean up the super block and root inode
645 jffs2_free_ino_caches(c);
646 jffs2_free_raw_node_refs(c);
647 free(c->blocks);
648
649 // Clear root pointer
650 mte->root = CYG_DIR_NULL;
651
652 mte->fs->data = 0; // fstab entry, visible to all mounts. No current mount
653 // That's all folks.
654 D2(printf("jffs2_umount No current mounts\n"));
655 }
656
657 return ENOERR;
658 }
659
660 // -------------------------------------------------------------------------
661 // jffs2_open()
662 // Open a file for reading or writing.
663
664 static int jffs2_open ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
665 int mode, cyg_file *file )
666 {
667
668 jffs2_dirsearch ds;
669 struct inode *node = NULL;
670 int err;
671
672 D2(printf("jffs2_open\n"));
673
674 icache_evict((struct inode *)mte->root, (struct inode *)dir);
675
676 init_dirsearch( &ds, (struct inode *)dir, name );
677
678 err = jffs2_find( &ds );
679
680 if( err == ENOENT )
681 {
682 if( ds.last && (mode & O_CREAT) )
683 {
684 unsigned long hash;
685 struct qstr this;
686 unsigned int c;
687 const char * hashname;
688
689 // No node there, if the O_CREAT bit is set then we must
690 // create a new one. The dir and name fields of the dirsearch
691 // object will have been updated so we know where to put it.
692
693 hashname = ds.name;
694 this.name = hashname;
695 c = *(const unsigned char *)hashname;
696
697 hash = init_name_hash();
698 do {
699 hashname++;
700 hash = partial_name_hash(c, hash);
701 c = *(const unsigned char *)hashname;
702 } while (c && (c != '/'));
703 this.len = hashname - (const char *) this.name;
704 this.hash = end_name_hash(hash);
705
706 err = jffs2_create(ds.dir, &this, 0644, &node);
707
708 if( err != 0 )
709 {
710 //Possible orphaned inode on the flash - but will be gc'd
711 return err;
712 }
713
714 err = ENOERR;
715 }
716 }
717 else if( err == ENOERR )
718 {
719 // The node exists. If the O_CREAT and O_EXCL bits are set, we
720 // must fail the open.
721
722 if( (mode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) )
723 err = EEXIST;
724 else node = ds.node;
725 }
726
727 if( err == ENOERR && (mode & O_TRUNC ) )
728 {
729 // If the O_TRUNC bit is set we must clean out the file data.
730
731 node->i_size = 0;
732
733 // Update file times
734 node->i_ctime =
735 node->i_mtime = cyg_timestamp();
736 }
737
738 if( err != ENOERR ) return err;
739
740 // Check that we actually have a file here
741 if( S_ISDIR(node->i_mode) ) return EISDIR;
742
743 node->i_count++; // Count successful open
744
745 // Initialize the file object
746
747 file->f_flag |= mode & CYG_FILE_MODE_MASK;
748 file->f_type = CYG_FILE_TYPE_FILE;
749 file->f_ops = &jffs2_fileops;
750 file->f_offset = (mode&O_APPEND) ? node->i_size : 0;
751 file->f_data = (CYG_ADDRWORD)node;
752 file->f_xops = 0;
753
754 return ENOERR;
755 }
756
757 // -------------------------------------------------------------------------
758 // jffs2_ops_unlink()
759 // Remove a file link from its directory.
760
761 static int jffs2_ops_unlink ( cyg_mtab_entry *mte, cyg_dir dir, const char *name )
762 {
763 unsigned long hash;
764 struct qstr this;
765 unsigned int c;
766 const char * hashname;
767 jffs2_dirsearch ds;
768 int err;
769
770 D2(printf("jffs2_ops_unlink\n"));
771
772 icache_evict((struct inode *)mte->root, (struct inode *)dir);
773
774 init_dirsearch( &ds, (struct inode *)dir, name );
775
776 err = jffs2_find( &ds );
777
778 if( err != ENOERR ) return err;
779
780 // Cannot unlink directories, use rmdir() instead
781 if( S_ISDIR(ds.node->i_mode) )
782 return EPERM;
783
784 // Delete it from its directory
785
786 hashname = ds.name;
787 this.name = hashname;
788 c = *(const unsigned char *)hashname;
789
790 hash = init_name_hash();
791 do {
792 hashname++;
793 hash = partial_name_hash(c, hash);
794 c = *(const unsigned char *)hashname;
795 } while (c && (c != '/'));
796 this.len = hashname - (const char *) this.name;
797 this.hash = end_name_hash(hash);
798
799 err = jffs2_unlink(ds.dir, ds.node, &this);
800
801 return err;
802 }
803
804 // -------------------------------------------------------------------------
805 // jffs2_ops_mkdir()
806 // Create a new directory.
807
808 static int jffs2_ops_mkdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name )
809 {
810 jffs2_dirsearch ds;
811 struct inode *node = NULL;
812 int err;
813
814 D2(printf("jffs2_ops_mkdir\n"));
815
816 icache_evict((struct inode *)mte->root, (struct inode *)dir);
817
818 init_dirsearch( &ds, (struct inode *)dir, name );
819
820 err = jffs2_find( &ds );
821
822 if( err == ENOENT )
823 {
824 if( ds.last )
825 {
826 unsigned long hash;
827 struct qstr this;
828 unsigned int c;
829 const char * hashname;
830 // The entry does not exist, and it is the last element in
831 // the pathname, so we can create it here.
832
833 hashname = ds.name;
834 this.name = hashname;
835 c = *(const unsigned char *)hashname;
836
837 hash = init_name_hash();
838 do {
839 hashname++;
840 hash = partial_name_hash(c, hash);
841 c = *(const unsigned char *)hashname;
842 } while (c && (c != '/'));
843 this.len = hashname - (const char *) this.name;
844 this.hash = end_name_hash(hash);
845
846 err = jffs2_mkdir(ds.dir, &this, 0, &node);
847
848 if( err != 0 )
849 return ENOSPC;
850
851 }
852 // If this was not the last element, then and intermediate
853 // directory does not exist.
854 }
855 else
856 {
857 // If there we no error, something already exists with that
858 // name, so we cannot create another one.
859
860 if( err == ENOERR )
861 err = EEXIST;
862 }
863
864 return err;
865 }
866
867 // -------------------------------------------------------------------------
868 // jffs2_ops_rmdir()
869 // Remove a directory.
870
871 static int jffs2_ops_rmdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name )
872 {
873 unsigned long hash;
874 struct qstr this;
875 unsigned int c;
876 const char * hashname;
877 jffs2_dirsearch ds;
878 int err;
879
880 D2(printf("jffs2_ops_rmdir\n"));
881
882 icache_evict((struct inode *)mte->root, (struct inode *)dir);
883
884 init_dirsearch( &ds, (struct inode *)dir, name );
885
886 err = jffs2_find( &ds );
887
888 if( err != ENOERR ) return err;
889
890 // Check that this is actually a directory.
891 if( !S_ISDIR(ds.node->i_mode) )
892 return EPERM;
893
894 // Delete the entry.
895 hashname = ds.name;
896 this.name = hashname;
897 c = *(const unsigned char *)hashname;
898
899 hash = init_name_hash();
900 do {
901 hashname++;
902 hash = partial_name_hash(c, hash);
903 c = *(const unsigned char *)hashname;
904 } while (c && (c != '/'));
905 this.len = hashname - (const char *) this.name;
906 this.hash = end_name_hash(hash);
907
908 err = jffs2_rmdir(ds.dir, ds.node, &this);
909
910 return err;
911
912 return ENOERR;
913 }
914
915 // -------------------------------------------------------------------------
916 // jffs2_ops_rename()
917 // Rename a file/dir.
918
919 static int jffs2_ops_rename ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
920 cyg_dir dir2, const char *name2 )
921 {
922 unsigned long hash;
923 struct qstr this1,this2;
924 unsigned int c;
925 const char * hashname;
926 jffs2_dirsearch ds1, ds2;
927 int err;
928
929 D2(printf("jffs2_ops_rename\n"));
930
931 init_dirsearch( &ds1, (struct inode *)dir1, name1 );
932
933 err = jffs2_find( &ds1 );
934
935 if( err != ENOERR ) return err;
936
937 init_dirsearch( &ds2, (struct inode *)dir2, name2 );
938
939 err = jffs2_find( &ds2 );
940
941 // Allow through renames to non-existent objects.
942 if( ds2.last && err == ENOENT )
943 ds2.node = NULL, err = ENOERR;
944
945 if( err != ENOERR ) return err;
946
947 // Null rename, just return
948 if( ds1.node == ds2.node )
949 return ENOERR;
950
951 hashname = ds1.name;
952 this1.name = hashname;
953 c = *(const unsigned char *)hashname;
954
955 hash = init_name_hash();
956 do {
957 hashname++;
958 hash = partial_name_hash(c, hash);
959 c = *(const unsigned char *)hashname;
960 } while (c && (c != '/'));
961 this1.len = hashname - (const char *) this1.name;
962 this1.hash = end_name_hash(hash);
963
964 hashname = ds2.name;
965 this2.name = hashname;
966 c = *(const unsigned char *)hashname;
967
968 hash = init_name_hash();
969 do {
970 hashname++;
971 hash = partial_name_hash(c, hash);
972 c = *(const unsigned char *)hashname;
973 } while (c && (c != '/'));
974 this2.len = hashname - (const char *) this2.name;
975 this2.hash = end_name_hash(hash);
976
977 // First deal with any entry that is at the destination
978 if( ds2.node )
979 {
980 // Check that we are renaming like-for-like
981
982 if( !S_ISDIR(ds1.node->i_mode) && S_ISDIR(ds2.node->i_mode) )
983 return EISDIR;
984
985 if( S_ISDIR(ds1.node->i_mode) && !S_ISDIR(ds2.node->i_mode) )
986 return ENOTDIR;
987
988 // Now delete the destination directory entry
989
990 err = jffs2_unlink(ds2.dir, ds2.node, &this2);
991
992 if( err != 0 ) return err;
993
994 }
995
996 // Now we know that there is no clashing node at the destination,
997 // make a new direntry at the destination and delete the old entry
998 // at the source.
999
1000 err = jffs2_rename(ds1.dir, ds1.node, &this1, ds2.dir, &this2);
1001
1002 // Update directory times
1003 if( err == 0 )
1004 ds1.dir->i_ctime =
1005 ds1.dir->i_mtime =
1006 ds2.dir->i_ctime =
1007 ds2.dir->i_mtime = cyg_timestamp();
1008
1009 return err;
1010 }
1011
1012 // -------------------------------------------------------------------------
1013 // jffs2_ops_link()
1014 // Make a new directory entry for a file.
1015
1016 static int jffs2_ops_link ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
1017 cyg_dir dir2, const char *name2, int type )
1018 {
1019 unsigned long hash;
1020 struct qstr this;
1021 unsigned int c;
1022 const char * hashname;
1023 jffs2_dirsearch ds1, ds2;
1024 int err;
1025
1026 D2(printf("jffs2_ops_link\n"));
1027
1028 // Only do hard links for now in this filesystem
1029 if( type != CYG_FSLINK_HARD )
1030 return EINVAL;
1031
1032 init_dirsearch( &ds1, (struct inode *)dir1, name1 );
1033
1034 err = jffs2_find( &ds1 );
1035
1036 if( err != ENOERR ) return err;
1037
1038 init_dirsearch( &ds2, (struct inode *)dir2, name2 );
1039
1040 err = jffs2_find( &ds2 );
1041
1042 // Don't allow links to existing objects
1043 if( err == ENOERR ) return EEXIST;
1044
1045 // Allow through links to non-existing terminal objects
1046 if( ds2.last && err == ENOENT )
1047 ds2.node = NULL, err = ENOERR;
1048
1049 if( err != ENOERR ) return err;
1050
1051 // Now we know that there is no existing node at the destination,
1052 // make a new direntry at the destination.
1053
1054 hashname = ds2.name;
1055 this.name = hashname;
1056 c = *(const unsigned char *)hashname;
1057
1058 hash = init_name_hash();
1059 do {
1060 hashname++;
1061 hash = partial_name_hash(c, hash);
1062 c = *(const unsigned char *)hashname;
1063 } while (c && (c != '/'));
1064 this.len = hashname - (const char *) this.name;
1065 this.hash = end_name_hash(hash);
1066
1067 err = jffs2_link(ds2.dir, ds1.node, &this);
1068
1069 if( err == 0 )
1070 ds1.node->i_ctime =
1071 ds2.dir->i_ctime =
1072 ds2.dir->i_mtime = cyg_timestamp();
1073
1074 return err;
1075 }
1076
1077 // -------------------------------------------------------------------------
1078 // jffs2_opendir()
1079 // Open a directory for reading.
1080
1081 static int jffs2_opendir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1082 cyg_file *file )
1083 {
1084 jffs2_dirsearch ds;
1085 int err;
1086
1087 D2(printf("jffs2_opendir\n"));
1088
1089 icache_evict((struct inode *)mte->root, (struct inode *)dir);
1090
1091 init_dirsearch( &ds, (struct inode *)dir, name );
1092
1093 err = jffs2_find( &ds );
1094
1095 if( err != ENOERR ) return err;
1096
1097 // check it is really a directory.
1098 if( !S_ISDIR(ds.node->i_mode) ) return ENOTDIR;
1099
1100 ds.node->i_count++; // Count successful open
1101
1102 // Initialize the file object, setting the f_ops field to a
1103 // special set of file ops.
1104
1105 file->f_type = CYG_FILE_TYPE_FILE;
1106 file->f_ops = &jffs2_dirops;
1107 file->f_offset = 0;
1108 file->f_data = (CYG_ADDRWORD)ds.node;
1109 file->f_xops = 0;
1110
1111
1112 return ENOERR;
1113
1114 }
1115
1116 // -------------------------------------------------------------------------
1117 // jffs2_chdir()
1118 // Change directory support.
1119
1120 static int jffs2_chdir ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1121 cyg_dir *dir_out )
1122 {
1123 D2(printf("jffs2_chdir\n"));
1124
1125 if( dir_out != NULL )
1126 {
1127 // This is a request to get a new directory pointer in
1128 // *dir_out.
1129
1130 jffs2_dirsearch ds;
1131 int err;
1132
1133 icache_evict((struct inode *)mte->root, (struct inode *)dir);
1134
1135 init_dirsearch( &ds, (struct inode *)dir, name );
1136
1137 err = jffs2_find( &ds );
1138
1139 if( err != ENOERR ) return err;
1140
1141 // check it is a directory
1142 if( !S_ISDIR(ds.node->i_mode) )
1143 return ENOTDIR;
1144
1145 // Increment ref count to keep this directory in existance
1146 // while it is the current cdir.
1147 ds.node->i_count++;
1148
1149 // Pass it out
1150 *dir_out = (cyg_dir)ds.node;
1151 }
1152 else
1153 {
1154 // If no output dir is required, this means that the mte and
1155 // dir arguments are the current cdir setting and we should
1156 // forget this fact.
1157
1158 struct inode *node = (struct inode *)dir;
1159
1160 // Just decrement directory reference count.
1161 dec_refcnt( node );
1162 }
1163
1164 return ENOERR;
1165 }
1166
1167 // -------------------------------------------------------------------------
1168 // jffs2_stat()
1169 // Get struct stat info for named object.
1170
1171 static int jffs2_stat ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1172 struct stat *buf)
1173 {
1174 jffs2_dirsearch ds;
1175 int err;
1176
1177 D2(printf("jffs2_stat\n"));
1178
1179 icache_evict((struct inode *)mte->root, (struct inode *)dir);
1180
1181 init_dirsearch( &ds, (struct inode *)dir, name );
1182
1183 err = jffs2_find( &ds );
1184
1185 if( err != ENOERR ) return err;
1186
1187 // Fill in the status
1188 buf->st_mode = ds.node->i_mode;
1189 buf->st_ino = (ino_t)ds.node;
1190 buf->st_dev = 0;
1191 buf->st_nlink = ds.node->i_nlink;
1192 buf->st_uid = 0;
1193 buf->st_gid = 0;
1194 buf->st_size = ds.node->i_size;
1195 buf->st_atime = ds.node->i_atime;
1196 buf->st_mtime = ds.node->i_mtime;
1197 buf->st_ctime = ds.node->i_ctime;
1198
1199 return err;
1200
1201 return ENOERR;
1202 }
1203
1204 // -------------------------------------------------------------------------
1205 // jffs2_getinfo()
1206 // Getinfo. Currently only support pathconf().
1207
1208 static int jffs2_getinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1209 int key, void *buf, int len )
1210 {
1211 jffs2_dirsearch ds;
1212 int err;
1213
1214 D2(printf("jffs2_getinfo\n"));
1215
1216 icache_evict((struct inode *)mte->root, (struct inode *)dir);
1217
1218 init_dirsearch( &ds, (struct inode *)dir, name );
1219
1220 err = jffs2_find( &ds );
1221
1222 if( err != ENOERR ) return err;
1223
1224 switch( key )
1225 {
1226 case FS_INFO_CONF:
1227 err = jffs2_pathconf( ds.node, (struct cyg_pathconf_info *)buf );
1228 break;
1229
1230 default:
1231 err = EINVAL;
1232 }
1233 return err;
1234
1235 return ENOERR;
1236 }
1237
1238 // -------------------------------------------------------------------------
1239 // jffs2_setinfo()
1240 // Setinfo. Nothing to support here at present.
1241
1242 static int jffs2_setinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1243 int key, void *buf, int len )
1244 {
1245 // No setinfo keys supported at present
1246
1247 D2(printf("jffs2_setinfo\n"));
1248
1249 return EINVAL;
1250 }
1251
1252
1253 //==========================================================================
1254 // File operations
1255
1256 // -------------------------------------------------------------------------
1257 // jffs2_fo_read()
1258 // Read data from the file.
1259
1260 static int jffs2_fo_read (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1261 {
1262 struct inode *inode = (struct inode *)fp->f_data;
1263 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
1264 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
1265 int i;
1266 ssize_t resid = uio->uio_resid;
1267 off_t pos = fp->f_offset;
1268
1269 down(&f->sem);
1270
1271 // Loop over the io vectors until there are none left
1272 for( i = 0; i < uio->uio_iovcnt && pos < inode->i_size; i++ )
1273 {
1274 int ret;
1275 cyg_iovec *iov = &uio->uio_iov[i];
1276 off_t len = min(iov->iov_len, inode->i_size - pos);
1277
1278 D2(printf("jffs2_fo_read inode size %d\n", inode->i_size));
1279
1280 ret = jffs2_read_inode_range(c, f, (unsigned char *)iov->iov_base,
1281 pos, len);
1282 if (ret) {
1283 D1(printf("jffs2_fo_read(): read_inode_range failed %d\n",
1284 ret));
1285 uio->uio_resid = resid;
1286 up(&f->sem);
1287 return -ret;
1288 }
1289 resid -= len;
1290 pos += len;
1291 }
1292
1293 // We successfully read some data, update the node's access time
1294 // and update the file offset and transfer residue.
1295
1296 inode->i_atime = cyg_timestamp();
1297
1298 uio->uio_resid = resid;
1299 fp->f_offset = pos;
1300
1301 up(&f->sem);
1302
1303 return ENOERR;
1304 }
1305
1306 // -------------------------------------------------------------------------
1307 // jffs2_fo_write()
1308 // Write data to file.
1309
1310 static int jffs2_fo_write (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1311 {
1312 struct page write_page;
1313 off_t page_start_pos;
1314 struct inode *node = (struct inode *)fp->f_data;
1315 off_t pos = fp->f_offset;
1316 ssize_t resid = uio->uio_resid;
1317 int i;
1318
1319 memset(&read_write_buffer, 0, PAGE_CACHE_SIZE);
1320 write_page.virtual = &read_write_buffer;
1321
1322 // If the APPEND mode bit was supplied, force all writes to
1323 // the end of the file.
1324 if( fp->f_flag & CYG_FAPPEND )
1325 pos = fp->f_offset = node->i_size;
1326
1327 // Check that pos is within current file size, or at the very end.
1328 if( pos < 0 || pos > node->i_size )
1329 return EINVAL;
1330
1331 // Now loop over the iovecs until they are all done, or
1332 // we get an error.
1333 for( i = 0; i < uio->uio_iovcnt; i++ )
1334 {
1335 cyg_iovec *iov = &uio->uio_iov[i];
1336 char *buf = (char *)iov->iov_base;
1337 off_t len = iov->iov_len;
1338
1339 // loop over the vector writing it to the file until it has
1340 // all been done.
1341 while( len > 0 )
1342 {
1343 //cyg_uint8 *fbuf;
1344 //size_t bsize;
1345 size_t writtenlen;
1346 off_t l = len;
1347 int err;
1348
1349 write_page.index = 0;
1350
1351 page_start_pos = pos;
1352 while(page_start_pos >= (PAGE_CACHE_SIZE)) {
1353 write_page.index++;
1354 page_start_pos -= PAGE_CACHE_SIZE;
1355 }
1356
1357 if( l > PAGE_CACHE_SIZE - page_start_pos)
1358 l = PAGE_CACHE_SIZE - page_start_pos;
1359
1360 D2(printf("jffs2_fo_write write_page.index %d\n", write_page.index));
1361 D2(printf("jffs2_fo_write page_start_pos %d\n", page_start_pos));
1362 D2(printf("jffs2_fo_write transfer size %d\n", l));
1363
1364 err = jffs2_prepare_write(node, &write_page, page_start_pos, page_start_pos + l);
1365
1366 if( err != 0 )
1367 return err;
1368
1369 // copy data in
1370 memcpy(&read_write_buffer[page_start_pos], buf, l);
1371
1372 writtenlen = jffs2_commit_write(node, &write_page, page_start_pos, page_start_pos + l);
1373
1374 if( writtenlen != l )
1375 return ENOSPC;
1376
1377 // Update working vars
1378 len -= l;
1379 buf += l;
1380 pos += l;
1381 resid -= l;
1382 }
1383 }
1384
1385 // We wrote some data successfully, update the modified and access
1386 // times of the node, increase its size appropriately, and update
1387 // the file offset and transfer residue.
1388 node->i_mtime =
1389 node->i_ctime = cyg_timestamp();
1390 if( pos > node->i_size )
1391 node->i_size = pos;
1392
1393 uio->uio_resid = resid;
1394 fp->f_offset = pos;
1395
1396 return ENOERR;
1397 }
1398
1399 // -------------------------------------------------------------------------
1400 // jffs2_fo_lseek()
1401 // Seek to a new file position.
1402
1403 static int jffs2_fo_lseek (struct CYG_FILE_TAG *fp, off_t *apos, int whence )
1404 {
1405 struct inode *node = (struct inode *)fp->f_data;
1406 off_t pos = *apos;
1407
1408 D2(printf("jffs2_fo_lseek\n"));
1409
1410 switch( whence )
1411 {
1412 case SEEK_SET:
1413 // Pos is already where we want to be.
1414 break;
1415
1416 case SEEK_CUR:
1417 // Add pos to current offset.
1418 pos += fp->f_offset;
1419 break;
1420
1421 case SEEK_END:
1422 // Add pos to file size.
1423 pos += node->i_size;
1424 break;
1425
1426 default:
1427 return EINVAL;
1428 }
1429
1430 // Check that pos is still within current file size, or at the
1431 // very end.
1432 if( pos < 0 || pos > node->i_size )
1433 return EINVAL;
1434
1435 // All OK, set fp offset and return new position.
1436 *apos = fp->f_offset = pos;
1437
1438 return ENOERR;
1439 }
1440
1441 // -------------------------------------------------------------------------
1442 // jffs2_fo_ioctl()
1443 // Handle ioctls. Currently none are defined.
1444
1445 static int jffs2_fo_ioctl (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
1446 CYG_ADDRWORD data)
1447 {
1448 // No Ioctls currenly defined.
1449
1450 D2(printf("jffs2_fo_ioctl\n"));
1451
1452 return EINVAL;
1453 }
1454
1455 // -------------------------------------------------------------------------
1456 // jffs2_fo_fsync().
1457 // Force the file out to data storage.
1458
1459 static int jffs2_fo_fsync (struct CYG_FILE_TAG *fp, int mode )
1460 {
1461 // Data is always permanently where it belongs, nothing to do
1462 // here.
1463
1464 D2(printf("jffs2_fo_fsync\n"));
1465
1466 return ENOERR;
1467 }
1468
1469 // -------------------------------------------------------------------------
1470 // jffs2_fo_close()
1471 // Close a file. We just decrement the refcnt and let it go away if
1472 // that is all that is keeping it here.
1473
1474 static int jffs2_fo_close (struct CYG_FILE_TAG *fp)
1475 {
1476 struct inode *node = (struct inode *)fp->f_data;
1477
1478 D2(printf("jffs2_fo_close\n"));
1479
1480 dec_refcnt( node );
1481
1482 fp->f_data = 0; // zero data pointer
1483
1484 return ENOERR;
1485 }
1486
1487 // -------------------------------------------------------------------------
1488 //jffs2_fo_fstat()
1489 // Get file status.
1490
1491 static int jffs2_fo_fstat (struct CYG_FILE_TAG *fp, struct stat *buf )
1492 {
1493 struct inode *node = (struct inode *)fp->f_data;
1494
1495 D2(printf("jffs2_fo_fstat\n"));
1496
1497 // Fill in the status
1498 buf->st_mode = node->i_mode;
1499 buf->st_ino = (ino_t)node;
1500 buf->st_dev = 0;
1501 buf->st_nlink = node->i_nlink;
1502 buf->st_uid = 0;
1503 buf->st_gid = 0;
1504 buf->st_size = node->i_size;
1505 buf->st_atime = node->i_atime;
1506 buf->st_mtime = node->i_mtime;
1507 buf->st_ctime = node->i_ctime;
1508
1509 return ENOERR;
1510 }
1511
1512 // -------------------------------------------------------------------------
1513 // jffs2_fo_getinfo()
1514 // Get info. Currently only supports fpathconf().
1515
1516 static int jffs2_fo_getinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len )
1517 {
1518 struct inode *node = (struct inode *)fp->f_data;
1519 int err;
1520
1521 D2(printf("jffs2_fo_getinfo\n"));
1522
1523 switch( key )
1524 {
1525 case FS_INFO_CONF:
1526 err = jffs2_pathconf( node, (struct cyg_pathconf_info *)buf );
1527 break;
1528
1529 default:
1530 err = EINVAL;
1531 }
1532 return err;
1533
1534 return ENOERR;
1535 }
1536
1537 // -------------------------------------------------------------------------
1538 // jffs2_fo_setinfo()
1539 // Set info. Nothing supported here.
1540
1541 static int jffs2_fo_setinfo (struct CYG_FILE_TAG *fp, int key, void *buf, int len )
1542 {
1543 // No setinfo key supported at present
1544
1545 D2(printf("jffs2_fo_setinfo\n"));
1546
1547 return ENOERR;
1548 }
1549
1550
1551 //==========================================================================
1552 // Directory operations
1553
1554 // -------------------------------------------------------------------------
1555 // jffs2_fo_dirread()
1556 // Read a single directory entry from a file.
1557
1558 static __inline void
1559 filldir(char *nbuf, int nlen, const char * name, int namlen)
1560 {
1561 int len = nlen < namlen ? nlen : namlen;
1562 memcpy(nbuf, name, len);
1563 nbuf[len] = '\0';
1564 }
1565
1566 static int jffs2_fo_dirread (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1567 {
1568 struct inode *d_inode = (struct inode *)fp->f_data;
1569 struct dirent *ent = (struct dirent *)uio->uio_iov[0].iov_base;
1570 char *nbuf = ent->d_name;
1571 int nlen = sizeof(ent->d_name)-1;
1572 off_t len = uio->uio_iov[0].iov_len;
1573 struct jffs2_inode_info *f;
1574 struct jffs2_sb_info *c;
1575 struct inode *inode = d_inode;
1576 struct jffs2_full_dirent *fd;
1577 unsigned long offset, curofs;
1578 int found = 1;
1579
1580 if( len < sizeof(struct dirent) )
1581 return EINVAL;
1582
1583 D1(printk(KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", d_inode->i_ino));
1584
1585 f = JFFS2_INODE_INFO(inode);
1586 c = JFFS2_SB_INFO(inode->i_sb);
1587
1588 offset = fp->f_offset;
1589
1590 if (offset == 0) {
1591 D1(printk(KERN_DEBUG "Dirent 0: \".\", ino #%lu\n", inode->i_ino));
1592 filldir(nbuf, nlen, ".", 1);
1593 goto out;
1594 }
1595 if (offset == 1) {
1596 filldir(nbuf, nlen, "..", 2);
1597 goto out;
1598 }
1599
1600 curofs=1;
1601 down(&f->sem);
1602 for (fd = f->dents; fd; fd = fd->next) {
1603
1604 curofs++;
1605 /* First loop: curofs = 2; offset = 2 */
1606 if (curofs < offset) {
1607 D2(printk(KERN_DEBUG "Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld\n",
1608 fd->name, fd->ino, fd->type, curofs, offset));
1609 continue;
1610 }
1611 if (!fd->ino) {
1612 D2(printk(KERN_DEBUG "Skipping deletion dirent \"%s\"\n", fd->name));
1613 offset++;
1614 continue;
1615 }
1616 D2(printk(KERN_DEBUG "Dirent %ld: \"%s\", ino #%u, type %d\n", offset, fd->name, fd->ino, fd->type));
1617 filldir(nbuf, nlen, fd->name, strlen(fd->name));
1618 goto out_sem;
1619 }
1620 /* Reached the end of the directory */
1621 found = 0;
1622 out_sem:
1623 up(&f->sem);
1624 out:
1625 fp->f_offset = ++offset;
1626 if (found) {
1627 uio->uio_resid -= sizeof(struct dirent);
1628 }
1629 return ENOERR;
1630 }
1631
1632 // -------------------------------------------------------------------------
1633 // jffs2_fo_dirlseek()
1634 // Seek directory to start.
1635
1636 static int jffs2_fo_dirlseek (struct CYG_FILE_TAG *fp, off_t *pos, int whence )
1637 {
1638 // Only allow SEEK_SET to zero
1639
1640 D2(printf("jffs2_fo_dirlseek\n"));
1641
1642 if( whence != SEEK_SET || *pos != 0)
1643 return EINVAL;
1644
1645 *pos = fp->f_offset = 0;
1646
1647 return ENOERR;
1648 }
1649
1650
1651 //==========================================================================
1652 //
1653 // Called by JFFS2
1654 // ===============
1655 //
1656 //
1657 //==========================================================================
1658
1659
1660 struct page *read_cache_page(unsigned long index,
1661 int (*filler)(void *,struct page*),
1662 void *data)
1663 {
1664 // Only called in gc.c jffs2_garbage_collect_dnode
1665 // but gets a real page for the specified inode
1666
1667 int err;
1668 struct page *gc_page = malloc(sizeof(struct page));
1669
1670 printf("read_cache_page\n");
1671 memset(&gc_buffer, 0, PAGE_CACHE_SIZE);
1672
1673 if(gc_page != NULL) {
1674 gc_page->virtual = &gc_buffer;
1675 gc_page->index = index;
1676
1677 err = filler(data, gc_page);
1678 if (err < 0) {
1679 free(gc_page);
1680 gc_page = NULL;
1681 }
1682 }
1683
1684 return gc_page;
1685 }
1686
1687 void page_cache_release(struct page * pg) {
1688
1689 // Only called in gc.c jffs2_garbage_collect_dnode
1690 // but should free the page malloc'd by read_cache_page
1691
1692 printf("page_cache_release\n");
1693 free(pg);
1694 }
1695
1696 struct inode * new_inode(struct super_block *sb) {
1697
1698 // Only called in write.c jffs2_new_inode
1699 // Always adds itself to inode cache
1700
1701 struct inode * inode;
1702 struct inode * cached_inode;
1703
1704 inode = malloc(sizeof(struct inode));
1705 if (inode == NULL)
1706 return 0;
1707
1708 D2(printf("malloc new_inode %x ####################################\n", inode));
1709
1710 memset(inode, 0, sizeof(struct inode));
1711 inode->i_sb = sb;
1712 inode->i_ino = 1;
1713 inode->i_count = 0;//1; // Let ecos manage the open count
1714
1715 inode->i_nlink = 1; // Let JFFS2 manage the link count
1716 inode->i_size = 0;
1717
1718 inode->i_cache_next = NULL; // Newest inode, about to be cached
1719
1720 // Add to the icache
1721 for(cached_inode = sb->s_root; cached_inode != NULL; cached_inode = cached_inode->i_cache_next) {
1722 if (cached_inode->i_cache_next == NULL) {
1723 cached_inode->i_cache_next = inode; // Current last in cache points to newcomer
1724 inode->i_cache_prev = cached_inode; // Newcomer points back to last
1725 break;
1726 }
1727 }
1728
1729 return inode;
1730 }
1731
1732 struct inode * iget(struct super_block *sb, cyg_uint32 ino) {
1733
1734 // Substitute for iget drops straight through to reading the
1735 // inode from disk if it is not in the inode cache
1736
1737 // Called in super.c jffs2_read_super, dir.c jffs2_lookup,
1738 // and gc.c jffs2_garbage_collect_pass
1739
1740 // Must first check for cached inode
1741 // If this fails let new_inode create one
1742
1743 struct inode * inode;
1744
1745 D2(printf("iget\n"));
1746
1747 // Check for this inode in the cache
1748 for(inode = sb->s_root; inode != NULL; inode = inode->i_cache_next) {
1749 if (inode->i_ino == ino)
1750 return inode;
1751 }
1752 inode = NULL;
1753
1754 // Not cached, so malloc it
1755 inode = new_inode(sb);
1756 if (inode == NULL)
1757 return 0;
1758
1759 inode->i_ino = ino;
1760 jffs2_read_inode(inode);
1761
1762 return inode;
1763 }
1764
1765 void iput(struct inode * i) {
1766
1767 // Called in dec_refcnt, jffs2_find
1768 // (and jffs2_open and jffs2_ops_mkdir?)
1769 // super.c jffs2_read_super,
1770 // and gc.c jffs2_garbage_collect_pass
1771
1772 struct inode *cached_inode;
1773
1774 D2(printf("free iput inode %x $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n", i));
1775 if (i && i->i_count) {
1776 /* Added by dwmw2. iget/iput in Linux track the use count,
1777 don't just unconditionally free it */
1778 printf("iput called for used inode\n");
1779 return;
1780 }
1781 if (i != NULL) {
1782 // Remove from the icache
1783 for(cached_inode = i->i_sb->s_root; cached_inode != NULL; cached_inode = cached_inode->i_cache_next) {
1784 if (cached_inode == i) {
1785 cached_inode->i_cache_prev->i_cache_next = cached_inode->i_cache_next; // Prveious entry points ahead of us
1786 if (cached_inode->i_cache_next != NULL)
1787 cached_inode->i_cache_next->i_cache_prev = cached_inode->i_cache_prev; // Next entry points behind us
1788 break;
1789 }
1790 }
1791 // inode has been seperated from the cache
1792 jffs2_clear_inode(i);
1793 free(i);
1794 }
1795 }
1796
1797 static int return_EIO(void)
1798 {
1799 return -EIO;
1800 }
1801
1802 #define EIO_ERROR ((void *) (return_EIO))
1803
1804 void make_bad_inode(struct inode * inode) {
1805
1806 // In readinode.c JFFS2 checks whether the inode has appropriate
1807 // content for its marked type
1808
1809 D2(printf("make_bad_inode\n"));
1810
1811 inode->i_mode = S_IFREG;
1812 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
1813 inode->i_op = EIO_ERROR;
1814 inode->i_fop = EIO_ERROR;
1815 }
1816
1817 int is_bad_inode(struct inode * inode) {
1818
1819 // Called in super.c jffs2_read_super,
1820 // and gc.c jffs2_garbage_collect_pass
1821
1822 D2(printf("is_bad_inode\n"));
1823
1824 return (inode->i_op == EIO_ERROR);
1825 /*if(i == NULL)
1826 return 1;
1827 return 0;*/
1828 }
1829
1830 cyg_bool jffs2_flash_read(struct jffs2_sb_info *c, cyg_uint32 read_buffer_offset, const size_t size, size_t * return_size, char * write_buffer) {
1831 Cyg_ErrNo err;
1832 cyg_uint32 len = size;
1833 struct super_block *sb = OFNI_BS_2SFFJ( c );
1834
1835 //D2(printf("FLASH READ\n"));
1836 //D2(printf("read address = %x\n", CYGNUM_FS_JFFS2_BASE_ADDRESS + read_buffer_offset));
1837 //D2(printf("write address = %x\n", write_buffer));
1838 //D2(printf("size = %x\n", size));
1839 err = cyg_io_bread( sb->s_dev, write_buffer, &len, read_buffer_offset );
1840
1841 *return_size = (size_t)len;
1842 return ( err != ENOERR );
1843 }
1844
1845 cyg_bool jffs2_flash_write(struct jffs2_sb_info *c, cyg_uint32 write_buffer_offset, const size_t size, size_t * return_size, char * read_buffer) {
1846
1847 Cyg_ErrNo err;
1848 cyg_uint32 len = size;
1849 struct super_block *sb = OFNI_BS_2SFFJ( c );
1850
1851 // D2(printf("FLASH WRITE ENABLED!!!\n"));
1852 // D2(printf("write address = %x\n", CYGNUM_FS_JFFS2_BASE_ADDRESS + write_buffer_offset));
1853 // D2(printf("read address = %x\n", read_buffer));
1854 // D2(printf("size = %x\n", size));
1855
1856 err = cyg_io_bwrite( sb->s_dev, read_buffer, &len, write_buffer_offset );
1857 *return_size = (size_t)len;
1858
1859 return ( err != ENOERR );
1860 }
1861
1862 int
1863 jffs2_flash_writev(struct jffs2_sb_info *c, const struct iovec *vecs,
1864 unsigned long count, loff_t to, size_t *retlen)
1865 {
1866 unsigned long i;
1867 size_t totlen = 0, thislen;
1868 int ret = 0;
1869
1870 for (i=0; i<count; i++) {
1871 // writes need to be aligned but the data we're passed may not be
1872 // Observation suggests most unaligned writes are small, so we
1873 // optimize for that case.
1874
1875 if ( ((vecs[i].iov_len & (sizeof(int)-1))) ||
1876 (((unsigned long)vecs[i].iov_base & (sizeof(unsigned long)-1))) )
1877 {
1878 // are there iov's after this one? Or is it so much we'd need
1879 // to do multiple writes anyway?
1880 if ( (i+1)<count || vecs[i].iov_len > 256 )
1881 {
1882 // cop out and malloc
1883 unsigned long j;
1884 ssize_t sizetomalloc=0, totvecsize=0;
1885 char *cbuf, *cbufptr;
1886
1887 for (j=i;j<count; j++)
1888 totvecsize += vecs[j].iov_len;
1889
1890 // pad up in case unaligned
1891 sizetomalloc = totvecsize + sizeof(int)-1;
1892 sizetomalloc &= ~(sizeof(int)-1);
1893 cbuf = (char *)malloc( sizetomalloc );
1894 // malloc returns aligned memory
1895 if (!cbuf)
1896 {
1897 ret = -ENOMEM;
1898 goto writev_out;
1899 }
1900 cbufptr = cbuf;
1901 for (j=i;j<count; j++)
1902 {
1903 memcpy( cbufptr, vecs[j].iov_base, vecs[j].iov_len );
1904 cbufptr += vecs[j].iov_len;
1905 }
1906 ret = jffs2_flash_write(c, to, sizetomalloc, &thislen, cbuf );
1907 if ( thislen > totvecsize ) // in case it was aligned up
1908 thislen = totvecsize;
1909 totlen += thislen;
1910 free(cbuf);
1911 goto writev_out;
1912 }
1913 else
1914 {
1915 // otherwise optimize for the common case
1916 int buf[256/sizeof(int)]; // int, so int aligned
1917 size_t lentowrite;
1918
1919 lentowrite = vecs[i].iov_len;
1920 // pad up in case its unaligned
1921 lentowrite += sizeof(int)-1;
1922 lentowrite &= ~(sizeof(int)-1);
1923 memcpy( buf, vecs[i].iov_base, lentowrite );
1924
1925 ret = jffs2_flash_write(c, to, lentowrite, &thislen,
1926 (char *)&buf );
1927 if ( thislen > vecs[i].iov_len )
1928 thislen = vecs[i].iov_len;
1929 } // else
1930 }
1931 else
1932 ret = jffs2_flash_write(c, to, vecs[i].iov_len, &thislen,
1933 vecs[i].iov_base);
1934 totlen += thislen;
1935 if (ret || thislen != vecs[i].iov_len)
1936 break;
1937 to += vecs[i].iov_len;
1938 }
1939 writev_out:
1940 if (retlen)
1941 *retlen = totlen;
1942
1943 return ret;
1944 }
1945
1946 cyg_bool jffs2_flash_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) {
1947 cyg_io_flash_getconfig_erase_t e;
1948 void *err_addr;
1949 Cyg_ErrNo err;
1950 cyg_uint32 len = sizeof(e);
1951 struct super_block *sb = OFNI_BS_2SFFJ( c );
1952
1953 e.offset = jeb->offset;
1954 e.len = c->sector_size;
1955 e.err_address = &err_addr;
1956
1957 // D2(printf("FLASH ERASE ENABLED!!!\n"));
1958 // D2(printf("erase address = %x\n", CYGNUM_FS_JFFS2_BASE_ADDRESS + jeb->offset));
1959 // D2(printf("size = %x\n", c->sector_size));
1960
1961 err = cyg_io_get_config( sb->s_dev, CYG_IO_GET_CONFIG_FLASH_ERASE,
1962 &e, &len );
1963
1964 return ( err != ENOERR || e.flasherr != 0 );
1965 }
1966
1967 // -------------------------------------------------------------------------
1968 // EOF jffs2.c