📄 fs-ecos.c
字号:
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// ===============// ////==========================================================================struct page *read_cache_page(unsigned long index, int (*filler) (void *, struct page *), void *data){ // Only called in gc.c jffs2_garbage_collect_dnode // but gets a real page for the specified inode int err; struct page *gc_page = malloc(sizeof (struct page)); printf("read_cache_page\n"); memset(&gc_buffer, 0, PAGE_CACHE_SIZE); if (gc_page != NULL) { gc_page->virtual = &gc_buffer; gc_page->index = index; err = filler(data, gc_page); if (err < 0) { free(gc_page); gc_page = NULL; } } return gc_page;}void page_cache_release(struct page *pg){ // Only called in gc.c jffs2_garbage_collect_dnode // but should free the page malloc'd by read_cache_page printf("page_cache_release\n"); free(pg);}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 = 0; //1; // Let ecos manage the open count 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;}struct inode *iget(struct super_block *sb, cyg_uint32 ino){ // Substitute for iget drops straight through to reading the // inode from disk if it is not in the inode cache // 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; D2(printf("iget\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) return inode; } inode = NULL; // Not cached, so malloc it inode = new_inode(sb); if (inode == NULL) return 0; inode->i_ino = ino; jffs2_read_inode(inode); return inode;}void iput(struct inode *i){ // Called in dec_refcnt, jffs2_find // (and jffs2_open and jffs2_ops_mkdir?) // super.c jffs2_read_super, // and gc.c jffs2_garbage_collect_pass struct inode *cached_inode; D2(printf ("free iput inode %x $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n", i)); if (i && i->i_count) { /* Added by dwmw2. iget/iput in Linux track the use count, don't just unconditionally free it */ printf("iput called for used inode\n"); return; } if (i != NULL) { // Remove from the icache for (cached_inode = i->i_sb->s_root; cached_inode != NULL; cached_inode = cached_inode->i_cache_next) { if (cached_inode == i) { cached_inode->i_cache_prev->i_cache_next = cached_inode->i_cache_next; // Prveious entry points ahead of us if (cached_inode->i_cache_next != NULL) cached_inode->i_cache_next->i_cache_prev = cached_inode->i_cache_prev; // Next entry points behind us break; } } // inode has been seperated from the cache jffs2_clear_inode(i); free(i); }}static int return_EIO(void){ return -EIO;}#define EIO_ERROR ((void *) (return_EIO))void make_bad_inode(struct inode *inode){ // In readinode.c JFFS2 checks whether the inode has appropriate // content for its marked type D2(printf("make_bad_inode\n")); inode->i_mode = S_IFREG; inode->i_atime = inode->i_mtime = inode->i_ctime = cyg_timestamp(); inode->i_op = EIO_ERROR; inode->i_fop = EIO_ERROR;}int is_bad_inode(struct inode *inode){ // Called in super.c jffs2_read_super, // and gc.c jffs2_garbage_collect_pass D2(printf("is_bad_inode\n")); return (inode->i_op == EIO_ERROR); /*if(i == NULL) return 1; return 0; */}cyg_bool jffs2_flash_read(struct jffs2_sb_info * c, cyg_uint32 read_buffer_offset, const size_t size, size_t * return_size, char *write_buffer){ Cyg_ErrNo err; cyg_uint32 len = size; struct super_block *sb = OFNI_BS_2SFFJ(c); //D2(printf("FLASH READ\n")); //D2(printf("read address = %x\n", CYGNUM_FS_JFFS2_BASE_ADDRESS + read_buffer_offset)); //D2(printf("write address = %x\n", write_buffer)); //D2(printf("size = %x\n", size)); err = cyg_io_bread(sb->s_dev, write_buffer, &len, read_buffer_offset); *return_size = (size_t) len; return (err != ENOERR);}cyg_bool jffs2_flash_write(struct jffs2_sb_info * c, cyg_uint32 write_buffer_offset, const size_t size, size_t * return_size, char *read_buffer){ Cyg_ErrNo err; cyg_uint32 len = size; struct super_block *sb = OFNI_BS_2SFFJ(c); // D2(printf("FLASH WRITE ENABLED!!!\n")); // D2(printf("write address = %x\n", CYGNUM_FS_JFFS2_BASE_ADDRESS + write_buffer_offset)); // D2(printf("read address = %x\n", read_buffer)); // D2(printf("size = %x\n", size)); err = cyg_io_bwrite(sb->s_dev, read_buffer, &len, write_buffer_offset); *return_size = (size_t) len; return (err != ENOERR);}intjffs2_flash_writev(struct jffs2_sb_info *c, const struct iovec *vecs, unsigned long count, loff_t to, size_t * retlen){ unsigned long i; size_t totlen = 0, thislen; int ret = 0; for (i = 0; i < count; i++) { // writes need to be aligned but the data we're passed may not be // Observation suggests most unaligned writes are small, so we // optimize for that case. if (((vecs[i].iov_len & (sizeof (int) - 1))) || (((unsigned long) vecs[i]. iov_base & (sizeof (unsigned long) - 1)))) { // are there iov's after this one? Or is it so much we'd need // to do multiple writes anyway? if ((i + 1) < count || vecs[i].iov_len > 256) { // cop out and malloc unsigned long j; ssize_t sizetomalloc = 0, totvecsize = 0; char *cbuf, *cbufptr; for (j = i; j < count; j++) totvecsize += vecs[j].iov_len; // pad up in case unaligned sizetomalloc = totvecsize + sizeof (int) - 1; sizetomalloc &= ~(sizeof (int) - 1); cbuf = (char *) malloc(sizetomalloc); // malloc returns aligned memory if (!cbuf) { ret = -ENOMEM; goto writev_out; } cbufptr = cbuf; for (j = i; j < count; j++) { memcpy(cbufptr, vecs[j].iov_base, vecs[j].iov_len); cbufptr += vecs[j].iov_len; } ret = jffs2_flash_write(c, to, sizetomalloc, &thislen, cbuf); if (thislen > totvecsize) // in case it was aligned up thislen = totvecsize; totlen += thislen; free(cbuf); goto writev_out; } else { // otherwise optimize for the common case int buf[256 / sizeof (int)]; // int, so int aligned size_t lentowrite; lentowrite = vecs[i].iov_len; // pad up in case its unaligned lentowrite += sizeof (int) - 1; lentowrite &= ~(sizeof (int) - 1); memcpy(buf, vecs[i].iov_base, lentowrite); ret = jffs2_flash_write(c, to, lentowrite, &thislen, (char *) &buf); if (thislen > vecs[i].iov_len) thislen = vecs[i].iov_len; } // else } else ret = jffs2_flash_write(c, to, vecs[i].iov_len, &thislen, vecs[i].iov_base); totlen += thislen; if (ret || thislen != vecs[i].iov_len) break; to += vecs[i].iov_len; } writev_out: if (retlen) *retlen = totlen; return ret;}cyg_bool jffs2_flash_erase(struct jffs2_sb_info * c, struct jffs2_eraseblock * jeb){ cyg_io_flash_getconfig_erase_t e; void *err_addr; Cyg_ErrNo err; cyg_uint32 len = sizeof (e); struct super_block *sb = OFNI_BS_2SFFJ(c); e.offset = jeb->offset; e.len = c->sector_size; e.err_address = &err_addr; // D2(printf("FLASH ERASE ENABLED!!!\n")); // D2(printf("erase address = %x\n", CYGNUM_FS_JFFS2_BASE_ADDRESS + jeb->offset)); // D2(printf("size = %x\n", c->sector_size)); err = cyg_io_get_config(sb->s_dev, CYG_IO_GET_CONFIG_FLASH_ERASE, &e, &len); return (err != ENOERR || e.flasherr != 0);}// -------------------------------------------------------------------------// EOF jffs2.cvoid 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) { make_bad_inode(inode); 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; insert_inode_hash(inode); return inode;}void 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) { make_bad_inode(inode); up(&f->sem); return; } 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"));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -