embox

Форк
0
/
jffs2.c 
1713 строк · 40.0 Кб
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 <dominic.ostrowski@3glab.com>
7
 * Contributors: David Woodhouse, Nick Garnett, Richard Panton.
8
 *
9
 * For licensing information, see the file 'LICENCE' in this directory.
10
 *
11
 * $Id: fs-ecos.c,v 1.44 2005/07/24 15:29:57 dedekind Exp $
12
 *
13
 */
14

15
#include <linux/kernel.h>
16
#include <linux/pagemap.h>
17
#include <linux/crc32.h>
18

19
#include "nodelist.h"
20
#include "compr.h"
21

22
#include <errno.h>
23
#include <string.h>
24

25
#include <stdio.h>
26
#include <stdlib.h>
27
#include <unistd.h>
28
#include <fcntl.h>
29

30
#include <fs/fs_driver.h>
31
#include <fs/super_block.h>
32
#include <fs/dir_context.h>
33
#include <fs/inode_operation.h>
34
#include <fs/vfs.h>
35
#include <fs/inode.h>
36
#include <fs/hlpr_path.h>
37
#include <fs/file_desc.h>
38

39
#include <lib/libds/array.h>
40
#include <util/err.h>
41
#include <embox/unit.h>
42

43
#include <mem/misc/pool.h>
44
#include <mem/phymem.h>
45
#include <mem/sysmalloc.h>
46

47
#include <drivers/block_dev.h>
48
#include <drivers/flash/flash.h>
49
#include <drivers/flash/emulator.h>
50

51
#define FS_NAME "jffs2"
52

53
/* ext filesystem description pool */
54
POOL_DEF(jffs2_fs_pool, struct jffs2_fs_info,
55
		OPTION_GET(NUMBER,jffs2_descriptor_quantity));
56

57
/* ext file description pool */
58
POOL_DEF(jffs2_file_pool, struct jffs2_file_info,
59
		OPTION_GET(NUMBER,inode_quantity));
60

61
static int jffs2fs_iterate(struct inode *next, char *name, struct inode *parent, struct dir_ctx *dir_ctx);
62

63
static int jffs2_free_fs(struct super_block *sb);
64
static int jffs2_read_inode (struct _inode *inode);
65
static void jffs2_clear_inode (struct _inode *inode);
66

67
static int jffs2_truncate_file (struct _inode *inode);
68
static unsigned char gc_buffer[PAGE_CACHE_SIZE];	/*avoids kmalloc when user may be under memory pressure */
69

70
/***********************
71
 * Directory operations
72
 */
73
struct jffs2_dirsearch {
74
	struct _inode *dir;	    	/* directory to search */
75
	const unsigned char *path;  /* path to follow */
76
	struct _inode *node;	    /* Node found */
77
	const unsigned char *name;  /* last name fragment used */
78
	int namelen;		    	/* name fragment length */
79
	bool last;		    		/* last name in path? */
80
};
81

82
typedef struct jffs2_dirsearch jffs2_dirsearch_t;
83

84
/**
85
 * Ref count and nlink management
86
 */
87

88
/**
89
 * FIXME: This seems like real cruft. Wouldn't it be better just to do the
90
 * right thing?
91
 */
92
static void icache_evict(struct _inode *root_i, struct _inode *i) {
93
	struct _inode *this = root_i, *next;
94
	struct _inode *parent;
95

96
 restart:
97
	D2(printf("icache_evict\n"));
98
	/* If this is an absolute search path from the root,
99
	 * remove all cached inodes with i_count of zero (these are only
100
	 * held where needed for dotdot filepaths)
101
	 */
102
	while (this) {
103
		next = this->i_cache_next;
104
		if (this != i && this->i_count == 0) {
105
			parent = this->i_parent;
106
			if (this->i_cache_next) {
107
				this->i_cache_next->i_cache_prev = this->i_cache_prev;
108
			}
109
			if (this->i_cache_prev) {
110
				this->i_cache_prev->i_cache_next = this->i_cache_next;
111
			}
112
			jffs2_clear_inode(this);
113
			memset(this, 0x5a, sizeof(*this));
114
			sysfree(this);
115
			if (parent && parent != this) {
116
				parent->i_count--;
117
				this = root_i;
118
				goto restart;
119
			}
120
		}
121
		this = next;
122
	}
123
}
124

125
/******************************
126
 * Directory search
127
 */
128

129
/**
130
 * Initialize a dirsearch object to start a search
131
 */
132
static void init_dirsearch(jffs2_dirsearch_t * ds,
133
			   struct _inode *dir, const unsigned char *name) {
134
	D2(printf("init_dirsearch name = %s\n", name));
135
	D2(printf("init_dirsearch dir = %#x\n",(unsigned int) dir));
136

137
	dir->i_count++;
138
	ds->dir = dir;
139
	ds->path = name;
140
	ds->node = dir;
141
	ds->name = name;
142
	ds->namelen = 0;
143
	ds->last = false;
144
}
145

146
/**
147
 * Search a single directory for the next name in a path and update the
148
 * dirsearch object appropriately.
149
 */
150
static int find_entry(jffs2_dirsearch_t * ds) {
151
	struct _inode *dir = ds->dir;
152
	const unsigned char *name = ds->path;
153
	const unsigned char *n = name;
154
	char namelen = 0;
155
	struct _inode *d;
156

157
	D2(printf("find_entry\n"));
158

159
	/* check that we really have a directory */
160
	if (!S_ISDIR(dir->i_mode)) {
161
		return ENOTDIR;
162
	}
163
	/* Isolate the next element of the path name. */
164
	while (*n != '\0' && *n != '/') {
165
		n++, namelen++;
166
	}
167
	/* Check if this is the last path element. */
168
	while( *n == '/') {
169
		n++;
170
	}
171
	if (*n == '\0') {
172
		ds->last = true;
173
	}
174

175
	/* update name in dirsearch object */
176
	ds->name = name;
177
	ds->namelen = namelen;
178

179
	if (name[0] == '.') {
180
		switch (namelen) {
181
		default:
182
			break;
183
		case 2:
184
			/* Dot followed by not Dot, treat as any other name */
185
			if (name[1] != '.')
186
				break;
187
			/* Dot Dot
188
			 * Move back up the search path
189
			 */
190
			D2(printf("find_entry found ..\n"));
191
			ds->dir = ds->node;
192
			ds->node = ds->dir->i_parent;
193
			ds->node->i_count++;
194
			return ENOERR;
195
		case 1:
196
			/* Dot is consumed */
197
			D2(printf("find_entry found .\n"));
198
			ds->node = ds->dir;
199
			ds->dir->i_count++;
200
			return ENOERR;
201
		}
202
	}
203

204
	/* Here we have the name and its length set up. */
205
	/* Search the directory for a matching entry */
206

207
	D2(printf("find_entry for name = %s\n", ds->path));
208
	d = jffs2_lookup(dir, name, namelen);
209
	D2(printf("find_entry got dir = %#x\n",(unsigned int) d));
210

211
	if (d == NULL) {
212
		return ENOENT;
213
	}
214
	if (IS_ERR(d)) {
215
		return -PTR_ERR(d);
216
	}
217

218
	/* If it's a new directory inode, increase refcount on its parent */
219
	if (S_ISDIR(d->i_mode) && !d->i_parent) {
220
		d->i_parent = dir;
221
		dir->i_count++;
222
	}
223

224
	/* pass back the node we have found */
225
	ds->node = d;
226
	return ENOERR;
227
}
228

229
/**
230
 * Main interface to directory search code. This is used in all file
231
 * level operations to locate the object named by the pathname.
232
 *
233
 * Returns with use count incremented on both the sought object and
234
 * the directory it was found in
235
 */
