OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [fs/] [jffs2/] [current/] [src/] [fs-ecos.c] - Blame information for rev 838

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.