source: rtems/cpukit/libfs/src/jffs2/src/fs-rtems.c @ eb77534

4.115
Last change on this file since eb77534 was eb77534, checked in by Sebastian Huber <sebastian.huber@…>, on 02/09/15 at 14:37:00

Filesystem: Delete unused fsmountme_h handler

  • Property mode set to 100644
File size: 41.3 KB
Line 
1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright © 2001-2003 Free Software Foundation, Inc.
5 * Copyright © 2001-2007 Red Hat, Inc.
6 * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
7 * Copyright © 2013 embedded brains GmbH <rtems@embedded-brains.de>
8 *
9 * Created by Dominic Ostrowski <dominic.ostrowski@3glab.com>
10 * Contributors: David Woodhouse, Nick Garnett, Richard Panton.
11 *
12 * Port to the RTEMS by embedded brains GmbH.
13 *
14 * For licensing information, see the file 'LICENCE' in this directory.
15 *
16 * $Id: fs-ecos.c,v 1.44 2005/07/24 15:29:57 dedekind Exp $
17 *
18 */
19
20#include <linux/kernel.h>
21#include "nodelist.h"
22#include <linux/pagemap.h>
23#include <linux/crc32.h>
24#include "compr.h"
25#include <errno.h>
26#include <string.h>
27#include <assert.h>
28#include <rtems/libio.h>
29#include <rtems/libio_.h>
30
31/* Ensure that the JFFS2 values are identical to the POSIX defines */
32
33RTEMS_STATIC_ASSERT(DT_DIR == (S_IFDIR >> 12), DT_DIR);
34RTEMS_STATIC_ASSERT(DT_LNK == (S_IFLNK >> 12), DT_LNK);
35RTEMS_STATIC_ASSERT(DT_REG == (S_IFREG >> 12), DT_REG);
36
37RTEMS_STATIC_ASSERT(00400 == S_IRUSR, S_IRUSR);
38RTEMS_STATIC_ASSERT(00200 == S_IWUSR, S_IWUSR);
39RTEMS_STATIC_ASSERT(00100 == S_IXUSR, S_IXUSR);
40RTEMS_STATIC_ASSERT(00040 == S_IRGRP, S_IRGRP);
41RTEMS_STATIC_ASSERT(00020 == S_IWGRP, S_IWGRP);
42RTEMS_STATIC_ASSERT(00010 == S_IXGRP, S_IXGRP);
43RTEMS_STATIC_ASSERT(00004 == S_IROTH, S_IROTH);
44RTEMS_STATIC_ASSERT(00002 == S_IWOTH, S_IWOTH);
45RTEMS_STATIC_ASSERT(00001 == S_IXOTH, S_IXOTH);
46
47RTEMS_STATIC_ASSERT(0140000 == S_IFSOCK, S_IFSOCK);
48RTEMS_STATIC_ASSERT(0120000 == S_IFLNK, S_IFLNK);
49RTEMS_STATIC_ASSERT(0100000 == S_IFREG, S_IFREG);
50RTEMS_STATIC_ASSERT(0060000 == S_IFBLK, S_IFBLK);
51RTEMS_STATIC_ASSERT(0040000 == S_IFDIR, S_IFDIR);
52RTEMS_STATIC_ASSERT(0020000 == S_IFCHR, S_IFCHR);
53RTEMS_STATIC_ASSERT(0010000 == S_IFIFO, S_IFIFO);
54RTEMS_STATIC_ASSERT(0004000 == S_ISUID, S_ISUID);
55RTEMS_STATIC_ASSERT(0002000 == S_ISGID, S_ISGID);
56RTEMS_STATIC_ASSERT(0001000 == S_ISVTX, S_ISVTX);
57
58static int jffs2_read_inode (struct _inode *inode);
59static void jffs2_clear_inode (struct _inode *inode);
60
61//==========================================================================
62// Ref count and nlink management
63
64
65// FIXME: This seems like real cruft. Wouldn't it be better just to do the
66// right thing?
67static void icache_evict(struct _inode *root_i, struct _inode *i)
68{
69        struct _inode *this = root_i, *next;
70
71 restart:
72        D2(printf("icache_evict\n"));
73        // If this is an absolute search path from the root,
74        // remove all cached inodes with i_count of zero (these are only
75        // held where needed for dotdot filepaths)
76        while (this) {
77                next = this->i_cache_next;
78                if (this != i && this->i_count == 0) {
79                        struct _inode *parent = this->i_parent;
80                        if (this->i_cache_next)
81                                this->i_cache_next->i_cache_prev = this->i_cache_prev;
82                        if (this->i_cache_prev)
83                                this->i_cache_prev->i_cache_next = this->i_cache_next;
84                        jffs2_clear_inode(this);
85                        memset(this, 0x5a, sizeof(*this));
86                        free(this);
87                        if (parent && parent != this) {
88                                parent->i_count--;
89                                this = root_i;
90                                goto restart;
91                        }
92                }
93                this = next;
94        }
95}
96
97// -------------------------------------------------------------------------
98// jffs2_fo_write()
99// Write data to file.
100static int jffs2_extend_file (struct _inode *inode, struct jffs2_raw_inode *ri,
101                       unsigned long offset)
102{
103        struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
104        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
105        struct jffs2_full_dnode *fn;
106        uint32_t alloc_len;
107        int ret = 0;
108
109        /* Make new hole frag from old EOF to new page */
110        D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",
111                  (unsigned int)inode->i_size, offset));
112
113        ret = jffs2_reserve_space(c, sizeof(*ri), &alloc_len, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
114        if (ret)
115                return ret;
116
117        mutex_lock(&f->sem);
118
119        ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
120        ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
121        ri->totlen = cpu_to_je32(sizeof(*ri));
122        ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
123
124        ri->version = cpu_to_je32(++f->highest_version);
125        ri->isize = cpu_to_je32(max((uint32_t)inode->i_size, offset));
126
127        ri->offset = cpu_to_je32(inode->i_size);
128        ri->dsize = cpu_to_je32(offset - inode->i_size);
129        ri->csize = cpu_to_je32(0);
130        ri->compr = JFFS2_COMPR_ZERO;
131        ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
132        ri->data_crc = cpu_to_je32(0);
133               
134        fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL);
135        jffs2_complete_reservation(c);
136        if (IS_ERR(fn)) {
137                ret = PTR_ERR(fn);
138                mutex_unlock(&f->sem);
139                return ret;
140        }
141        ret = jffs2_add_full_dnode_to_inode(c, f, fn);
142        if (f->metadata) {
143                jffs2_mark_node_obsolete(c, f->metadata->raw);
144                jffs2_free_full_dnode(f->metadata);
145                f->metadata = NULL;
146        }
147        if (ret) {
148                D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in prepare_write, returned %d\n", ret));
149                jffs2_mark_node_obsolete(c, fn->raw);
150                jffs2_free_full_dnode(fn);
151                mutex_unlock(&f->sem);
152                return ret;
153        }
154        inode->i_size = offset;
155        mutex_unlock(&f->sem);
156        return 0;
157}
158
159static int jffs2_do_setattr (struct _inode *inode, struct iattr *iattr)
160{
161        struct jffs2_full_dnode *old_metadata, *new_metadata;
162        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
163        struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
164        struct jffs2_raw_inode *ri;
165        unsigned char *mdata = NULL;
166        int mdatalen = 0;
167        unsigned int ivalid;
168        uint32_t alloclen;
169        int ret;
170        int alloc_type = ALLOC_NORMAL;
171
172        jffs2_dbg(1, "%s(): ino #%lu\n", __func__, inode->i_ino);
173
174        /* Special cases - we don't want more than one data node
175           for these types on the medium at any time. So setattr
176           must read the original data associated with the node
177           (i.e. the device numbers or the target name) and write
178           it out again with the appropriate data attached */
179        if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
180                return -EIO;
181        } else if (S_ISLNK(inode->i_mode)) {
182                mutex_lock(&f->sem);
183                mdatalen = f->metadata->size;
184                mdata = kmalloc(f->metadata->size, GFP_USER);
185                if (!mdata) {
186                        mutex_unlock(&f->sem);
187                        return -ENOMEM;
188                }
189                ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen);
190                if (ret) {
191                        mutex_unlock(&f->sem);
192                        kfree(mdata);
193                        return ret;
194                }
195                mutex_unlock(&f->sem);
196                jffs2_dbg(1, "%s(): Writing %d bytes of symlink target\n",
197                          __func__, mdatalen);
198        }
199
200        ri = jffs2_alloc_raw_inode();
201        if (!ri) {
202                if (S_ISLNK(inode->i_mode))
203                        kfree(mdata);
204                return -ENOMEM;
205        }
206
207        ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &alloclen,
208                                  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
209        if (ret) {
210                jffs2_free_raw_inode(ri);
211                if (S_ISLNK(inode->i_mode))
212                         kfree(mdata);
213                return ret;
214        }
215        mutex_lock(&f->sem);
216        ivalid = iattr->ia_valid;
217
218        ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
219        ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
220        ri->totlen = cpu_to_je32(sizeof(*ri) + mdatalen);
221        ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
222
223        ri->ino = cpu_to_je32(inode->i_ino);
224        ri->version = cpu_to_je32(++f->highest_version);
225
226        ri->uid = cpu_to_je16((ivalid & ATTR_UID)?
227                from_kuid(&init_user_ns, iattr->ia_uid):i_uid_read(inode));
228        ri->gid = cpu_to_je16((ivalid & ATTR_GID)?
229                from_kgid(&init_user_ns, iattr->ia_gid):i_gid_read(inode));
230
231        if (ivalid & ATTR_MODE)
232                ri->mode = cpu_to_jemode(iattr->ia_mode);
233        else
234                ri->mode = cpu_to_jemode(inode->i_mode);
235
236
237        ri->isize = cpu_to_je32((ivalid & ATTR_SIZE)?iattr->ia_size:inode->i_size);
238        ri->atime = cpu_to_je32(I_SEC((ivalid & ATTR_ATIME)?iattr->ia_atime:inode->i_atime));
239        ri->mtime = cpu_to_je32(I_SEC((ivalid & ATTR_MTIME)?iattr->ia_mtime:inode->i_mtime));
240        ri->ctime = cpu_to_je32(I_SEC((ivalid & ATTR_CTIME)?iattr->ia_ctime:inode->i_ctime));
241
242        ri->offset = cpu_to_je32(0);
243        ri->csize = ri->dsize = cpu_to_je32(mdatalen);
244        ri->compr = JFFS2_COMPR_NONE;
245        if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) {
246                /* It's an extension. Make it a hole node */
247                ri->compr = JFFS2_COMPR_ZERO;
248                ri->dsize = cpu_to_je32(iattr->ia_size - inode->i_size);
249                ri->offset = cpu_to_je32(inode->i_size);
250        } else if (ivalid & ATTR_SIZE && !iattr->ia_size) {
251                /* For truncate-to-zero, treat it as deletion because
252                   it'll always be obsoleting all previous nodes */
253                alloc_type = ALLOC_DELETION;
254        }
255        ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
256        if (mdatalen)
257                ri->data_crc = cpu_to_je32(crc32(0, mdata, mdatalen));
258        else
259                ri->data_crc = cpu_to_je32(0);
260
261        new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, alloc_type);
262        if (S_ISLNK(inode->i_mode))
263                kfree(mdata);
264
265        if (IS_ERR(new_metadata)) {
266                jffs2_complete_reservation(c);
267                jffs2_free_raw_inode(ri);
268                mutex_unlock(&f->sem);
269                return PTR_ERR(new_metadata);
270        }
271        /* It worked. Update the inode */
272        inode->i_atime = ITIME(je32_to_cpu(ri->atime));
273        inode->i_ctime = ITIME(je32_to_cpu(ri->ctime));
274        inode->i_mtime = ITIME(je32_to_cpu(ri->mtime));
275        inode->i_mode = jemode_to_cpu(ri->mode);
276        i_uid_write(inode, je16_to_cpu(ri->uid));
277        i_gid_write(inode, je16_to_cpu(ri->gid));
278
279
280        old_metadata = f->metadata;
281
282        if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size)
283                jffs2_truncate_fragtree (c, &f->fragtree, iattr->ia_size);
284
285        if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) {
286                jffs2_add_full_dnode_to_inode(c, f, new_metadata);
287                inode->i_size = iattr->ia_size;
288                f->metadata = NULL;
289        } else {
290                f->metadata = new_metadata;
291        }
292        if (old_metadata) {
293                jffs2_mark_node_obsolete(c, old_metadata->raw);
294                jffs2_free_full_dnode(old_metadata);
295        }
296        jffs2_free_raw_inode(ri);
297
298        mutex_unlock(&f->sem);
299        jffs2_complete_reservation(c);
300
301        /* We have to do the truncate_setsize() without f->sem held, since
302           some pages may be locked and waiting for it in readpage().
303           We are protected from a simultaneous write() extending i_size
304           back past iattr->ia_size, because do_truncate() holds the
305           generic inode semaphore. */
306        if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) {
307                truncate_setsize(inode, iattr->ia_size);
308        }       
309
310        return 0;
311}
312
313typedef struct {
314        struct super_block sb;
315        struct jffs2_inode_cache *inode_cache[];
316} rtems_jffs2_fs_info;
317
318static void rtems_jffs2_do_lock(const struct super_block *sb)
319{
320        rtems_status_code sc = rtems_semaphore_obtain(sb->s_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
321        assert(sc == RTEMS_SUCCESSFUL);
322        (void) sc; /* avoid unused variable warning */
323}
324
325static void rtems_jffs2_do_unlock(const struct super_block *sb)
326{
327        rtems_status_code sc = rtems_semaphore_release(sb->s_mutex);
328        assert(sc == RTEMS_SUCCESSFUL);
329        (void) sc; /* avoid unused variable warning */
330}
331
332static void rtems_jffs2_free_directory_entries(struct _inode *inode)
333{
334        struct jffs2_full_dirent *current = inode->jffs2_i.dents;
335
336        while (current != NULL) {
337                struct jffs2_full_dirent *victim = current;
338
339                current = victim->next;
340                jffs2_free_full_dirent(victim);
341        }
342}
343
344static void rtems_jffs2_flash_control_destroy(rtems_jffs2_flash_control *fc)
345{
346        if (fc->destroy != NULL) {
347                (*fc->destroy)(fc);
348        }
349}
350static void rtems_jffs2_compressor_control_destroy(rtems_jffs2_compressor_control *cc)
351{
352        if (cc != NULL && cc->destroy != NULL) {
353                (*cc->destroy)(cc);
354        }
355}
356
357
358static void rtems_jffs2_free_fs_info(rtems_jffs2_fs_info *fs_info, bool do_mount_fs_was_successful)
359{
360        struct super_block *sb = &fs_info->sb;
361        struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
362
363        if (do_mount_fs_was_successful) {
364                jffs2_free_ino_caches(c);
365                jffs2_free_raw_node_refs(c);
366                free(c->blocks);
367        }
368
369        if (sb->s_mutex != 0) {
370                rtems_status_code sc = rtems_semaphore_delete(sb->s_mutex);
371                assert(sc == RTEMS_SUCCESSFUL);
372                (void) sc; /* avoid unused variable warning */
373        }
374
375        rtems_jffs2_flash_control_destroy(fs_info->sb.s_flash_control);
376        rtems_jffs2_compressor_control_destroy(fs_info->sb.s_compressor_control);
377
378        free(fs_info);
379}
380
381static int rtems_jffs2_eno_to_rv_and_errno(int eno)
382{
383        if (eno == 0) {
384                return 0;
385        } else {
386                errno = eno;
387
388                return -1;
389        }
390}
391
392static struct _inode *rtems_jffs2_get_inode_by_location(
393        const rtems_filesystem_location_info_t *loc
394)
395{
396        return loc->node_access;
397}
398
399static struct _inode *rtems_jffs2_get_inode_by_iop(
400        const rtems_libio_t *iop
401)
402{
403        return iop->pathinfo.node_access;
404}
405
406static int rtems_jffs2_fstat(
407        const rtems_filesystem_location_info_t *loc,
408        struct stat *buf
409)
410{
411        struct _inode *inode = rtems_jffs2_get_inode_by_location(loc);
412        struct super_block *sb = inode->i_sb;
413        rtems_jffs2_flash_control *fc = sb->s_flash_control;
414
415        rtems_jffs2_do_lock(sb);
416
417        buf->st_dev = fc->device_identifier;
418        buf->st_blksize = PAGE_SIZE;
419        buf->st_mode = inode->i_mode;
420        buf->st_ino = inode->i_ino;
421        buf->st_nlink = inode->i_nlink;
422        buf->st_uid = inode->i_uid;
423        buf->st_gid = inode->i_gid;
424        buf->st_size = inode->i_size;
425        buf->st_atime = inode->i_atime;
426        buf->st_mtime = inode->i_mtime;
427        buf->st_ctime = inode->i_ctime;
428
429        rtems_jffs2_do_unlock(sb);
430
431        return 0;
432}
433
434static int rtems_jffs2_fill_dirent(struct dirent *de, off_t off, uint32_t ino, const char *name)
435{
436        int eno = 0;
437        size_t len;
438
439        memset(de, 0, sizeof(*de));
440
441        de->d_off = off * sizeof(*de);
442        de->d_reclen = sizeof(*de);
443        de->d_ino = ino;
444
445        len = strlen(name);
446        de->d_namlen = len;
447
448        if (len < sizeof(de->d_name) - 1) {
449                memcpy(&de->d_name[0], name, len);
450        } else {
451                eno = EOVERFLOW;
452        }
453
454        return eno;
455}
456
457static ssize_t rtems_jffs2_dir_read(rtems_libio_t *iop, void *buf, size_t len)
458{
459        struct _inode *inode = rtems_jffs2_get_inode_by_iop(iop);
460        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
461        struct dirent *de = buf;
462        off_t fd_off = 2;
463        int eno = 0;
464        struct jffs2_full_dirent *fd;
465        off_t begin;
466        off_t end;
467        off_t off;
468
469        rtems_jffs2_do_lock(inode->i_sb);
470
471        fd = f->dents;
472        begin = iop->offset;
473        end = begin + len / sizeof(*de);
474        off = begin;
475
476        if (off == 0 && off < end) {
477                eno = rtems_jffs2_fill_dirent(de, off, inode->i_ino, ".");
478                assert(eno == 0);
479                ++off;
480                ++de;
481        }
482
483        if (off == 1 && off < end) {
484                eno = rtems_jffs2_fill_dirent(de, off, inode->i_parent->i_ino, "..");
485                assert(eno == 0);
486                ++off;
487                ++de;
488        }
489
490        while (eno == 0 && off < end && fd != NULL) {
491                if (fd->ino != 0) {
492                        if (off == fd_off) {
493                                eno = rtems_jffs2_fill_dirent(de, off, fd->ino, fd->name);
494                                ++off;
495                                ++de;
496                        }
497
498                        ++fd_off;
499                }
500
501                fd = fd->next;
502        }
503
504        rtems_jffs2_do_unlock(inode->i_sb);
505
506        if (eno == 0) {
507                iop->offset = off;
508
509                return (off - begin) * sizeof(*de);
510        } else {
511                return rtems_jffs2_eno_to_rv_and_errno(eno);
512        }
513}
514
515static const rtems_filesystem_file_handlers_r rtems_jffs2_directory_handlers = {
516        .open_h = rtems_filesystem_default_open,
517        .close_h = rtems_filesystem_default_close,
518        .read_h = rtems_jffs2_dir_read,
519        .write_h = rtems_filesystem_default_write,
520        .ioctl_h = rtems_filesystem_default_ioctl,
521        .lseek_h = rtems_filesystem_default_lseek_directory,
522        .fstat_h = rtems_jffs2_fstat,
523        .ftruncate_h = rtems_filesystem_default_ftruncate_directory,
524        .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
525        .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
526        .fcntl_h = rtems_filesystem_default_fcntl,
527        .kqfilter_h = rtems_filesystem_default_kqfilter,
528        .poll_h = rtems_filesystem_default_poll,
529        .readv_h = rtems_filesystem_default_readv,
530        .writev_h = rtems_filesystem_default_writev
531};
532
533static ssize_t rtems_jffs2_file_read(rtems_libio_t *iop, void *buf, size_t len)
534{
535        struct _inode *inode = rtems_jffs2_get_inode_by_iop(iop);
536        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
537        struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
538        int err = 0;
539        off_t pos;
540
541        rtems_jffs2_do_lock(inode->i_sb);
542
543        pos = iop->offset;
544
545        if (pos >= inode->i_size) {
546                len = 0;
547        } else {
548                uint32_t pos_32 = (uint32_t) pos;
549                uint32_t max_available = inode->i_size - pos_32;
550
551                if (len > max_available) {
552                        len = max_available;
553                }
554
555                err = jffs2_read_inode_range(c, f, buf, pos_32, len);
556        }
557
558        if (err == 0) {
559                iop->offset += len;
560        }
561
562        rtems_jffs2_do_unlock(inode->i_sb);
563
564        if (err == 0) {
565                return (ssize_t) len;
566        } else {
567                errno = -err;
568
569                return -1;
570        }
571}
572
573static ssize_t rtems_jffs2_file_write(rtems_libio_t *iop, const void *buf, size_t len)
574{
575        struct _inode *inode = rtems_jffs2_get_inode_by_iop(iop);
576        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
577        struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
578        struct jffs2_raw_inode ri;
579        uint32_t writtenlen;
580        off_t pos;
581        int eno = 0;
582
583        memset(&ri, 0, sizeof(ri));
584
585        ri.ino = cpu_to_je32(f->inocache->ino);
586        ri.mode = cpu_to_jemode(inode->i_mode);
587        ri.uid = cpu_to_je16(inode->i_uid);
588        ri.gid = cpu_to_je16(inode->i_gid);
589        ri.atime = ri.ctime = ri.mtime = cpu_to_je32(get_seconds());
590
591        rtems_jffs2_do_lock(inode->i_sb);
592
593        if ((iop->flags & LIBIO_FLAGS_APPEND) == 0) {
594                pos = iop->offset;
595        } else {
596                pos = inode->i_size;
597        }
598
599        if (pos > inode->i_size) {
600                ri.version = cpu_to_je32(++f->highest_version);
601                eno = -jffs2_extend_file(inode, &ri, pos);
602        }
603
604        if (eno == 0) {
605                ri.isize = cpu_to_je32(inode->i_size);
606
607                eno = -jffs2_write_inode_range(c, f, &ri, (void *) buf, pos, len, &writtenlen);
608        }
609
610        if (eno == 0) {
611                pos += writtenlen;
612
613                inode->i_mtime = inode->i_ctime = je32_to_cpu(ri.mtime);
614
615                if (pos > inode->i_size) {
616                        inode->i_size = pos;
617                }
618
619                iop->offset = pos;
620
621                if (writtenlen != len) {
622                        eno = ENOSPC;
623                }
624        }
625
626        rtems_jffs2_do_unlock(inode->i_sb);
627
628        if (eno == 0) {
629                return writtenlen;
630        } else {
631                errno = eno;
632
633                return -1;
634        }
635}
636
637static int rtems_jffs2_file_ftruncate(rtems_libio_t *iop, off_t length)
638{
639        struct _inode *inode = rtems_jffs2_get_inode_by_iop(iop);
640        struct iattr iattr;
641        int eno;
642
643        iattr.ia_valid = ATTR_SIZE | ATTR_MTIME | ATTR_CTIME;
644        iattr.ia_size = length;
645        iattr.ia_mtime = get_seconds();
646        iattr.ia_ctime = iattr.ia_mtime;
647
648        rtems_jffs2_do_lock(inode->i_sb);
649
650        eno = -jffs2_do_setattr(inode, &iattr);
651
652        rtems_jffs2_do_unlock(inode->i_sb);
653
654        return rtems_jffs2_eno_to_rv_and_errno(eno);
655}
656
657static const rtems_filesystem_file_handlers_r rtems_jffs2_file_handlers = {
658        .open_h = rtems_filesystem_default_open,
659        .close_h = rtems_filesystem_default_close,
660        .read_h = rtems_jffs2_file_read,
661        .write_h = rtems_jffs2_file_write,
662        .ioctl_h = rtems_filesystem_default_ioctl,
663        .lseek_h = rtems_filesystem_default_lseek_file,
664        .fstat_h = rtems_jffs2_fstat,
665        .ftruncate_h = rtems_jffs2_file_ftruncate,
666        .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
667        .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
668        .fcntl_h = rtems_filesystem_default_fcntl,
669        .kqfilter_h = rtems_filesystem_default_kqfilter,
670        .poll_h = rtems_filesystem_default_poll,
671        .readv_h = rtems_filesystem_default_readv,
672        .writev_h = rtems_filesystem_default_writev
673};
674
675static const rtems_filesystem_file_handlers_r rtems_jffs2_link_handlers = {
676        .open_h = rtems_filesystem_default_open,
677        .close_h = rtems_filesystem_default_close,
678        .read_h = rtems_filesystem_default_read,
679        .write_h = rtems_filesystem_default_write,
680        .ioctl_h = rtems_filesystem_default_ioctl,
681        .lseek_h = rtems_filesystem_default_lseek,
682        .fstat_h = rtems_jffs2_fstat,
683        .ftruncate_h = rtems_filesystem_default_ftruncate,
684        .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
685        .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
686        .fcntl_h = rtems_filesystem_default_fcntl,
687        .kqfilter_h = rtems_filesystem_default_kqfilter,
688        .poll_h = rtems_filesystem_default_poll,
689        .readv_h = rtems_filesystem_default_readv,
690        .writev_h = rtems_filesystem_default_writev
691};
692
693static void rtems_jffs2_set_location(rtems_filesystem_location_info_t *loc, struct _inode *inode)
694{
695        loc->node_access = inode;
696
697        switch (inode->i_mode & S_IFMT) {
698                case S_IFREG:
699                        loc->handlers = &rtems_jffs2_file_handlers;
700                        break;
701                case S_IFDIR:
702                        loc->handlers = &rtems_jffs2_directory_handlers;
703                        break;
704                case S_IFLNK:
705                        loc->handlers = &rtems_jffs2_link_handlers;
706                        break;
707                default:
708                        loc->handlers = &rtems_filesystem_null_handlers;
709                        break;
710        };
711}
712
713static bool rtems_jffs2_eval_is_directory(
714        rtems_filesystem_eval_path_context_t *ctx,
715        void *arg
716)
717{
718        rtems_filesystem_location_info_t *currentloc =
719                rtems_filesystem_eval_path_get_currentloc(ctx);
720        struct _inode *inode = rtems_jffs2_get_inode_by_location(currentloc);
721
722        return S_ISDIR(inode->i_mode);
723}
724
725static rtems_filesystem_eval_path_generic_status rtems_jffs2_eval_token(
726        rtems_filesystem_eval_path_context_t *ctx,
727        void *arg,
728        const char *token,
729        size_t tokenlen
730)
731{
732        rtems_filesystem_eval_path_generic_status status =
733                RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
734        rtems_filesystem_location_info_t *currentloc =
735                rtems_filesystem_eval_path_get_currentloc(ctx);
736        struct _inode *dir_i = rtems_jffs2_get_inode_by_location(currentloc);
737        bool access_ok = rtems_filesystem_eval_path_check_access(
738                ctx,
739                RTEMS_FS_PERMS_EXEC,
740                dir_i->i_mode,
741                dir_i->i_uid,
742                dir_i->i_gid
743        );
744
745        if (access_ok) {
746                struct _inode *entry_i;
747
748                if (rtems_filesystem_is_current_directory(token, tokenlen)) {
749                        entry_i = dir_i;
750                        ++entry_i->i_count;
751                } else if (rtems_filesystem_is_parent_directory(token, tokenlen)) {
752                        entry_i = dir_i->i_parent;
753                        ++entry_i->i_count;
754                } else {
755                        entry_i = jffs2_lookup(dir_i, token, (int) tokenlen);
756                }
757
758                if (IS_ERR(entry_i)) {
759                        rtems_filesystem_eval_path_error(ctx, PTR_ERR(entry_i));
760                } else if (entry_i != NULL) {
761                        bool terminal = !rtems_filesystem_eval_path_has_path(ctx);
762                        int eval_flags = rtems_filesystem_eval_path_get_flags(ctx);
763                        bool follow_sym_link = (eval_flags & RTEMS_FS_FOLLOW_SYM_LINK) != 0;
764
765                        rtems_filesystem_eval_path_clear_token(ctx);
766
767                        if (S_ISLNK(entry_i->i_mode) && (follow_sym_link || !terminal)) {
768                                struct jffs2_inode_info *f = JFFS2_INODE_INFO(entry_i);
769                                const char *target = f->target;
770
771                                rtems_filesystem_eval_path_recursive(ctx, target, strlen(target));
772
773                                jffs2_iput(entry_i);
774                        } else {
775                                if (S_ISDIR(entry_i->i_mode) && entry_i->i_parent == NULL) {
776                                        entry_i->i_parent = dir_i;
777                                        ++dir_i->i_count;
778                                }
779
780                                jffs2_iput(dir_i);
781                                rtems_jffs2_set_location(currentloc, entry_i);
782
783                                if (rtems_filesystem_eval_path_has_path(ctx)) {
784                                        status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
785                                }
786                        }
787                } else {
788                        status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY;
789                }
790        }
791
792        return status;
793}
794
795static const rtems_filesystem_eval_path_generic_config rtems_jffs2_eval_config = {
796        .is_directory = rtems_jffs2_eval_is_directory,
797        .eval_token = rtems_jffs2_eval_token
798};
799
800static void rtems_jffs2_lock(const rtems_filesystem_mount_table_entry_t *mt_entry)
801{
802        const rtems_jffs2_fs_info *fs_info = mt_entry->fs_info;
803        const struct super_block *sb = &fs_info->sb;
804
805        rtems_jffs2_do_lock(sb);
806}
807
808static void rtems_jffs2_unlock(const rtems_filesystem_mount_table_entry_t *mt_entry)
809{
810        const rtems_jffs2_fs_info *fs_info = mt_entry->fs_info;
811        const struct super_block *sb = &fs_info->sb;
812
813        rtems_jffs2_do_unlock(sb);
814}
815
816static void rtems_jffs2_eval_path(rtems_filesystem_eval_path_context_t *ctx)
817{
818        rtems_filesystem_eval_path_generic(ctx, NULL, &rtems_jffs2_eval_config);
819}
820
821static int rtems_jffs2_link(
822        const rtems_filesystem_location_info_t *parentloc,
823        const rtems_filesystem_location_info_t *targetloc,
824        const char *name,
825        size_t namelen
826)
827{
828        struct _inode *old_d_inode = rtems_jffs2_get_inode_by_location(targetloc);
829        struct _inode *dir_i = rtems_jffs2_get_inode_by_location(parentloc);
830        int eno;
831
832        eno = -jffs2_link(old_d_inode, dir_i, name, namelen);
833
834        return rtems_jffs2_eno_to_rv_and_errno(eno);
835}
836
837static bool rtems_jffs2_are_nodes_equal(
838        const rtems_filesystem_location_info_t *a,
839        const rtems_filesystem_location_info_t *b
840)
841{
842        struct _inode *inode_a = rtems_jffs2_get_inode_by_location(a);
843        struct _inode *inode_b = rtems_jffs2_get_inode_by_location(b);
844
845        return inode_a->i_ino == inode_b->i_ino;
846}
847
848static int rtems_jffs2_mknod(
849        const rtems_filesystem_location_info_t *parentloc,
850        const char *name,
851        size_t namelen,
852        mode_t mode,
853        dev_t dev
854)
855{
856        struct _inode *dir_i = rtems_jffs2_get_inode_by_location(parentloc);
857        int eno;
858
859        switch (mode & S_IFMT) {
860                case S_IFDIR:
861                        eno = -jffs2_mknod(dir_i, name, namelen, mode, NULL, 0);
862                        break;
863                case S_IFREG:
864                        eno = -jffs2_create(dir_i, name, namelen, mode);
865                        break;
866                default:
867                        eno = EINVAL;
868                        break;
869        }
870
871        return rtems_jffs2_eno_to_rv_and_errno(eno);
872}
873
874static int rtems_jffs2_cache_fd_name(struct _inode *inode, char **name, size_t *namelen)
875{
876        struct super_block *sb = inode->i_sb;
877        char *fd_name = inode->i_fd->name;
878        size_t fd_namelen = strlen(fd_name);
879        int eno = 0;
880
881        if (fd_namelen <= sizeof(sb->s_name_buf)) {
882                *namelen = fd_namelen;
883                *name = memcpy(&sb->s_name_buf[0], fd_name, fd_namelen);
884        } else {
885                eno = ENOMEM;
886        }
887
888        return eno;
889}
890
891static int rtems_jffs2_rmnod(
892        const rtems_filesystem_location_info_t *parentloc,
893        const rtems_filesystem_location_info_t *loc
894)
895{
896        struct _inode *dir_i = rtems_jffs2_get_inode_by_location(parentloc);
897        struct _inode *entry_i = rtems_jffs2_get_inode_by_location(loc);
898        char *name;
899        size_t namelen;
900        int eno = rtems_jffs2_cache_fd_name(entry_i, &name, &namelen);
901
902        if (eno == 0) {
903                switch (dir_i->i_mode & S_IFMT) {
904                        case S_IFDIR:
905                                eno = -jffs2_rmdir(dir_i, entry_i, name, namelen);
906                                break;
907                        case S_IFREG:
908                                eno = -jffs2_unlink(dir_i, entry_i, name, namelen);
909                                break;
910                        default:
911                                eno = EINVAL;
912                                break;
913                }
914        }
915
916        return rtems_jffs2_eno_to_rv_and_errno(eno);
917}
918
919static int rtems_jffs2_fchmod(
920        const rtems_filesystem_location_info_t *loc,
921        mode_t mode
922)
923{
924        struct _inode *inode = rtems_jffs2_get_inode_by_location(loc);
925        struct iattr iattr;
926        int eno;
927
928        iattr.ia_valid = ATTR_MODE | ATTR_CTIME;
929        iattr.ia_mode = mode;
930        iattr.ia_ctime = get_seconds();
931
932        eno = -jffs2_do_setattr(inode, &iattr);
933
934        return rtems_jffs2_eno_to_rv_and_errno(eno);
935}
936
937static int rtems_jffs2_chown(
938        const rtems_filesystem_location_info_t *loc,
939        uid_t owner,
940        gid_t group
941)
942{
943        struct _inode *inode = rtems_jffs2_get_inode_by_location(loc);
944        struct iattr iattr;
945        int eno;
946
947        iattr.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
948        iattr.ia_uid = owner;
949        iattr.ia_gid = group;
950        iattr.ia_ctime = get_seconds();
951
952        eno = -jffs2_do_setattr(inode, &iattr);
953
954        return rtems_jffs2_eno_to_rv_and_errno(eno);
955}
956
957static int rtems_jffs2_clonenode(rtems_filesystem_location_info_t *loc)
958{
959        struct _inode *inode = rtems_jffs2_get_inode_by_location(loc);
960
961        ++inode->i_count;
962
963        return 0;
964}
965
966static void rtems_jffs2_freenode(const rtems_filesystem_location_info_t *loc)
967{
968        struct _inode *inode = rtems_jffs2_get_inode_by_location(loc);
969
970        jffs2_iput(inode);
971}
972
973static void rtems_jffs2_fsunmount(rtems_filesystem_mount_table_entry_t *mt_entry)
974{
975        rtems_jffs2_fs_info *fs_info = mt_entry->fs_info;
976        struct _inode *root_i = mt_entry->mt_fs_root->location.node_access;
977
978        icache_evict(root_i, NULL);
979        assert(root_i->i_cache_next == NULL);
980        assert(root_i->i_count == 1);
981        jffs2_iput(root_i);
982
983        rtems_jffs2_free_directory_entries(root_i);
984        free(root_i);
985
986        rtems_jffs2_free_fs_info(fs_info, true);
987}
988
989static int rtems_jffs2_rename(
990        const rtems_filesystem_location_info_t *oldparentloc,
991        const rtems_filesystem_location_info_t *oldloc,
992        const rtems_filesystem_location_info_t *newparentloc,
993        const char *name,
994        size_t namelen
995)
996{
997        struct _inode *old_dir_i = rtems_jffs2_get_inode_by_location(oldparentloc);
998        struct _inode *new_dir_i = rtems_jffs2_get_inode_by_location(newparentloc);
999        struct _inode *d_inode = rtems_jffs2_get_inode_by_location(oldloc);
1000        char *oldname;
1001        size_t oldnamelen;
1002        int eno = rtems_jffs2_cache_fd_name(d_inode, &oldname, &oldnamelen);
1003
1004        if (eno == 0) {
1005                eno = -jffs2_rename(old_dir_i, d_inode, oldname, oldnamelen, new_dir_i, name, namelen);
1006        }
1007
1008        return rtems_jffs2_eno_to_rv_and_errno(eno);
1009}
1010
1011static int rtems_jffs2_statvfs(
1012        const rtems_filesystem_location_info_t *__restrict loc,
1013        struct statvfs *__restrict buf
1014)
1015{
1016        struct _inode *inode = rtems_jffs2_get_inode_by_location(loc);
1017        struct super_block *sb = inode->i_sb;
1018        struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
1019        unsigned long avail;
1020
1021        spin_lock(&c->erase_completion_lock);
1022        avail = c->dirty_size + c->free_size;
1023        if (avail > c->sector_size * c->resv_blocks_write) {
1024                avail -= c->sector_size * c->resv_blocks_write;
1025        } else {
1026                avail = 0;
1027        }
1028        spin_unlock(&c->erase_completion_lock);
1029
1030        buf->f_bavail = avail >> PAGE_SHIFT;
1031        buf->f_blocks = c->flash_size >> PAGE_SHIFT;
1032        buf->f_bsize = 1UL << PAGE_SHIFT;
1033        buf->f_fsid = JFFS2_SUPER_MAGIC;
1034        buf->f_namemax = JFFS2_MAX_NAME_LEN;
1035
1036        buf->f_bfree = buf->f_bavail;
1037        buf->f_frsize = buf->f_bsize;
1038
1039        return 0;
1040}
1041
1042static int rtems_jffs2_utime(
1043        const rtems_filesystem_location_info_t *loc,
1044        time_t actime,
1045        time_t modtime
1046)
1047{
1048        struct _inode *inode = rtems_jffs2_get_inode_by_location(loc);
1049        struct iattr iattr;
1050        int eno;
1051
1052        iattr.ia_valid = ATTR_ATIME | ATTR_MTIME | ATTR_CTIME;
1053        iattr.ia_atime = actime;
1054        iattr.ia_mtime = modtime;
1055        iattr.ia_ctime = get_seconds();
1056
1057        eno = -jffs2_do_setattr(inode, &iattr);
1058
1059        return rtems_jffs2_eno_to_rv_and_errno(eno);
1060}
1061
1062static int rtems_jffs2_symlink(
1063        const rtems_filesystem_location_info_t *parentloc,
1064        const char *name,
1065        size_t namelen,
1066        const char *target
1067)
1068{
1069        struct _inode *dir_i = rtems_jffs2_get_inode_by_location(parentloc);
1070        int eno;
1071
1072        eno = -jffs2_mknod(dir_i, name, namelen, S_IFLNK | S_IRWXUGO, target, strlen(target));
1073
1074        return rtems_jffs2_eno_to_rv_and_errno(eno);
1075}
1076
1077static ssize_t rtems_jffs2_readlink(
1078        const rtems_filesystem_location_info_t *loc,
1079        char *buf,
1080        size_t bufsize
1081)
1082{
1083        struct _inode *inode = rtems_jffs2_get_inode_by_location(loc);
1084        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
1085        const char *target = f->target;
1086        ssize_t i;
1087
1088        for (i = 0; i < (ssize_t) bufsize && target[i] != '\0'; ++i) {
1089                buf[i] = target[i];
1090        }
1091
1092        return i;
1093}
1094
1095static const rtems_filesystem_operations_table rtems_jffs2_ops = {
1096        .lock_h = rtems_jffs2_lock,
1097        .unlock_h = rtems_jffs2_unlock,
1098        .eval_path_h = rtems_jffs2_eval_path,
1099        .link_h = rtems_jffs2_link,
1100        .are_nodes_equal_h = rtems_jffs2_are_nodes_equal,
1101        .mknod_h = rtems_jffs2_mknod,
1102        .rmnod_h = rtems_jffs2_rmnod,
1103        .fchmod_h = rtems_jffs2_fchmod,
1104        .chown_h = rtems_jffs2_chown,
1105        .clonenod_h = rtems_jffs2_clonenode,
1106        .freenod_h = rtems_jffs2_freenode,
1107        .mount_h = rtems_filesystem_default_mount,
1108        .unmount_h = rtems_filesystem_default_unmount,
1109        .fsunmount_me_h = rtems_jffs2_fsunmount,
1110        .utime_h = rtems_jffs2_utime,
1111        .symlink_h = rtems_jffs2_symlink,
1112        .readlink_h = rtems_jffs2_readlink,
1113        .rename_h = rtems_jffs2_rename,
1114        .statvfs_h = rtems_jffs2_statvfs
1115};
1116
1117static int calculate_inocache_hashsize(uint32_t flash_size)
1118{
1119        /*
1120         * Pick a inocache hash size based on the size of the medium.
1121         * Count how many megabytes we're dealing with, apply a hashsize twice
1122         * that size, but rounding down to the usual big powers of 2. And keep
1123         * to sensible bounds.
1124         */
1125
1126        int size_mb = flash_size / 1024 / 1024;
1127        int hashsize = (size_mb * 2) & ~0x3f;
1128
1129        if (hashsize < INOCACHE_HASHSIZE_MIN)
1130                return INOCACHE_HASHSIZE_MIN;
1131        if (hashsize > INOCACHE_HASHSIZE_MAX)
1132                return INOCACHE_HASHSIZE_MAX;
1133
1134        return hashsize;
1135}
1136
1137int rtems_jffs2_initialize(
1138        rtems_filesystem_mount_table_entry_t *mt_entry,
1139        const void *data
1140)
1141{
1142        const rtems_jffs2_mount_data *jffs2_mount_data = data;
1143        rtems_jffs2_flash_control *fc = jffs2_mount_data->flash_control;
1144        int inocache_hashsize = calculate_inocache_hashsize(fc->flash_size);
1145        rtems_jffs2_fs_info *fs_info = calloc(
1146                1,
1147                sizeof(*fs_info) + (size_t) inocache_hashsize * sizeof(fs_info->inode_cache[0])
1148        );
1149        bool do_mount_fs_was_successful = false;
1150        struct super_block *sb;
1151        struct jffs2_sb_info *c;
1152        int err;
1153
1154        if (fs_info != NULL) {
1155                err = 0;
1156        } else {
1157                err = -ENOMEM;
1158        }
1159
1160        sb = &fs_info->sb;
1161        c = JFFS2_SB_INFO(sb);
1162
1163        if (err == 0) {
1164                uint32_t blocks = fc->flash_size / fc->block_size;
1165
1166                if ((fc->block_size * blocks) != fc->flash_size) {
1167                        fc->flash_size = fc->block_size * blocks;
1168                        pr_info("Flash size not aligned to erasesize, reducing to %dKiB\n",
1169                                fc->flash_size / 1024);
1170                }
1171
1172                if (fc->flash_size < 5*fc->block_size) {
1173                        pr_err("Too few erase blocks (%d)\n",
1174                               fc->flash_size / fc->block_size);
1175                        err = -EINVAL;
1176                }
1177        }
1178
1179        if (err == 0) {
1180                rtems_status_code sc = rtems_semaphore_create(
1181                        rtems_build_name('J', 'F', 'F', 'S'),
1182                        1,
1183                        RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY | RTEMS_BINARY_SEMAPHORE,
1184                        0,
1185                        &sb->s_mutex
1186                );
1187
1188                err = sc == RTEMS_SUCCESSFUL ? 0 : -ENOMEM;
1189        }
1190
1191        if (err == 0) {
1192                sb->s_is_readonly = !mt_entry->writeable;
1193                sb->s_flash_control = fc;
1194                sb->s_compressor_control = jffs2_mount_data->compressor_control;
1195
1196                c->inocache_hashsize = inocache_hashsize;
1197                c->inocache_list = &fs_info->inode_cache[0];
1198                c->sector_size = fc->block_size;
1199                c->flash_size = fc->flash_size;
1200                c->cleanmarker_size = sizeof(struct jffs2_unknown_node);
1201
1202                err = jffs2_do_mount_fs(c);
1203        }
1204
1205        if (err == 0) {
1206                do_mount_fs_was_successful = true;
1207
1208                sb->s_root = jffs2_iget(sb, 1);
1209                if (IS_ERR(sb->s_root)) {
1210                        err = PTR_ERR(sb->s_root);
1211                }
1212        }
1213
1214        if (err == 0) {
1215                sb->s_root->i_parent = sb->s_root;
1216
1217                if (!jffs2_is_readonly(c)) {
1218                        jffs2_erase_pending_blocks(c, 0);
1219                }
1220
1221                mt_entry->fs_info = fs_info;
1222                mt_entry->ops = &rtems_jffs2_ops;
1223                mt_entry->mt_fs_root->location.node_access = sb->s_root;
1224                mt_entry->mt_fs_root->location.handlers = &rtems_jffs2_directory_handlers;
1225
1226                return 0;
1227        } else {
1228                if (fs_info != NULL) {
1229                        rtems_jffs2_free_fs_info(fs_info, do_mount_fs_was_successful);
1230                } else {
1231                        rtems_jffs2_flash_control_destroy(fc);
1232                        rtems_jffs2_compressor_control_destroy(jffs2_mount_data->compressor_control);
1233                }
1234
1235                errno = -err;
1236
1237                return -1;
1238        }
1239}
1240
1241//==========================================================================
1242//
1243// Called by JFFS2
1244// ===============
1245//
1246//
1247//==========================================================================
1248
1249unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c,
1250                                   struct jffs2_inode_info *f,
1251                                   unsigned long offset,
1252                                   unsigned long *priv)
1253{
1254        int ret;
1255        struct super_block *sb = OFNI_BS_2SFFJ(c);
1256        unsigned char *gc_buffer = &sb->s_gc_buffer[0];
1257
1258        ret = jffs2_read_inode_range(c, f, gc_buffer,
1259                                     offset & ~(PAGE_CACHE_SIZE-1), PAGE_CACHE_SIZE);
1260        if (ret)
1261                return ERR_PTR(ret);
1262
1263        return gc_buffer;
1264}
1265
1266void jffs2_gc_release_page(struct jffs2_sb_info *c,
1267                           unsigned char *ptr,
1268                           unsigned long *priv)
1269{
1270        /* Do nothing */
1271}
1272
1273static struct _inode *new_inode(struct super_block *sb)
1274{
1275
1276        // Only called in write.c jffs2_new_inode
1277        // Always adds itself to inode cache
1278
1279        struct _inode *inode;
1280        struct _inode *cached_inode;
1281
1282        inode = malloc(sizeof (struct _inode));
1283        if (inode == NULL)
1284                return 0;
1285
1286        D2(printf
1287           ("malloc new_inode %x ####################################\n",
1288            inode));
1289
1290        memset(inode, 0, sizeof (struct _inode));
1291        inode->i_sb = sb;
1292        inode->i_ino = 1;
1293        inode->i_count = 1;
1294        inode->i_nlink = 1;     // Let JFFS2 manage the link count
1295        inode->i_size = 0;
1296
1297        inode->i_cache_next = NULL;     // Newest inode, about to be cached
1298
1299        // Add to the icache
1300        for (cached_inode = sb->s_root; cached_inode != NULL;
1301             cached_inode = cached_inode->i_cache_next) {
1302                if (cached_inode->i_cache_next == NULL) {
1303                        cached_inode->i_cache_next = inode;     // Current last in cache points to newcomer
1304                        inode->i_cache_prev = cached_inode;     // Newcomer points back to last
1305                        break;
1306                }
1307        }
1308        return inode;
1309}
1310
1311static struct _inode *ilookup(struct super_block *sb, cyg_uint32 ino)
1312{
1313        struct _inode *inode = NULL;
1314
1315        D2(printf("ilookup\n"));
1316        // Check for this inode in the cache
1317        for (inode = sb->s_root; inode != NULL; inode = inode->i_cache_next) {
1318                if (inode->i_ino == ino) {
1319                        inode->i_count++;
1320                        break;
1321                }
1322        }
1323        return inode;
1324}
1325
1326struct _inode *jffs2_iget(struct super_block *sb, cyg_uint32 ino)
1327{
1328        // Called in super.c jffs2_read_super, dir.c jffs2_lookup,
1329        // and gc.c jffs2_garbage_collect_pass
1330
1331        // Must first check for cached inode
1332        // If this fails let new_inode create one
1333
1334        struct _inode *inode;
1335        int err;
1336
1337        D2(printf("jffs2_iget\n"));
1338
1339        inode = ilookup(sb, ino);
1340        if (inode)
1341                return inode;
1342
1343        // Not cached, so malloc it
1344        inode = new_inode(sb);
1345        if (inode == NULL)
1346                return ERR_PTR(-ENOMEM);
1347
1348        inode->i_ino = ino;
1349
1350        err = jffs2_read_inode(inode);
1351        if (err) {
1352                printk("jffs2_read_inode() failed\n");
1353                inode->i_nlink = 0; // free _this_ bad inode right now
1354                jffs2_iput(inode);
1355                inode = NULL;
1356                return ERR_PTR(err);
1357        }
1358        return inode;
1359}
1360
1361// -------------------------------------------------------------------------
1362// Decrement the reference count on an inode. If this makes the ref count
1363// zero, then this inode can be freed.
1364
1365void jffs2_iput(struct _inode *i)
1366{
1367        // Called in jffs2_find
1368        // (and jffs2_open and jffs2_ops_mkdir?)
1369        // super.c jffs2_read_super,
1370        // and gc.c jffs2_garbage_collect_pass
1371 recurse:
1372        assert(i != NULL);
1373
1374        i->i_count--;
1375
1376        if (i->i_count < 0)
1377                BUG();
1378
1379        if (i->i_count)
1380                return;
1381       
1382        if (!i->i_nlink) {
1383                struct _inode *parent;
1384
1385                // Remove from the icache linked list and free immediately
1386                if (i->i_cache_prev)
1387                        i->i_cache_prev->i_cache_next = i->i_cache_next;
1388                if (i->i_cache_next)
1389                        i->i_cache_next->i_cache_prev = i->i_cache_prev;
1390
1391                parent = i->i_parent;
1392                jffs2_clear_inode(i);
1393                memset(i, 0x5a, sizeof(*i));
1394                free(i);
1395
1396                if (parent && parent != i) {
1397                        i = parent;
1398                        goto recurse;
1399                }
1400
1401        } else {
1402                // Evict some _other_ inode with i_count zero, leaving
1403                // this latest one in the cache for a while
1404                icache_evict(i->i_sb->s_root, i);
1405        }
1406}
1407
1408
1409// -------------------------------------------------------------------------
1410// EOF jffs2.c
1411
1412
1413static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
1414{
1415        memset(f, 0, sizeof(*f));
1416}
1417
1418static void jffs2_clear_inode (struct _inode *inode)
1419{
1420        /* We can forget about this inode for now - drop all
1421         *  the nodelists associated with it, etc.
1422         */
1423        struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
1424        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
1425
1426        D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode));
1427
1428        jffs2_do_clear_inode(c, f);
1429}
1430
1431
1432/* jffs2_new_inode: allocate a new inode and inocache, add it to the hash,
1433   fill in the raw_inode while you're at it. */
1434struct _inode *jffs2_new_inode (struct _inode *dir_i, int mode, struct jffs2_raw_inode *ri)
1435{
1436        struct _inode *inode;
1437        struct super_block *sb = dir_i->i_sb;
1438        struct jffs2_sb_info *c;
1439        struct jffs2_inode_info *f;
1440        int ret;
1441
1442        D1(printk(KERN_DEBUG "jffs2_new_inode(): dir_i %ld, mode 0x%x\n", dir_i->i_ino, mode));
1443
1444        c = JFFS2_SB_INFO(sb);
1445       
1446        inode = new_inode(sb);
1447       
1448        if (!inode)
1449                return ERR_PTR(-ENOMEM);
1450
1451        f = JFFS2_INODE_INFO(inode);
1452        jffs2_init_inode_info(f);
1453
1454        memset(ri, 0, sizeof(*ri));
1455        /* Set OS-specific defaults for new inodes */
1456        ri->uid = cpu_to_je16(geteuid());
1457        ri->gid = cpu_to_je16(getegid());
1458        ri->mode =  cpu_to_jemode(mode);
1459        ret = jffs2_do_new_inode (c, f, mode, ri);
1460        if (ret) {
1461                // forceful evict: f->sem is locked already, and the
1462                // inode is bad.
1463                if (inode->i_cache_prev)
1464                       inode->i_cache_prev->i_cache_next = inode->i_cache_next;
1465                if (inode->i_cache_next)
1466                       inode->i_cache_next->i_cache_prev = inode->i_cache_prev;
1467                mutex_unlock(&(f->sem));
1468                jffs2_clear_inode(inode);
1469                memset(inode, 0x6a, sizeof(*inode));
1470                free(inode);
1471                return ERR_PTR(ret);
1472        }
1473        inode->i_nlink = 1;
1474        inode->i_ino = je32_to_cpu(ri->ino);
1475        inode->i_mode = jemode_to_cpu(ri->mode);
1476        inode->i_gid = je16_to_cpu(ri->gid);
1477        inode->i_uid = je16_to_cpu(ri->uid);
1478        inode->i_atime = inode->i_ctime = inode->i_mtime = get_seconds();
1479        ri->atime = ri->mtime = ri->ctime = cpu_to_je32(inode->i_mtime);
1480
1481        inode->i_size = 0;
1482
1483        return inode;
1484}
1485
1486
1487static int jffs2_read_inode (struct _inode *inode)
1488{
1489        struct jffs2_inode_info *f;
1490        struct jffs2_sb_info *c;
1491        struct jffs2_raw_inode latest_node;
1492        int ret;
1493
1494        D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino));
1495
1496        f = JFFS2_INODE_INFO(inode);
1497        c = JFFS2_SB_INFO(inode->i_sb);
1498
1499        jffs2_init_inode_info(f);
1500       
1501        ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node);
1502
1503        if (ret) {
1504                mutex_unlock(&f->sem);
1505                return ret;
1506        }
1507        inode->i_mode = jemode_to_cpu(latest_node.mode);
1508        inode->i_uid = je16_to_cpu(latest_node.uid);
1509        inode->i_gid = je16_to_cpu(latest_node.gid);
1510        inode->i_size = je32_to_cpu(latest_node.isize);
1511        inode->i_atime = je32_to_cpu(latest_node.atime);
1512        inode->i_mtime = je32_to_cpu(latest_node.mtime);
1513        inode->i_ctime = je32_to_cpu(latest_node.ctime);
1514
1515        inode->i_nlink = f->inocache->pino_nlink;
1516        mutex_unlock(&f->sem);
1517
1518        D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n"));
1519        return 0;
1520}
1521
1522
1523void jffs2_gc_release_inode(struct jffs2_sb_info *c,
1524                                   struct jffs2_inode_info *f)
1525{
1526        jffs2_iput(OFNI_EDONI_2SFFJ(f));
1527}
1528
1529struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
1530                                              int inum, int unlinked)
1531{
1532        struct _inode *inode;
1533        struct jffs2_inode_cache *ic;
1534
1535        if (unlinked) {
1536                /* The inode has zero nlink but its nodes weren't yet marked
1537                   obsolete. This has to be because we're still waiting for
1538                   the final (close() and) iput() to happen.
1539
1540                   There's a possibility that the final iput() could have
1541                   happened while we were contemplating. In order to ensure
1542                   that we don't cause a new read_inode() (which would fail)
1543                   for the inode in question, we use ilookup() in this case
1544                   instead of iget().
1545
1546                   The nlink can't _become_ zero at this point because we're
1547                   holding the alloc_sem, and jffs2_do_unlink() would also
1548                   need that while decrementing nlink on any inode.
1549                */
1550                inode = ilookup(OFNI_BS_2SFFJ(c), inum);
1551                if (!inode) {
1552                        jffs2_dbg(1, "ilookup() failed for ino #%u; inode is probably deleted.\n",
1553                                  inum);
1554
1555                        spin_lock(&c->inocache_lock);
1556                        ic = jffs2_get_ino_cache(c, inum);
1557                        if (!ic) {
1558                                jffs2_dbg(1, "Inode cache for ino #%u is gone\n",
1559                                          inum);
1560                                spin_unlock(&c->inocache_lock);
1561                                return NULL;
1562                        }
1563                        if (ic->state != INO_STATE_CHECKEDABSENT) {
1564                                /* Wait for progress. Don't just loop */
1565                                jffs2_dbg(1, "Waiting for ino #%u in state %d\n",
1566                                          ic->ino, ic->state);
1567                                sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
1568                        } else {
1569                                spin_unlock(&c->inocache_lock);
1570                        }
1571
1572                        return NULL;
1573                }
1574        } else {
1575                /* Inode has links to it still; they're not going away because
1576                   jffs2_do_unlink() would need the alloc_sem and we have it.
1577                   Just iget() it, and if read_inode() is necessary that's OK.
1578                */
1579                inode = jffs2_iget(OFNI_BS_2SFFJ(c), inum);
1580                if (IS_ERR(inode))
1581                        return ERR_CAST(inode);
1582        }
1583
1584        return JFFS2_INODE_INFO(inode);
1585}
Note: See TracBrowser for help on using the repository browser.