236
static int jffs2_find(jffs2_dirsearch_t * d) {
237
	int err;
238

239
	D2(printf("jffs2_find for path =%s\n", d->path));
240

241
	/* Short circuit empty paths */
242
	if (*(d->path) == '\0') {
243
		d->node->i_count++;
244
		return ENOERR;
245
	}
246
	/* skip dirname separators */
247
	while (*(d->path) == '/') {
248
		d->path++;
249
	}
250

251
	/* iterate down directory tree until we find the object we want. */
252
	for (;;) {
253
		err = find_entry(d);
254

255
		if (err != ENOERR) {
256
			return err;
257
		}
258
		if (d->last) {
259
			return ENOERR;
260
		}
261
		/* We're done with it, although it we found a subdir that
262
		 * will have caused the refcount to have been increased
263
		 */
264
		jffs2_iput(d->dir);
265

266
		/* Update dirsearch object to search next directory. */
267
		d->dir = d->node;
268
		d->path += d->namelen;
269
		while (*(d->path) == '/') {
270
			d->path++;	/* skip dirname separators */
271
		}
272
	}
273
}
274

275
/**
276
 * Process a mount request. This mainly creates a root for the
277
 * filesystem.
278
 */
279
static int jffs2_read_super(struct jffs2_super_block *sb) {
280
	struct jffs2_sb_info *c;
281
	int err;
282

283
	D1(printk( "jffs2: read_super\n"));
284

285
	c = &sb->jffs2_sb;
286

287
	c->flash_size = sb->bdev->size < 4096 ? 4096 : sb->bdev->size;
288
	c->sector_size = sb->bdev->block_size < 4096 ? 4096 : sb->bdev->size;
289
	/* Number 4096 is used here beacuse actually there are no real flash
290
	 * drives with less than 4KiB erasable block. But if device is provided
291
	 * with QEMU, than it's just a block device with 512 bytes block size.
292
	 * So, this is generally just for continious testing of OS. If JFFS2
293
	 * will detect block or device size incorrectly, then this device was
294
	 * detected in wrong way on probe. Changing these values will not fix
295
	 * such issue.*/
296

297
	c->cleanmarker_size = sizeof(struct jffs2_unknown_node);
298

299
	err = jffs2_do_mount_fs(c);
300
	if (err) {
301
		return -err;
302
	}
303
	D1(printk( "jffs2_read_super(): Getting root inode\n"));
304
	sb->s_root = jffs2_iget(sb, 1);
305
	if (IS_ERR(sb->s_root)) {
306
		D1(printk(KERN_WARNING "get root inode failed\n"));
307
		err = PTR_ERR(sb->s_root);
308
		sb->s_root = NULL;
309
		goto out_nodes;
310
	}
311

312
	return 0;
313

314
    out_nodes:
315
	jffs2_free_ino_caches(c);
316
	jffs2_free_raw_node_refs(c);
317
	sysfree(c->blocks);
318

319
	return err;
320
}
321

322
static int jffs2_mount(struct inode *dir_node) {
323
	struct jffs2_super_block *jffs2_sb;
324
	struct jffs2_sb_info *c;
325
	int err;
326

327
	struct jffs2_fs_info *fsi;
328

329
	fsi = dir_node->i_sb->sb_data;
330

331
	jffs2_sb = &fsi->jffs2_sb;
332

333
	if (jffs2_sb == NULL) {
334
		return ENOMEM;
335
	}
336

337
	c = &jffs2_sb->jffs2_sb;
338
	memset(jffs2_sb, 0, sizeof (struct jffs2_super_block));
339

340
	jffs2_sb->bdev = dir_node->i_sb->bdev;
341

342
	c->inocache_list = sysmalloc(sizeof(struct jffs2_inode_cache *) * INOCACHE_HASHSIZE);
343
	if (!c->inocache_list) {
344
		return ENOMEM;
345
	}
346
	memset(c->inocache_list, 0, sizeof(struct jffs2_inode_cache *) * INOCACHE_HASHSIZE);
347

348
	spin_init(&c->inocache_lock, __SPIN_UNLOCKED);
349
	spin_init(&c->erase_completion_lock, __SPIN_UNLOCKED);
350

351
	jffs2_compressors_init();
352

353
	err = jffs2_read_super(jffs2_sb);
354

355
	if (err) {
356
		jffs2_compressors_exit();
357

358
		sysfree(c->inocache_list);
359
		return err;
360
	}
361

362
	jffs2_sb->s_root->i_parent = jffs2_sb->s_root;	/* points to itself, no dotdot paths above mountpoint */
363
	jffs2_sb->s_root->i_cache_prev = NULL;	/* root inode, so always null */
364
	jffs2_sb->s_root->i_cache_next = NULL;
365
	jffs2_sb->s_root->i_count = 1;	/* Ensures the root inode is always in ram until umount */
366

367
	D2(printf("jffs2_mount erasing pending blocks\n"));
368
	jffs2_erase_pending_blocks(c, 0);
369

370
#ifdef CYGOPT_FS_JFFS2_GCTHREAD
371
	jffs2_start_garbage_collect_thread(c);
372
#endif
373

374
	D2(printf("jffs2_mounted superblock"));
375

376
	return ENOERR;
377
}
378

379
/**
380
 * Unmount the filesystem.
381
 */
382
static int jffs2_clean_sb(struct super_block *sb) {
383
	struct _inode *root;
384
	struct jffs2_super_block *jffs2_sb;
385
	struct jffs2_fs_info *fsi;
386
	struct jffs2_sb_info *c;
387
	struct jffs2_full_dirent *fd, *next;
388

389
	fsi = sb->sb_data;
390
	jffs2_sb = &fsi->jffs2_sb;
391
	root = jffs2_sb->s_root;
392
	c = &jffs2_sb->jffs2_sb;
393

394
	D2(printf("jffs2_umount\n"));
395

396
	/* Only really umount if this is the only mount */
397
	icache_evict(root, NULL);
398

399
	if (root->i_count != 1) {
400
		printf("Ino #1 has use count %d\n", root->i_count);
401
		return EBUSY;
402
	}
403
#ifdef CYGOPT_FS_JFFS2_GCTHREAD
404
	jffs2_stop_garbage_collect_thread(c);
405
#endif
406
	jffs2_iput(root);	/* Time to free the root inode */
407

408
	/* free directory entries */
409
	for (fd = root->jffs2_i.dents; fd; fd = next) {
410
		next=fd->next;
411
		jffs2_free_full_dirent(fd);
412
	}
413

414
	sysfree(root);
415

416
	/* Clean up the super block and root inode */
417
	jffs2_free_ino_caches(c);
418
	jffs2_free_raw_node_refs(c);
419
	sysfree(c->blocks);
420
	sysfree(c->inocache_list);
421

422
	D2(printf("jffs2_umount No current mounts\n"));
423

424
	jffs2_compressors_exit();
425

426
	jffs2_free_fs(sb);
427

428
	pool_free(&jffs2_file_pool, inode_priv(sb->sb_root));
429

430
	return 0;
431
}
432

433
/**
434
 * Open a file for reading or writing.
435
 */
