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