xref: /nrf52832-nimble/rt-thread/components/dfs/filesystems/jffs2/src/fs-ecos.c (revision 104654410c56c573564690304ae786df310c91fc)
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