436
static int jffs2_open(struct _inode *dir_ino, const char *name, int mode) {
437
	jffs2_dirsearch_t ds;
438
	struct _inode *node = NULL;
439
	int err;
440

441
	D2(printf("jffs2_open\n"));
442

443
	if (!dir_ino) {
444
		return ENOENT;
445
	}
446

447
	init_dirsearch(&ds, (struct _inode *) dir_ino,
448
                       (const unsigned char *) name);
449

450
	err = jffs2_find(&ds);
451

452
	if (err == ENOENT) {
453
		if (ds.last && (mode & O_CREAT)) {
454
		/* No node there, if the O_CREAT bit is set then we must
455
		 * create a new one. The dir and name fields of the dirsearch
456
		 * object will have been updated so we know where to put it.
457
		 */
458
			err = jffs2_create(ds.dir, ds.name,
459
					S_IRUGO|S_IXUGO|S_IWUSR|S_IFREG, &node);
460
			if (err != 0) {
461
				/*Possible orphaned inode on the flash - but will be gc'd */
462
				jffs2_iput(ds.dir);
463
				return -err;
464
			}
465
			err = ENOERR;
466
		}
467
	} else if (err == ENOERR) {
468
		/**
469
		 * The node exists. If the O_CREAT and O_EXCL bits are set, we
470
		 * must fail the open.
471
		 */
472
		if ((mode & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
473
			jffs2_iput(ds.node);
474
			err = EEXIST;
475
		} else {
476
			node = ds.node;
477
		}
478
	}
479

480
	/* Finished with the directory now */
481
	jffs2_iput(ds.dir);
482

483
	if (err != ENOERR) {
484
		return err;
485
	}
486
	/* Check that we actually have a file here */
487
	if (S_ISDIR(node->i_mode)) {
488
		jffs2_iput(node);
489
		return EISDIR;
490
	}
491
    /* If the O_TRUNC bit is set we must clean out the file data. */
492
	if (mode & O_TRUNC) {
493
		err = jffs2_truncate_file(node);
494
		if (err) {
495
			jffs2_iput(node);
496
			return err;
497
		}
498
	}
499
	return ENOERR;
500
}
501

502
/**
503
 * Remove a file link from its directory.
504
 */
505
static int jffs2_ops_unlink(struct _inode * dir, const char *name) {
506
	struct jffs2_dirsearch ds;
507
	int err;
508

509
	D2(printf("jffs2_ops_unlink\n"));
510

511
	init_dirsearch(&ds, (struct _inode *) dir,
512
                       (const unsigned char *)name);
513

514
	err = jffs2_find(&ds);
515

516
	if (err != ENOERR) {
517
		jffs2_iput(ds.dir);
518
		return err;
519
	}
520

521
	/*  Cannot unlink directories, use rmdir() instead */
522
	if (S_ISDIR(ds.node->i_mode)) {
523
		jffs2_iput(ds.dir);
524
		jffs2_iput(ds.node);
525
		return EPERM;
526
	}
527

528
	/* Delete it from its directory */
529
	err = jffs2_unlink(ds.dir, ds.node, ds.name);
530
	jffs2_iput(ds.dir);
531
	jffs2_iput(ds.node);
532

533
	return -err;
534
}
535

536
/**
537
 *  Create a new directory.
538
 */
539
static int jffs2_ops_mkdir(struct _inode *dir, const char *name, mode_t mode) {
540
	jffs2_dirsearch_t ds;
541
	int err;
542

543
	D2(printf("jffs2_ops_mkdir\n"));
544

545
	init_dirsearch(&ds, (struct _inode *) dir,
546
                       (const unsigned char *)name);
547

548
	err = jffs2_find(&ds);
549

550
	if (err == ENOENT) {
551
		if (ds.last) {
552
			/* The entry does not exist, and it is the last element in
553
			 * the pathname, so we can create it here.
554
			 */
555
			err = -jffs2_mkdir(ds.dir, ds.name, mode); /*S_IRUGO|S_IXUGO|S_IWUSR); */
556
		}
557
		/* If this was not the last element, then an intermediate
558
		 * directory does not exist.
559
		 */
560
	} else {
561
		/* If there we no error, something already exists with that
562
		 * name, so we cannot create another one.
563
		 */
564
		if (err == ENOERR) {
565
			jffs2_iput(ds.node);
566
			err = EEXIST;
567
		}
568
	}
569
	jffs2_iput(ds.dir);
570
	return err;
571
}
572

573
/**
574
 *  Remove a directory.
575
 */
576
static int jffs2_ops_rmdir(struct _inode * dir, const char *name) {
577
	struct jffs2_dirsearch ds;
578
	int err;
579

580
	D2(printf("jffs2_ops_rmdir\n"));
581

582
	init_dirsearch(&ds, (struct _inode *) dir,
583
                       (const unsigned char *)name);
584

585
	err = jffs2_find(&ds);
586

587
	if (err != ENOERR) {
588
		jffs2_iput(ds.dir);
589
		return err;
590
	}
591

592
	/* Check that this is actually a directory. */
593
	if (!S_ISDIR(ds.node->i_mode)) {
594
		jffs2_iput(ds.dir);
595
		jffs2_iput(ds.node);
596
		return EPERM;
597
	}
598

599
	err = jffs2_rmdir(ds.dir, ds.node, ds.name);
600

601
	jffs2_iput(ds.dir);
602
	jffs2_iput(ds.node);
603
	return -err;
604
}
605

606
/*
607
// -------------------------------------------------------------------------
608
// jffs2_ops_rename()
609
// Rename a file/dir.
610
static int jffs2_ops_rename(cyg_mtab_entry * mte, cyg_dir dir1,
611
			    const char *name1, cyg_dir dir2, const char *name2)
612
{
613
	jffs2_dirsearch ds1, ds2;
614
	int err;
615

616
	D2(printf("jffs2_ops_rename\n"));
617

618
	init_dirsearch(&ds1, (struct _inode *) dir1,
619
                       (const unsigned char *)name1);
620

621
	err = jffs2_find(&ds1);
622

623
	if (err != ENOERR) {
624
		jffs2_iput(ds1.dir);
625
		return err;
626
	}
627

628
	init_dirsearch(&ds2, (struct _inode *) dir2,
629
                       (const unsigned char *)name2);
630

631
	err = jffs2_find(&ds2);
632

633
	// Allow through renames to non-existent objects.
634
	if (ds2.last && err == ENOENT) {
635
		ds2.node = NULL;
636
		err = ENOERR;
637
	}
638

639
	if (err != ENOERR) {
640
		jffs2_iput(ds1.dir);
641
		jffs2_iput(ds1.node);
642
		jffs2_iput(ds2.dir);
643
		return err;
644
	}
645

646
	// Null rename, just return
647
	if (ds1.node == ds2.node) {
648
		err = ENOERR;
649
		goto out;
650
	}
651

652
	// First deal with any entry that is at the destination
653
	if (ds2.node) {
654
		// Check that we are renaming like-for-like
655

656
		if (!S_ISDIR(ds1.node->i_mode) && S_ISDIR(ds2.node->i_mode)) {
657
			err = EISDIR;
658
			goto out;
659
		}
660

661
		if (S_ISDIR(ds1.node->i_mode) && !S_ISDIR(ds2.node->i_mode)) {
662
			err = ENOTDIR;
663
			goto out;
664
		}
665

666
		// Now delete the destination directory entry
667
		// Er, what happened to atomicity of rename()?
668
		err = -jffs2_unlink(ds2.dir, ds2.node, ds2.name);
669

670
		if (err != 0)
671
			goto out;
672

673
	}
674
	// Now we know that there is no clashing node at the destination,
675
	// make a new direntry at the destination and delete the old entry
676
	// at the source.
677

678
	err = -jffs2_rename(ds1.dir, ds1.node, ds1.name, ds2.dir, ds2.name);
679

680
	// Update directory times
681
	if (!err)
682
		ds1.dir->i_ctime =
683
		    ds1.dir->i_mtime =
684
		    ds2.dir->i_ctime = ds2.dir->i_mtime = cyg_timestamp();
685
 out:
686
	jffs2_iput(ds1.dir);
687
	if (S_ISDIR(ds1.node->i_mode)) {
688
//		   Renamed a directory to elsewhere... so fix up its
689
//		   i_parent pointer and the i_counts of its old and
690
//		   new parents.
691
		jffs2_iput(ds1.node->i_parent);
692
		ds1.node->i_parent = ds2.dir;
693
		// We effectively increase its use count by not...
694
	} else {
695
		jffs2_iput(ds2.dir); // ... doing this
696
	}
697
	jffs2_iput(ds1.node);
698
	if (ds2.node)
699
		jffs2_iput(ds2.node);
700

701
	return err;
702
}
703
*/
704

705
/**
706
 * Write data to file.
707
 */
708
static int jffs2_extend_file (struct _inode *inode,
709
		struct jffs2_raw_inode *ri, unsigned long offset) {
710
	struct jffs2_sb_info *c;
711
	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
712
	struct jffs2_full_dnode *fn;
713
	uint32_t phys_ofs, alloc_len;
714
	int ret = 0;
715

716
	c = &inode->i_sb->jffs2_sb;
717

718
	/* Make new hole frag from old EOF to new page */
719
	D1(printk( "Writing new hole frag %#x-%#x between current EOF and new page\n",
720
		  (unsigned int)inode->i_size, (unsigned int)offset));
721

722
	ret = jffs2_reserve_space(c, sizeof(*ri),
723
			&phys_ofs, &alloc_len, ALLOC_NORMAL);
724
	if (ret) {
725
		return ret;
726
	}
727
	down(&f->sem);
728

729
	ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
730
	ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
731
	ri->totlen = cpu_to_je32(sizeof(*ri));
732
	ri->hdr_crc = cpu_to_je32(crc32(0, ri,
733
			sizeof(struct jffs2_unknown_node)-4));
734

735
	ri->version = cpu_to_je32(++f->highest_version);
736
	ri->isize = cpu_to_je32(max((uint32_t)inode->i_size, offset));
737

738
	ri->offset = cpu_to_je32(inode->i_size);
739
	ri->dsize = cpu_to_je32(offset - inode->i_size);
740
	ri->csize = cpu_to_je32(0);
741
	ri->compr = JFFS2_COMPR_ZERO;
742
	ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
743
	ri->data_crc = cpu_to_je32(0);
744

745
	fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL);
746
	jffs2_complete_reservation(c);
747
	if (IS_ERR(fn)) {
748
		ret = PTR_ERR(fn);
749
		up(&f->sem);
750
		return ret;
751
	}
752
	ret = jffs2_add_full_dnode_to_inode(c, f, fn);
753
	if (f->metadata) {
754
		jffs2_mark_node_obsolete(c, f->metadata->raw);
755
		jffs2_free_full_dnode(f->metadata);
756
		f->metadata = NULL;
757
	}
758
	if (ret) {
759
		D1(printk( "Eep. add_full_dnode_to_inode() failed in prepare_write, returned %d\n", ret));
760
		jffs2_mark_node_obsolete(c, fn->raw);
761
		jffs2_free_full_dnode(fn);
762
		up(&f->sem);
763
		return ret;
764
	}
765
	inode->i_size = offset;
766
	up(&f->sem);
767
	return 0;
768
}
769

