📄 fs-ecos.c
字号:
memcpy(nbuf, name, len); nbuf[len] = '\0';}static int jffs2_fo_dirread(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio){ struct _inode *d_inode = (struct _inode *) fp->f_data; struct dirent *ent = (struct dirent *) uio->uio_iov[0].iov_base; char *nbuf = ent->d_name; int nlen = sizeof (ent->d_name) - 1; off_t len = uio->uio_iov[0].iov_len; struct jffs2_inode_info *f; struct jffs2_sb_info *c; struct _inode *inode = d_inode; struct jffs2_full_dirent *fd; unsigned long offset, curofs; int found = 1; if (len < sizeof (struct dirent)) return EINVAL; D1(printk (KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", d_inode->i_ino)); f = JFFS2_INODE_INFO(inode); c = JFFS2_SB_INFO(inode->i_sb); offset = fp->f_offset; if (offset == 0) { D1(printk (KERN_DEBUG "Dirent 0: \".\", ino #%lu\n", inode->i_ino)); filldir(nbuf, nlen, ".", 1); goto out; } if (offset == 1) { filldir(nbuf, nlen, "..", 2); goto out; } curofs = 1; down(&f->sem); for (fd = f->dents; fd; fd = fd->next) { curofs++; /* First loop: curofs = 2; offset = 2 */ if (curofs < offset) { D2(printk (KERN_DEBUG "Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld\n", fd->name, fd->ino, fd->type, curofs, offset)); continue; } if (!fd->ino) { D2(printk (KERN_DEBUG "Skipping deletion dirent \"%s\"\n", fd->name)); offset++; continue; } D2(printk (KERN_DEBUG "Dirent %ld: \"%s\", ino #%u, type %d\n", offset, fd->name, fd->ino, fd->type)); filldir(nbuf, nlen, fd->name, strlen(fd->name)); goto out_sem; } /* Reached the end of the directory */ found = 0; out_sem: up(&f->sem); out: fp->f_offset = ++offset; if (found) { uio->uio_resid -= sizeof (struct dirent); } return ENOERR;}// -------------------------------------------------------------------------// jffs2_fo_dirlseek()// Seek directory to start.static int jffs2_fo_dirlseek(struct CYG_FILE_TAG *fp, off_t * pos, int whence){ // Only allow SEEK_SET to zero D2(printf("jffs2_fo_dirlseek\n")); if (whence != SEEK_SET || *pos != 0) return EINVAL; *pos = fp->f_offset = 0; return ENOERR;}//==========================================================================// // Called by JFFS2// ===============// ////==========================================================================unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, struct jffs2_inode_info *f, unsigned long offset, unsigned long *priv){ /* FIXME: This works only with one file system mounted at a time */ int ret; ret = jffs2_read_inode_range(c, f, gc_buffer, offset, PAGE_CACHE_SIZE); if (ret) return ERR_PTR(ret); return gc_buffer;}void jffs2_gc_release_page(struct jffs2_sb_info *c, unsigned char *ptr, unsigned long *priv){ /* Do nothing */}static struct _inode *new_inode(struct super_block *sb){ // Only called in write.c jffs2_new_inode // Always adds itself to inode cache struct _inode *inode; struct _inode *cached_inode; inode = malloc(sizeof (struct _inode)); if (inode == NULL) return 0; D2(printf ("malloc new_inode %x ####################################\n", inode)); memset(inode, 0, sizeof (struct _inode)); inode->i_sb = sb; inode->i_ino = 1; inode->i_count = 1; inode->i_nlink = 1; // Let JFFS2 manage the link count inode->i_size = 0; inode->i_cache_next = NULL; // Newest inode, about to be cached // Add to the icache for (cached_inode = sb->s_root; cached_inode != NULL; cached_inode = cached_inode->i_cache_next) { if (cached_inode->i_cache_next == NULL) { cached_inode->i_cache_next = inode; // Current last in cache points to newcomer inode->i_cache_prev = cached_inode; // Newcomer points back to last break; } } return inode;}static struct _inode *ilookup(struct super_block *sb, cyg_uint32 ino){ struct _inode *inode = NULL; D2(printf("ilookup\n")); // Check for this inode in the cache for (inode = sb->s_root; inode != NULL; inode = inode->i_cache_next) { if (inode->i_ino == ino) { inode->i_count++; break; } } return inode;}struct _inode *jffs2_iget(struct super_block *sb, cyg_uint32 ino){ // Called in super.c jffs2_read_super, dir.c jffs2_lookup, // and gc.c jffs2_garbage_collect_pass // Must first check for cached inode // If this fails let new_inode create one struct _inode *inode; int err; D2(printf("jffs2_iget\n")); inode = ilookup(sb, ino); if (inode) return inode; // Not cached, so malloc it inode = new_inode(sb); if (inode == NULL) return 0; inode->i_ino = ino; err = jffs2_read_inode(inode); if (err) { printf("jffs2_read_inode() failed\n"); jffs2_iput(inode); inode = NULL; return ERR_PTR(err); } return inode;}// -------------------------------------------------------------------------// Decrement the reference count on an inode. If this makes the ref count// zero, then this inode can be freed.void jffs2_iput(struct _inode *i){ // Called in jffs2_find // (and jffs2_open and jffs2_ops_mkdir?) // super.c jffs2_read_super, // and gc.c jffs2_garbage_collect_pass recurse: if (!i) { printf("jffs2_iput() called with NULL inode\n"); // and let it fault... } i->i_count--; if (i->i_count < 0) BUG(); if (i->i_count) return; if (!i->i_nlink) { struct _inode *parent; // Remove from the icache linked list and free immediately if (i->i_cache_prev) i->i_cache_prev->i_cache_next = i->i_cache_next; if (i->i_cache_next) i->i_cache_next->i_cache_prev = i->i_cache_prev; parent = i->i_parent; jffs2_clear_inode(i); memset(i, 0x5a, sizeof(*i)); free(i); if (parent && parent != i) { i = parent; goto recurse; } } else { // Evict some _other_ inode with i_count zero, leaving // this latest one in the cache for a while icache_evict(i->i_sb->s_root, i); }}// -------------------------------------------------------------------------// EOF jffs2.cstatic inline void jffs2_init_inode_info(struct jffs2_inode_info *f){ memset(f, 0, sizeof(*f)); init_MUTEX_LOCKED(&f->sem);}static void jffs2_clear_inode (struct _inode *inode){ /* We can forget about this inode for now - drop all * the nodelists associated with it, etc. */ struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode)); jffs2_do_clear_inode(c, f);}/* jffs2_new_inode: allocate a new inode and inocache, add it to the hash, fill in the raw_inode while you're at it. */struct _inode *jffs2_new_inode (struct _inode *dir_i, int mode, struct jffs2_raw_inode *ri){ struct _inode *inode; struct super_block *sb = dir_i->i_sb; struct jffs2_sb_info *c; struct jffs2_inode_info *f; int ret; D1(printk(KERN_DEBUG "jffs2_new_inode(): dir_i %ld, mode 0x%x\n", dir_i->i_ino, mode)); c = JFFS2_SB_INFO(sb); inode = new_inode(sb); if (!inode) return ERR_PTR(-ENOMEM); f = JFFS2_INODE_INFO(inode); jffs2_init_inode_info(f); memset(ri, 0, sizeof(*ri)); /* Set OS-specific defaults for new inodes */ ri->uid = ri->gid = cpu_to_je16(0); ri->mode = cpu_to_jemode(mode); ret = jffs2_do_new_inode (c, f, mode, ri); if (ret) { jffs2_iput(inode); return ERR_PTR(ret); } inode->i_nlink = 1; inode->i_ino = je32_to_cpu(ri->ino); inode->i_mode = jemode_to_cpu(ri->mode); inode->i_gid = je16_to_cpu(ri->gid); inode->i_uid = je16_to_cpu(ri->uid); inode->i_atime = inode->i_ctime = inode->i_mtime = cyg_timestamp(); ri->atime = ri->mtime = ri->ctime = cpu_to_je32(inode->i_mtime); inode->i_size = 0; return inode;}static int jffs2_read_inode (struct _inode *inode){ struct jffs2_inode_info *f; struct jffs2_sb_info *c; struct jffs2_raw_inode latest_node; int ret; D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino)); f = JFFS2_INODE_INFO(inode); c = JFFS2_SB_INFO(inode->i_sb); jffs2_init_inode_info(f); ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node); if (ret) { up(&f->sem); return ret; } inode->i_mode = jemode_to_cpu(latest_node.mode); inode->i_uid = je16_to_cpu(latest_node.uid); inode->i_gid = je16_to_cpu(latest_node.gid); inode->i_size = je32_to_cpu(latest_node.isize); inode->i_atime = je32_to_cpu(latest_node.atime); inode->i_mtime = je32_to_cpu(latest_node.mtime); inode->i_ctime = je32_to_cpu(latest_node.ctime); inode->i_nlink = f->inocache->nlink; up(&f->sem); D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n")); return 0;}void jffs2_gc_release_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f){ jffs2_iput(OFNI_EDONI_2SFFJ(f));}struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, int inum, int nlink){ struct _inode *inode; struct jffs2_inode_cache *ic; if (!nlink) { /* The inode has zero nlink but its nodes weren't yet marked obsolete. This has to be because we're still waiting for the final (close() and) jffs2_iput() to happen. There's a possibility that the final jffs2_iput() could have happened while we were contemplating. In order to ensure that we don't cause a new read_inode() (which would fail) for the inode in question, we use ilookup() in this case instead of jffs2_iget(). The nlink can't _become_ zero at this point because we're holding the alloc_sem, and jffs2_do_unlink() would also need that while decrementing nlink on any inode. */ inode = ilookup(OFNI_BS_2SFFJ(c), inum); if (!inode) { D1(printk(KERN_DEBUG "ilookup() failed for ino #%u; inode is probably deleted.\n", inum)); spin_lock(&c->inocache_lock); ic = jffs2_get_ino_cache(c, inum); if (!ic) { D1(printk(KERN_DEBUG "Inode cache for ino #%u is gone.\n", inum)); spin_unlock(&c->inocache_lock); return NULL; } if (ic->state != INO_STATE_CHECKEDABSENT) { /* Wait for progress. Don't just loop */ D1(printk(KERN_DEBUG "Waiting for ino #%u in state %d\n", ic->ino, ic->state)); sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); } else { spin_unlock(&c->inocache_lock); } return NULL; } } else { /* Inode has links to it still; they're not going away because jffs2_do_unlink() would need the alloc_sem and we have it. Just jffs2_iget() it, and if read_inode() is necessary that's OK. */ inode = jffs2_iget(OFNI_BS_2SFFJ(c), inum); if (IS_ERR(inode)) return (void *)inode; } return JFFS2_INODE_INFO(inode);}uint32_t jffs2_from_os_mode(uint32_t osmode){ uint32_t jmode = ((osmode & S_IRUSR)?00400:0) | ((osmode & S_IWUSR)?00200:0) | ((osmode & S_IXUSR)?00100:0) | ((osmode & S_IRGRP)?00040:0) | ((osmode & S_IWGRP)?00020:0) | ((osmode & S_IXGRP)?00010:0) | ((osmode & S_IROTH)?00004:0) | ((osmode & S_IWOTH)?00002:0) | ((osmode & S_IXOTH)?00001:0); switch (osmode & S_IFMT) { case S_IFSOCK: return jmode | 0140000; case S_IFLNK: return jmode | 0120000; case S_IFREG: return jmode | 0100000; case S_IFBLK: return jmode | 0060000; case S_IFDIR: return jmode | 0040000; case S_IFCHR: return jmode | 0020000; case S_IFIFO: return jmode | 0010000; case S_ISUID: return jmode | 0004000; case S_ISGID: return jmode | 0002000;#ifdef S_ISVTX case S_ISVTX: return jmode | 0001000;#endif } printf("os_to_jffs2_mode() cannot convert 0x%x\n", osmode); BUG(); return 0;}uint32_t jffs2_to_os_mode (uint32_t jmode){ uint32_t osmode = ((jmode & 00400)?S_IRUSR:0) | ((jmode & 00200)?S_IWUSR:0) | ((jmode & 00100)?S_IXUSR:0) | ((jmode & 00040)?S_IRGRP:0) | ((jmode & 00020)?S_IWGRP:0) | ((jmode & 00010)?S_IXGRP:0) | ((jmode & 00004)?S_IROTH:0) | ((jmode & 00002)?S_IWOTH:0) | ((jmode & 00001)?S_IXOTH:0); switch(jmode & 00170000) { case 0140000: return osmode | S_IFSOCK; case 0120000: return osmode | S_IFLNK; case 0100000: return osmode | S_IFREG; case 0060000: return osmode | S_IFBLK; case 0040000: return osmode | S_IFDIR; case 0020000: return osmode | S_IFCHR; case 0010000: return osmode | S_IFIFO; case 0004000: return osmode | S_ISUID; case 0002000: return osmode | S_ISGID;#ifdef S_ISVTX case 0001000: return osmode | S_ISVTX;#endif } printf("jffs2_to_os_mode() cannot convert 0x%x\n", osmode); BUG(); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -