Maximal file size
Ferenc Havasi <[email protected]> Tue, 07 Dec 2004 11:58:03 +0100
| Newsgroups | gmane.linux.file-systems.jffs |
|---|---|
| Message-ID | <[email protected]> |
Dear All, Here is a patch which allows the developer to limit the created file size. It can be usefull on embadded devices where there are users who don't know too much about the system. If the user uses too big files JFFS2 can run out of RAM easily - and simply hangs the system (dd if=/dev/zero of=/mnt/flash bs=4K hangs the system quickly) I know that the the memory requirements of JFFS2 depends on not only the size of the opened file but I have no better idea - and it solves a part of the problem. This limitation can be understood by the user, and is not too dificult to implement. (see the small patch I attached) David, can I commit it? Or wait for JFFS3? When will it happen? Regards, Ferenc
jffs2-maxfilesize.patch
(text/plain, 4.9 KB)
diff --unified --recursive --new-file mtd2/fs/Kconfig mtd/fs/Kconfig --- mtd2/fs/Kconfig 2004-11-03 13:57:37.000000000 +0100 +++ mtd/fs/Kconfig 2004-12-07 09:58:31.000000000 +0100 @@ -77,6 +77,21 @@ ECC for JFFS2. This type of flash chip is not common, however it is available from STMicro. +config JFFS2_MAXFILESIZE + bool "Use a file size limit" + depends on JFFS2_FS + default n + help + Storing too large files can consume much memory. + +config JFFS2_MAXFILESIZE_VALUE + int "File size limit to use (in bytes, 0=no limit)" + depends on JFFS2_MAXFILESIZE + default "0" + help + It is the default value of maximal file size. + You can modify it using the mount option 'maxfilesize'. + config JFFS2_COMPRESSION_OPTIONS bool "Advanced compression options for JFFS2" default n diff --unified --recursive --new-file mtd2/fs/jffs2/fs.c mtd/fs/jffs2/fs.c --- mtd2/fs/jffs2/fs.c 2004-11-28 13:19:37.000000000 +0100 +++ mtd/fs/jffs2/fs.c 2004-12-07 09:57:11.000000000 +0100 @@ -341,10 +341,58 @@ jffs2_do_setattr(inode, &iattr); } +/* Mount options added by Patrik Kluba <[email protected]> */ +/* (University of Szeged, Hungary) based on affs source */ + +#ifdef CONFIG_JFFS2_MAXFILESIZE + +#include <linux/string.h> +#include <linux/parser.h> + +enum { + Opt_maxfilesize, Opt_err, +}; + +static match_table_t tokens = { + {Opt_maxfilesize, "maxfilesize=%d"}, + {Opt_err, NULL}, +}; + +static int parse_options(char *options, int *maxsize) { + char *p; + substring_t args[MAX_OPT_ARGS]; + *maxsize = CONFIG_JFFS2_MAXFILESIZE_VALUE; + if (!options) return 1; + while ((p = strsep(&options, ",")) != NULL) { + int token, n; + if (!*p) continue; + token = match_token(p, tokens, args); + switch (token) { + case Opt_maxfilesize: + if (match_int(&args[0], &n)) return -EINVAL; + *maxsize = n; + break; + default: + printk("JFFS2: Unrecognized mount option \"%s\" or missing value\n", p); + return 0; + } + } + return 1; +} + +#endif + int jffs2_remount_fs (struct super_block *sb, int *flags, char *data) { struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); +#ifdef CONFIG_JFFS2_MAXFILESIZE + if (!parse_options(data, &c->max_file_size)) { + printk(KERN_ERR "JFFS2: error parsing options\n"); + return -EINVAL; + } +#endif + if (c->flags & JFFS2_SB_FLAG_RO && !(sb->s_flags & MS_RDONLY)) return -EROFS; @@ -439,7 +487,6 @@ return inode; } - int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) { struct jffs2_sb_info *c; @@ -449,6 +496,13 @@ c = JFFS2_SB_INFO(sb); +#ifdef CONFIG_JFFS2_MAXFILESIZE + if (!parse_options(data, &c->max_file_size)) { + printk(KERN_ERR "JFFS2: error parsing options\n"); + return -EINVAL; + } +#endif + #ifndef CONFIG_JFFS2_FS_NAND if (c->mtd->type == MTD_NANDFLASH) { printk(KERN_ERR "jffs2: Cannot operate on NAND flash unless jffs2 NAND support is compiled in.\n"); diff --unified --recursive --new-file mtd2/fs/jffs2/write.c mtd/fs/jffs2/write.c --- mtd2/fs/jffs2/write.c 2004-11-16 21:36:12.000000000 +0100 +++ mtd/fs/jffs2/write.c 2004-12-07 09:57:11.000000000 +0100 @@ -366,18 +366,31 @@ uint16_t comprtype = JFFS2_COMPR_NONE; uint32_t phys_ofs, alloclen; uint32_t datalen, cdatalen; + uint32_t isize; int retried = 0; retry: D2(printk(KERN_DEBUG "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, offset)); + datalen = min_t(uint32_t, writelen, PAGE_CACHE_SIZE - (offset & (PAGE_CACHE_SIZE-1))); + isize = max(je32_to_cpu(ri->isize), offset + datalen); + +#ifdef CONFIG_JFFS2_MAXFILESIZE + if (c->max_file_size) { + if (isize > c->max_file_size) { + D1(printk(KERN_DEBUG "reached file size limit\n")); + ret = -EFBIG; + break; + } + } +#endif + ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen, ALLOC_NORMAL); if (ret) { D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret)); break; } down(&f->sem); - 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(c, f, buf, &comprbuf, &datalen, &cdatalen); @@ -389,7 +402,7 @@ ri->ino = cpu_to_je32(f->inocache->ino); ri->version = cpu_to_je32(++f->highest_version); - ri->isize = cpu_to_je32(max(je32_to_cpu(ri->isize), offset + datalen)); + ri->isize = cpu_to_je32(isize); ri->offset = cpu_to_je32(offset); ri->csize = cpu_to_je32(cdatalen); ri->dsize = cpu_to_je32(datalen); diff --unified --recursive --new-file mtd2/include/linux/jffs2_fs_sb.h mtd/include/linux/jffs2_fs_sb.h --- mtd2/include/linux/jffs2_fs_sb.h 2004-11-20 11:41:12.000000000 +0100 +++ mtd/include/linux/jffs2_fs_sb.h 2004-12-07 09:57:11.000000000 +0100 @@ -111,6 +111,10 @@ uint32_t fsdata_len; #endif +#ifdef CONFIG_JFFS2_MAXFILESIZE + uint32_t max_file_size; +#endif + /* OS-private pointer for getting back to master superblock info */ void *os_priv; };