770
/**
771
 * Truncate a file
772
 */
773
static int jffs2_truncate_file (struct _inode *inode) {
774
     struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
775
     struct jffs2_sb_info *c;
776
     struct jffs2_full_dnode *new_metadata, * old_metadata;
777
     struct jffs2_raw_inode *ri;
778
     uint32_t phys_ofs, alloclen;
779
     int err;
780

781
     ri = jffs2_alloc_raw_inode();
782
     if (!ri) {
783
          return ENOMEM;
784
     }
785
     c = &inode->i_sb->jffs2_sb;
786
     err = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL);
787

788
     if (err) {
789
          jffs2_free_raw_inode(ri);
790
          return err;
791
     }
792
     down(&f->sem);
793
     ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
794
     ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
795
     ri->totlen = cpu_to_je32(sizeof(*ri));
796
     ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
797

798
     ri->ino = cpu_to_je32(inode->i_ino);
799
     ri->version = cpu_to_je32(++f->highest_version);
800

801
     ri->uid = cpu_to_je16(inode->i_uid);
802
     ri->gid = cpu_to_je16(inode->i_gid);
803
     ri->mode = cpu_to_jemode(inode->i_mode);
804
     ri->isize = cpu_to_je32(0);
805
     ri->atime = cpu_to_je32(inode->i_atime);
806
     ri->mtime = cpu_to_je32(timestamp());
807
     ri->offset = cpu_to_je32(0);
808
     ri->csize = ri->dsize = cpu_to_je32(0);
809
     ri->compr = JFFS2_COMPR_NONE;
810
     ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
811
     ri->data_crc = cpu_to_je32(0);
812
     new_metadata = jffs2_write_dnode(c, f, ri, NULL, 0,
813
                                      phys_ofs, ALLOC_NORMAL);
814
	if (IS_ERR(new_metadata)) {
815
		jffs2_complete_reservation(c);
816
		jffs2_free_raw_inode(ri);
817
		up(&f->sem);
818
		return PTR_ERR(new_metadata);
819
	}
820

821
     /* It worked. Update the inode */
822
     inode->i_mtime = timestamp();
823
     inode->i_size = 0;
824
     old_metadata = f->metadata;
825
     jffs2_truncate_fragtree (c, &f->fragtree, 0);
826
     f->metadata = new_metadata;
827
     if (old_metadata) {
828
          jffs2_mark_node_obsolete(c, old_metadata->raw);
829
          jffs2_free_full_dnode(old_metadata);
830
     }
831
     jffs2_free_raw_inode(ri);
832

833
     up(&f->sem);
834
     jffs2_complete_reservation(c);
835

836
     return 0;
837
}
838

839
static int jffs2_fo_write(struct file_desc *desc, char *buf, ssize_t size) {
840
	struct _inode *inode;
841
	off_t pos = file_get_pos(desc);
842
	ssize_t resid = size;
843
	struct jffs2_raw_inode ri;
844
	struct jffs2_inode_info *f;
845
	struct jffs2_sb_info *c;
846
	struct jffs2_file_info *fi;
847

848
	uint32_t writtenlen;
849
	int err;
850
	off_t len;
851

852
	fi = inode_priv(desc->f_inode);
853

854
	inode = fi->_inode;
855
	f = JFFS2_INODE_INFO(inode);
856
	c = &inode->i_sb->jffs2_sb;
857

858
	if (pos < 0) {
859
		SET_ERRNO(EINVAL);
860
		return 0;
861
	}
862

863
	memset(&ri, 0, sizeof(ri));
864

865
	ri.ino = cpu_to_je32(f->inocache->ino);
866
	ri.mode = cpu_to_jemode(inode->i_mode);
867
	ri.uid = cpu_to_je16(inode->i_uid);
868
	ri.gid = cpu_to_je16(inode->i_gid);
869
	ri.atime = ri.ctime = ri.mtime = cpu_to_je32(timestamp());
870

871
	if (pos > inode->i_size) {
872
		ri.version = cpu_to_je32(++f->highest_version);
873
		err = jffs2_extend_file(inode, &ri, pos);
874
		if (err) {
875
			SET_ERRNO(-err);
876
			return 0;
877
		}
878

879
	}
880
	ri.isize = cpu_to_je32(inode->i_size);
881

882
	len = size;
883

884
	D2(printf("jffs2_fo_write page_start_pos %d\n", pos));
885
	D2(printf("jffs2_fo_write transfer size %d\n", len));
886

887
	err = jffs2_write_inode_range(c, f, &ri, (unsigned char *)buf,
888
					  pos, len, &writtenlen);
889

890
	if (err) {
891
		SET_ERRNO(-err);
892
		return 0;
893
	}
894

895
	if (writtenlen != len) {
896
		SET_ERRNO(ENOSPC);
897
		return 0;
898
	}
899

900
	pos += len;
901
	resid -= len;
902

903
	/* We wrote some data successfully, update the modified and access
904
	 * times of the inode, increase its size appropriately, and update
905
	 * the file offset and transfer residue.
906
	 */
907
	inode->i_mtime = inode->i_ctime = je32_to_cpu(ri.mtime);
908
	if (pos > inode->i_size) {
909
		inode->i_size = pos;
910
	}
911

912
	return writtenlen;
913
}
914

