Mercurial > flash_v2
changeset 1562:8bafb5f8a697
Merge changes from MTD - fix file truncate issue
| author | gthomas |
|---|---|
| date | Thu, 01 Apr 2004 03:17:55 +0000 |
| parents | 31dd38f564ec |
| children | 4e2a59620a29 |
| files | packages/fs/jffs2/current/ChangeLog packages/fs/jffs2/current/doc/TODO packages/fs/jffs2/current/src/compr.c packages/fs/jffs2/current/src/fs-ecos.c packages/fs/jffs2/current/src/gc.c packages/fs/jffs2/current/src/nodelist.h packages/fs/jffs2/current/src/read.c packages/fs/jffs2/current/src/scan.c packages/fs/jffs2/current/src/write.c |
| diffstat | 9 files changed, 142 insertions(+), 86 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/fs/jffs2/current/ChangeLog +++ b/packages/fs/jffs2/current/ChangeLog @@ -1,3 +1,8 @@ +2004-03-31 David Woodhouse <dwmw2@infradead.org> + + * src/fs-ecos.c (jffs2_fo_write): Set ri.isize so that non-append + writes don't truncate the file. + 2004-03-03 Thomas Koeller <thomas.koeller@baslerweb.com> * src/fs-ecos.c:
--- a/packages/fs/jffs2/current/doc/TODO +++ b/packages/fs/jffs2/current/doc/TODO @@ -1,5 +1,11 @@ -$Id: TODO,v 1.15 2003/10/06 14:50:37 dwmw2 Exp $ +$Id: TODO,v 1.16 2004/03/20 15:01:34 dwmw2 Exp $ + - support asynchronous operation -- add a per-fs 'reserved_space' count, + let each outstanding write reserve the _maximum_ amount of physical + space it could take. Let GC flush the outstanding writes because the + reservations will necessarily be pessimistic. With this we could even + do shared writable mmap, if we can have a fs hook for do_wp_page() to + make the reservation. - disable compression in commit_write()? - fine-tune the allocation / GC thresholds - chattr support - turning on/off and tuning compression per-inode
--- a/packages/fs/jffs2/current/src/compr.c +++ b/packages/fs/jffs2/current/src/compr.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: compr.c,v 1.33 2003/11/28 17:22:54 dwmw2 Exp $ + * $Id: compr.c,v 1.34 2004/03/08 15:29:09 dwmw2 Exp $ * */ @@ -46,8 +46,9 @@ void jffs2_dynrubin_decompress(unsigned * jffs2_compress should compress as much as will fit, and should set * *datalen accordingly to show the amount of data which were compressed. */ -unsigned char jffs2_compress(unsigned char *data_in, unsigned char **cpage_out, - uint32_t *datalen, uint32_t *cdatalen) +unsigned char jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, + unsigned char *data_in, unsigned char **cpage_out, + uint32_t *datalen, uint32_t *cdatalen) { #ifdef JFFS2_COMPRESSION int ret; @@ -97,7 +98,8 @@ void jffs2_free_comprbuf(unsigned char * kfree(comprbuf); } -int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in, +int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, + unsigned char comprtype, unsigned char *cdata_in, unsigned char *data_out, uint32_t cdatalen, uint32_t datalen) { switch (comprtype) {
--- a/packages/fs/jffs2/current/src/fs-ecos.c +++ b/packages/fs/jffs2/current/src/fs-ecos.c @@ -8,7 +8,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: fs-ecos.c,v 1.33 2003/12/02 10:43:03 dwmw2 Exp $ + * $Id: fs-ecos.c,v 1.34 2004/03/31 12:17:09 dwmw2 Exp $ * */ @@ -1347,6 +1347,7 @@ static int jffs2_fo_write(struct CYG_FIL if (err) return -err; } + ri.isize = cpu_to_je32(inode->i_size); // Now loop over the iovecs until they are all done, or // we get an error.
--- a/packages/fs/jffs2/current/src/gc.c +++ b/packages/fs/jffs2/current/src/gc.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: gc.c,v 1.132 2003/12/01 11:32:11 dwmw2 Exp $ + * $Id: gc.c,v 1.133 2004/03/08 15:29:09 dwmw2 Exp $ * */ @@ -674,7 +674,7 @@ static int jffs2_garbage_collect_metadat printk(KERN_WARNING "kmalloc of mdata failed in jffs2_garbage_collect_metadata()\n"); return -ENOMEM; } - ret = jffs2_read_dnode(c, fn, mdata, 0, mdatalen); + ret = jffs2_read_dnode(c, f, fn, mdata, 0, mdatalen); if (ret) { printk(KERN_WARNING "read of old metadata failed in jffs2_garbage_collect_metadata(): %d\n", ret); kfree(mdata); @@ -1190,7 +1190,7 @@ static int jffs2_garbage_collect_dnode(s writebuf = pg_ptr + (offset & (PAGE_CACHE_SIZE -1)); - comprtype = jffs2_compress(writebuf, &comprbuf, &datalen, &cdatalen); + comprtype = jffs2_compress(c, f, writebuf, &comprbuf, &datalen, &cdatalen); ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
--- a/packages/fs/jffs2/current/src/nodelist.h +++ b/packages/fs/jffs2/current/src/nodelist.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.h,v 1.115 2003/11/26 15:30:58 dwmw2 Exp $ + * $Id: nodelist.h,v 1.116 2004/03/08 15:29:09 dwmw2 Exp $ * */ @@ -432,16 +432,20 @@ void jffs2_free_inode_cache(struct jffs2 int jffs2_garbage_collect_pass(struct jffs2_sb_info *c); /* read.c */ -int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_full_dnode *fd, unsigned char *buf, int ofs, int len); +int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, + struct jffs2_full_dnode *fd, unsigned char *buf, + int ofs, int len); int jffs2_read_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, unsigned char *buf, uint32_t offset, uint32_t len); char *jffs2_getlink(struct jffs2_sb_info *c, struct jffs2_inode_info *f); /* compr.c */ -unsigned char jffs2_compress(unsigned char *data_in, unsigned char **cpage_out, +unsigned char jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, + unsigned char *data_in, unsigned char **cpage_out, uint32_t *datalen, uint32_t *cdatalen); void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig); -int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in, +int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, + unsigned char comprtype, unsigned char *cdata_in, unsigned char *data_out, uint32_t cdatalen, uint32_t datalen); /* scan.c */
--- a/packages/fs/jffs2/current/src/read.c +++ b/packages/fs/jffs2/current/src/read.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: read.c,v 1.34 2003/10/04 08:33:06 dwmw2 Exp $ + * $Id: read.c,v 1.35 2004/03/08 15:29:09 dwmw2 Exp $ * */ @@ -19,7 +19,9 @@ #include <linux/compiler.h> #include "nodelist.h" -int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_full_dnode *fd, unsigned char *buf, int ofs, int len) +int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, + struct jffs2_full_dnode *fd, unsigned char *buf, + int ofs, int len) { struct jffs2_raw_inode *ri; size_t readlen; @@ -127,7 +129,7 @@ int jffs2_read_dnode(struct jffs2_sb_inf if (ri->compr != JFFS2_COMPR_NONE) { D2(printk(KERN_DEBUG "Decompress %d bytes from %p to %d bytes at %p\n", je32_to_cpu(ri->csize), readbuf, je32_to_cpu(ri->dsize), decomprbuf)); - ret = jffs2_decompress(ri->compr, readbuf, decomprbuf, je32_to_cpu(ri->csize), je32_to_cpu(ri->dsize)); + ret = jffs2_decompress(c, f, ri->compr, readbuf, decomprbuf, je32_to_cpu(ri->csize), je32_to_cpu(ri->dsize)); if (ret) { printk(KERN_WARNING "Error: jffs2_decompress returned %d\n", ret); goto out_decomprbuf; @@ -195,7 +197,7 @@ int jffs2_read_inode_range(struct jffs2_ D1(printk(KERN_DEBUG "Reading %d-%d from node at 0x%08x (%d)\n", frag->ofs+fragofs, frag->ofs+fragofs+readlen, ref_offset(frag->node->raw), ref_flags(frag->node->raw))); - ret = jffs2_read_dnode(c, frag->node, buf, fragofs + frag->ofs - frag->node->ofs, readlen); + ret = jffs2_read_dnode(c, f, frag->node, buf, fragofs + frag->ofs - frag->node->ofs, readlen); D2(printk(KERN_DEBUG "node read done\n")); if (ret) { D1(printk(KERN_DEBUG"jffs2_read_inode_range error %d\n",ret)); @@ -231,7 +233,7 @@ char *jffs2_getlink(struct jffs2_sb_info } buf[f->metadata->size]=0; - ret = jffs2_read_dnode(c, f->metadata, buf, 0, f->metadata->size); + ret = jffs2_read_dnode(c, f, f->metadata, buf, 0, f->metadata->size); up(&f->sem);
--- a/packages/fs/jffs2/current/src/scan.c +++ b/packages/fs/jffs2/current/src/scan.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: scan.c,v 1.106 2003/10/28 17:01:13 dwmw2 Exp $ + * $Id: scan.c,v 1.109 2004/03/19 16:40:50 dwmw2 Exp $ * */ #include <linux/kernel.h> @@ -285,8 +285,6 @@ static int jffs2_scan_eraseblock (struct uint32_t hdr_crc, buf_ofs, buf_len; int err; int noise = 0; - int wasempty = 0; - uint32_t empty_start = 0; #ifdef CONFIG_JFFS2_FS_NAND int cleanmarkerfound = 0; #endif @@ -359,6 +357,7 @@ static int jffs2_scan_eraseblock (struct noise = 10; +scan_more: while(ofs < jeb->offset + c->sector_size) { D1(ACCT_PARANOIA_CHECK(jeb)); @@ -398,42 +397,52 @@ static int jffs2_scan_eraseblock (struct node = (struct jffs2_unknown_node *)&buf[ofs-buf_ofs]; if (*(uint32_t *)(&buf[ofs-buf_ofs]) == 0xffffffff) { - uint32_t inbuf_ofs = ofs - buf_ofs + 4; - uint32_t scanend; + uint32_t inbuf_ofs; + uint32_t empty_start; empty_start = ofs; ofs += 4; - /* If scanning empty space after only a cleanmarker, don't - bother scanning the whole block */ - if (unlikely(empty_start == jeb->offset + c->cleanmarker_size && - jeb->offset + EMPTY_SCAN_SIZE < buf_ofs + buf_len)) - scanend = jeb->offset + EMPTY_SCAN_SIZE - buf_ofs; - else - scanend = buf_len; - D1(printk(KERN_DEBUG "Found empty flash at 0x%08x\n", ofs)); - while (inbuf_ofs < scanend) { - if (*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff) - goto emptyends; + more_empty: + inbuf_ofs = ofs - buf_ofs; + while (inbuf_ofs < buf_len) { + if (*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff) { + printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n", + empty_start, ofs); + DIRTY_SPACE(ofs-empty_start); + goto scan_more; + } inbuf_ofs+=4; ofs += 4; } /* Ran off end. */ - D1(printk(KERN_DEBUG "Empty flash ends normally at 0x%08x\n", ofs)); + D1(printk(KERN_DEBUG "Empty flash to end of buffer at 0x%08x\n", ofs)); - if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) && - c->cleanmarker_size && !jeb->first_node->next_in_ino && !jeb->dirty_size) + /* If we're only checking the beginning of a block with a cleanmarker, + bail now */ + if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) && + c->cleanmarker_size && !jeb->dirty_size && !jeb->first_node->next_in_ino) { + D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE)); return BLK_STATE_CLEANMARKER; - wasempty = 1; - continue; - } else if (wasempty) { - emptyends: - printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n", empty_start, ofs); - DIRTY_SPACE(ofs-empty_start); - wasempty = 0; - continue; + } + + /* See how much more there is to read in this eraseblock... */ + buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); + if (!buf_len) { + /* No more to read. Break out of main loop without marking + this range of empty space as dirty (because it's not) */ + D1(printk(KERN_DEBUG "Empty flash at %08x runs to end of block. Treating as free_space\n", + empty_start)); + break; + } + D1(printk(KERN_DEBUG "Reading another 0x%x at 0x%08x\n", buf_len, ofs)); + err = jffs2_fill_scan_buf(c, buf, ofs, buf_len); + if (err) + return err; + buf_ofs = ofs; + goto more_empty; } if (ofs == jeb->offset && je16_to_cpu(node->magic) == KSAMTIB_CIGAM_2SFFJ) { @@ -610,7 +619,7 @@ static int jffs2_scan_eraseblock (struct } if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size - && (!jeb->first_node || jeb->first_node->next_in_ino) ) + && (!jeb->first_node || !jeb->first_node->next_in_ino) ) return BLK_STATE_CLEANMARKER; /* move blocks with max 4 byte dirty space to cleanlist */
--- a/packages/fs/jffs2/current/src/write.c +++ b/packages/fs/jffs2/current/src/write.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: write.c,v 1.81 2004/02/17 14:58:16 dwmw2 Exp $ + * $Id: write.c,v 1.83 2004/03/30 09:36:09 dwmw2 Exp $ * */ @@ -375,7 +375,7 @@ int jffs2_write_inode_range(struct jffs2 datalen = min_t(uint32_t, writelen, PAGE_CACHE_SIZE - (offset & (PAGE_CACHE_SIZE-1))); cdatalen = min_t(uint32_t, alloclen - sizeof(*ri), datalen); - comprtype = jffs2_compress(buf, &comprbuf, &datalen, &cdatalen); + comprtype = jffs2_compress(c, f, buf, &comprbuf, &datalen, &cdatalen); ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); @@ -543,48 +543,75 @@ int jffs2_do_unlink(struct jffs2_sb_info uint32_t alloclen, phys_ofs; int ret; - rd = jffs2_alloc_raw_dirent(); - if (!rd) - return -ENOMEM; + if (1 /* alternative branch needs testing */ || + !jffs2_can_mark_obsolete(c)) { + /* We can't mark stuff obsolete on the medium. We need to write a deletion dirent */ + + rd = jffs2_alloc_raw_dirent(); + if (!rd) + return -ENOMEM; + + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_DELETION); + if (ret) { + jffs2_free_raw_dirent(rd); + return ret; + } + + down(&dir_f->sem); + + /* Build a deletion node */ + rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); + rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); + rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); + + rd->pino = cpu_to_je32(dir_f->inocache->ino); + rd->version = cpu_to_je32(++dir_f->highest_version); + rd->ino = cpu_to_je32(0); + rd->mctime = cpu_to_je32(get_seconds()); + rd->nsize = namelen; + rd->type = DT_UNKNOWN; + rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); + rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_DELETION); - if (ret) { + fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_DELETION); + jffs2_free_raw_dirent(rd); - return ret; + + if (IS_ERR(fd)) { + jffs2_complete_reservation(c); + up(&dir_f->sem); + return PTR_ERR(fd); + } + + /* File it. This will mark the old one obsolete. */ + jffs2_add_fd_to_list(c, fd, &dir_f->dents); + up(&dir_f->sem); + } else { + struct jffs2_full_dirent **prev = &dir_f->dents; + uint32_t nhash = full_name_hash(name, namelen); + + down(&dir_f->sem); + + while ((*prev) && (*prev)->nhash <= nhash) { + if ((*prev)->nhash == nhash && + !memcmp((*prev)->name, name, namelen) && + !(*prev)->name[namelen]) { + struct jffs2_full_dirent *this = *prev; + + D1(printk(KERN_DEBUG "Marking old dirent node (ino #%u) @%08x obsolete\n", + this->ino, ref_offset(this->raw))); + + *prev = this->next; + jffs2_mark_node_obsolete(c, (this->raw)); + jffs2_free_full_dirent(this); + break; + } + prev = &((*prev)->next); + } + up(&dir_f->sem); } - down(&dir_f->sem); - - /* Build a deletion node */ - rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); - rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); - rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); - rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); - - rd->pino = cpu_to_je32(dir_f->inocache->ino); - rd->version = cpu_to_je32(++dir_f->highest_version); - rd->ino = cpu_to_je32(0); - rd->mctime = cpu_to_je32(get_seconds()); - rd->nsize = namelen; - rd->type = DT_UNKNOWN; - rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); - rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); - - fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_DELETION); - - jffs2_free_raw_dirent(rd); - - if (IS_ERR(fd)) { - jffs2_complete_reservation(c); - up(&dir_f->sem); - return PTR_ERR(fd); - } - - /* File it. This will mark the old one obsolete. */ - jffs2_add_fd_to_list(c, fd, &dir_f->dents); - - up(&dir_f->sem); - /* dead_f is NULL if this was a rename not a real unlink */ /* Also catch the !f->inocache case, where there was a dirent pointing to an inode which didn't exist. */
