aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-13 13:12:15 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-13 13:12:15 -0400
commitc8c55bcb43d790d97790cfa319d80045a71fde39 (patch)
treeb791d9478d3e7f1eb26e51bb999fde21847d4391 /fs
parent3749c66c67fb5c257771815c186bc32290cacf44 (diff)
parentebf8889bd1fe3615991ff4494635d237280652a2 (diff)
Merge git://git.infradead.org/mtd-2.6
* git://git.infradead.org/mtd-2.6: (91 commits) [MTD] [NAND] Blackfin on-chip NAND Flash Controller driver [MTD] [NOR] fix ctrl-alt-del can't reboot for intel flash bug [MTD] [NAND] Fix compiler warning in Alauda driver [JFFS2] Remove stray debugging printk [JFFS2] Handle dirents on the flash with embedded zero bytes in names. [JFFS2] Check for creation of dirents with embedded zero bytes in name. [JFFS2] Don't count all 'very dirty' blocks except in debug mode [JFFS2] Check whether garbage-collection actually obsoleted its victim. [JFFS2] Relax threshold for triggering GC due to dirty blocks. [MTD] [OneNAND] Fix typo related with recent commit [JFFS2] Trigger garbage collection when very_dirty_list size becomes excessive [MTD] [NAND] Avoid deadlock in erase callback; release chip lock first. [MTD] [NAND] Resume method for CAFÉ NAND controller [MTD] [NAND] Fix PCI ident table for CAFÉ NAND controller. [MTD] [NAND] s3c2410: fix arch moves [MTD] [OneNAND] fix numerous races [MTD] map driver for NOR flash on the Intel Vermilion Range chipset [JFFS2] Fix unpoint length [MTD] fix CFI point method for discontiguous maps [MTD] MAPS: Merge Lubbock and Mainstone drivers into common PXA2xx driver ...
Diffstat (limited to 'fs')
-rw-r--r--fs/Kconfig81
-rw-r--r--fs/jffs2/Makefile1
-rw-r--r--fs/jffs2/acl.c23
-rw-r--r--fs/jffs2/acl.h4
-rw-r--r--fs/jffs2/background.c4
-rw-r--r--fs/jffs2/build.c10
-rw-r--r--fs/jffs2/compr.c422
-rw-r--r--fs/jffs2/compr.h54
-rw-r--r--fs/jffs2/compr_lzo.c108
-rw-r--r--fs/jffs2/compr_rtime.c2
-rw-r--r--fs/jffs2/compr_rubin.c4
-rw-r--r--fs/jffs2/compr_zlib.c6
-rw-r--r--fs/jffs2/dir.c37
-rw-r--r--fs/jffs2/erase.c57
-rw-r--r--fs/jffs2/fs.c32
-rw-r--r--fs/jffs2/gc.c23
-rw-r--r--fs/jffs2/jffs2_fs_sb.h5
-rw-r--r--fs/jffs2/nodelist.h2
-rw-r--r--fs/jffs2/nodemgmt.c25
-rw-r--r--fs/jffs2/os-linux.h5
-rw-r--r--fs/jffs2/readinode.c8
-rw-r--r--fs/jffs2/scan.c19
-rw-r--r--fs/jffs2/security.c6
-rw-r--r--fs/jffs2/summary.c30
-rw-r--r--fs/jffs2/summary.h6
-rw-r--r--fs/jffs2/wbuf.c81
-rw-r--r--fs/jffs2/write.c13
-rw-r--r--fs/jffs2/xattr.h2
-rw-r--r--fs/jffs2/xattr_user.c4
29 files changed, 736 insertions, 338 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
index f9eed6d79066..bb02b39380a3 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1225,6 +1225,14 @@ config JFFS2_FS_WRITEBUFFER
1225 - NOR flash with transparent ECC 1225 - NOR flash with transparent ECC
1226 - DataFlash 1226 - DataFlash
1227 1227
1228config JFFS2_FS_WBUF_VERIFY
1229 bool "Verify JFFS2 write-buffer reads"
1230 depends on JFFS2_FS_WRITEBUFFER
1231 default n
1232 help
1233 This causes JFFS2 to read back every page written through the
1234 write-buffer, and check for errors.
1235
1228config JFFS2_SUMMARY 1236config JFFS2_SUMMARY
1229 bool "JFFS2 summary support (EXPERIMENTAL)" 1237 bool "JFFS2 summary support (EXPERIMENTAL)"
1230 depends on JFFS2_FS && EXPERIMENTAL 1238 depends on JFFS2_FS && EXPERIMENTAL
@@ -1295,52 +1303,71 @@ config JFFS2_ZLIB
1295 select ZLIB_DEFLATE 1303 select ZLIB_DEFLATE
1296 depends on JFFS2_FS 1304 depends on JFFS2_FS
1297 default y 1305 default y
1298 help 1306 help
1299 Zlib is designed to be a free, general-purpose, legally unencumbered, 1307 Zlib is designed to be a free, general-purpose, legally unencumbered,
1300 lossless data-compression library for use on virtually any computer 1308 lossless data-compression library for use on virtually any computer
1301 hardware and operating system. See <http://www.gzip.org/zlib/> for 1309 hardware and operating system. See <http://www.gzip.org/zlib/> for
1302 further information. 1310 further information.
1303 1311
1304 Say 'Y' if unsure. 1312 Say 'Y' if unsure.
1313
1314config JFFS2_LZO
1315 bool "JFFS2 LZO compression support" if JFFS2_COMPRESSION_OPTIONS
1316 select LZO_COMPRESS
1317 select LZO_DECOMPRESS
1318 depends on JFFS2_FS
1319 default n
1320 help
1321 minilzo-based compression. Generally works better than Zlib.
1322
1323 This feature was added in July, 2007. Say 'N' if you need
1324 compatibility with older bootloaders or kernels.
1305 1325
1306config JFFS2_RTIME 1326config JFFS2_RTIME
1307 bool "JFFS2 RTIME compression support" if JFFS2_COMPRESSION_OPTIONS 1327 bool "JFFS2 RTIME compression support" if JFFS2_COMPRESSION_OPTIONS
1308 depends on JFFS2_FS 1328 depends on JFFS2_FS
1309 default y 1329 default y
1310 help 1330 help
1311 Rtime does manage to recompress already-compressed data. Say 'Y' if unsure. 1331 Rtime does manage to recompress already-compressed data. Say 'Y' if unsure.
1312 1332
1313config JFFS2_RUBIN 1333config JFFS2_RUBIN
1314 bool "JFFS2 RUBIN compression support" if JFFS2_COMPRESSION_OPTIONS 1334 bool "JFFS2 RUBIN compression support" if JFFS2_COMPRESSION_OPTIONS
1315 depends on JFFS2_FS 1335 depends on JFFS2_FS
1316 default n 1336 default n
1317 help 1337 help
1318 RUBINMIPS and DYNRUBIN compressors. Say 'N' if unsure. 1338 RUBINMIPS and DYNRUBIN compressors. Say 'N' if unsure.
1319 1339
1320choice 1340choice
1321 prompt "JFFS2 default compression mode" if JFFS2_COMPRESSION_OPTIONS 1341 prompt "JFFS2 default compression mode" if JFFS2_COMPRESSION_OPTIONS
1322 default JFFS2_CMODE_PRIORITY 1342 default JFFS2_CMODE_PRIORITY
1323 depends on JFFS2_FS 1343 depends on JFFS2_FS
1324 help 1344 help
1325 You can set here the default compression mode of JFFS2 from 1345 You can set here the default compression mode of JFFS2 from
1326 the available compression modes. Don't touch if unsure. 1346 the available compression modes. Don't touch if unsure.
1327 1347
1328config JFFS2_CMODE_NONE 1348config JFFS2_CMODE_NONE
1329 bool "no compression" 1349 bool "no compression"
1330 help 1350 help
1331 Uses no compression. 1351 Uses no compression.
1332 1352
1333config JFFS2_CMODE_PRIORITY 1353config JFFS2_CMODE_PRIORITY
1334 bool "priority" 1354 bool "priority"
1335 help 1355 help
1336 Tries the compressors in a predefined order and chooses the first 1356 Tries the compressors in a predefined order and chooses the first
1337 successful one. 1357 successful one.
1338 1358
1339config JFFS2_CMODE_SIZE 1359config JFFS2_CMODE_SIZE
1340 bool "size (EXPERIMENTAL)" 1360 bool "size (EXPERIMENTAL)"
1341 help 1361 help
1342 Tries all compressors and chooses the one which has the smallest 1362 Tries all compressors and chooses the one which has the smallest
1343 result. 1363 result.
1364
1365config JFFS2_CMODE_FAVOURLZO
1366 bool "Favour LZO"
1367 help
1368 Tries all compressors and chooses the one which has the smallest
1369 result but gives some preference to LZO (which has faster
1370 decompression) at the expense of size.
1344 1371
1345endchoice 1372endchoice
1346 1373
diff --git a/fs/jffs2/Makefile b/fs/jffs2/Makefile
index c32b241e3d91..60e5d49ca03e 100644
--- a/fs/jffs2/Makefile
+++ b/fs/jffs2/Makefile
@@ -17,4 +17,5 @@ jffs2-$(CONFIG_JFFS2_FS_POSIX_ACL) += acl.o
17jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o 17jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o
18jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o 18jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o
19jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o 19jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o
20jffs2-$(CONFIG_JFFS2_LZO) += compr_lzo.o
20jffs2-$(CONFIG_JFFS2_SUMMARY) += summary.o 21jffs2-$(CONFIG_JFFS2_SUMMARY) += summary.o
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index 65b3a1b5b88d..8ec9323e830a 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -176,7 +176,7 @@ static void jffs2_iset_acl(struct inode *inode, struct posix_acl **i_acl, struct
176 spin_unlock(&inode->i_lock); 176 spin_unlock(&inode->i_lock);
177} 177}
178 178
179static struct posix_acl *jffs2_get_acl(struct inode *inode, int type) 179struct posix_acl *jffs2_get_acl(struct inode *inode, int type)
180{ 180{
181 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 181 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
182 struct posix_acl *acl; 182 struct posix_acl *acl;
@@ -247,8 +247,13 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
247 if (rc < 0) 247 if (rc < 0)
248 return rc; 248 return rc;
249 if (inode->i_mode != mode) { 249 if (inode->i_mode != mode) {
250 inode->i_mode = mode; 250 struct iattr attr;
251 jffs2_dirty_inode(inode); 251
252 attr.ia_valid = ATTR_MODE;
253 attr.ia_mode = mode;
254 rc = jffs2_do_setattr(inode, &attr);
255 if (rc < 0)
256 return rc;
252 } 257 }
253 if (rc == 0) 258 if (rc == 0)
254 acl = NULL; 259 acl = NULL;
@@ -307,22 +312,16 @@ int jffs2_permission(struct inode *inode, int mask, struct nameidata *nd)
307 return generic_permission(inode, mask, jffs2_check_acl); 312 return generic_permission(inode, mask, jffs2_check_acl);
308} 313}
309 314
310int jffs2_init_acl(struct inode *inode, struct inode *dir) 315int jffs2_init_acl(struct inode *inode, struct posix_acl *acl)
311{ 316{
312 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 317 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
313 struct posix_acl *acl = NULL, *clone; 318 struct posix_acl *clone;
314 mode_t mode; 319 mode_t mode;
315 int rc = 0; 320 int rc = 0;
316 321
317 f->i_acl_access = JFFS2_ACL_NOT_CACHED; 322 f->i_acl_access = JFFS2_ACL_NOT_CACHED;
318 f->i_acl_default = JFFS2_ACL_NOT_CACHED; 323 f->i_acl_default = JFFS2_ACL_NOT_CACHED;
319 if (!S_ISLNK(inode->i_mode)) { 324
320 acl = jffs2_get_acl(dir, ACL_TYPE_DEFAULT);
321 if (IS_ERR(acl))
322 return PTR_ERR(acl);
323 if (!acl)
324 inode->i_mode &= ~current->fs->umask;
325 }
326 if (acl) { 325 if (acl) {
327 if (S_ISDIR(inode->i_mode)) { 326 if (S_ISDIR(inode->i_mode)) {
328 rc = jffs2_set_acl(inode, ACL_TYPE_DEFAULT, acl); 327 rc = jffs2_set_acl(inode, ACL_TYPE_DEFAULT, acl);
diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h
index c84378cee82a..90a2dbf59051 100644
--- a/fs/jffs2/acl.h
+++ b/fs/jffs2/acl.h
@@ -28,9 +28,10 @@ struct jffs2_acl_header {
28 28
29#define JFFS2_ACL_NOT_CACHED ((void *)-1) 29#define JFFS2_ACL_NOT_CACHED ((void *)-1)
30 30
31extern struct posix_acl *jffs2_get_acl(struct inode *inode, int type);
31extern int jffs2_permission(struct inode *, int, struct nameidata *); 32extern int jffs2_permission(struct inode *, int, struct nameidata *);
32extern int jffs2_acl_chmod(struct inode *); 33extern int jffs2_acl_chmod(struct inode *);
33extern int jffs2_init_acl(struct inode *, struct inode *); 34extern int jffs2_init_acl(struct inode *, struct posix_acl *);
34extern void jffs2_clear_acl(struct jffs2_inode_info *); 35extern void jffs2_clear_acl(struct jffs2_inode_info *);
35 36
36extern struct xattr_handler jffs2_acl_access_xattr_handler; 37extern struct xattr_handler jffs2_acl_access_xattr_handler;
@@ -38,6 +39,7 @@ extern struct xattr_handler jffs2_acl_default_xattr_handler;
38 39
39#else 40#else
40 41
42#define jffs2_get_acl(inode, type) (NULL)
41#define jffs2_permission NULL 43#define jffs2_permission NULL
42#define jffs2_acl_chmod(inode) (0) 44#define jffs2_acl_chmod(inode) (0)
43#define jffs2_init_acl(inode,dir) (0) 45#define jffs2_init_acl(inode,dir) (0)
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c
index 504643f2e98b..d568ae846741 100644
--- a/fs/jffs2/background.c
+++ b/fs/jffs2/background.c
@@ -23,8 +23,8 @@ static int jffs2_garbage_collect_thread(void *);
23void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c) 23void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c)
24{ 24{
25 spin_lock(&c->erase_completion_lock); 25 spin_lock(&c->erase_completion_lock);
26 if (c->gc_task && jffs2_thread_should_wake(c)) 26 if (c->gc_task && jffs2_thread_should_wake(c))
27 send_sig(SIGHUP, c->gc_task, 1); 27 send_sig(SIGHUP, c->gc_task, 1);
28 spin_unlock(&c->erase_completion_lock); 28 spin_unlock(&c->erase_completion_lock);
29} 29}
30 30
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
index 0ca2fff2617f..722a6b682951 100644
--- a/fs/jffs2/build.c
+++ b/fs/jffs2/build.c
@@ -285,6 +285,14 @@ static void jffs2_calc_trigger_levels(struct jffs2_sb_info *c)
285 than actually making progress? */ 285 than actually making progress? */
286 c->resv_blocks_gcbad = 0;//c->resv_blocks_deletion + 2; 286 c->resv_blocks_gcbad = 0;//c->resv_blocks_deletion + 2;
287 287
288 /* What number of 'very dirty' eraseblocks do we allow before we
289 trigger the GC thread even if we don't _need_ the space. When we
290 can't mark nodes obsolete on the medium, the old dirty nodes cause
291 performance problems because we have to inspect and discard them. */
292 c->vdirty_blocks_gctrigger = c->resv_blocks_gctrigger;
293 if (jffs2_can_mark_obsolete(c))
294 c->vdirty_blocks_gctrigger *= 10;
295
288 /* If there's less than this amount of dirty space, don't bother 296 /* If there's less than this amount of dirty space, don't bother
289 trying to GC to make more space. It'll be a fruitless task */ 297 trying to GC to make more space. It'll be a fruitless task */
290 c->nospc_dirty_size = c->sector_size + (c->flash_size / 100); 298 c->nospc_dirty_size = c->sector_size + (c->flash_size / 100);
@@ -303,6 +311,8 @@ static void jffs2_calc_trigger_levels(struct jffs2_sb_info *c)
303 c->resv_blocks_gcbad, c->resv_blocks_gcbad*c->sector_size/1024); 311 c->resv_blocks_gcbad, c->resv_blocks_gcbad*c->sector_size/1024);
304 dbg_fsbuild("Amount of dirty space required to GC: %d bytes\n", 312 dbg_fsbuild("Amount of dirty space required to GC: %d bytes\n",
305 c->nospc_dirty_size); 313 c->nospc_dirty_size);
314 dbg_fsbuild("Very dirty blocks before GC triggered: %d\n",
315 c->vdirty_blocks_gctrigger);
306} 316}
307 317
308int jffs2_do_mount_fs(struct jffs2_sb_info *c) 318int jffs2_do_mount_fs(struct jffs2_sb_info *c)
diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c
index 485d065de41f..86739ee53b37 100644
--- a/fs/jffs2/compr.c
+++ b/fs/jffs2/compr.c
@@ -5,7 +5,7 @@
5 * Created by Arjan van de Ven <arjanv@redhat.com> 5 * Created by Arjan van de Ven <arjanv@redhat.com>
6 * 6 *
7 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>, 7 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
8 * University of Szeged, Hungary 8 * University of Szeged, Hungary
9 * 9 *
10 * For licensing information, see the file 'LICENCE' in this directory. 10 * For licensing information, see the file 'LICENCE' in this directory.
11 * 11 *
@@ -24,6 +24,34 @@ static int jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY;
24/* Statistics for blocks stored without compression */ 24/* Statistics for blocks stored without compression */
25static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_compr_size=0; 25static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_compr_size=0;
26 26
27
28/*
29 * Return 1 to use this compression
30 */
31static int jffs2_is_best_compression(struct jffs2_compressor *this,
32 struct jffs2_compressor *best, uint32_t size, uint32_t bestsize)
33{
34 switch (jffs2_compression_mode) {
35 case JFFS2_COMPR_MODE_SIZE:
36 if (bestsize > size)
37 return 1;
38 return 0;
39 case JFFS2_COMPR_MODE_FAVOURLZO:
40 if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > size))
41 return 1;
42 if ((best->compr != JFFS2_COMPR_LZO) && (bestsize > size))
43 return 1;
44 if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > (size * FAVOUR_LZO_PERCENT / 100)))
45 return 1;
46 if ((bestsize * FAVOUR_LZO_PERCENT / 100) > size)
47 return 1;
48
49 return 0;
50 }
51 /* Shouldn't happen */
52 return 0;
53}
54
27/* jffs2_compress: 55/* jffs2_compress:
28 * @data: Pointer to uncompressed data 56 * @data: Pointer to uncompressed data
29 * @cdata: Pointer to returned pointer to buffer for compressed data 57 * @cdata: Pointer to returned pointer to buffer for compressed data
@@ -43,121 +71,124 @@ static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_co
43 * *datalen accordingly to show the amount of data which were compressed. 71 * *datalen accordingly to show the amount of data which were compressed.
44 */ 72 */
45uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 73uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
46 unsigned char *data_in, unsigned char **cpage_out, 74 unsigned char *data_in, unsigned char **cpage_out,
47 uint32_t *datalen, uint32_t *cdatalen) 75 uint32_t *datalen, uint32_t *cdatalen)
48{ 76{
49 int ret = JFFS2_COMPR_NONE; 77 int ret = JFFS2_COMPR_NONE;
50 int compr_ret; 78 int compr_ret;
51 struct jffs2_compressor *this, *best=NULL; 79 struct jffs2_compressor *this, *best=NULL;
52 unsigned char *output_buf = NULL, *tmp_buf; 80 unsigned char *output_buf = NULL, *tmp_buf;
53 uint32_t orig_slen, orig_dlen; 81 uint32_t orig_slen, orig_dlen;
54 uint32_t best_slen=0, best_dlen=0; 82 uint32_t best_slen=0, best_dlen=0;
55 83
56 switch (jffs2_compression_mode) { 84 switch (jffs2_compression_mode) {
57 case JFFS2_COMPR_MODE_NONE: 85 case JFFS2_COMPR_MODE_NONE:
58 break; 86 break;
59 case JFFS2_COMPR_MODE_PRIORITY: 87 case JFFS2_COMPR_MODE_PRIORITY:
60 output_buf = kmalloc(*cdatalen,GFP_KERNEL); 88 output_buf = kmalloc(*cdatalen,GFP_KERNEL);
61 if (!output_buf) { 89 if (!output_buf) {
62 printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n"); 90 printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n");
63 goto out; 91 goto out;
64 } 92 }
65 orig_slen = *datalen; 93 orig_slen = *datalen;
66 orig_dlen = *cdatalen; 94 orig_dlen = *cdatalen;
67 spin_lock(&jffs2_compressor_list_lock); 95 spin_lock(&jffs2_compressor_list_lock);
68 list_for_each_entry(this, &jffs2_compressor_list, list) { 96 list_for_each_entry(this, &jffs2_compressor_list, list) {
69 /* Skip decompress-only backwards-compatibility and disabled modules */ 97 /* Skip decompress-only backwards-compatibility and disabled modules */
70 if ((!this->compress)||(this->disabled)) 98 if ((!this->compress)||(this->disabled))
71 continue; 99 continue;
72 100
73 this->usecount++; 101 this->usecount++;
74 spin_unlock(&jffs2_compressor_list_lock); 102 spin_unlock(&jffs2_compressor_list_lock);
75 *datalen = orig_slen; 103 *datalen = orig_slen;
76 *cdatalen = orig_dlen; 104 *cdatalen = orig_dlen;
77 compr_ret = this->compress(data_in, output_buf, datalen, cdatalen, NULL); 105 compr_ret = this->compress(data_in, output_buf, datalen, cdatalen, NULL);
78 spin_lock(&jffs2_compressor_list_lock); 106 spin_lock(&jffs2_compressor_list_lock);
79 this->usecount--; 107 this->usecount--;
80 if (!compr_ret) { 108 if (!compr_ret) {
81 ret = this->compr; 109 ret = this->compr;
82 this->stat_compr_blocks++; 110 this->stat_compr_blocks++;
83 this->stat_compr_orig_size += *datalen; 111 this->stat_compr_orig_size += *datalen;
84 this->stat_compr_new_size += *cdatalen; 112 this->stat_compr_new_size += *cdatalen;
85 break; 113 break;
86 } 114 }
87 } 115 }
88 spin_unlock(&jffs2_compressor_list_lock); 116 spin_unlock(&jffs2_compressor_list_lock);
89 if (ret == JFFS2_COMPR_NONE) kfree(output_buf); 117 if (ret == JFFS2_COMPR_NONE)
90 break; 118 kfree(output_buf);
91 case JFFS2_COMPR_MODE_SIZE: 119 break;
92 orig_slen = *datalen; 120 case JFFS2_COMPR_MODE_SIZE:
93 orig_dlen = *cdatalen; 121 case JFFS2_COMPR_MODE_FAVOURLZO:
94 spin_lock(&jffs2_compressor_list_lock); 122 orig_slen = *datalen;
95 list_for_each_entry(this, &jffs2_compressor_list, list) { 123 orig_dlen = *cdatalen;
96 /* Skip decompress-only backwards-compatibility and disabled modules */ 124 spin_lock(&jffs2_compressor_list_lock);
97 if ((!this->compress)||(this->disabled)) 125 list_for_each_entry(this, &jffs2_compressor_list, list) {
98 continue; 126 /* Skip decompress-only backwards-compatibility and disabled modules */
99 /* Allocating memory for output buffer if necessary */ 127 if ((!this->compress)||(this->disabled))
100 if ((this->compr_buf_size<orig_dlen)&&(this->compr_buf)) { 128 continue;
101 spin_unlock(&jffs2_compressor_list_lock); 129 /* Allocating memory for output buffer if necessary */
102 kfree(this->compr_buf); 130 if ((this->compr_buf_size < orig_slen) && (this->compr_buf)) {
103 spin_lock(&jffs2_compressor_list_lock); 131 spin_unlock(&jffs2_compressor_list_lock);
104 this->compr_buf_size=0; 132 kfree(this->compr_buf);
105 this->compr_buf=NULL; 133 spin_lock(&jffs2_compressor_list_lock);
106 } 134 this->compr_buf_size=0;
107 if (!this->compr_buf) { 135 this->compr_buf=NULL;
108 spin_unlock(&jffs2_compressor_list_lock); 136 }
109 tmp_buf = kmalloc(orig_dlen,GFP_KERNEL); 137 if (!this->compr_buf) {
110 spin_lock(&jffs2_compressor_list_lock); 138 spin_unlock(&jffs2_compressor_list_lock);
111 if (!tmp_buf) { 139 tmp_buf = kmalloc(orig_slen, GFP_KERNEL);
112 printk(KERN_WARNING "JFFS2: No memory for compressor allocation. (%d bytes)\n",orig_dlen); 140 spin_lock(&jffs2_compressor_list_lock);
113 continue; 141 if (!tmp_buf) {
114 } 142 printk(KERN_WARNING "JFFS2: No memory for compressor allocation. (%d bytes)\n", orig_slen);
115 else { 143 continue;
116 this->compr_buf = tmp_buf; 144 }
117 this->compr_buf_size = orig_dlen; 145 else {
118 } 146 this->compr_buf = tmp_buf;
119 } 147 this->compr_buf_size = orig_slen;
120 this->usecount++; 148 }
121 spin_unlock(&jffs2_compressor_list_lock); 149 }
122 *datalen = orig_slen; 150 this->usecount++;
123 *cdatalen = orig_dlen; 151 spin_unlock(&jffs2_compressor_list_lock);
124 compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen, NULL); 152 *datalen = orig_slen;
125 spin_lock(&jffs2_compressor_list_lock); 153 *cdatalen = orig_dlen;
126 this->usecount--; 154 compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen, NULL);
127 if (!compr_ret) { 155 spin_lock(&jffs2_compressor_list_lock);
128 if ((!best_dlen)||(best_dlen>*cdatalen)) { 156 this->usecount--;
129 best_dlen = *cdatalen; 157 if (!compr_ret) {
130 best_slen = *datalen; 158 if (((!best_dlen) || jffs2_is_best_compression(this, best, *cdatalen, best_dlen))
131 best = this; 159 && (*cdatalen < *datalen)) {
132 } 160 best_dlen = *cdatalen;
133 } 161 best_slen = *datalen;
134 } 162 best = this;
135 if (best_dlen) { 163 }
136 *cdatalen = best_dlen; 164 }
137 *datalen = best_slen; 165 }
138 output_buf = best->compr_buf; 166 if (best_dlen) {
139 best->compr_buf = NULL; 167 *cdatalen = best_dlen;
140 best->compr_buf_size = 0; 168 *datalen = best_slen;
141 best->stat_compr_blocks++; 169 output_buf = best->compr_buf;
142 best->stat_compr_orig_size += best_slen; 170 best->compr_buf = NULL;
143 best->stat_compr_new_size += best_dlen; 171 best->compr_buf_size = 0;
144 ret = best->compr; 172 best->stat_compr_blocks++;
145 } 173 best->stat_compr_orig_size += best_slen;
146 spin_unlock(&jffs2_compressor_list_lock); 174 best->stat_compr_new_size += best_dlen;
147 break; 175 ret = best->compr;
148 default: 176 }
149 printk(KERN_ERR "JFFS2: unknow compression mode.\n"); 177 spin_unlock(&jffs2_compressor_list_lock);
150 } 178 break;
179 default:
180 printk(KERN_ERR "JFFS2: unknow compression mode.\n");
181 }
151 out: 182 out:
152 if (ret == JFFS2_COMPR_NONE) { 183 if (ret == JFFS2_COMPR_NONE) {
153 *cpage_out = data_in; 184 *cpage_out = data_in;
154 *datalen = *cdatalen; 185 *datalen = *cdatalen;
155 none_stat_compr_blocks++; 186 none_stat_compr_blocks++;
156 none_stat_compr_size += *datalen; 187 none_stat_compr_size += *datalen;
157 } 188 }
158 else { 189 else {
159 *cpage_out = output_buf; 190 *cpage_out = output_buf;
160 } 191 }
161 return ret; 192 return ret;
162} 193}
163 194
@@ -165,8 +196,8 @@ int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
165 uint16_t comprtype, unsigned char *cdata_in, 196 uint16_t comprtype, unsigned char *cdata_in,
166 unsigned char *data_out, uint32_t cdatalen, uint32_t datalen) 197 unsigned char *data_out, uint32_t cdatalen, uint32_t datalen)
167{ 198{
168 struct jffs2_compressor *this; 199 struct jffs2_compressor *this;
169 int ret; 200 int ret;
170 201
171 /* Older code had a bug where it would write non-zero 'usercompr' 202 /* Older code had a bug where it would write non-zero 'usercompr'
172 fields. Deal with it. */ 203 fields. Deal with it. */
@@ -177,32 +208,32 @@ int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
177 case JFFS2_COMPR_NONE: 208 case JFFS2_COMPR_NONE:
178 /* This should be special-cased elsewhere, but we might as well deal with it */ 209 /* This should be special-cased elsewhere, but we might as well deal with it */
179 memcpy(data_out, cdata_in, datalen); 210 memcpy(data_out, cdata_in, datalen);
180 none_stat_decompr_blocks++; 211 none_stat_decompr_blocks++;
181 break; 212 break;
182 case JFFS2_COMPR_ZERO: 213 case JFFS2_COMPR_ZERO:
183 memset(data_out, 0, datalen); 214 memset(data_out, 0, datalen);
184 break; 215 break;
185 default: 216 default:
186 spin_lock(&jffs2_compressor_list_lock); 217 spin_lock(&jffs2_compressor_list_lock);
187 list_for_each_entry(this, &jffs2_compressor_list, list) { 218 list_for_each_entry(this, &jffs2_compressor_list, list) {
188 if (comprtype == this->compr) { 219 if (comprtype == this->compr) {
189 this->usecount++; 220 this->usecount++;
190 spin_unlock(&jffs2_compressor_list_lock); 221 spin_unlock(&jffs2_compressor_list_lock);
191 ret = this->decompress(cdata_in, data_out, cdatalen, datalen, NULL); 222 ret = this->decompress(cdata_in, data_out, cdatalen, datalen, NULL);
192 spin_lock(&jffs2_compressor_list_lock); 223 spin_lock(&jffs2_compressor_list_lock);
193 if (ret) { 224 if (ret) {
194 printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret); 225 printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret);
195 } 226 }
196 else { 227 else {
197 this->stat_decompr_blocks++; 228 this->stat_decompr_blocks++;
198 } 229 }
199 this->usecount--; 230 this->usecount--;
200 spin_unlock(&jffs2_compressor_list_lock); 231 spin_unlock(&jffs2_compressor_list_lock);
201 return ret; 232 return ret;
202 } 233 }
203 } 234 }
204 printk(KERN_WARNING "JFFS2 compression type 0x%02x not available.\n", comprtype); 235 printk(KERN_WARNING "JFFS2 compression type 0x%02x not available.\n", comprtype);
205 spin_unlock(&jffs2_compressor_list_lock); 236 spin_unlock(&jffs2_compressor_list_lock);
206 return -EIO; 237 return -EIO;
207 } 238 }
208 return 0; 239 return 0;
@@ -210,108 +241,119 @@ int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
210 241
211int jffs2_register_compressor(struct jffs2_compressor *comp) 242int jffs2_register_compressor(struct jffs2_compressor *comp)
212{ 243{
213 struct jffs2_compressor *this; 244 struct jffs2_compressor *this;
214 245
215 if (!comp->name) { 246 if (!comp->name) {
216 printk(KERN_WARNING "NULL compressor name at registering JFFS2 compressor. Failed.\n"); 247 printk(KERN_WARNING "NULL compressor name at registering JFFS2 compressor. Failed.\n");
217 return -1; 248 return -1;
218 } 249 }
219 comp->compr_buf_size=0; 250 comp->compr_buf_size=0;
220 comp->compr_buf=NULL; 251 comp->compr_buf=NULL;
221 comp->usecount=0; 252 comp->usecount=0;
222 comp->stat_compr_orig_size=0; 253 comp->stat_compr_orig_size=0;
223 comp->stat_compr_new_size=0; 254 comp->stat_compr_new_size=0;
224 comp->stat_compr_blocks=0; 255 comp->stat_compr_blocks=0;
225 comp->stat_decompr_blocks=0; 256 comp->stat_decompr_blocks=0;
226 D1(printk(KERN_DEBUG "Registering JFFS2 compressor \"%s\"\n", comp->name)); 257 D1(printk(KERN_DEBUG "Registering JFFS2 compressor \"%s\"\n", comp->name));
227 258
228 spin_lock(&jffs2_compressor_list_lock); 259 spin_lock(&jffs2_compressor_list_lock);
229 260
230 list_for_each_entry(this, &jffs2_compressor_list, list) { 261 list_for_each_entry(this, &jffs2_compressor_list, list) {
231 if (this->priority < comp->priority) { 262 if (this->priority < comp->priority) {
232 list_add(&comp->list, this->list.prev); 263 list_add(&comp->list, this->list.prev);
233 goto out; 264 goto out;
234 } 265 }
235 } 266 }
236 list_add_tail(&comp->list, &jffs2_compressor_list); 267 list_add_tail(&comp->list, &jffs2_compressor_list);
237out: 268out:
238 D2(list_for_each_entry(this, &jffs2_compressor_list, list) { 269 D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
239 printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority); 270 printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
240 }) 271 })
241 272
242 spin_unlock(&jffs2_compressor_list_lock); 273 spin_unlock(&jffs2_compressor_list_lock);
243 274
244 return 0; 275 return 0;
245} 276}
246 277
247int jffs2_unregister_compressor(struct jffs2_compressor *comp) 278int jffs2_unregister_compressor(struct jffs2_compressor *comp)
248{ 279{
249 D2(struct jffs2_compressor *this;) 280 D2(struct jffs2_compressor *this;)
250 281
251 D1(printk(KERN_DEBUG "Unregistering JFFS2 compressor \"%s\"\n", comp->name)); 282 D1(printk(KERN_DEBUG "Unregistering JFFS2 compressor \"%s\"\n", comp->name));
252 283
253 spin_lock(&jffs2_compressor_list_lock); 284 spin_lock(&jffs2_compressor_list_lock);
254 285
255 if (comp->usecount) { 286 if (comp->usecount) {
256 spin_unlock(&jffs2_compressor_list_lock); 287 spin_unlock(&jffs2_compressor_list_lock);
257 printk(KERN_WARNING "JFFS2: Compressor modul is in use. Unregister failed.\n"); 288 printk(KERN_WARNING "JFFS2: Compressor modul is in use. Unregister failed.\n");
258 return -1; 289 return -1;
259 } 290 }
260 list_del(&comp->list); 291 list_del(&comp->list);
261 292
262 D2(list_for_each_entry(this, &jffs2_compressor_list, list) { 293 D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
263 printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority); 294 printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
264 }) 295 })
265 spin_unlock(&jffs2_compressor_list_lock); 296 spin_unlock(&jffs2_compressor_list_lock);
266 return 0; 297 return 0;
267} 298}
268 299
269void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig) 300void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig)
270{ 301{
271 if (orig != comprbuf) 302 if (orig != comprbuf)
272 kfree(comprbuf); 303 kfree(comprbuf);
273} 304}
274 305
275int __init jffs2_compressors_init(void) 306int __init jffs2_compressors_init(void)
276{ 307{
277/* Registering compressors */ 308/* Registering compressors */
278#ifdef CONFIG_JFFS2_ZLIB 309#ifdef CONFIG_JFFS2_ZLIB
279 jffs2_zlib_init(); 310 jffs2_zlib_init();
280#endif 311#endif
281#ifdef CONFIG_JFFS2_RTIME 312#ifdef CONFIG_JFFS2_RTIME
282 jffs2_rtime_init(); 313 jffs2_rtime_init();
283#endif 314#endif
284#ifdef CONFIG_JFFS2_RUBIN 315#ifdef CONFIG_JFFS2_RUBIN
285 jffs2_rubinmips_init(); 316 jffs2_rubinmips_init();
286 jffs2_dynrubin_init(); 317 jffs2_dynrubin_init();
318#endif
319#ifdef CONFIG_JFFS2_LZO
320 jffs2_lzo_init();
287#endif 321#endif
288/* Setting default compression mode */ 322/* Setting default compression mode */
289#ifdef CONFIG_JFFS2_CMODE_NONE 323#ifdef CONFIG_JFFS2_CMODE_NONE
290 jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; 324 jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
291 D1(printk(KERN_INFO "JFFS2: default compression mode: none\n");) 325 D1(printk(KERN_INFO "JFFS2: default compression mode: none\n");)
292#else 326#else
293#ifdef CONFIG_JFFS2_CMODE_SIZE 327#ifdef CONFIG_JFFS2_CMODE_SIZE
294 jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE; 328 jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
295 D1(printk(KERN_INFO "JFFS2: default compression mode: size\n");) 329 D1(printk(KERN_INFO "JFFS2: default compression mode: size\n");)
330#else
331#ifdef CONFIG_JFFS2_CMODE_FAVOURLZO
332 jffs2_compression_mode = JFFS2_COMPR_MODE_FAVOURLZO;
333 D1(printk(KERN_INFO "JFFS2: default compression mode: favourlzo\n");)
296#else 334#else
297 D1(printk(KERN_INFO "JFFS2: default compression mode: priority\n");) 335 D1(printk(KERN_INFO "JFFS2: default compression mode: priority\n");)
336#endif
298#endif 337#endif
299#endif 338#endif
300 return 0; 339 return 0;
301} 340}
302 341
303int jffs2_compressors_exit(void) 342int jffs2_compressors_exit(void)
304{ 343{
305/* Unregistering compressors */ 344/* Unregistering compressors */
345#ifdef CONFIG_JFFS2_LZO
346 jffs2_lzo_exit();
347#endif
306#ifdef CONFIG_JFFS2_RUBIN 348#ifdef CONFIG_JFFS2_RUBIN
307 jffs2_dynrubin_exit(); 349 jffs2_dynrubin_exit();
308 jffs2_rubinmips_exit(); 350 jffs2_rubinmips_exit();
309#endif 351#endif
310#ifdef CONFIG_JFFS2_RTIME 352#ifdef CONFIG_JFFS2_RTIME
311 jffs2_rtime_exit(); 353 jffs2_rtime_exit();
312#endif 354#endif
313#ifdef CONFIG_JFFS2_ZLIB 355#ifdef CONFIG_JFFS2_ZLIB
314 jffs2_zlib_exit(); 356 jffs2_zlib_exit();
315#endif 357#endif
316 return 0; 358 return 0;
317} 359}
diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h
index 68cc7010dbdf..7d1d72faa774 100644
--- a/fs/jffs2/compr.h
+++ b/fs/jffs2/compr.h
@@ -2,7 +2,7 @@
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>, 4 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
5 * University of Szeged, Hungary 5 * University of Szeged, Hungary
6 * 6 *
7 * For licensing information, see the file 'LICENCE' in this directory. 7 * For licensing information, see the file 'LICENCE' in this directory.
8 * 8 *
@@ -27,34 +27,38 @@
27#define JFFS2_RUBINMIPS_PRIORITY 10 27#define JFFS2_RUBINMIPS_PRIORITY 10
28#define JFFS2_DYNRUBIN_PRIORITY 20 28#define JFFS2_DYNRUBIN_PRIORITY 20
29#define JFFS2_LZARI_PRIORITY 30 29#define JFFS2_LZARI_PRIORITY 30
30#define JFFS2_LZO_PRIORITY 40
31#define JFFS2_RTIME_PRIORITY 50 30#define JFFS2_RTIME_PRIORITY 50
32#define JFFS2_ZLIB_PRIORITY 60 31#define JFFS2_ZLIB_PRIORITY 60
32#define JFFS2_LZO_PRIORITY 80
33
33 34
34#define JFFS2_RUBINMIPS_DISABLED /* RUBINs will be used only */ 35#define JFFS2_RUBINMIPS_DISABLED /* RUBINs will be used only */
35#define JFFS2_DYNRUBIN_DISABLED /* for decompression */ 36#define JFFS2_DYNRUBIN_DISABLED /* for decompression */
36 37
37#define JFFS2_COMPR_MODE_NONE 0 38#define JFFS2_COMPR_MODE_NONE 0
38#define JFFS2_COMPR_MODE_PRIORITY 1 39#define JFFS2_COMPR_MODE_PRIORITY 1
39#define JFFS2_COMPR_MODE_SIZE 2 40#define JFFS2_COMPR_MODE_SIZE 2
41#define JFFS2_COMPR_MODE_FAVOURLZO 3
42
43#define FAVOUR_LZO_PERCENT 80
40 44
41struct jffs2_compressor { 45struct jffs2_compressor {
42 struct list_head list; 46 struct list_head list;
43 int priority; /* used by prirority comr. mode */ 47 int priority; /* used by prirority comr. mode */
44 char *name; 48 char *name;
45 char compr; /* JFFS2_COMPR_XXX */ 49 char compr; /* JFFS2_COMPR_XXX */
46 int (*compress)(unsigned char *data_in, unsigned char *cpage_out, 50 int (*compress)(unsigned char *data_in, unsigned char *cpage_out,
47 uint32_t *srclen, uint32_t *destlen, void *model); 51 uint32_t *srclen, uint32_t *destlen, void *model);
48 int (*decompress)(unsigned char *cdata_in, unsigned char *data_out, 52 int (*decompress)(unsigned char *cdata_in, unsigned char *data_out,
49 uint32_t cdatalen, uint32_t datalen, void *model); 53 uint32_t cdatalen, uint32_t datalen, void *model);
50 int usecount; 54 int usecount;
51 int disabled; /* if seted the compressor won't compress */ 55 int disabled; /* if set the compressor won't compress */
52 unsigned char *compr_buf; /* used by size compr. mode */ 56 unsigned char *compr_buf; /* used by size compr. mode */
53 uint32_t compr_buf_size; /* used by size compr. mode */ 57 uint32_t compr_buf_size; /* used by size compr. mode */
54 uint32_t stat_compr_orig_size; 58 uint32_t stat_compr_orig_size;
55 uint32_t stat_compr_new_size; 59 uint32_t stat_compr_new_size;
56 uint32_t stat_compr_blocks; 60 uint32_t stat_compr_blocks;
57 uint32_t stat_decompr_blocks; 61 uint32_t stat_decompr_blocks;
58}; 62};
59 63
60int jffs2_register_compressor(struct jffs2_compressor *comp); 64int jffs2_register_compressor(struct jffs2_compressor *comp);
@@ -64,12 +68,12 @@ int jffs2_compressors_init(void);
64int jffs2_compressors_exit(void); 68int jffs2_compressors_exit(void);
65 69
66uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 70uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
67 unsigned char *data_in, unsigned char **cpage_out, 71 unsigned char *data_in, unsigned char **cpage_out,
68 uint32_t *datalen, uint32_t *cdatalen); 72 uint32_t *datalen, uint32_t *cdatalen);
69 73
70int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 74int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
71 uint16_t comprtype, unsigned char *cdata_in, 75 uint16_t comprtype, unsigned char *cdata_in,
72 unsigned char *data_out, uint32_t cdatalen, uint32_t datalen); 76 unsigned char *data_out, uint32_t cdatalen, uint32_t datalen);
73 77
74void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig); 78void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig);
75 79
@@ -90,5 +94,9 @@ void jffs2_rtime_exit(void);
90int jffs2_zlib_init(void); 94int jffs2_zlib_init(void);
91void jffs2_zlib_exit(void); 95void jffs2_zlib_exit(void);
92#endif 96#endif
97#ifdef CONFIG_JFFS2_LZO
98int jffs2_lzo_init(void);
99void jffs2_lzo_exit(void);
100#endif
93 101
94#endif /* __JFFS2_COMPR_H__ */ 102#endif /* __JFFS2_COMPR_H__ */
diff --git a/fs/jffs2/compr_lzo.c b/fs/jffs2/compr_lzo.c
new file mode 100644
index 000000000000..47b045797e42
--- /dev/null
+++ b/fs/jffs2/compr_lzo.c
@@ -0,0 +1,108 @@
1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright © 2007 Nokia Corporation. All rights reserved.
5 *
6 * Created by Richard Purdie <rpurdie@openedhand.com>
7 *
8 * For licensing information, see the file 'LICENCE' in this directory.
9 *
10 */
11
12#include <linux/kernel.h>
13#include <linux/sched.h>
14#include <linux/slab.h>
15#include <linux/vmalloc.h>
16#include <linux/init.h>
17#include <linux/lzo.h>
18#include "compr.h"
19
20static void *lzo_mem;
21static void *lzo_compress_buf;
22static DEFINE_MUTEX(deflate_mutex);
23
24static void free_workspace(void)
25{
26 vfree(lzo_mem);
27 vfree(lzo_compress_buf);
28}
29
30static int __init alloc_workspace(void)
31{
32 lzo_mem = vmalloc(LZO1X_MEM_COMPRESS);
33 lzo_compress_buf = vmalloc(lzo1x_worst_compress(PAGE_SIZE));
34
35 if (!lzo_mem || !lzo_compress_buf) {
36 printk(KERN_WARNING "Failed to allocate lzo deflate workspace\n");
37 free_workspace();
38 return -ENOMEM;
39 }
40
41 return 0;
42}
43
44static int jffs2_lzo_compress(unsigned char *data_in, unsigned char *cpage_out,
45 uint32_t *sourcelen, uint32_t *dstlen, void *model)
46{
47 size_t compress_size;
48 int ret;
49
50 mutex_lock(&deflate_mutex);
51 ret = lzo1x_1_compress(data_in, *sourcelen, lzo_compress_buf, &compress_size, lzo_mem);
52 mutex_unlock(&deflate_mutex);
53
54 if (ret != LZO_E_OK)
55 return -1;
56
57 if (compress_size > *dstlen)
58 return -1;
59
60 memcpy(cpage_out, lzo_compress_buf, compress_size);
61 *dstlen = compress_size;
62
63 return 0;
64}
65
66static int jffs2_lzo_decompress(unsigned char *data_in, unsigned char *cpage_out,
67 uint32_t srclen, uint32_t destlen, void *model)
68{
69 size_t dl = destlen;
70 int ret;
71
72 ret = lzo1x_decompress_safe(data_in, srclen, cpage_out, &dl);
73
74 if (ret != LZO_E_OK || dl != destlen)
75 return -1;
76
77 return 0;
78}
79
80static struct jffs2_compressor jffs2_lzo_comp = {
81 .priority = JFFS2_LZO_PRIORITY,
82 .name = "lzo",
83 .compr = JFFS2_COMPR_LZO,
84 .compress = &jffs2_lzo_compress,
85 .decompress = &jffs2_lzo_decompress,
86 .disabled = 0,
87};
88
89int __init jffs2_lzo_init(void)
90{
91 int ret;
92
93 ret = alloc_workspace();
94 if (ret < 0)
95 return ret;
96
97 ret = jffs2_register_compressor(&jffs2_lzo_comp);
98 if (ret)
99 free_workspace();
100
101 return ret;
102}
103
104void jffs2_lzo_exit(void)
105{
106 jffs2_unregister_compressor(&jffs2_lzo_comp);
107 free_workspace();
108}
diff --git a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c
index 0d0bfd2e4e0d..546d1538d076 100644
--- a/fs/jffs2/compr_rtime.c
+++ b/fs/jffs2/compr_rtime.c
@@ -104,7 +104,7 @@ static int jffs2_rtime_decompress(unsigned char *data_in,
104 } 104 }
105 } 105 }
106 } 106 }
107 return 0; 107 return 0;
108} 108}
109 109
110static struct jffs2_compressor jffs2_rtime_comp = { 110static struct jffs2_compressor jffs2_rtime_comp = {
diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c
index ea0431e047d5..c73fa89b5f8a 100644
--- a/fs/jffs2/compr_rubin.c
+++ b/fs/jffs2/compr_rubin.c
@@ -384,7 +384,7 @@ static int jffs2_rubinmips_decompress(unsigned char *data_in,
384 void *model) 384 void *model)
385{ 385{
386 rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen); 386 rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen);
387 return 0; 387 return 0;
388} 388}
389 389
390static int jffs2_dynrubin_decompress(unsigned char *data_in, 390static int jffs2_dynrubin_decompress(unsigned char *data_in,
@@ -399,7 +399,7 @@ static int jffs2_dynrubin_decompress(unsigned char *data_in,
399 bits[c] = data_in[c]; 399 bits[c] = data_in[c];
400 400
401 rubin_do_decompress(256, bits, data_in+8, cpage_out, sourcelen-8, dstlen); 401 rubin_do_decompress(256, bits, data_in+8, cpage_out, sourcelen-8, dstlen);
402 return 0; 402 return 0;
403} 403}
404 404
405static struct jffs2_compressor jffs2_rubinmips_comp = { 405static struct jffs2_compressor jffs2_rubinmips_comp = {
diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c
index 2b87fccc1557..cfd301a5edfc 100644
--- a/fs/jffs2/compr_zlib.c
+++ b/fs/jffs2/compr_zlib.c
@@ -181,7 +181,7 @@ static int jffs2_zlib_decompress(unsigned char *data_in,
181 } 181 }
182 zlib_inflateEnd(&inf_strm); 182 zlib_inflateEnd(&inf_strm);
183 mutex_unlock(&inflate_mutex); 183 mutex_unlock(&inflate_mutex);
184 return 0; 184 return 0;
185} 185}
186 186
187static struct jffs2_compressor jffs2_zlib_comp = { 187static struct jffs2_compressor jffs2_zlib_comp = {
@@ -203,11 +203,11 @@ int __init jffs2_zlib_init(void)
203 203
204 ret = alloc_workspaces(); 204 ret = alloc_workspaces();
205 if (ret) 205 if (ret)
206 return ret; 206 return ret;
207 207
208 ret = jffs2_register_compressor(&jffs2_zlib_comp); 208 ret = jffs2_register_compressor(&jffs2_zlib_comp);
209 if (ret) 209 if (ret)
210 free_workspaces(); 210 free_workspaces();
211 211
212 return ret; 212 return ret;
213} 213}
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index c1dfca310dd6..8353eb9c1799 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -32,7 +32,7 @@ static int jffs2_mkdir (struct inode *,struct dentry *,int);
32static int jffs2_rmdir (struct inode *,struct dentry *); 32static int jffs2_rmdir (struct inode *,struct dentry *);
33static int jffs2_mknod (struct inode *,struct dentry *,int,dev_t); 33static int jffs2_mknod (struct inode *,struct dentry *,int,dev_t);
34static int jffs2_rename (struct inode *, struct dentry *, 34static int jffs2_rename (struct inode *, struct dentry *,
35 struct inode *, struct dentry *); 35 struct inode *, struct dentry *);
36 36
37const struct file_operations jffs2_dir_operations = 37const struct file_operations jffs2_dir_operations =
38{ 38{
@@ -182,6 +182,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
182 struct jffs2_inode_info *f, *dir_f; 182 struct jffs2_inode_info *f, *dir_f;
183 struct jffs2_sb_info *c; 183 struct jffs2_sb_info *c;
184 struct inode *inode; 184 struct inode *inode;
185 struct posix_acl *acl;
185 int ret; 186 int ret;
186 187
187 ri = jffs2_alloc_raw_inode(); 188 ri = jffs2_alloc_raw_inode();
@@ -192,7 +193,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
192 193
193 D1(printk(KERN_DEBUG "jffs2_create()\n")); 194 D1(printk(KERN_DEBUG "jffs2_create()\n"));
194 195
195 inode = jffs2_new_inode(dir_i, mode, ri); 196 inode = jffs2_new_inode(dir_i, mode, ri, &acl);
196 197
197 if (IS_ERR(inode)) { 198 if (IS_ERR(inode)) {
198 D1(printk(KERN_DEBUG "jffs2_new_inode() failed\n")); 199 D1(printk(KERN_DEBUG "jffs2_new_inode() failed\n"));
@@ -212,12 +213,12 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
212 dentry->d_name.name, dentry->d_name.len); 213 dentry->d_name.name, dentry->d_name.len);
213 214
214 if (ret) 215 if (ret)
215 goto fail; 216 goto fail_acl;
216 217
217 ret = jffs2_init_security(inode, dir_i); 218 ret = jffs2_init_security(inode, dir_i);
218 if (ret) 219 if (ret)
219 goto fail; 220 goto fail_acl;
220 ret = jffs2_init_acl(inode, dir_i); 221 ret = jffs2_init_acl(inode, acl);
221 if (ret) 222 if (ret)
222 goto fail; 223 goto fail;
223 224
@@ -230,6 +231,8 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
230 inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink, inode->i_mapping->nrpages)); 231 inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink, inode->i_mapping->nrpages));
231 return 0; 232 return 0;
232 233
234 fail_acl:
235 posix_acl_release(acl);
233 fail: 236 fail:
234 make_bad_inode(inode); 237 make_bad_inode(inode);
235 iput(inode); 238 iput(inode);
@@ -306,6 +309,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
306 struct jffs2_full_dirent *fd; 309 struct jffs2_full_dirent *fd;
307 int namelen; 310 int namelen;
308 uint32_t alloclen; 311 uint32_t alloclen;
312 struct posix_acl *acl;
309 int ret, targetlen = strlen(target); 313 int ret, targetlen = strlen(target);
310 314
311 /* FIXME: If you care. We'd need to use frags for the target 315 /* FIXME: If you care. We'd need to use frags for the target
@@ -332,7 +336,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
332 return ret; 336 return ret;
333 } 337 }
334 338
335 inode = jffs2_new_inode(dir_i, S_IFLNK | S_IRWXUGO, ri); 339 inode = jffs2_new_inode(dir_i, S_IFLNK | S_IRWXUGO, ri, &acl);
336 340
337 if (IS_ERR(inode)) { 341 if (IS_ERR(inode)) {
338 jffs2_free_raw_inode(ri); 342 jffs2_free_raw_inode(ri);
@@ -362,6 +366,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
362 up(&f->sem); 366 up(&f->sem);
363 jffs2_complete_reservation(c); 367 jffs2_complete_reservation(c);
364 jffs2_clear_inode(inode); 368 jffs2_clear_inode(inode);
369 posix_acl_release(acl);
365 return PTR_ERR(fn); 370 return PTR_ERR(fn);
366 } 371 }
367 372
@@ -372,6 +377,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
372 up(&f->sem); 377 up(&f->sem);
373 jffs2_complete_reservation(c); 378 jffs2_complete_reservation(c);
374 jffs2_clear_inode(inode); 379 jffs2_clear_inode(inode);
380 posix_acl_release(acl);
375 return -ENOMEM; 381 return -ENOMEM;
376 } 382 }
377 383
@@ -389,9 +395,10 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
389 ret = jffs2_init_security(inode, dir_i); 395 ret = jffs2_init_security(inode, dir_i);
390 if (ret) { 396 if (ret) {
391 jffs2_clear_inode(inode); 397 jffs2_clear_inode(inode);
398 posix_acl_release(acl);
392 return ret; 399 return ret;
393 } 400 }
394 ret = jffs2_init_acl(inode, dir_i); 401 ret = jffs2_init_acl(inode, acl);
395 if (ret) { 402 if (ret) {
396 jffs2_clear_inode(inode); 403 jffs2_clear_inode(inode);
397 return ret; 404 return ret;
@@ -469,6 +476,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
469 struct jffs2_full_dirent *fd; 476 struct jffs2_full_dirent *fd;
470 int namelen; 477 int namelen;
471 uint32_t alloclen; 478 uint32_t alloclen;
479 struct posix_acl *acl;
472 int ret; 480 int ret;
473 481
474 mode |= S_IFDIR; 482 mode |= S_IFDIR;
@@ -491,7 +499,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
491 return ret; 499 return ret;
492 } 500 }
493 501
494 inode = jffs2_new_inode(dir_i, mode, ri); 502 inode = jffs2_new_inode(dir_i, mode, ri, &acl);
495 503
496 if (IS_ERR(inode)) { 504 if (IS_ERR(inode)) {
497 jffs2_free_raw_inode(ri); 505 jffs2_free_raw_inode(ri);
@@ -518,6 +526,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
518 up(&f->sem); 526 up(&f->sem);
519 jffs2_complete_reservation(c); 527 jffs2_complete_reservation(c);
520 jffs2_clear_inode(inode); 528 jffs2_clear_inode(inode);
529 posix_acl_release(acl);
521 return PTR_ERR(fn); 530 return PTR_ERR(fn);
522 } 531 }
523 /* No data here. Only a metadata node, which will be 532 /* No data here. Only a metadata node, which will be
@@ -531,9 +540,10 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
531 ret = jffs2_init_security(inode, dir_i); 540 ret = jffs2_init_security(inode, dir_i);
532 if (ret) { 541 if (ret) {
533 jffs2_clear_inode(inode); 542 jffs2_clear_inode(inode);
543 posix_acl_release(acl);
534 return ret; 544 return ret;
535 } 545 }
536 ret = jffs2_init_acl(inode, dir_i); 546 ret = jffs2_init_acl(inode, acl);
537 if (ret) { 547 if (ret) {
538 jffs2_clear_inode(inode); 548 jffs2_clear_inode(inode);
539 return ret; 549 return ret;
@@ -629,6 +639,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
629 union jffs2_device_node dev; 639 union jffs2_device_node dev;
630 int devlen = 0; 640 int devlen = 0;
631 uint32_t alloclen; 641 uint32_t alloclen;
642 struct posix_acl *acl;
632 int ret; 643 int ret;
633 644
634 if (!new_valid_dev(rdev)) 645 if (!new_valid_dev(rdev))
@@ -655,7 +666,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
655 return ret; 666 return ret;
656 } 667 }
657 668
658 inode = jffs2_new_inode(dir_i, mode, ri); 669 inode = jffs2_new_inode(dir_i, mode, ri, &acl);
659 670
660 if (IS_ERR(inode)) { 671 if (IS_ERR(inode)) {
661 jffs2_free_raw_inode(ri); 672 jffs2_free_raw_inode(ri);
@@ -684,6 +695,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
684 up(&f->sem); 695 up(&f->sem);
685 jffs2_complete_reservation(c); 696 jffs2_complete_reservation(c);
686 jffs2_clear_inode(inode); 697 jffs2_clear_inode(inode);
698 posix_acl_release(acl);
687 return PTR_ERR(fn); 699 return PTR_ERR(fn);
688 } 700 }
689 /* No data here. Only a metadata node, which will be 701 /* No data here. Only a metadata node, which will be
@@ -697,9 +709,10 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
697 ret = jffs2_init_security(inode, dir_i); 709 ret = jffs2_init_security(inode, dir_i);
698 if (ret) { 710 if (ret) {
699 jffs2_clear_inode(inode); 711 jffs2_clear_inode(inode);
712 posix_acl_release(acl);
700 return ret; 713 return ret;
701 } 714 }
702 ret = jffs2_init_acl(inode, dir_i); 715 ret = jffs2_init_acl(inode, acl);
703 if (ret) { 716 if (ret) {
704 jffs2_clear_inode(inode); 717 jffs2_clear_inode(inode);
705 return ret; 718 return ret;
@@ -770,7 +783,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
770} 783}
771 784
772static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, 785static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
773 struct inode *new_dir_i, struct dentry *new_dentry) 786 struct inode *new_dir_i, struct dentry *new_dentry)
774{ 787{
775 int ret; 788 int ret;
776 struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb); 789 struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb);
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index 66e7c2f1e644..a1db9180633f 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -38,8 +38,8 @@ static void jffs2_erase_block(struct jffs2_sb_info *c,
38#ifdef __ECOS 38#ifdef __ECOS
39 ret = jffs2_flash_erase(c, jeb); 39 ret = jffs2_flash_erase(c, jeb);
40 if (!ret) { 40 if (!ret) {
41 jffs2_erase_succeeded(c, jeb); 41 jffs2_erase_succeeded(c, jeb);
42 return; 42 return;
43 } 43 }
44 bad_offset = jeb->offset; 44 bad_offset = jeb->offset;
45#else /* Linux */ 45#else /* Linux */
@@ -50,12 +50,14 @@ static void jffs2_erase_block(struct jffs2_sb_info *c,
50 instr = kmalloc(sizeof(struct erase_info) + sizeof(struct erase_priv_struct), GFP_KERNEL); 50 instr = kmalloc(sizeof(struct erase_info) + sizeof(struct erase_priv_struct), GFP_KERNEL);
51 if (!instr) { 51 if (!instr) {
52 printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n"); 52 printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n");
53 down(&c->erase_free_sem);
53 spin_lock(&c->erase_completion_lock); 54 spin_lock(&c->erase_completion_lock);
54 list_move(&jeb->list, &c->erase_pending_list); 55 list_move(&jeb->list, &c->erase_pending_list);
55 c->erasing_size -= c->sector_size; 56 c->erasing_size -= c->sector_size;
56 c->dirty_size += c->sector_size; 57 c->dirty_size += c->sector_size;
57 jeb->dirty_size = c->sector_size; 58 jeb->dirty_size = c->sector_size;
58 spin_unlock(&c->erase_completion_lock); 59 spin_unlock(&c->erase_completion_lock);
60 up(&c->erase_free_sem);
59 return; 61 return;
60 } 62 }
61 63
@@ -82,12 +84,14 @@ static void jffs2_erase_block(struct jffs2_sb_info *c,
82 if (ret == -ENOMEM || ret == -EAGAIN) { 84 if (ret == -ENOMEM || ret == -EAGAIN) {
83 /* Erase failed immediately. Refile it on the list */ 85 /* Erase failed immediately. Refile it on the list */
84 D1(printk(KERN_DEBUG "Erase at 0x%08x failed: %d. Refiling on erase_pending_list\n", jeb->offset, ret)); 86 D1(printk(KERN_DEBUG "Erase at 0x%08x failed: %d. Refiling on erase_pending_list\n", jeb->offset, ret));
87 down(&c->erase_free_sem);
85 spin_lock(&c->erase_completion_lock); 88 spin_lock(&c->erase_completion_lock);
86 list_move(&jeb->list, &c->erase_pending_list); 89 list_move(&jeb->list, &c->erase_pending_list);
87 c->erasing_size -= c->sector_size; 90 c->erasing_size -= c->sector_size;
88 c->dirty_size += c->sector_size; 91 c->dirty_size += c->sector_size;
89 jeb->dirty_size = c->sector_size; 92 jeb->dirty_size = c->sector_size;
90 spin_unlock(&c->erase_completion_lock); 93 spin_unlock(&c->erase_completion_lock);
94 up(&c->erase_free_sem);
91 return; 95 return;
92 } 96 }
93 97
@@ -114,6 +118,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
114 jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list); 118 jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list);
115 list_del(&jeb->list); 119 list_del(&jeb->list);
116 spin_unlock(&c->erase_completion_lock); 120 spin_unlock(&c->erase_completion_lock);
121 up(&c->erase_free_sem);
117 jffs2_mark_erased_block(c, jeb); 122 jffs2_mark_erased_block(c, jeb);
118 123
119 if (!--count) { 124 if (!--count) {
@@ -134,6 +139,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
134 jffs2_free_jeb_node_refs(c, jeb); 139 jffs2_free_jeb_node_refs(c, jeb);
135 list_add(&jeb->list, &c->erasing_list); 140 list_add(&jeb->list, &c->erasing_list);
136 spin_unlock(&c->erase_completion_lock); 141 spin_unlock(&c->erase_completion_lock);
142 up(&c->erase_free_sem);
137 143
138 jffs2_erase_block(c, jeb); 144 jffs2_erase_block(c, jeb);
139 145
@@ -142,23 +148,25 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
142 } 148 }
143 149
144 /* Be nice */ 150 /* Be nice */
145 cond_resched(); 151 yield();
152 down(&c->erase_free_sem);
146 spin_lock(&c->erase_completion_lock); 153 spin_lock(&c->erase_completion_lock);
147 } 154 }
148 155
149 spin_unlock(&c->erase_completion_lock); 156 spin_unlock(&c->erase_completion_lock);
157 up(&c->erase_free_sem);
150 done: 158 done:
151 D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n")); 159 D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n"));
152
153 up(&c->erase_free_sem);
154} 160}
155 161
156static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) 162static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
157{ 163{
158 D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset)); 164 D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset));
165 down(&c->erase_free_sem);
159 spin_lock(&c->erase_completion_lock); 166 spin_lock(&c->erase_completion_lock);
160 list_move_tail(&jeb->list, &c->erase_complete_list); 167 list_move_tail(&jeb->list, &c->erase_complete_list);
161 spin_unlock(&c->erase_completion_lock); 168 spin_unlock(&c->erase_completion_lock);
169 up(&c->erase_free_sem);
162 /* Ensure that kupdated calls us again to mark them clean */ 170 /* Ensure that kupdated calls us again to mark them clean */
163 jffs2_erase_pending_trigger(c); 171 jffs2_erase_pending_trigger(c);
164} 172}
@@ -172,22 +180,26 @@ static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock
172 failed too many times. */ 180 failed too many times. */
173 if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) { 181 if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) {
174 /* We'd like to give this block another try. */ 182 /* We'd like to give this block another try. */
183 down(&c->erase_free_sem);
175 spin_lock(&c->erase_completion_lock); 184 spin_lock(&c->erase_completion_lock);
176 list_move(&jeb->list, &c->erase_pending_list); 185 list_move(&jeb->list, &c->erase_pending_list);
177 c->erasing_size -= c->sector_size; 186 c->erasing_size -= c->sector_size;
178 c->dirty_size += c->sector_size; 187 c->dirty_size += c->sector_size;
179 jeb->dirty_size = c->sector_size; 188 jeb->dirty_size = c->sector_size;
180 spin_unlock(&c->erase_completion_lock); 189 spin_unlock(&c->erase_completion_lock);
190 up(&c->erase_free_sem);
181 return; 191 return;
182 } 192 }
183 } 193 }
184 194
195 down(&c->erase_free_sem);
185 spin_lock(&c->erase_completion_lock); 196 spin_lock(&c->erase_completion_lock);
186 c->erasing_size -= c->sector_size; 197 c->erasing_size -= c->sector_size;
187 c->bad_size += c->sector_size; 198 c->bad_size += c->sector_size;
188 list_move(&jeb->list, &c->bad_list); 199 list_move(&jeb->list, &c->bad_list);
189 c->nr_erasing_blocks--; 200 c->nr_erasing_blocks--;
190 spin_unlock(&c->erase_completion_lock); 201 spin_unlock(&c->erase_completion_lock);
202 up(&c->erase_free_sem);
191 wake_up(&c->erase_wait); 203 wake_up(&c->erase_wait);
192} 204}
193 205
@@ -317,6 +329,33 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
317 size_t retlen; 329 size_t retlen;
318 int ret = -EIO; 330 int ret = -EIO;
319 331
332 if (c->mtd->point) {
333 unsigned long *wordebuf;
334
335 ret = c->mtd->point(c->mtd, jeb->offset, c->sector_size, &retlen, (unsigned char **)&ebuf);
336 if (ret) {
337 D1(printk(KERN_DEBUG "MTD point failed %d\n", ret));
338 goto do_flash_read;
339 }
340 if (retlen < c->sector_size) {
341 /* Don't muck about if it won't let us point to the whole erase sector */
342 D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", retlen));
343 c->mtd->unpoint(c->mtd, ebuf, jeb->offset, retlen);
344 goto do_flash_read;
345 }
346 wordebuf = ebuf-sizeof(*wordebuf);
347 retlen /= sizeof(*wordebuf);
348 do {
349 if (*++wordebuf != ~0)
350 break;
351 } while(--retlen);
352 c->mtd->unpoint(c->mtd, ebuf, jeb->offset, c->sector_size);
353 if (retlen)
354 printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08tx\n",
355 *wordebuf, jeb->offset + c->sector_size-retlen*sizeof(*wordebuf));
356 return 0;
357 }
358 do_flash_read:
320 ebuf = kmalloc(PAGE_SIZE, GFP_KERNEL); 359 ebuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
321 if (!ebuf) { 360 if (!ebuf) {
322 printk(KERN_WARNING "Failed to allocate page buffer for verifying erase at 0x%08x. Refiling\n", jeb->offset); 361 printk(KERN_WARNING "Failed to allocate page buffer for verifying erase at 0x%08x. Refiling\n", jeb->offset);
@@ -362,7 +401,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
362{ 401{
363 size_t retlen; 402 size_t retlen;
364 int ret; 403 int ret;
365 uint32_t bad_offset; 404 uint32_t uninitialized_var(bad_offset);
366 405
367 switch (jffs2_block_check_erase(c, jeb, &bad_offset)) { 406 switch (jffs2_block_check_erase(c, jeb, &bad_offset)) {
368 case -EAGAIN: goto refile; 407 case -EAGAIN: goto refile;
@@ -417,6 +456,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
417 jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL); 456 jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);
418 } 457 }
419 458
459 down(&c->erase_free_sem);
420 spin_lock(&c->erase_completion_lock); 460 spin_lock(&c->erase_completion_lock);
421 c->erasing_size -= c->sector_size; 461 c->erasing_size -= c->sector_size;
422 c->free_size += jeb->free_size; 462 c->free_size += jeb->free_size;
@@ -429,23 +469,28 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
429 c->nr_erasing_blocks--; 469 c->nr_erasing_blocks--;
430 c->nr_free_blocks++; 470 c->nr_free_blocks++;
431 spin_unlock(&c->erase_completion_lock); 471 spin_unlock(&c->erase_completion_lock);
472 up(&c->erase_free_sem);
432 wake_up(&c->erase_wait); 473 wake_up(&c->erase_wait);
433 return; 474 return;
434 475
435filebad: 476filebad:
477 down(&c->erase_free_sem);
436 spin_lock(&c->erase_completion_lock); 478 spin_lock(&c->erase_completion_lock);
437 /* Stick it on a list (any list) so erase_failed can take it 479 /* Stick it on a list (any list) so erase_failed can take it
438 right off again. Silly, but shouldn't happen often. */ 480 right off again. Silly, but shouldn't happen often. */
439 list_add(&jeb->list, &c->erasing_list); 481 list_add(&jeb->list, &c->erasing_list);
440 spin_unlock(&c->erase_completion_lock); 482 spin_unlock(&c->erase_completion_lock);
483 up(&c->erase_free_sem);
441 jffs2_erase_failed(c, jeb, bad_offset); 484 jffs2_erase_failed(c, jeb, bad_offset);
442 return; 485 return;
443 486
444refile: 487refile:
445 /* Stick it back on the list from whence it came and come back later */ 488 /* Stick it back on the list from whence it came and come back later */
446 jffs2_erase_pending_trigger(c); 489 jffs2_erase_pending_trigger(c);
490 down(&c->erase_free_sem);
447 spin_lock(&c->erase_completion_lock); 491 spin_lock(&c->erase_completion_lock);
448 list_add(&jeb->list, &c->erase_complete_list); 492 list_add(&jeb->list, &c->erase_complete_list);
449 spin_unlock(&c->erase_completion_lock); 493 spin_unlock(&c->erase_completion_lock);
494 up(&c->erase_free_sem);
450 return; 495 return;
451} 496}
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 8bc727b71696..ed85f9afdbc8 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -24,7 +24,7 @@
24 24
25static int jffs2_flash_setup(struct jffs2_sb_info *c); 25static int jffs2_flash_setup(struct jffs2_sb_info *c);
26 26
27static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) 27int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
28{ 28{
29 struct jffs2_full_dnode *old_metadata, *new_metadata; 29 struct jffs2_full_dnode *old_metadata, *new_metadata;
30 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 30 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
@@ -36,10 +36,8 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
36 unsigned int ivalid; 36 unsigned int ivalid;
37 uint32_t alloclen; 37 uint32_t alloclen;
38 int ret; 38 int ret;
39
39 D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino)); 40 D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino));
40 ret = inode_change_ok(inode, iattr);
41 if (ret)
42 return ret;
43 41
44 /* Special cases - we don't want more than one data node 42 /* Special cases - we don't want more than one data node
45 for these types on the medium at any time. So setattr 43 for these types on the medium at any time. So setattr
@@ -183,9 +181,14 @@ int jffs2_setattr(struct dentry *dentry, struct iattr *iattr)
183{ 181{
184 int rc; 182 int rc;
185 183
184 rc = inode_change_ok(dentry->d_inode, iattr);
185 if (rc)
186 return rc;
187
186 rc = jffs2_do_setattr(dentry->d_inode, iattr); 188 rc = jffs2_do_setattr(dentry->d_inode, iattr);
187 if (!rc && (iattr->ia_valid & ATTR_MODE)) 189 if (!rc && (iattr->ia_valid & ATTR_MODE))
188 rc = jffs2_acl_chmod(dentry->d_inode); 190 rc = jffs2_acl_chmod(dentry->d_inode);
191
189 return rc; 192 return rc;
190} 193}
191 194
@@ -399,7 +402,8 @@ void jffs2_write_super (struct super_block *sb)
399 402
400/* jffs2_new_inode: allocate a new inode and inocache, add it to the hash, 403/* jffs2_new_inode: allocate a new inode and inocache, add it to the hash,
401 fill in the raw_inode while you're at it. */ 404 fill in the raw_inode while you're at it. */
402struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_inode *ri) 405struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_inode *ri,
406 struct posix_acl **acl)
403{ 407{
404 struct inode *inode; 408 struct inode *inode;
405 struct super_block *sb = dir_i->i_sb; 409 struct super_block *sb = dir_i->i_sb;
@@ -431,7 +435,23 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i
431 } else { 435 } else {
432 ri->gid = cpu_to_je16(current->fsgid); 436 ri->gid = cpu_to_je16(current->fsgid);
433 } 437 }
434 ri->mode = cpu_to_jemode(mode); 438
439 /* POSIX ACLs have to be processed now, at least partly.
440 The umask is only applied if there's no default ACL */
441 if (!S_ISLNK(mode)) {
442 *acl = jffs2_get_acl(dir_i, ACL_TYPE_DEFAULT);
443 if (IS_ERR(*acl)) {
444 make_bad_inode(inode);
445 iput(inode);
446 inode = (void *)*acl;
447 *acl = NULL;
448 return inode;
449 }
450 if (!(*acl))
451 mode &= ~current->fs->umask;
452 } else {
453 *acl = NULL;
454 }
435 ret = jffs2_do_new_inode (c, f, mode, ri); 455 ret = jffs2_do_new_inode (c, f, mode, ri);
436 if (ret) { 456 if (ret) {
437 make_bad_inode(inode); 457 make_bad_inode(inode);
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 2d99e06ab223..32ff0373aa04 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -122,6 +122,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
122 struct jffs2_inode_cache *ic; 122 struct jffs2_inode_cache *ic;
123 struct jffs2_eraseblock *jeb; 123 struct jffs2_eraseblock *jeb;
124 struct jffs2_raw_node_ref *raw; 124 struct jffs2_raw_node_ref *raw;
125 uint32_t gcblock_dirty;
125 int ret = 0, inum, nlink; 126 int ret = 0, inum, nlink;
126 int xattr = 0; 127 int xattr = 0;
127 128
@@ -236,6 +237,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
236 } 237 }
237 238
238 raw = jeb->gc_node; 239 raw = jeb->gc_node;
240 gcblock_dirty = jeb->dirty_size;
239 241
240 while(ref_obsolete(raw)) { 242 while(ref_obsolete(raw)) {
241 D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", ref_offset(raw))); 243 D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", ref_offset(raw)));
@@ -282,7 +284,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
282 } else { 284 } else {
283 ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic, raw); 285 ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic, raw);
284 } 286 }
285 goto release_sem; 287 goto test_gcnode;
286 } 288 }
287#endif 289#endif
288 290
@@ -376,7 +378,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
376 378
377 if (ret != -EBADFD) { 379 if (ret != -EBADFD) {
378 spin_unlock(&c->inocache_lock); 380 spin_unlock(&c->inocache_lock);
379 goto release_sem; 381 goto test_gcnode;
380 } 382 }
381 383
382 /* Fall through if it wanted us to, with inocache_lock held */ 384 /* Fall through if it wanted us to, with inocache_lock held */
@@ -407,6 +409,12 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
407 409
408 jffs2_gc_release_inode(c, f); 410 jffs2_gc_release_inode(c, f);
409 411
412 test_gcnode:
413 if (jeb->dirty_size == gcblock_dirty && !ref_obsolete(jeb->gc_node)) {
414 /* Eep. This really should never happen. GC is broken */
415 printk(KERN_ERR "Error garbage collecting node at %08x!\n", ref_offset(jeb->gc_node));
416 ret = -ENOSPC;
417 }
410 release_sem: 418 release_sem:
411 up(&c->alloc_sem); 419 up(&c->alloc_sem);
412 420
@@ -556,7 +564,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
556 564
557 node = kmalloc(rawlen, GFP_KERNEL); 565 node = kmalloc(rawlen, GFP_KERNEL);
558 if (!node) 566 if (!node)
559 return -ENOMEM; 567 return -ENOMEM;
560 568
561 ret = jffs2_flash_read(c, ref_offset(raw), rawlen, &retlen, (char *)node); 569 ret = jffs2_flash_read(c, ref_offset(raw), rawlen, &retlen, (char *)node);
562 if (!ret && retlen != rawlen) 570 if (!ret && retlen != rawlen)
@@ -598,10 +606,15 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
598 goto bail; 606 goto bail;
599 } 607 }
600 608
609 if (strnlen(node->d.name, node->d.nsize) != node->d.nsize) {
610 printk(KERN_WARNING "Name in dirent node at 0x%08x contains zeroes\n", ref_offset(raw));
611 goto bail;
612 }
613
601 if (node->d.nsize) { 614 if (node->d.nsize) {
602 crc = crc32(0, node->d.name, node->d.nsize); 615 crc = crc32(0, node->d.name, node->d.nsize);
603 if (je32_to_cpu(node->d.name_crc) != crc) { 616 if (je32_to_cpu(node->d.name_crc) != crc) {
604 printk(KERN_WARNING "Name CRC failed on REF_PRISTINE dirent ode at 0x%08x: Read 0x%08x, calculated 0x%08x\n", 617 printk(KERN_WARNING "Name CRC failed on REF_PRISTINE dirent node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
605 ref_offset(raw), je32_to_cpu(node->d.name_crc), crc); 618 ref_offset(raw), je32_to_cpu(node->d.name_crc), crc);
606 goto bail; 619 goto bail;
607 } 620 }
@@ -624,7 +637,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
624 637
625 if (ret || (retlen != rawlen)) { 638 if (ret || (retlen != rawlen)) {
626 printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n", 639 printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n",
627 rawlen, phys_ofs, ret, retlen); 640 rawlen, phys_ofs, ret, retlen);
628 if (retlen) { 641 if (retlen) {
629 jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, rawlen, NULL); 642 jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, rawlen, NULL);
630 } else { 643 } else {
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
index b13298a824ed..3a2197f3c812 100644
--- a/fs/jffs2/jffs2_fs_sb.h
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -69,6 +69,8 @@ struct jffs2_sb_info {
69 uint8_t resv_blocks_gctrigger; /* ... wake up the GC thread */ 69 uint8_t resv_blocks_gctrigger; /* ... wake up the GC thread */
70 uint8_t resv_blocks_gcbad; /* ... pick a block from the bad_list to GC */ 70 uint8_t resv_blocks_gcbad; /* ... pick a block from the bad_list to GC */
71 uint8_t resv_blocks_gcmerge; /* ... merge pages when garbage collecting */ 71 uint8_t resv_blocks_gcmerge; /* ... merge pages when garbage collecting */
72 /* Number of 'very dirty' blocks before we trigger immediate GC */
73 uint8_t vdirty_blocks_gctrigger;
72 74
73 uint32_t nospc_dirty_size; 75 uint32_t nospc_dirty_size;
74 76
@@ -106,6 +108,9 @@ struct jffs2_sb_info {
106 108
107 uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */ 109 uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */
108 110
111#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
112 unsigned char *wbuf_verify; /* read-back buffer for verification */
113#endif
109#ifdef CONFIG_JFFS2_FS_WRITEBUFFER 114#ifdef CONFIG_JFFS2_FS_WRITEBUFFER
110 unsigned char *wbuf; /* Write-behind buffer for NAND flash */ 115 unsigned char *wbuf; /* Write-behind buffer for NAND flash */
111 uint32_t wbuf_ofs; 116 uint32_t wbuf_ofs;
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index bc5509fe577b..ec1aae9e695e 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -127,7 +127,7 @@ static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_nod
127 return ((struct jffs2_inode_cache *)raw); 127 return ((struct jffs2_inode_cache *)raw);
128} 128}
129 129
130 /* flash_offset & 3 always has to be zero, because nodes are 130 /* flash_offset & 3 always has to be zero, because nodes are
131 always aligned at 4 bytes. So we have a couple of extra bits 131 always aligned at 4 bytes. So we have a couple of extra bits
132 to play with, which indicate the node's status; see below: */ 132 to play with, which indicate the node's status; see below: */
133#define REF_UNCHECKED 0 /* We haven't yet checked the CRC or built its inode */ 133#define REF_UNCHECKED 0 /* We haven't yet checked the CRC or built its inode */
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index dbc908ad622b..a0313fa8748e 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -154,7 +154,7 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
154 while(ret == -EAGAIN) { 154 while(ret == -EAGAIN) {
155 ret = jffs2_do_reserve_space(c, minsize, len, sumsize); 155 ret = jffs2_do_reserve_space(c, minsize, len, sumsize);
156 if (ret) { 156 if (ret) {
157 D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret)); 157 D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret));
158 } 158 }
159 } 159 }
160 spin_unlock(&c->erase_completion_lock); 160 spin_unlock(&c->erase_completion_lock);
@@ -423,7 +423,12 @@ struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c,
423 even after refiling c->nextblock */ 423 even after refiling c->nextblock */
424 if ((c->nextblock || ((ofs & 3) != REF_OBSOLETE)) 424 if ((c->nextblock || ((ofs & 3) != REF_OBSOLETE))
425 && (jeb != c->nextblock || (ofs & ~3) != jeb->offset + (c->sector_size - jeb->free_size))) { 425 && (jeb != c->nextblock || (ofs & ~3) != jeb->offset + (c->sector_size - jeb->free_size))) {
426 printk(KERN_WARNING "argh. node added in wrong place\n"); 426 printk(KERN_WARNING "argh. node added in wrong place at 0x%08x(%d)\n", ofs & ~3, ofs & 3);
427 if (c->nextblock)
428 printk(KERN_WARNING "nextblock 0x%08x", c->nextblock->offset);
429 else
430 printk(KERN_WARNING "No nextblock");
431 printk(", expected at %08x\n", jeb->offset + (c->sector_size - jeb->free_size));
427 return ERR_PTR(-EINVAL); 432 return ERR_PTR(-EINVAL);
428 } 433 }
429#endif 434#endif
@@ -717,6 +722,8 @@ int jffs2_thread_should_wake(struct jffs2_sb_info *c)
717{ 722{
718 int ret = 0; 723 int ret = 0;
719 uint32_t dirty; 724 uint32_t dirty;
725 int nr_very_dirty = 0;
726 struct jffs2_eraseblock *jeb;
720 727
721 if (c->unchecked_size) { 728 if (c->unchecked_size) {
722 D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): unchecked_size %d, checked_ino #%d\n", 729 D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): unchecked_size %d, checked_ino #%d\n",
@@ -738,8 +745,18 @@ int jffs2_thread_should_wake(struct jffs2_sb_info *c)
738 (dirty > c->nospc_dirty_size)) 745 (dirty > c->nospc_dirty_size))
739 ret = 1; 746 ret = 1;
740 747
741 D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x: %s\n", 748 list_for_each_entry(jeb, &c->very_dirty_list, list) {
742 c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size, ret?"yes":"no")); 749 nr_very_dirty++;
750 if (nr_very_dirty == c->vdirty_blocks_gctrigger) {
751 ret = 1;
752 /* In debug mode, actually go through and count them all */
753 D1(continue);
754 break;
755 }
756 }
757
758 D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x, vdirty_blocks %d: %s\n",
759 c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size, nr_very_dirty, ret?"yes":"no"));
743 760
744 return ret; 761 return ret;
745} 762}
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 80daea96bbc2..f6743a915cf3 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -173,12 +173,15 @@ int jffs2_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
173extern const struct inode_operations jffs2_symlink_inode_operations; 173extern const struct inode_operations jffs2_symlink_inode_operations;
174 174
175/* fs.c */ 175/* fs.c */
176struct posix_acl;
177
176int jffs2_setattr (struct dentry *, struct iattr *); 178int jffs2_setattr (struct dentry *, struct iattr *);
179int jffs2_do_setattr (struct inode *, struct iattr *);
177void jffs2_read_inode (struct inode *); 180void jffs2_read_inode (struct inode *);
178void jffs2_clear_inode (struct inode *); 181void jffs2_clear_inode (struct inode *);
179void jffs2_dirty_inode(struct inode *inode); 182void jffs2_dirty_inode(struct inode *inode);
180struct inode *jffs2_new_inode (struct inode *dir_i, int mode, 183struct inode *jffs2_new_inode (struct inode *dir_i, int mode,
181 struct jffs2_raw_inode *ri); 184 struct jffs2_raw_inode *ri, struct posix_acl **acl);
182int jffs2_statfs (struct dentry *, struct kstatfs *); 185int jffs2_statfs (struct dentry *, struct kstatfs *);
183void jffs2_write_super (struct super_block *); 186void jffs2_write_super (struct super_block *);
184int jffs2_remount_fs (struct super_block *, int *, char *); 187int jffs2_remount_fs (struct super_block *, int *, char *);
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index b5baa356fed2..2eae5d2dbebe 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -65,7 +65,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info
65 err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer); 65 err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer);
66 if (!err && retlen < tn->csize) { 66 if (!err && retlen < tn->csize) {
67 JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize); 67 JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize);
68 c->mtd->unpoint(c->mtd, buffer, ofs, len); 68 c->mtd->unpoint(c->mtd, buffer, ofs, retlen);
69 } else if (err) 69 } else if (err)
70 JFFS2_WARNING("MTD point failed: error code %d.\n", err); 70 JFFS2_WARNING("MTD point failed: error code %d.\n", err);
71 else 71 else
@@ -211,7 +211,7 @@ static void jffs2_kill_tn(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *
211 * ordering. 211 * ordering.
212 * 212 *
213 * Returns 0 if the node was handled (including marking it obsolete) 213 * Returns 0 if the node was handled (including marking it obsolete)
214 * < 0 an if error occurred 214 * < 0 an if error occurred
215 */ 215 */
216static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, 216static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
217 struct jffs2_readinode_info *rii, 217 struct jffs2_readinode_info *rii,
@@ -862,8 +862,8 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re
862 JFFS2_ERROR("REF_UNCHECKED but unknown node at %#08x\n", 862 JFFS2_ERROR("REF_UNCHECKED but unknown node at %#08x\n",
863 ref_offset(ref)); 863 ref_offset(ref));
864 JFFS2_ERROR("Node is {%04x,%04x,%08x,%08x}. Please report this error.\n", 864 JFFS2_ERROR("Node is {%04x,%04x,%08x,%08x}. Please report this error.\n",
865 je16_to_cpu(un->magic), je16_to_cpu(un->nodetype), 865 je16_to_cpu(un->magic), je16_to_cpu(un->nodetype),
866 je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc)); 866 je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc));
867 jffs2_mark_node_obsolete(c, ref); 867 jffs2_mark_node_obsolete(c, ref);
868 return 0; 868 return 0;
869 } 869 }
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 6c75cd433342..272872d27fd5 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -101,7 +101,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
101 if (!ret && pointlen < c->mtd->size) { 101 if (!ret && pointlen < c->mtd->size) {
102 /* Don't muck about if it won't let us point to the whole flash */ 102 /* Don't muck about if it won't let us point to the whole flash */
103 D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", pointlen)); 103 D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", pointlen));
104 c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size); 104 c->mtd->unpoint(c->mtd, flashbuf, 0, pointlen);
105 flashbuf = NULL; 105 flashbuf = NULL;
106 } 106 }
107 if (ret) 107 if (ret)
@@ -863,7 +863,7 @@ scan_more:
863 switch (je16_to_cpu(node->nodetype) & JFFS2_COMPAT_MASK) { 863 switch (je16_to_cpu(node->nodetype) & JFFS2_COMPAT_MASK) {
864 case JFFS2_FEATURE_ROCOMPAT: 864 case JFFS2_FEATURE_ROCOMPAT:
865 printk(KERN_NOTICE "Read-only compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs); 865 printk(KERN_NOTICE "Read-only compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs);
866 c->flags |= JFFS2_SB_FLAG_RO; 866 c->flags |= JFFS2_SB_FLAG_RO;
867 if (!(jffs2_is_readonly(c))) 867 if (!(jffs2_is_readonly(c)))
868 return -EROFS; 868 return -EROFS;
869 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen))))) 869 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
@@ -1004,6 +1004,7 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo
1004{ 1004{
1005 struct jffs2_full_dirent *fd; 1005 struct jffs2_full_dirent *fd;
1006 struct jffs2_inode_cache *ic; 1006 struct jffs2_inode_cache *ic;
1007 uint32_t checkedlen;
1007 uint32_t crc; 1008 uint32_t crc;
1008 int err; 1009 int err;
1009 1010
@@ -1024,12 +1025,18 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo
1024 1025
1025 pseudo_random += je32_to_cpu(rd->version); 1026 pseudo_random += je32_to_cpu(rd->version);
1026 1027
1027 fd = jffs2_alloc_full_dirent(rd->nsize+1); 1028 /* Should never happen. Did. (OLPC trac #4184)*/
1029 checkedlen = strnlen(rd->name, rd->nsize);
1030 if (checkedlen < rd->nsize) {
1031 printk(KERN_ERR "Dirent at %08x has zeroes in name. Truncating to %d chars\n",
1032 ofs, checkedlen);
1033 }
1034 fd = jffs2_alloc_full_dirent(checkedlen+1);
1028 if (!fd) { 1035 if (!fd) {
1029 return -ENOMEM; 1036 return -ENOMEM;
1030 } 1037 }
1031 memcpy(&fd->name, rd->name, rd->nsize); 1038 memcpy(&fd->name, rd->name, checkedlen);
1032 fd->name[rd->nsize] = 0; 1039 fd->name[checkedlen] = 0;
1033 1040
1034 crc = crc32(0, fd->name, rd->nsize); 1041 crc = crc32(0, fd->name, rd->nsize);
1035 if (crc != je32_to_cpu(rd->name_crc)) { 1042 if (crc != je32_to_cpu(rd->name_crc)) {
@@ -1055,7 +1062,7 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo
1055 fd->next = NULL; 1062 fd->next = NULL;
1056 fd->version = je32_to_cpu(rd->version); 1063 fd->version = je32_to_cpu(rd->version);
1057 fd->ino = je32_to_cpu(rd->ino); 1064 fd->ino = je32_to_cpu(rd->ino);
1058 fd->nhash = full_name_hash(fd->name, rd->nsize); 1065 fd->nhash = full_name_hash(fd->name, checkedlen);
1059 fd->type = rd->type; 1066 fd->type = rd->type;
1060 jffs2_add_fd_to_list(c, fd, &ic->scan_dents); 1067 jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
1061 1068
diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c
index bc9f6ba10823..02c39c64ecb3 100644
--- a/fs/jffs2/security.c
+++ b/fs/jffs2/security.c
@@ -38,9 +38,9 @@ int jffs2_init_security(struct inode *inode, struct inode *dir)
38 } 38 }
39 rc = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, value, len, 0); 39 rc = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, value, len, 0);
40 40
41 kfree(name); 41 kfree(name);
42 kfree(value); 42 kfree(value);
43 return rc; 43 return rc;
44} 44}
45 45
46/* ---- XATTR Handler for "security.*" ----------------- */ 46/* ---- XATTR Handler for "security.*" ----------------- */
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index d828b296392a..629af01e5ade 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -2,10 +2,10 @@
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>, 4 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
5 * Zoltan Sogor <weth@inf.u-szeged.hu>, 5 * Zoltan Sogor <weth@inf.u-szeged.hu>,
6 * Patrik Kluba <pajko@halom.u-szeged.hu>, 6 * Patrik Kluba <pajko@halom.u-szeged.hu>,
7 * University of Szeged, Hungary 7 * University of Szeged, Hungary
8 * 2006 KaiGai Kohei <kaigai@ak.jp.nec.com> 8 * 2006 KaiGai Kohei <kaigai@ak.jp.nec.com>
9 * 9 *
10 * For licensing information, see the file 'LICENCE' in this directory. 10 * For licensing information, see the file 'LICENCE' in this directory.
11 * 11 *
@@ -429,6 +429,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
429 429
430 case JFFS2_NODETYPE_DIRENT: { 430 case JFFS2_NODETYPE_DIRENT: {
431 struct jffs2_sum_dirent_flash *spd; 431 struct jffs2_sum_dirent_flash *spd;
432 int checkedlen;
432 spd = sp; 433 spd = sp;
433 434
434 dbg_summary("Dirent at 0x%08x-0x%08x\n", 435 dbg_summary("Dirent at 0x%08x-0x%08x\n",
@@ -436,12 +437,25 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
436 jeb->offset + je32_to_cpu(spd->offset) + je32_to_cpu(spd->totlen)); 437 jeb->offset + je32_to_cpu(spd->offset) + je32_to_cpu(spd->totlen));
437 438
438 439
439 fd = jffs2_alloc_full_dirent(spd->nsize+1); 440 /* This should never happen, but https://dev.laptop.org/ticket/4184 */
441 checkedlen = strnlen(spd->name, spd->nsize);
442 if (!checkedlen) {
443 printk(KERN_ERR "Dirent at %08x has zero at start of name. Aborting mount.\n",
444 jeb->offset + je32_to_cpu(spd->offset));
445 return -EIO;
446 }
447 if (checkedlen < spd->nsize) {
448 printk(KERN_ERR "Dirent at %08x has zeroes in name. Truncating to %d chars\n",
449 jeb->offset + je32_to_cpu(spd->offset), checkedlen);
450 }
451
452
453 fd = jffs2_alloc_full_dirent(checkedlen+1);
440 if (!fd) 454 if (!fd)
441 return -ENOMEM; 455 return -ENOMEM;
442 456
443 memcpy(&fd->name, spd->name, spd->nsize); 457 memcpy(&fd->name, spd->name, checkedlen);
444 fd->name[spd->nsize] = 0; 458 fd->name[checkedlen] = 0;
445 459
446 ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino)); 460 ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino));
447 if (!ic) { 461 if (!ic) {
@@ -455,7 +469,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
455 fd->next = NULL; 469 fd->next = NULL;
456 fd->version = je32_to_cpu(spd->version); 470 fd->version = je32_to_cpu(spd->version);
457 fd->ino = je32_to_cpu(spd->ino); 471 fd->ino = je32_to_cpu(spd->ino);
458 fd->nhash = full_name_hash(fd->name, spd->nsize); 472 fd->nhash = full_name_hash(fd->name, checkedlen);
459 fd->type = spd->type; 473 fd->type = spd->type;
460 474
461 jffs2_add_fd_to_list(c, fd, &ic->scan_dents); 475 jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h
index 0c6669e21390..8bf34f2fa5ce 100644
--- a/fs/jffs2/summary.h
+++ b/fs/jffs2/summary.h
@@ -2,9 +2,9 @@
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>, 4 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
5 * Zoltan Sogor <weth@inf.u-szeged.hu>, 5 * Zoltan Sogor <weth@inf.u-szeged.hu>,
6 * Patrik Kluba <pajko@halom.u-szeged.hu>, 6 * Patrik Kluba <pajko@halom.u-szeged.hu>,
7 * University of Szeged, Hungary 7 * University of Szeged, Hungary
8 * 8 *
9 * For licensing information, see the file 'LICENCE' in this directory. 9 * For licensing information, see the file 'LICENCE' in this directory.
10 * 10 *
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 91d1d0f1c66c..d1d4f27464ba 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -220,6 +220,47 @@ static struct jffs2_raw_node_ref **jffs2_incore_replace_raw(struct jffs2_sb_info
220 return NULL; 220 return NULL;
221} 221}
222 222
223#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
224static int jffs2_verify_write(struct jffs2_sb_info *c, unsigned char *buf,
225 uint32_t ofs)
226{
227 int ret;
228 size_t retlen;
229 char *eccstr;
230
231 ret = c->mtd->read(c->mtd, ofs, c->wbuf_pagesize, &retlen, c->wbuf_verify);
232 if (ret && ret != -EUCLEAN && ret != -EBADMSG) {
233 printk(KERN_WARNING "jffs2_verify_write(): Read back of page at %08x failed: %d\n", c->wbuf_ofs, ret);
234 return ret;
235 } else if (retlen != c->wbuf_pagesize) {
236 printk(KERN_WARNING "jffs2_verify_write(): Read back of page at %08x gave short read: %zd not %d.\n", ofs, retlen, c->wbuf_pagesize);
237 return -EIO;
238 }
239 if (!memcmp(buf, c->wbuf_verify, c->wbuf_pagesize))
240 return 0;
241
242 if (ret == -EUCLEAN)
243 eccstr = "corrected";
244 else if (ret == -EBADMSG)
245 eccstr = "correction failed";
246 else
247 eccstr = "OK or unused";
248
249 printk(KERN_WARNING "Write verify error (ECC %s) at %08x. Wrote:\n",
250 eccstr, c->wbuf_ofs);
251 print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
252 c->wbuf, c->wbuf_pagesize, 0);
253
254 printk(KERN_WARNING "Read back:\n");
255 print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
256 c->wbuf_verify, c->wbuf_pagesize, 0);
257
258 return -EIO;
259}
260#else
261#define jffs2_verify_write(c,b,o) (0)
262#endif
263
223/* Recover from failure to write wbuf. Recover the nodes up to the 264/* Recover from failure to write wbuf. Recover the nodes up to the
224 * wbuf, not the one which we were starting to try to write. */ 265 * wbuf, not the one which we were starting to try to write. */
225 266
@@ -380,7 +421,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
380 ret = c->mtd->write(c->mtd, ofs, towrite, &retlen, 421 ret = c->mtd->write(c->mtd, ofs, towrite, &retlen,
381 rewrite_buf); 422 rewrite_buf);
382 423
383 if (ret || retlen != towrite) { 424 if (ret || retlen != towrite || jffs2_verify_write(c, rewrite_buf, ofs)) {
384 /* Argh. We tried. Really we did. */ 425 /* Argh. We tried. Really we did. */
385 printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n"); 426 printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n");
386 kfree(buf); 427 kfree(buf);
@@ -587,15 +628,16 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
587 628
588 ret = c->mtd->write(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf); 629 ret = c->mtd->write(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf);
589 630
590 if (ret || retlen != c->wbuf_pagesize) { 631 if (ret) {
591 if (ret) 632 printk(KERN_WARNING "jffs2_flush_wbuf(): Write failed with %d\n", ret);
592 printk(KERN_WARNING "jffs2_flush_wbuf(): Write failed with %d\n",ret); 633 goto wfail;
593 else { 634 } else if (retlen != c->wbuf_pagesize) {
594 printk(KERN_WARNING "jffs2_flush_wbuf(): Write was short: %zd instead of %d\n", 635 printk(KERN_WARNING "jffs2_flush_wbuf(): Write was short: %zd instead of %d\n",
595 retlen, c->wbuf_pagesize); 636 retlen, c->wbuf_pagesize);
596 ret = -EIO; 637 ret = -EIO;
597 } 638 goto wfail;
598 639 } else if ((ret = jffs2_verify_write(c, c->wbuf, c->wbuf_ofs))) {
640 wfail:
599 jffs2_wbuf_recover(c); 641 jffs2_wbuf_recover(c);
600 642
601 return ret; 643 return ret;
@@ -966,8 +1008,8 @@ exit:
966 1008
967#define NR_OOB_SCAN_PAGES 4 1009#define NR_OOB_SCAN_PAGES 4
968 1010
969/* For historical reasons we use only 12 bytes for OOB clean marker */ 1011/* For historical reasons we use only 8 bytes for OOB clean marker */
970#define OOB_CM_SIZE 12 1012#define OOB_CM_SIZE 8
971 1013
972static const struct jffs2_unknown_node oob_cleanmarker = 1014static const struct jffs2_unknown_node oob_cleanmarker =
973{ 1015{
@@ -1021,8 +1063,8 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c,
1021/* 1063/*
1022 * Check for a valid cleanmarker. 1064 * Check for a valid cleanmarker.
1023 * Returns: 0 if a valid cleanmarker was found 1065 * Returns: 0 if a valid cleanmarker was found
1024 * 1 if no cleanmarker was found 1066 * 1 if no cleanmarker was found
1025 * negative error code if an error occurred 1067 * negative error code if an error occurred
1026 */ 1068 */
1027int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, 1069int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c,
1028 struct jffs2_eraseblock *jeb) 1070 struct jffs2_eraseblock *jeb)
@@ -1138,11 +1180,22 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
1138 return -ENOMEM; 1180 return -ENOMEM;
1139 } 1181 }
1140 1182
1183#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
1184 c->wbuf_verify = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
1185 if (!c->wbuf_verify) {
1186 kfree(c->oobbuf);
1187 kfree(c->wbuf);
1188 return -ENOMEM;
1189 }
1190#endif
1141 return 0; 1191 return 0;
1142} 1192}
1143 1193
1144void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c) 1194void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c)
1145{ 1195{
1196#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
1197 kfree(c->wbuf_verify);
1198#endif
1146 kfree(c->wbuf); 1199 kfree(c->wbuf);
1147 kfree(c->oobbuf); 1200 kfree(c->oobbuf);
1148} 1201}
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
index 664c164aa67c..2f5695446d0f 100644
--- a/fs/jffs2/write.c
+++ b/fs/jffs2/write.c
@@ -215,6 +215,17 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
215 BUG(); 215 BUG();
216 }); 216 });
217 217
218 if (strnlen(name, namelen) != namelen) {
219 /* This should never happen, but seems to have done on at least one
220 occasion: https://dev.laptop.org/ticket/4184 */
221 printk(KERN_CRIT "Error in jffs2_write_dirent() -- name contains zero bytes!\n");
222 printk(KERN_CRIT "Directory inode #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x\n",
223 je32_to_cpu(rd->pino), name, name, je32_to_cpu(rd->ino),
224 je32_to_cpu(rd->name_crc));
225 WARN_ON(1);
226 return ERR_PTR(-EIO);
227 }
228
218 vecs[0].iov_base = rd; 229 vecs[0].iov_base = rd;
219 vecs[0].iov_len = sizeof(*rd); 230 vecs[0].iov_len = sizeof(*rd);
220 vecs[1].iov_base = (unsigned char *)name; 231 vecs[1].iov_base = (unsigned char *)name;
@@ -226,7 +237,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
226 237
227 fd->version = je32_to_cpu(rd->version); 238 fd->version = je32_to_cpu(rd->version);
228 fd->ino = je32_to_cpu(rd->ino); 239 fd->ino = je32_to_cpu(rd->ino);
229 fd->nhash = full_name_hash(name, strlen(name)); 240 fd->nhash = full_name_hash(name, namelen);
230 fd->type = rd->type; 241 fd->type = rd->type;
231 memcpy(fd->name, name, namelen); 242 memcpy(fd->name, name, namelen);
232 fd->name[namelen]=0; 243 fd->name[namelen]=0;
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h
index 3b0ff2925937..6e3b5ddfb7ab 100644
--- a/fs/jffs2/xattr.h
+++ b/fs/jffs2/xattr.h
@@ -75,7 +75,7 @@ extern void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c);
75extern void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c); 75extern void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c);
76 76
77extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c, 77extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
78 uint32_t xid, uint32_t version); 78 uint32_t xid, uint32_t version);
79 79
80extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); 80extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
81extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); 81extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c
index 40942bc516bb..8bbeab90ada1 100644
--- a/fs/jffs2/xattr_user.c
+++ b/fs/jffs2/xattr_user.c
@@ -17,7 +17,7 @@
17#include "nodelist.h" 17#include "nodelist.h"
18 18
19static int jffs2_user_getxattr(struct inode *inode, const char *name, 19static int jffs2_user_getxattr(struct inode *inode, const char *name,
20 void *buffer, size_t size) 20 void *buffer, size_t size)
21{ 21{
22 if (!strcmp(name, "")) 22 if (!strcmp(name, ""))
23 return -EINVAL; 23 return -EINVAL;
@@ -25,7 +25,7 @@ static int jffs2_user_getxattr(struct inode *inode, const char *name,
25} 25}
26 26
27static int jffs2_user_setxattr(struct inode *inode, const char *name, const void *buffer, 27static int jffs2_user_setxattr(struct inode *inode, const char *name, const void *buffer,
28 size_t size, int flags) 28 size_t size, int flags)
29{ 29{
30 if (!strcmp(name, "")) 30 if (!strcmp(name, ""))
31 return -EINVAL; 31 return -EINVAL;