915
/**
916
 * Close a file. We just decrement the refcnt and let it go away if
917
 * that is all that is keeping it here.
918
 */
919
static int jffs2_fo_close(struct _inode *node) {
920
	D2(printf("jffs2_fo_close\n"));
921

922
	jffs2_iput(node);
923

924
	return ENOERR;
925
}
926

927
unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c,
928
	struct jffs2_inode_info *f, unsigned long offset, unsigned long *priv) {
929
	/* FIXME: This works only with one file system mounted at a time */
930
	int ret;
931

932
	ret = jffs2_read_inode_range(c, f, gc_buffer,
933
				     offset & ~(PAGE_CACHE_SIZE-1), PAGE_CACHE_SIZE);
934
	if (ret) {
935
		return ERR_PTR(ret);
936
	}
937

938
	return gc_buffer;
939
}
940

941
void jffs2_gc_release_page(struct jffs2_sb_info *c,
942
			   unsigned char *ptr, unsigned long *priv) {
943
	/* Do nothing */
944
}
945

946
static struct _inode *new_inode(struct jffs2_super_block *sb) {
947
	/* Only called in write.c jffs2_new_inode
948
	 * Always adds itself to inode cache	 */
949

950
	struct _inode *inode;
951
	struct _inode *cached_inode;
952

953
	inode = sysmalloc(sizeof (struct _inode));
954
	if (inode == NULL) {
955
		return 0;
956
	}
957

958
	D2(printf
959
	   ("malloc new_inode %x ####################################\n",
960
	    (unsigned int)inode));
961

962
	memset(inode, 0, sizeof (struct _inode));
963
	inode->i_sb = sb;
964
	inode->i_ino = 1;
965
	inode->i_count = 1;
966
	inode->i_nlink = 1;	/* Let JFFS2 manage the link count */
967
	inode->i_size = 0;
968

969
	inode->i_cache_next = NULL;	/* Newest inode, about to be cached */
970

971
	/* Add to the icache */
972
	for (cached_inode = sb->s_root; cached_inode != NULL;
973
	     cached_inode = cached_inode->i_cache_next) {
974
		if (cached_inode->i_cache_next == NULL) {
975
			cached_inode->i_cache_next = inode;	/* Current last in cache points to newcomer */
976
			inode->i_cache_prev = cached_inode;	/* Newcomer points back to last */
977
			break;
978
		}
979
	}
980
	return inode;
981
}
982

983
static struct _inode *ilookup(struct jffs2_super_block *sb, uint32_t ino)
984
{
985
	struct _inode *inode = NULL;
986

987
	D2(printf("ilookup\n"));
988
	/* Check for this inode in the cache */
989
	for (inode = sb->s_root; inode != NULL; inode = inode->i_cache_next) {
990
		if (inode->i_ino == ino) {
991
			inode->i_count++;
992
			break;
993
		}
994
	}
995
	return inode;
996
}
997

998
struct _inode *jffs2_iget(struct jffs2_super_block *sb, uint32_t ino) {
999
	/* Must first check for cached inode
1000
	 * If this fails let new_inode create one
1001
	 */
1002
	struct _inode *inode;
1003
	int err;
1004

1005
	D2(printf("jffs2_iget\n"));
1006

1007
	inode = ilookup(sb, ino);
1008
	if (inode) {
1009
		return inode;
1010
	}
1011

1012
	/* Not cached, so kmalloc it */
1013
	inode = new_inode(sb);
1014
	if (inode == NULL) {
1015
		return ERR_PTR(-ENOMEM);
1016
	}
1017

1018
	inode->i_ino = ino;
1019

1020
	err = jffs2_read_inode(inode);
1021
	if (err) {
1022
		printf("jffs2_read_inode() failed\n");
1023
                inode->i_nlink = 0; /* free _this_ bad inode right now */
1024
		jffs2_iput(inode);
1025
		inode = NULL;
1026
		return ERR_PTR(err);
1027
	}
1028
	return inode;
1029
}
1030

1031
/**
1032
 * Decrement the reference count on an inode. If this makes the ref count
1033
 * zero, then this inode can be freed.
1034
 */
1035
void jffs2_iput(struct _inode *i) {
1036
	struct _inode *parent;
1037

1038
 recurse:
1039
	if (!i) {
1040
		printf("jffs2_iput() called with NULL inode\n");
1041
		/* and let it fault... */
1042
	}
1043

1044
	i->i_count--;
1045

1046
	if (i->i_count < 0) {
1047
		BUG();
1048
	}
1049

1050
	if (i->i_count) {
1051
		return;
1052
	}
1053

1054
	if (!i->i_nlink) {
1055
		/* Remove from the icache linked list and free immediately */
1056
		if (i->i_cache_prev) {
1057
			i->i_cache_prev->i_cache_next = i->i_cache_next;
1058
		}
1059
		if (i->i_cache_next) {
1060
			i->i_cache_next->i_cache_prev = i->i_cache_prev;
1061
		}
1062

1063
		parent = i->i_parent;
1064
		jffs2_clear_inode(i);
1065
		memset(i, 0x5a, sizeof(*i));
1066
		sysfree(i);
1067

1068
		if (parent && parent != i) {
1069
			i = parent;
1070
			goto recurse;
1071
		}
1072

1073
	} else {
1074
	/* Evict some _other_ inode with i_count zero, leaving
1075
	 * this latest one in the cache for a while
1076
	 */
1077
		icache_evict(i->i_sb->s_root, i);
1078
	}
1079
}
1080

1081
static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) {
1082
	memset(f, 0, sizeof(*f));
1083
	init_MUTEX_LOCKED(&f->sem);
1084
}
1085

1086
static void jffs2_clear_inode (struct _inode *inode) {
1087
	/* We can forget about this inode for now - drop all
1088
	*  the nodelists associated with it, etc.
1089
	*/
1090
	struct jffs2_sb_info *c;// = JFFS2_SB_INFO(inode->i_sb);
1091
	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
1092

1093
	c = &inode->i_sb->jffs2_sb;
1094

1095
	D1(printk( "jffs2_clear_inode(): ino #%u mode %o\n", inode->i_ino, inode->i_mode));
1096

1097
	jffs2_do_clear_inode(c, f);
1098
}
1099

1100

1101
/**
1102
 * allocate a new inode and inocache, add it to the hash,
1103
 * fill in the raw_inode while you're at it.
1104
 */
