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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [fs/] [jffs2/] [v2_0/] [src/] [fs-ecos.c] - Blame information for rev 313

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

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

powered by: WebSVN 2.1.0

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