diff -urN linux-2.4.10-wt1-5e/fs/Config.in linux-2.4.10-wt1/fs/Config.in --- linux-2.4.10-wt1-5e/fs/Config.in Sun Oct 7 17:27:52 2001 +++ linux-2.4.10-wt1/fs/Config.in Sun Oct 7 18:58:30 2001 @@ -41,9 +41,10 @@ int 'JFFS debugging verbosity (0 = quiet, 3 = noisy)' CONFIG_JFFS_FS_VERBOSE 0 bool 'JFFS stats available in /proc filesystem' CONFIG_JFFS_PROC_FS fi -dep_tristate 'Journalling Flash File System v2 (JFFS2) support' CONFIG_JFFS2_FS $CONFIG_MTD +tristate 'Journalling Flash File System v2 (JFFS2) support' CONFIG_JFFS2_FS if [ "$CONFIG_JFFS2_FS" = "y" -o "$CONFIG_JFFS2_FS" = "m" ] ; then int 'JFFS2 debugging verbosity (0 = quiet, 2 = noisy)' CONFIG_JFFS2_FS_DEBUG 0 + bool 'JFFS2 support for non-MTD block devices' CONFIG_JFFS2_NON_MTD_BD fi tristate 'Compressed ROM file system support' CONFIG_CRAMFS bool 'Virtual memory file system support (former shm fs)' CONFIG_TMPFS diff -urN linux-2.4.10-wt1-5e/fs/jffs2/Makefile linux-2.4.10-wt1/fs/jffs2/Makefile --- linux-2.4.10-wt1-5e/fs/jffs2/Makefile Sun Oct 7 17:27:55 2001 +++ linux-2.4.10-wt1/fs/jffs2/Makefile Sun Oct 7 18:59:41 2001 @@ -16,6 +16,10 @@ read.o nodemgmt.o readinode.o super.o write.o scan.o gc.o \ symlink.o build.o erase.o background.o +ifdef CONFIG_JFFS2_NON_MTD_BD +JFFS2_OBJS += blockdev.o +endif + O_TARGET := jffs2.o obj-y := $(COMPR_OBJS) $(JFFS2_OBJS) diff -urN linux-2.4.10-wt1-5e/fs/jffs2/blockdev.c linux-2.4.10-wt1/fs/jffs2/blockdev.c --- linux-2.4.10-wt1-5e/fs/jffs2/blockdev.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.10-wt1/fs/jffs2/blockdev.c Sun Oct 7 18:58:30 2001 @@ -0,0 +1,192 @@ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * JFFS2 is Copyright (C) 2001 Red Hat, Inc. + * + * blockdev.c : standard block device support for JFFS2. + * + * Created by Willy Tarreau + * Mainly inspired from David Woodhouse's code. + * + * The original JFFS, from which the design for JFFS2 was derived, + * was designed and implemented by Axis Communications AB. + * + * The contents of this file are subject to the Red Hat eCos Public + * License Version 1.1 (the "Licence"); you may not use this file + * except in compliance with the Licence. You may obtain a copy of + * the Licence at http://www.redhat.com/ + * + * Software distributed under the Licence is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the Licence for the specific language governing rights and + * limitations under the Licence. + * + * The Original Code is JFFS2 - Journalling Flash File System, version 2 + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License version 2 (the "GPL"), in + * which case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use your + * version of this file under the RHEPL, indicate your decision by + * deleting the provisions above and replace them with the notice and + * other provisions required by the GPL. If you do not delete the + * provisions above, a recipient may use your version of this file + * under either the RHEPL or the GPL. + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nodelist.h" + +int jffs2_bd_read(struct mtd_info *mtd, loff_t offset, size_t len, + size_t *retlen, u_char *buf) +{ + struct buffer_head *bh; + struct super_block *sb = (struct super_block *)mtd->priv; + size_t bytesleft; + int blocknr; + + if (offset + len > mtd->size) { + DEBUG(MTD_DEBUG_LEVEL1, "jffs2_bd_read() out of bounds (%ld > %ld)\n", (long)(offset + len), (long)mtd->size); + return -EINVAL; + } + + blocknr = offset >> sb->s_blocksize_bits; + offset &= sb->s_blocksize - 1; + + bytesleft = len; + + while (bytesleft > 0) { + size_t readlen; + + readlen = bytesleft; + if (readlen + offset > sb->s_blocksize) + readlen = sb->s_blocksize - offset; + + bh = getblk(sb->s_dev, blocknr, sb->s_blocksize); + if (!buffer_uptodate(bh)) { + ll_rw_block(READ, 1, &bh); + wait_on_buffer(bh); + } + + memcpy(buf, bh->b_data + offset, readlen); + brelse(bh); + + buf += readlen; + bytesleft -= readlen; + offset = 0; + blocknr++; + } + *retlen=len; + return 0; +} + +int jffs2_bd_write(struct mtd_info *mtd, loff_t offset, size_t len, + size_t *retlen, const u_char *buf) +{ + struct buffer_head *bh; + struct super_block *sb = (struct super_block *)mtd->priv; + size_t bytesleft; + int blocknr; + + if (offset + len > mtd->size) { + DEBUG(MTD_DEBUG_LEVEL1, "jffs2_bd_write() out of bounds (%ld > %ld)\n", (long)(offset + len), (long)mtd->size); + return -EINVAL; + } + + blocknr = offset >> sb->s_blocksize_bits; + offset &= sb->s_blocksize - 1; + + bytesleft = len; + + while (bytesleft > 0) { + size_t writelen; + + writelen = bytesleft; + if (writelen + offset > sb->s_blocksize) + writelen = sb->s_blocksize - offset; + + bh = getblk(sb->s_dev, blocknr, sb->s_blocksize); + if (writelen < sb->s_blocksize) { /* incomplete block : must read it modifying it */ + if (!buffer_uptodate(bh)) { + ll_rw_block(READ, 1, &bh); + wait_on_buffer(bh); + } + } + + memcpy(bh->b_data + offset, buf, writelen); + mark_buffer_dirty(bh); + brelse(bh); + + buf += writelen; + bytesleft -= writelen; + offset = 0; + blocknr++; + } + *retlen=len; + return 0; +} + +int jffs2_bd_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + struct buffer_head *bh; + struct super_block *sb = (struct super_block *)mtd->priv; + loff_t offset = instr->addr; + size_t bytesleft = instr->len; + int blocknr; + + + if (offset + bytesleft > mtd->size) { + DEBUG(MTD_DEBUG_LEVEL1, "jffs2_bd_erase() out of bounds (%ld > %ld)\n", (long)(instr->addr + instr->len), (long)mtd->size); + return -EINVAL; + } + + blocknr = offset >> sb->s_blocksize_bits; + offset &= sb->s_blocksize - 1; + + while (bytesleft > 0) { + size_t writelen; + + writelen = bytesleft; + if (writelen + offset > sb->s_blocksize) + writelen = sb->s_blocksize - offset; + + bh = getblk(sb->s_dev, blocknr, sb->s_blocksize); + if (writelen < sb->s_blocksize) { /* incomplete block : must read it modifying it */ + if (!buffer_uptodate(bh)) { + ll_rw_block(READ, 1, &bh); + wait_on_buffer(bh); + } + } + + memset(bh->b_data + offset, 0xff, writelen); + mark_buffer_dirty(bh); + brelse(bh); + + bytesleft -= writelen; + offset = 0; + blocknr++; + } + + instr->state = MTD_ERASE_DONE; + + if (instr->callback) + (*(instr->callback))(instr); + + return 0; +} diff -urN linux-2.4.10-wt1-5e/fs/jffs2/compr.c linux-2.4.10-wt1/fs/jffs2/compr.c --- linux-2.4.10-wt1-5e/fs/jffs2/compr.c Sun Oct 7 17:27:55 2001 +++ linux-2.4.10-wt1/fs/jffs2/compr.c Sun Oct 7 18:58:30 2001 @@ -41,7 +41,7 @@ #include #include -int zlib_compress(unsigned char *data_in, unsigned char *cpage_out, __u32 *sourcelen, __u32 *dstlen); +int zlib_compress(unsigned char *data_in, unsigned char *cpage_out, __u32 *sourcelen, __u32 *dstlen, int level); void zlib_decompress(unsigned char *data_in, unsigned char *cpage_out, __u32 srclen, __u32 destlen); int rtime_compress(unsigned char *data_in, unsigned char *cpage_out, __u32 *sourcelen, __u32 *dstlen); void rtime_decompress(unsigned char *data_in, unsigned char *cpage_out, __u32 srclen, __u32 destlen); @@ -69,11 +69,11 @@ * *datalen accordingly to show the amount of data which were compressed. */ unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out, - __u32 *datalen, __u32 *cdatalen) + __u32 *datalen, __u32 *cdatalen, int level) { int ret; - ret = zlib_compress(data_in, cpage_out, datalen, cdatalen); + ret = zlib_compress(data_in, cpage_out, datalen, cdatalen, level); if (!ret) { return JFFS2_COMPR_ZLIB; } diff -urN linux-2.4.10-wt1-5e/fs/jffs2/compr_zlib.c linux-2.4.10-wt1/fs/jffs2/compr_zlib.c --- linux-2.4.10-wt1-5e/fs/jffs2/compr_zlib.c Sun Oct 7 17:27:55 2001 +++ linux-2.4.10-wt1/fs/jffs2/compr_zlib.c Sun Oct 7 18:58:30 2001 @@ -77,7 +77,7 @@ #define STREAM_END_SPACE 12 int zlib_compress(unsigned char *data_in, unsigned char *cpage_out, - __u32 *sourcelen, __u32 *dstlen) + __u32 *sourcelen, __u32 *dstlen, int level) { z_stream strm; int ret; @@ -93,7 +93,7 @@ strm.zfree = (void *)0; #endif - if (Z_OK != deflateInit(&strm, 3)) { + if (Z_OK != deflateInit(&strm, level)) { printk(KERN_WARNING "deflateInit failed\n"); return -1; } diff -urN linux-2.4.10-wt1-5e/fs/jffs2/comprtest.c linux-2.4.10-wt1/fs/jffs2/comprtest.c --- linux-2.4.10-wt1-5e/fs/jffs2/comprtest.c Sun Oct 7 17:23:02 2001 +++ linux-2.4.10-wt1/fs/jffs2/comprtest.c Sun Oct 7 18:58:30 2001 @@ -268,7 +268,7 @@ int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in, unsigned char *data_out, __u32 cdatalen, __u32 datalen); unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out, - __u32 *datalen, __u32 *cdatalen); + __u32 *datalen, __u32 *cdatalen, int level); int init_module(void ) { unsigned char comprtype; @@ -282,7 +282,7 @@ testdata[12],testdata[13],testdata[14],testdata[15]); d = TESTDATA_LEN; c = TESTDATA_LEN; - comprtype = jffs2_compress(testdata, comprbuf, &d, &c); + comprtype = jffs2_compress(testdata, comprbuf, &d, &c, 3); printk("jffs2_compress used compression type %d. Compressed size %d, uncompressed size %d\n", comprtype, c, d); diff -urN linux-2.4.10-wt1-5e/fs/jffs2/file.c linux-2.4.10-wt1/fs/jffs2/file.c --- linux-2.4.10-wt1-5e/fs/jffs2/file.c Sun Oct 7 17:27:55 2001 +++ linux-2.4.10-wt1/fs/jffs2/file.c Sun Oct 7 18:58:30 2001 @@ -445,7 +445,8 @@ comprbuf = kmalloc(cdatalen, GFP_KERNEL); if (comprbuf) { - comprtype = jffs2_compress(page_address(pg)+ (file_ofs & (PAGE_CACHE_SIZE-1)), comprbuf, &datalen, &cdatalen); + comprtype = jffs2_compress(page_address(pg)+ (file_ofs & (PAGE_CACHE_SIZE-1)), comprbuf, &datalen, &cdatalen, + (c->flags & JFFS2_SB_FLAG_DEFLATE_MASK) >> JFFS2_SB_FLAG_DEFLATE_SHIFT); } if (comprtype == JFFS2_COMPR_NONE) { /* Either compression failed, or the allocation of comprbuf failed */ diff -urN linux-2.4.10-wt1-5e/fs/jffs2/gc.c linux-2.4.10-wt1/fs/jffs2/gc.c --- linux-2.4.10-wt1-5e/fs/jffs2/gc.c Sun Oct 7 17:27:55 2001 +++ linux-2.4.10-wt1/fs/jffs2/gc.c Sun Oct 7 18:58:30 2001 @@ -606,7 +606,8 @@ writebuf = pg_ptr + (offset & (PAGE_CACHE_SIZE -1)); if (comprbuf) { - comprtype = jffs2_compress(writebuf, comprbuf, &datalen, &cdatalen); + comprtype = jffs2_compress(writebuf, comprbuf, &datalen, &cdatalen, + (c->flags & JFFS2_SB_FLAG_DEFLATE_MASK) >> JFFS2_SB_FLAG_DEFLATE_SHIFT); } if (comprtype) { writebuf = comprbuf; diff -urN linux-2.4.10-wt1-5e/fs/jffs2/nodelist.h linux-2.4.10-wt1/fs/jffs2/nodelist.h --- linux-2.4.10-wt1-5e/fs/jffs2/nodelist.h Sun Oct 7 17:27:55 2001 +++ linux-2.4.10-wt1/fs/jffs2/nodelist.h Sun Oct 7 18:58:30 2001 @@ -330,7 +330,7 @@ /* compr.c */ unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out, - __u32 *datalen, __u32 *cdatalen); + __u32 *datalen, __u32 *cdatalen, int level); int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in, unsigned char *data_out, __u32 cdatalen, __u32 datalen); diff -urN linux-2.4.10-wt1-5e/fs/jffs2/scan.c linux-2.4.10-wt1/fs/jffs2/scan.c --- linux-2.4.10-wt1-5e/fs/jffs2/scan.c Sun Oct 7 17:27:55 2001 +++ linux-2.4.10-wt1/fs/jffs2/scan.c Sun Oct 7 19:02:05 2001 @@ -137,9 +137,20 @@ } else { /* Nothing valid - not even a clean marker. Needs erasing. */ /* For now we just put it on the erasing list. We'll start the erases later */ - printk(KERN_NOTICE "JFFS2: Erase block at 0x%08x is not formatted. It will be erased\n", jeb->offset); - list_add(&jeb->list, &c->erase_pending_list); - c->nr_erasing_blocks++; +#ifdef CONFIG_JFFS2_NON_MTD_BD + if (!(c->flags & JFFS2_SB_FLAG_BLKDEV) || (c->flags & JFFS2_SB_FLAG_FORMAT)) +#else + if (1) +#endif + { + printk(KERN_NOTICE "JFFS2: Erase block at 0x%08x is not formatted. It will be erased\n", jeb->offset); + list_add(&jeb->list, &c->erase_pending_list); + c->nr_erasing_blocks++; + } else { + printk(KERN_NOTICE "JFFS2: Erase block at 0x%08x is not formatted." + " Remount with \"-o format\" to risk erasing. Aborting.\n", jeb->offset); + return 1; + } } } if (c->nr_erasing_blocks) { @@ -218,6 +229,12 @@ if (ofs == jeb->offset && node.magic == KSAMTIB_CIGAM_2SFFJ) { printk(KERN_WARNING "Magic bitmask is backwards at offset 0x%08x. Wrong endian filesystem?\n", ofs); +#ifdef CONFIG_JFFS2_NON_MTD_BD + if ((c->flags & JFFS2_SB_FLAG_BLKDEV) && !(c->flags & JFFS2_SB_FLAG_FORMAT)) { + printk(KERN_ERR "Remount with \"-o format\" to risk erasing. Aborting.\n"); + return 1; + } +#endif DIRTY_SPACE(4); ofs += 4; continue; @@ -231,6 +248,12 @@ if (node.magic == JFFS2_OLD_MAGIC_BITMASK) { printk(KERN_WARNING "Old JFFS2 bitmask found at 0x%08x\n", ofs); printk(KERN_WARNING "You cannot use older JFFS2 filesystems with newer kernels\n"); +#ifdef CONFIG_JFFS2_NON_MTD_BD + if ((c->flags & JFFS2_SB_FLAG_BLKDEV) && !(c->flags & JFFS2_SB_FLAG_FORMAT)) { + printk(KERN_ERR "Remount with \"-o format\" to risk erasing. Aborting.\n"); + return 1; + } +#endif DIRTY_SPACE(4); ofs += 4; continue; @@ -238,6 +261,12 @@ if (node.magic != JFFS2_MAGIC_BITMASK) { /* OK. We're out of possibilities. Whinge and move on */ noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n", JFFS2_MAGIC_BITMASK, ofs, node.magic); +#ifdef CONFIG_JFFS2_NON_MTD_BD + if ((c->flags & JFFS2_SB_FLAG_BLKDEV) && !(c->flags & JFFS2_SB_FLAG_FORMAT)) { + printk(KERN_ERR "Remount with \"-o format\" to risk erasing. Aborting.\n"); + return 1; + } +#endif DIRTY_SPACE(4); ofs += 4; continue; diff -urN linux-2.4.10-wt1-5e/fs/jffs2/super.c linux-2.4.10-wt1/fs/jffs2/super.c --- linux-2.4.10-wt1-5e/fs/jffs2/super.c Sun Oct 7 17:27:55 2001 +++ linux-2.4.10-wt1/fs/jffs2/super.c Sun Oct 7 19:06:15 2001 @@ -47,6 +47,8 @@ #include #include #include +#include +#include #include "nodelist.h" #ifndef MTD_BLOCK_MAJOR @@ -60,6 +62,24 @@ int jffs2_remount_fs (struct super_block *, int *, char *); extern void jffs2_clear_inode (struct inode *); +#ifdef CONFIG_JFFS2_NON_MTD_BD +#if !defined(CONFIG_MTD_BLOCK) && !defined(CONFIG_MTD_BLOCK_MODULE) +# define get_mtd_device(dummy1, dummy2) NULL +# define put_mtd_device(dummy) do {} while(0) +#endif + +/* masks all bits of (x) except the most significant */ +#define CALC_MSB(x) ({ long signed m = ~((unsigned)(x)>>1); \ + m &= m >> 1; m &= m >> 2; m &= m >> 4; m &= m >> 8; \ + m &= m >>16; m &= (x); }) + +extern int jffs2_bd_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); +extern int jffs2_bd_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf); +extern int jffs2_bd_erase(struct mtd_info *mtd, struct erase_info *instr); +#endif /* CONFIG_JFFS2_NON_MTD_BD */ + static struct super_operations jffs2_super_operations = { read_inode: jffs2_read_inode, @@ -191,6 +211,66 @@ return 0; } +/* returns zero if an error occurs */ +static int parse_options(struct jffs2_sb_info *c, char *options) +{ + char *sep, *end; + + if (!options) + return 1; + + while (*options) { + sep = options; + while (*sep && *sep != ',' && *sep != '=') + sep++; + if (*sep == '=') { + end = sep; + while (*end && *end != ',') + end++; + } + else { + end = sep; + } + + /* test for boolean arguments */ +#ifdef CONFIG_JFFS2_NON_MTD_BD + if (!strncmp(options, "blkdev", sep-options)) + c->flags |= JFFS2_SB_FLAG_BLKDEV; /* allows an MTD device to be mounted as a blkdev */ + else if (!strncmp(options, "format", sep-options)) + c->flags |= JFFS2_SB_FLAG_FORMAT; /* enables format for blkdev */ + else +#endif + if (*sep == '=') { + /* value-assigned arguments */ + if (!strncmp(options, "deflate", sep-options)) { /* set compression level */ + int level = 0; + + while (isdigit(*++sep)) { + level = 10 * level + *sep - '0'; + } + + if (level < 0 || level > 9) { + printk(KERN_WARNING "JFFS2: ignoring wrong deflate level %d.\n", level); + level = 3; + } + c->flags &= ~JFFS2_SB_FLAG_DEFLATE_MASK; + c->flags |= level << JFFS2_SB_FLAG_DEFLATE_SHIFT; + } + else { + printk(KERN_WARNING "JFFS2: ignoring unkown mount option.\n"); + } + } + else { + printk(KERN_WARNING "JFFS2: ignoring unkown mount option.\n"); + } + + options = end; + if (*options) + options++; + } + return 1; +} + static struct super_block *jffs2_read_super(struct super_block *sb, void *data, int silent) { struct jffs2_sb_info *c; @@ -199,26 +279,68 @@ D1(printk(KERN_DEBUG "jffs2: read_super for device %s\n", kdevname(sb->s_dev))); - if (MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR) { - if (!silent) - printk(KERN_DEBUG "jffs2: attempt to mount non-MTD device %s\n", kdevname(sb->s_dev)); + c = JFFS2_SB_INFO(sb); + memset(c, 0, sizeof(*c)); + + c->flags = JFFS2_SB_FLAG_DEFLATE_DEFAULT; + + if (sb->s_flags & MS_RDONLY) + c->flags |= JFFS2_SB_FLAG_RO; + + if (!parse_options(c, data)) { return NULL; } - c = JFFS2_SB_INFO(sb); - memset(c, 0, sizeof(*c)); - - c->mtd = get_mtd_device(NULL, MINOR(sb->s_dev)); - if (!c->mtd) { - D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", MINOR(sb->s_dev))); + if (!(c->flags & JFFS2_SB_FLAG_BLKDEV) && (MAJOR(sb->s_dev) == MTD_BLOCK_MAJOR)) { + c->mtd = get_mtd_device(NULL, MINOR(sb->s_dev)); + if (!c->mtd) { + D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", MINOR(sb->s_dev))); + return NULL; + } + } + else { +#ifdef CONFIG_JFFS2_NON_MTD_BD + c->flags |= JFFS2_SB_FLAG_BLKDEV; + c->mtd = kmalloc(sizeof(*c->mtd), GFP_KERNEL); + memset(c->mtd, 0, sizeof(*c->mtd)); + + if (blk_size[MAJOR(sb->s_dev)]) + c->mtd->size = (loff_t) blk_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)] << BLOCK_SIZE_BITS; + else { + printk(KERN_ERR "jffs2: unknown size for device #%x:%x\n", MAJOR(sb->s_dev), MINOR(sb->s_dev)); + goto out_mtd; + } + + /* this makes a 256 kB erase size for a 32 MB device, and only reserves about 3% space */ + c->mtd->erasesize = CALC_MSB(c->mtd->size / 128); + if (c->mtd->erasesize < PAGE_CACHE_SIZE) + c->mtd->erasesize = PAGE_CACHE_SIZE; + c->mtd->name = "JFFS2 on block device"; + c->mtd->type = MTD_OTHER; + c->mtd->flags = 0; + c->mtd->priv = sb; + c->mtd->module = THIS_MODULE; + c->mtd->point = NULL; + c->mtd->unpoint = NULL; + c->mtd->erase = jffs2_bd_erase; + c->mtd->read = jffs2_bd_read; + c->mtd->write = jffs2_bd_write; + D1(printk(KERN_DEBUG "jffs2: mounting device %d:%d as a block device of %d bytes, with erase size=%d\n", + MAJOR(sb->s_dev), MINOR(sb->s_dev), c->mtd->size, c->mtd->erasesize)); +#else + if (!silent) + printk(KERN_DEBUG "jffs2: attempt to mount non-MTD device %s\n", kdevname(sb->s_dev)); return NULL; +#endif } + c->sector_size = c->mtd->erasesize; c->free_size = c->flash_size = c->mtd->size; c->nr_blocks = c->mtd->size / c->mtd->erasesize; c->blocks = kmalloc(sizeof(struct jffs2_eraseblock) * c->nr_blocks, GFP_KERNEL); if (!c->blocks) goto out_mtd; + for (i=0; inr_blocks; i++) { INIT_LIST_HEAD(&c->blocks[i].list); c->blocks[i].offset = i * c->sector_size; @@ -280,7 +402,12 @@ jffs2_free_raw_node_refs(c); kfree(c->blocks); out_mtd: - put_mtd_device(c->mtd); +#ifdef CONFIG_JFFS2_NON_MTD_BD + if (c->mtd->priv == sb) + kfree(c->mtd); + else +#endif + put_mtd_device(c->mtd); return NULL; } @@ -297,7 +424,12 @@ kfree(c->blocks); if (c->mtd->sync) c->mtd->sync(c->mtd); - put_mtd_device(c->mtd); +#ifdef CONFIG_JFFS2_NON_MTD_BD + if (c->mtd->priv == sb) + kfree(c->mtd); + else +#endif + put_mtd_device(c->mtd); D1(printk(KERN_DEBUG "jffs2_put_super returning\n")); } diff -urN linux-2.4.10-wt1-5e/include/linux/jffs2_fs_sb.h linux-2.4.10-wt1/include/linux/jffs2_fs_sb.h --- linux-2.4.10-wt1-5e/include/linux/jffs2_fs_sb.h Sun Oct 7 17:28:06 2001 +++ linux-2.4.10-wt1/include/linux/jffs2_fs_sb.h Sun Oct 7 18:58:30 2001 @@ -11,7 +11,13 @@ #define INOCACHE_HASHSIZE 1 -#define JFFS2_SB_FLAG_RO 1 +#define JFFS2_SB_FLAG_RO 1 +#define JFFS2_SB_FLAG_BLKDEV 2 +#define JFFS2_SB_FLAG_FORMAT 4 + +#define JFFS2_SB_FLAG_DEFLATE_SHIFT 3 +#define JFFS2_SB_FLAG_DEFLATE_MASK (0xF << JFFS2_SB_FLAG_DEFLATE_SHIFT) +#define JFFS2_SB_FLAG_DEFLATE_DEFAULT (3 << JFFS2_SB_FLAG_DEFLATE_SHIFT) /* A struct for the overall file system control. Pointers to jffs2_sb_info structs are named `c' in the source code.