1105
struct _inode *jffs2_new_inode (struct _inode *dir_i,
1106
					int mode, struct jffs2_raw_inode *ri) {
1107
	struct _inode *inode;
1108
	struct jffs2_super_block *sb = dir_i->i_sb;
1109
	struct jffs2_sb_info *c;
1110
	struct jffs2_inode_info *f;
1111
	int ret;
1112

1113
	D1(printk( "jffs2_new_inode(): dir_i %d, mode 0x%x\n", dir_i->i_ino, i_mode));
1114

1115
	c = &sb->jffs2_sb;
1116

1117
	inode = new_inode(sb);
1118

1119
	if (!inode) {
1120
		return ERR_PTR(-ENOMEM);
1121
	}
1122

1123
	f = JFFS2_INODE_INFO(inode);
1124
	jffs2_init_inode_info(f);
1125

1126
	memset(ri, 0, sizeof(*ri));
1127
	/* Set OS-specific defaults for new inodes */
1128
	ri->uid = ri->gid = cpu_to_je16(0);
1129
	ri->mode =  cpu_to_jemode(mode);
1130
	ret = jffs2_do_new_inode (c, f, mode, ri);
1131
	if (ret) {
1132
	/* forceful evict: f->sem is locked already, and the
1133
	 * inode is bad.
1134
	 */
1135
		if (inode->i_cache_prev) {
1136
			inode->i_cache_prev->i_cache_next = inode->i_cache_next;
1137
		}
1138
		if (inode->i_cache_next) {
1139
			inode->i_cache_next->i_cache_prev = inode->i_cache_prev;
1140
		}
1141
		up(&(f->sem));
1142
		jffs2_clear_inode(inode);
1143
		memset(inode, 0x6a, sizeof(*inode));
1144
		sysfree(inode);
1145
		return ERR_PTR(ret);
1146
	}
1147
	inode->i_nlink = 1;
1148
	inode->i_ino = je32_to_cpu(ri->ino);
1149
	inode->i_mode = jemode_to_cpu(ri->mode);
1150
	inode->i_gid = je16_to_cpu(ri->gid);
1151
	inode->i_uid = je16_to_cpu(ri->uid);
1152
	inode->i_atime = inode->i_ctime = inode->i_mtime = timestamp();
1153
	ri->atime = ri->mtime = ri->ctime = cpu_to_je32(inode->i_mtime);
1154

1155
	inode->i_size = 0;
1156

1157
	return inode;
1158
}
1159

1160

1161
static int jffs2_read_inode (struct _inode *inode) {
1162
	struct jffs2_inode_info *f;
1163
	struct jffs2_sb_info *c;
1164
	struct jffs2_raw_inode latest_node;
1165
	int ret;
1166

1167
	D1(printk( "jffs2_read_inode(): inode->i_ino == %d\n", inode->i_ino));
1168

1169
	f = JFFS2_INODE_INFO(inode);
1170
	c = &inode->i_sb->jffs2_sb;
1171

1172
	jffs2_init_inode_info(f);
1173

1174
	ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node);
1175

1176
	if (ret) {
1177
		up(&f->sem);
1178
		return ret;
1179
	}
1180
	inode->i_mode = jemode_to_cpu(latest_node.mode);
1181
	inode->i_uid = je16_to_cpu(latest_node.uid);
1182
	inode->i_gid = je16_to_cpu(latest_node.gid);
1183
	inode->i_size = je32_to_cpu(latest_node.isize);
1184
	inode->i_atime = je32_to_cpu(latest_node.atime);
1185
	inode->i_mtime = je32_to_cpu(latest_node.mtime);
1186
	inode->i_ctime = je32_to_cpu(latest_node.ctime);
1187

1188
	inode->i_nlink = f->inocache->nlink;
1189
	up(&f->sem);
1190

1191
	D1(printk( "jffs2_read_inode() returning\n"));
1192
	return 0;
1193
}
1194

1195

1196
void jffs2_gc_release_inode(struct jffs2_sb_info *c,
1197
				   struct jffs2_inode_info *f) {
1198
	jffs2_iput(OFNI_EDONI_2SFFJ(f));
1199
}
1200

1201
struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
1202
						     int inum, int nlink) {
1203
	struct _inode *inode;
1204
	struct jffs2_inode_cache *ic;
1205
	struct jffs2_super_block *sb;
1206

1207
	sb = member_cast_out(c, struct jffs2_super_block, jffs2_sb);
1208

1209
	if (!nlink) {
1210
	/* The inode has zero nlink but its nodes weren't yet marked
1211
	 * obsolete. This has to be because we're still waiting for
1212
	 * the final (close() and) jffs2_iput() to happen.
1213
	 *
1214
	 * There's a possibility that the final jffs2_iput() could have
1215
	 * happened while we were contemplating. In order to ensure
1216
	 * that we don't cause a new read_inode() (which would fail)
1217
	 * for the inode in question, we use ilookup() in this case
1218
	 * instead of jffs2_iget().
1219
	 *
1220
	 * The nlink can't _become_ zero at this point because we're
1221
	 * holding the alloc_sem, and jffs2_do_unlink() would also
1222
	 * need that while decrementing nlink on any inode.
1223
	 */
1224
		inode = ilookup(sb, inum);
1225
		if (!inode) {
1226
			D1(printk( "ilookup() failed for ino #%u; inode is probably deleted.\n",
1227
				  inum));
1228

1229
			spin_lock(&c->inocache_lock);
1230
			ic = jffs2_get_ino_cache(c, inum);
1231
			if (!ic) {
1232
				D1(printk( "Inode cache for ino #%u is gone.\n", inum));
1233
				spin_unlock(&c->inocache_lock);
1234
				return NULL;
1235
			}
1236
			if (ic->state != INO_STATE_CHECKEDABSENT) {
1237
				/* Wait for progress. Don't just loop */
1238
				D1(printk( "Waiting for ino #%u in state %d\n",
1239
					  ic->ino, ic->state));
1240
				sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
1241
			} else {
1242
				spin_unlock(&c->inocache_lock);
1243
			}
1244

1245
			return NULL;
1246
		}
1247
	} else {
1248
		/* Inode has links to it still; they're not going away because
1249
		 * jffs2_do_unlink() would need the alloc_sem and we have it.
1250
		 * Just jffs2_iget() it, and if read_inode() is necessary that's OK.
1251
		 */
1252
		inode = jffs2_iget(sb, inum);
1253
		if (IS_ERR(inode)) {
1254
			return (void *)inode;
1255
		}
1256
	}
1257

1258
	return JFFS2_INODE_INFO(inode);
1259
}
1260

1261
uint32_t jffs2_from_os_mode(uint32_t osmode) {
1262
	uint32_t jmode = ((osmode & S_IRUSR)?00400:0) |
1263
		((osmode & S_IWUSR)?00200:0) |
1264
		((osmode & S_IXUSR)?00100:0) |
1265
		((osmode & S_IRGRP)?00040:0) |
1266
		((osmode & S_IWGRP)?00020:0) |
1267
		((osmode & S_IXGRP)?00010:0) |
1268
		((osmode & S_IROTH)?00004:0) |
1269
		((osmode & S_IWOTH)?00002:0) |
1270
		((osmode & S_IXOTH)?00001:0);
1271

1272
	switch (osmode & S_IFMT) {
1273
	case S_IFSOCK:
1274
		return jmode | 0140000;
1275
	case S_IFLNK:
1276
		return jmode | 0120000;
1277
	case S_IFREG:
1278
		return jmode | 0100000;
1279
	case S_IFBLK:
1280
		return jmode | 0060000;
1281
	case S_IFDIR:
1282
		return jmode | 0040000;
1283
	case S_IFCHR:
1284
		return jmode | 0020000;
1285
	case S_IFIFO:
1286
		return jmode | 0010000;
1287
	case S_ISUID:
1288
		return jmode | 0004000;
1289
	case S_ISGID:
1290
		return jmode | 0002000;
1291
#ifdef S_ISVTX
1292
	case S_ISVTX:
1293
		return jmode | 0001000;
1294
#endif
1295
	}
1296
	printf("os_to_jffs2_mode() cannot convert 0x%x\n", osmode);
1297
	BUG();
1298
	return 0;
1299
}
1300

1301
uint32_t jffs2_to_os_mode (uint32_t jmode) {
1302
	uint32_t osmode = ((jmode & 00400)?S_IRUSR:0) |
1303
		((jmode & 00200)?S_IWUSR:0) |
1304
		((jmode & 00100)?S_IXUSR:0) |
1305
		((jmode & 00040)?S_IRGRP:0) |
1306
		((jmode & 00020)?S_IWGRP:0) |
1307
		((jmode & 00010)?S_IXGRP:0) |
1308
		((jmode & 00004)?S_IROTH:0) |
1309
		((jmode & 00002)?S_IWOTH:0) |
1310
		((jmode & 00001)?S_IXOTH:0);
1311

1312
	switch(jmode & 00170000) {
1313
	case 0140000:
1314
		return osmode | S_IFSOCK;
1315
	case 0120000:
1316
		return osmode | S_IFLNK;
1317
	case 0100000:
1318
		return osmode | S_IFREG;
1319
	case 0060000:
1320
		return osmode | S_IFBLK;
1321
	case 0040000:
1322
		return osmode | S_IFDIR;
1323
	case 0020000:
1324
		return osmode | S_IFCHR;
1325
	case 0010000:
1326
		return osmode | S_IFIFO;
1327
	case 0004000:
1328
		return osmode | S_ISUID;
1329
	case 0002000:
1330
		return osmode | S_ISGID;
1331
#ifdef S_ISVTX
1332
	case 0001000:
1333
		return osmode | S_ISVTX;
1334
#endif
1335
	}
1336
	printf("jffs2_to_os_mode() cannot convert 0x%x\n", osmode);
1337
	BUG();
1338
	return 0;
1339
}
1340

1341
static struct idesc *jffs2fs_open(struct inode *node, struct idesc *idesc, int __oflag);
1342
static int jffs2fs_close(struct file_desc *desc);
1343
static size_t jffs2fs_read(struct file_desc *desc, void *buf, size_t size);
1344
static size_t jffs2fs_write(struct file_desc *desc, void *buf, size_t size);
1345

1346
static struct file_operations jffs2_fop = {
1347
	.open = jffs2fs_open,
1348
	.close = jffs2fs_close,
1349
	.read = jffs2fs_read,
1350
	.write = jffs2fs_write,
1351
};
1352

1353
/*
1354
 * file_operation
1355
 */
1356
static struct idesc *jffs2fs_open(struct inode *node, struct idesc *idesc, int __oflag) {
1357
	struct jffs2_file_info *fi;
1358
	struct jffs2_fs_info *fsi;
1359
	char path[PATH_MAX];
1360
	int res;
1361

1362
	fi = inode_priv(node);
1363
	fsi = node->i_sb->sb_data;
1364

1365
	file_set_size(file_desc_from_idesc(idesc), fi->_inode->i_size);
1366

1367
	vfs_get_relative_path(node, path, PATH_MAX);
1368

1369
	res = jffs2_open(fsi->jffs2_sb.s_root, path, idesc->idesc_flags);
1370
	if (res) {
1371
		return err2ptr(-res);
1372
	}
1373
	return idesc;
1374
}
1375

1376
static int jffs2fs_close(struct file_desc *desc) {
1377
	struct jffs2_file_info *fi;
1378

1379
	if (NULL == desc) {
1380
		return 0;
1381
	}
1382
	fi = inode_priv(desc->f_inode);
1383
	file_set_size(desc, fi->_inode->i_size);
1384

1385
	return jffs2_fo_close(fi->_inode);
1386
}
1387

1388
static size_t jffs2fs_read(struct file_desc *desc, void *buff, size_t size) {
1389
	int rc;
1390
	struct jffs2_file_info *fi;
1391
	struct jffs2_inode_info *f;
1392
	struct jffs2_sb_info *c;
1393
	size_t len;
1394
	off_t pos;
1395

1396
	pos = file_get_pos(desc);
1397

1398
	fi = inode_priv(desc->f_inode);
1399

1400
	f = JFFS2_INODE_INFO(fi->_inode);
1401
	c = &fi->_inode->i_sb->jffs2_sb;
1402

1403
	len = min(size, fi->_inode->i_size - pos);
1404

1405
	if (0 != (rc = jffs2_read_inode_range(c, f,
1406
			(unsigned char *) buff, pos, len))) {
1407
		SET_ERRNO(rc);
1408
		return 0;
1409
	}
1410

1411
	return len;
1412
}
1413

1414
static size_t jffs2fs_write(struct file_desc *desc, void *buff, size_t size) {
1415
	uint32_t bytecount;
1416
	struct jffs2_file_info *fi;
1417

1418
	fi = inode_priv(desc->f_inode);
1419

1420
	bytecount = jffs2_fo_write(desc, buff, size);
1421

1422
	file_set_size(desc, fi->_inode->i_size);
1423

1424
	return bytecount;
1425
}
1426

1427
static int jffs2_free_fs(struct super_block *sb) {
1428
	struct jffs2_fs_info *fsi = sb->sb_data;
1429

1430
	if (NULL != fsi) {
1431
		pool_free(&jffs2_fs_pool, fsi);
1432
	}
1433

1434
	return 0;
1435
}
1436

1437
static int jffs2fs_format(struct block_dev *bdev, void *priv);
1438
static int jffs2fs_create(struct inode *i_new, struct inode *parent_node, int mode);
1439
//static int jffs2fs_delete(struct inode *dir, struct inode *node);
1440
static int jffs2fs_truncate(struct inode *node, off_t length);
1441
static int jffs2_fill_sb(struct super_block *sb, const char *source);
1442

1443
static struct fs_driver jffs2fs_driver = {
1444
	.name = FS_NAME,
1445
	.format      = jffs2fs_format,
1446
	.fill_sb = jffs2_fill_sb,
1447
	.clean_sb = jffs2_clean_sb,
1448
};
1449

1450
static jffs2_file_info_t *jffs2_fi_alloc(struct inode *i_new, void *fs) {
1451
	jffs2_file_info_t *fi;
1452

1453
	fi = pool_alloc(&jffs2_file_pool);
1454
	if (fi) {
1455
		memset(fi, 0, sizeof(struct jffs2_file_info));
1456
		inode_priv_set(i_new, fi);
1457
		inode_size_set(i_new, 0);
1458
	}
1459

1460
	return fi;
1461
}
1462

1463
static int mount_vfs_dir_enty(struct inode *dir_node) {
1464
	struct jffs2_inode_info *dir_f;
1465
	struct jffs2_full_dirent *fd_list;
1466
	struct _inode *inode = NULL;
1467
	uint32_t ino = 0;
1468
	struct inode *vfs_node;
1469
	struct _inode *dir_i;
1470
	struct jffs2_file_info *fi;
1471

1472
	fi = inode_priv(dir_node);
1473
	dir_i = fi->_inode;
1474

1475
	dir_f = JFFS2_INODE_INFO(dir_i);
1476

1477
	for (fd_list = dir_f->dents; NULL != fd_list; fd_list = fd_list->next) {
1478
		if (fd_list) {
1479
			ino = fd_list->ino;
1480
			if (ino) {
1481
				inode = jffs2_iget(dir_i->i_sb, ino);
1482
				if(NULL == (vfs_node = vfs_subtree_lookup(dir_node,
1483
						(const char *) fd_list->name))) {
1484
					vfs_node = vfs_subtree_create(dir_node,
1485
							(const char *) fd_list->name, inode->i_mode);
1486
					if(NULL == vfs_node) {
1487
						return ENOMEM;
1488
					}
1489
				}
1490

1491
				if (NULL == inode_priv(vfs_node)) {
1492
					if (NULL == (fi = jffs2_fi_alloc(vfs_node, dir_node->i_sb))) {
1493
						inode_priv_set(vfs_node, fi);
1494
						return ENOMEM;
1495
					}
1496
					fi->_inode = inode;
1497
				}
1498

1499
				if(S_ISDIR(vfs_node->i_mode)) {
1500
					mount_vfs_dir_enty(vfs_node);
1501
				}
1502
			}
1503

1504
		}
1505
	}
1506
	return 0;
1507
}
1508

1509
static int jffs2fs_create(struct inode *i_new, struct inode *parent_node, int mode) {
1510
	int rc;
1511
	struct jffs2_file_info *fi, *parents_fi;
1512

1513
	parents_fi = inode_priv(parent_node);
1514

1515
	if (S_ISDIR(i_new->i_mode)) {
1516
		i_new->i_mode |= S_IRUGO|S_IXUGO|S_IWUSR;
1517
		if (0 != (rc = jffs2_ops_mkdir(parents_fi->_inode,
1518
				(const char *) inode_name(i_new), i_new->i_mode))) {
1519
			return -rc;
1520
		}
1521
		/* file info for new dir will be allocate into */
1522
		if (0 != (rc = mount_vfs_dir_enty(parent_node))) {
1523
			return -rc;
1524
		}
1525
	} else {
1526
		if (NULL == (fi = jffs2_fi_alloc(i_new, parent_node->i_sb))) {
1527
				inode_priv_set(i_new, fi);
1528
				return ENOMEM;
1529
			}
1530
		if (0 != (rc = jffs2_create(parents_fi->_inode,
1531
				(const unsigned char *) inode_name(i_new),
1532
								i_new->i_mode, &fi->_inode))) {
1533
			return -rc;
1534
		}
1535
	}
1536
	return 0;
1537
}
1538

1539
static int jffs2fs_delete(struct inode *dir, struct inode *node) {
1540
	int rc;
1541
	struct jffs2_file_info *par_fi, *fi;
1542
#if 0
1543
	struct inode *parent;
1544

1545
	if (NULL == (parent = vfs_subtree_get_parent(node))) {
1546
		rc = ENOENT;
1547
		return -rc;
1548
	}
1549
#endif
1550
	par_fi = inode_priv(dir);
1551
	fi = inode_priv(node);
1552
	if (S_ISDIR(node->i_mode)) {
1553
		if (0 != (rc = jffs2_ops_rmdir(par_fi->_inode,
1554
						(const char *) inode_name(node)))) {
1555
			return -rc;
1556
		}
1557
	} else {
1558
		if (0 != (rc = jffs2_ops_unlink(par_fi->_inode,
1559
						(const char *) inode_name(node)))) {
1560
			return -rc;
1561
		}
1562
	}
1563

1564
	if(NULL != (fi = inode_priv(node))) {
1565
		pool_free(&jffs2_file_pool, fi);
1566
	}
1567

1568
	return 0;
1569
}
1570

1571
static int jffs2fs_format(struct block_dev *bdev, void *priv) {
1572
	char flash_node_name[PATH_MAX];
1573

1574
	snprintf(flash_node_name, PATH_MAX, "%s_flash", block_dev_name(bdev));
1575

1576
	return flash_emu_dev_create(flash_node_name, 16 * 1024, 1024);
1577
}
1578

1579
static int jffs2fs_destroy_inode(struct inode *inode) {
1580
	return 0;
1581
}
1582

1583
static struct super_block_operations jffs2fs_sbops = {
1584
	//.open_idesc    = dvfs_file_open_idesc,
1585
	.destroy_inode = jffs2fs_destroy_inode,
1586
};
1587

1588
struct inode_operations jffs2fs_iops = {
1589
	.ino_create  = jffs2fs_create,
1590
	.ino_remove  = jffs2fs_delete,
1591
	.ino_iterate = jffs2fs_iterate,
1592
	.ino_truncate = jffs2fs_truncate,
1593
};
1594

1595
struct inode *jffs2fs_lookup(char const *name, struct inode const *dir) {
1596
	return NULL;
1597
}
1598

1599
static int jffs2fs_iterate(struct inode *next, char *next_name, struct inode *parent, struct dir_ctx *dir_ctx) {
1600
	struct jffs2_inode_info *dir_f;
1601
	struct jffs2_full_dirent *fd_list;
1602
	struct _inode *inode = NULL;
1603
	uint32_t ino = 0;
1604
	struct _inode *dir_i;
1605
	struct jffs2_file_info *fi;
1606
	int idx = 0;
1607

1608
	fi = inode_priv(parent);
1609
	dir_i = fi->_inode;
1610

1611
	dir_f = JFFS2_INODE_INFO(dir_i);
1612

1613
	for (fd_list = dir_f->dents; NULL != fd_list; fd_list = fd_list->next) {
1614
		if (fd_list) {
1615
			ino = fd_list->ino;
1616
			if (ino) {
1617
				inode = jffs2_iget(dir_i->i_sb, ino);
1618

1619
				if (idx++ < (int)(uintptr_t)dir_ctx->fs_ctx) {
1620
					continue;
1621
				}
1622
				if (NULL == (fi = jffs2_fi_alloc(next, parent->i_sb))) {
1623
					return -1;
1624
				}
1625
				inode_priv_set(next, fi);
1626
				fi->_inode = inode;
1627

1628
				next->i_mode = inode->i_mode;
1629

1630
				next->i_owner_id = inode->i_uid;
1631
				next->i_group_id =  inode->i_gid;
1632
				inode_size_set(next,  inode->i_size);
1633

1634
				strncpy(next_name, (const char *)fd_list->name, NAME_MAX - 1);
1635
				next_name[NAME_MAX - 1] = '\0';
1636

1637
				dir_ctx->fs_ctx = (void *)(uintptr_t)idx;
1638

1639
				return 0;
1640
			}
1641

1642
		}
1643
	}
1644

1645
	return -1;
1646
}
1647

1648
static int jffs2fs_create_root(struct super_block *sb, struct inode *dest) {
1649
	int rc;
1650
	struct jffs2_file_info *fi;
1651
	struct jffs2_fs_info *fsi;
1652

1653
	if (NULL == (fi = pool_alloc(&jffs2_file_pool))) {
1654
		inode_priv_set(dest, fi);
1655
		rc = ENOMEM;
1656
		goto error;
1657
	}
1658
	memset(fi, 0, sizeof(struct jffs2_file_info));
1659

1660
	if (0 != (rc = jffs2_mount(dest))) {
1661
		goto error;
1662
	}
1663

1664
	inode_priv_set(dest, fi);
1665
	fsi = sb->sb_data;
1666
	fi->_inode = fsi->jffs2_sb.s_root;
1667

1668
	return 0;
1669

1670
error:
1671
	jffs2_free_fs(sb);
1672

1673
	return -rc;
1674
}
1675

1676
static int jffs2_fill_sb(struct super_block *sb, const char *source) {
1677
	struct block_dev *bdev;
1678
	struct jffs2_fs_info *fsi;
1679

1680
	bdev = bdev_by_path(source);
1681
	if (bdev == NULL) {
1682
		return -ENODEV;
1683
	}
1684

1685
	sb->bdev = bdev;
1686

1687
	/* allocate this fs info */
1688
	if (NULL == (fsi = pool_alloc(&jffs2_fs_pool))) {
1689
		return -ENOMEM;
1690
	}
1691
	memset(fsi, 0, sizeof(struct jffs2_fs_info));
1692
	sb->sb_data = fsi;
1693
	sb->sb_ops = &jffs2fs_sbops;
1694
	sb->sb_iops = &jffs2fs_iops;
1695
	sb->sb_fops = &jffs2_fop;
1696

1697
	jffs2fs_create_root(sb, sb->sb_root);
1698

1699
	return 0;
1700
}
1701

1702
static int jffs2fs_truncate (struct inode *node, off_t length) {
1703
	struct jffs2_file_info *fi;
1704

1705
	inode_size_set(node, length);
1706

1707
	fi = inode_priv(node);
1708
	jffs2_truncate_file(fi->_inode);
1709

1710
	return 0;
1711
}
1712

1713
DECLARE_FILE_SYSTEM_DRIVER(jffs2fs_driver);
1714

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.