aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@shinybook.infradead.org>2005-07-19 17:49:39 -0400
committerDavid Woodhouse <dwmw2@shinybook.infradead.org>2005-07-19 17:49:39 -0400
commit39299d9d15c41cbdd7c7009967cd35afaf34d8fa (patch)
tree42a0c0408fcf76024eb6885a27d4f1ed0228abcf /fs/jffs2
parentce625a801664d8ed7344117bbb57510e4e0e872c (diff)
parentf60f700876cd51de9de69f3a3c865d95e287a24d (diff)
Merge with /shiny/git/linux-2.6/.git
Diffstat (limited to 'fs/jffs2')
-rw-r--r--fs/jffs2/build.c9
-rw-r--r--fs/jffs2/erase.c174
-rw-r--r--fs/jffs2/nodelist.c14
-rw-r--r--fs/jffs2/os-linux.h4
-rw-r--r--fs/jffs2/readinode.c11
-rw-r--r--fs/jffs2/super.c11
6 files changed, 117 insertions, 106 deletions
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
index 3dd5394921c9..97dc39796e2c 100644
--- a/fs/jffs2/build.c
+++ b/fs/jffs2/build.c
@@ -7,7 +7,7 @@
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: build.c,v 1.70 2005/02/28 08:21:05 dedekind Exp $ 10 * $Id: build.c,v 1.71 2005/07/12 16:37:08 dedekind Exp $
11 * 11 *
12 */ 12 */
13 13
@@ -336,13 +336,6 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c)
336 c->blocks[i].bad_count = 0; 336 c->blocks[i].bad_count = 0;
337 } 337 }
338 338
339 init_MUTEX(&c->alloc_sem);
340 init_MUTEX(&c->erase_free_sem);
341 init_waitqueue_head(&c->erase_wait);
342 init_waitqueue_head(&c->inocache_wq);
343 spin_lock_init(&c->erase_completion_lock);
344 spin_lock_init(&c->inocache_lock);
345
346 INIT_LIST_HEAD(&c->clean_list); 339 INIT_LIST_HEAD(&c->clean_list);
347 INIT_LIST_HEAD(&c->very_dirty_list); 340 INIT_LIST_HEAD(&c->very_dirty_list);
348 INIT_LIST_HEAD(&c->dirty_list); 341 INIT_LIST_HEAD(&c->dirty_list);
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index 6a4c0a3685da..787d84ac2bcd 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -7,7 +7,7 @@
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: erase.c,v 1.76 2005/05/03 15:11:40 dedekind Exp $ 10 * $Id: erase.c,v 1.80 2005/07/14 19:46:24 joern Exp $
11 * 11 *
12 */ 12 */
13 13
@@ -300,100 +300,86 @@ static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_erase
300 jeb->last_node = NULL; 300 jeb->last_node = NULL;
301} 301}
302 302
303static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) 303static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *bad_offset)
304{ 304{
305 struct jffs2_raw_node_ref *marker_ref = NULL; 305 void *ebuf;
306 unsigned char *ebuf; 306 uint32_t ofs;
307 size_t retlen; 307 size_t retlen;
308 int ret; 308 int ret = -EIO;
309 uint32_t bad_offset; 309
310
311 if ((!jffs2_cleanmarker_oob(c)) && (c->cleanmarker_size > 0)) {
312 marker_ref = jffs2_alloc_raw_node_ref();
313 if (!marker_ref) {
314 printk(KERN_WARNING "Failed to allocate raw node ref for clean marker\n");
315 /* Stick it back on the list from whence it came and come back later */
316 jffs2_erase_pending_trigger(c);
317 spin_lock(&c->erase_completion_lock);
318 list_add(&jeb->list, &c->erase_complete_list);
319 spin_unlock(&c->erase_completion_lock);
320 return;
321 }
322 }
323 ebuf = kmalloc(PAGE_SIZE, GFP_KERNEL); 310 ebuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
324 if (!ebuf) { 311 if (!ebuf) {
325 printk(KERN_WARNING "Failed to allocate page buffer for verifying erase at 0x%08x. Assuming it worked\n", jeb->offset); 312 printk(KERN_WARNING "Failed to allocate page buffer for verifying erase at 0x%08x. Refiling\n", jeb->offset);
326 } else { 313 return -EAGAIN;
327 uint32_t ofs = jeb->offset; 314 }
328 315
329 D1(printk(KERN_DEBUG "Verifying erase at 0x%08x\n", jeb->offset)); 316 D1(printk(KERN_DEBUG "Verifying erase at 0x%08x\n", jeb->offset));
330 while(ofs < jeb->offset + c->sector_size) {
331 uint32_t readlen = min((uint32_t)PAGE_SIZE, jeb->offset + c->sector_size - ofs);
332 int i;
333 317
334 bad_offset = ofs; 318 for (ofs = jeb->offset; ofs < jeb->offset + c->sector_size; ) {
319 uint32_t readlen = min((uint32_t)PAGE_SIZE, jeb->offset + c->sector_size - ofs);
320 int i;
335 321
336 ret = c->mtd->read(c->mtd, ofs, readlen, &retlen, ebuf); 322 *bad_offset = ofs;
337 323
338 if (ret) { 324 ret = jffs2_flash_read(c, ofs, readlen, &retlen, ebuf);
339 printk(KERN_WARNING "Read of newly-erased block at 0x%08x failed: %d. Putting on bad_list\n", ofs, ret); 325 if (ret) {
340 goto bad; 326 printk(KERN_WARNING "Read of newly-erased block at 0x%08x failed: %d. Putting on bad_list\n", ofs, ret);
341 } 327 goto fail;
342 if (retlen != readlen) { 328 }
343 printk(KERN_WARNING "Short read from newly-erased block at 0x%08x. Wanted %d, got %zd\n", ofs, readlen, retlen); 329 if (retlen != readlen) {
344 goto bad; 330 printk(KERN_WARNING "Short read from newly-erased block at 0x%08x. Wanted %d, got %zd\n", ofs, readlen, retlen);
345 } 331 goto fail;
346 for (i=0; i<readlen; i += sizeof(unsigned long)) { 332 }
347 /* It's OK. We know it's properly aligned */ 333 for (i=0; i<readlen; i += sizeof(unsigned long)) {
348 unsigned long datum = *(unsigned long *)(&ebuf[i]); 334 /* It's OK. We know it's properly aligned */
349 if (datum + 1) { 335 unsigned long *datum = ebuf + i;
350 bad_offset += i; 336 if (*datum + 1) {
351 printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08x\n", datum, bad_offset); 337 *bad_offset += i;
352 bad: 338 printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08x\n", *datum, *bad_offset);
353 if ((!jffs2_cleanmarker_oob(c)) && (c->cleanmarker_size > 0)) 339 goto fail;
354 jffs2_free_raw_node_ref(marker_ref);
355 kfree(ebuf);
356 bad2:
357 spin_lock(&c->erase_completion_lock);
358 /* Stick it on a list (any list) so
359 erase_failed can take it right off
360 again. Silly, but shouldn't happen
361 often. */
362 list_add(&jeb->list, &c->erasing_list);
363 spin_unlock(&c->erase_completion_lock);
364 jffs2_erase_failed(c, jeb, bad_offset);
365 return;
366 }
367 } 340 }
368 ofs += readlen;
369 cond_resched();
370 } 341 }
371 kfree(ebuf); 342 ofs += readlen;
343 cond_resched();
372 } 344 }
345 ret = 0;
346fail:
347 kfree(ebuf);
348 return ret;
349}
373 350
374 bad_offset = jeb->offset; 351static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
352{
353 struct jffs2_raw_node_ref *marker_ref = NULL;
354 size_t retlen;
355 int ret;
356 uint32_t bad_offset;
357
358 switch (jffs2_block_check_erase(c, jeb, &bad_offset)) {
359 case -EAGAIN: goto refile;
360 case -EIO: goto filebad;
361 }
375 362
376 /* Write the erase complete marker */ 363 /* Write the erase complete marker */
377 D1(printk(KERN_DEBUG "Writing erased marker to block at 0x%08x\n", jeb->offset)); 364 D1(printk(KERN_DEBUG "Writing erased marker to block at 0x%08x\n", jeb->offset));
378 if (jffs2_cleanmarker_oob(c)) { 365 bad_offset = jeb->offset;
379 366
380 if (jffs2_write_nand_cleanmarker(c, jeb)) 367 /* Cleanmarker in oob area or no cleanmarker at all ? */
381 goto bad2; 368 if (jffs2_cleanmarker_oob(c) || c->cleanmarker_size == 0) {
382
383 jeb->first_node = jeb->last_node = NULL;
384 369
385 jeb->free_size = c->sector_size; 370 if (jffs2_cleanmarker_oob(c)) {
386 jeb->used_size = 0; 371 if (jffs2_write_nand_cleanmarker(c, jeb))
387 jeb->dirty_size = 0; 372 goto filebad;
388 jeb->wasted_size = 0; 373 }
389 } else if (c->cleanmarker_size == 0) {
390 jeb->first_node = jeb->last_node = NULL;
391 374
375 jeb->first_node = jeb->last_node = NULL;
392 jeb->free_size = c->sector_size; 376 jeb->free_size = c->sector_size;
393 jeb->used_size = 0; 377 jeb->used_size = 0;
394 jeb->dirty_size = 0; 378 jeb->dirty_size = 0;
395 jeb->wasted_size = 0; 379 jeb->wasted_size = 0;
380
396 } else { 381 } else {
382
397 struct kvec vecs[1]; 383 struct kvec vecs[1];
398 struct jffs2_unknown_node marker = { 384 struct jffs2_unknown_node marker = {
399 .magic = cpu_to_je16(JFFS2_MAGIC_BITMASK), 385 .magic = cpu_to_je16(JFFS2_MAGIC_BITMASK),
@@ -401,21 +387,28 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
401 .totlen = cpu_to_je32(c->cleanmarker_size) 387 .totlen = cpu_to_je32(c->cleanmarker_size)
402 }; 388 };
403 389
390 marker_ref = jffs2_alloc_raw_node_ref();
391 if (!marker_ref) {
392 printk(KERN_WARNING "Failed to allocate raw node ref for clean marker. Refiling\n");
393 goto refile;
394 }
395
404 marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4)); 396 marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4));
405 397
406 vecs[0].iov_base = (unsigned char *) &marker; 398 vecs[0].iov_base = (unsigned char *) &marker;
407 vecs[0].iov_len = sizeof(marker); 399 vecs[0].iov_len = sizeof(marker);
408 ret = jffs2_flash_direct_writev(c, vecs, 1, jeb->offset, &retlen); 400 ret = jffs2_flash_direct_writev(c, vecs, 1, jeb->offset, &retlen);
409 401
410 if (ret) { 402 if (ret || retlen != sizeof(marker)) {
411 printk(KERN_WARNING "Write clean marker to block at 0x%08x failed: %d\n", 403 if (ret)
412 jeb->offset, ret); 404 printk(KERN_WARNING "Write clean marker to block at 0x%08x failed: %d\n",
413 goto bad2; 405 jeb->offset, ret);
414 } 406 else
415 if (retlen != sizeof(marker)) { 407 printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %zd, got %zd\n",
416 printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %zd, got %zd\n", 408 jeb->offset, sizeof(marker), retlen);
417 jeb->offset, sizeof(marker), retlen); 409
418 goto bad2; 410 jffs2_free_raw_node_ref(marker_ref);
411 goto filebad;
419 } 412 }
420 413
421 marker_ref->next_in_ino = NULL; 414 marker_ref->next_in_ino = NULL;
@@ -444,5 +437,22 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
444 c->nr_free_blocks++; 437 c->nr_free_blocks++;
445 spin_unlock(&c->erase_completion_lock); 438 spin_unlock(&c->erase_completion_lock);
446 wake_up(&c->erase_wait); 439 wake_up(&c->erase_wait);
447} 440 return;
441
442filebad:
443 spin_lock(&c->erase_completion_lock);
444 /* Stick it on a list (any list) so erase_failed can take it
445 right off again. Silly, but shouldn't happen often. */
446 list_add(&jeb->list, &c->erasing_list);
447 spin_unlock(&c->erase_completion_lock);
448 jffs2_erase_failed(c, jeb, bad_offset);
449 return;
448 450
451refile:
452 /* Stick it back on the list from whence it came and come back later */
453 jffs2_erase_pending_trigger(c);
454 spin_lock(&c->erase_completion_lock);
455 list_add(&jeb->list, &c->erase_complete_list);
456 spin_unlock(&c->erase_completion_lock);
457 return;
458}
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index c7bbdeec93a6..4991c348f6ec 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -7,7 +7,7 @@
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: nodelist.c,v 1.97 2005/07/06 15:18:41 dwmw2 Exp $ 10 * $Id: nodelist.c,v 1.98 2005/07/10 15:15:32 dedekind Exp $
11 * 11 *
12 */ 12 */
13 13
@@ -55,11 +55,11 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new
55 }); 55 });
56} 56}
57 57
58/* Put a new tmp_dnode_info into the list, keeping the list in 58/*
59 order of increasing version 59 * Put a new tmp_dnode_info into the temporaty RB-tree, keeping the list in
60*/ 60 * order of increasing version.
61 61 */
62static void jffs2_add_tn_to_list(struct jffs2_tmp_dnode_info *tn, struct rb_root *list) 62static void jffs2_add_tn_to_tree(struct jffs2_tmp_dnode_info *tn, struct rb_root *list)
63{ 63{
64 struct rb_node **p = &list->rb_node; 64 struct rb_node **p = &list->rb_node;
65 struct rb_node * parent = NULL; 65 struct rb_node * parent = NULL;
@@ -420,7 +420,7 @@ int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
420 D1(printk(KERN_DEBUG "dnode @%08x: ver %u, offset %04x, dsize %04x\n", 420 D1(printk(KERN_DEBUG "dnode @%08x: ver %u, offset %04x, dsize %04x\n",
421 ref_offset(ref), je32_to_cpu(node.i.version), 421 ref_offset(ref), je32_to_cpu(node.i.version),
422 je32_to_cpu(node.i.offset), je32_to_cpu(node.i.dsize))); 422 je32_to_cpu(node.i.offset), je32_to_cpu(node.i.dsize)));
423 jffs2_add_tn_to_list(tn, &ret_tn); 423 jffs2_add_tn_to_tree(tn, &ret_tn);
424 break; 424 break;
425 425
426 default: 426 default:
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 7bf72e012c94..d900c8929b09 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -7,7 +7,7 @@
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: os-linux.h,v 1.57 2005/07/06 12:13:09 dwmw2 Exp $ 10 * $Id: os-linux.h,v 1.58 2005/07/12 02:34:35 tpoynor Exp $
11 * 11 *
12 */ 12 */
13 13
@@ -86,6 +86,8 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
86#define jffs2_dataflash(c) (0) 86#define jffs2_dataflash(c) (0)
87#define jffs2_nor_ecc_flash_setup(c) (0) 87#define jffs2_nor_ecc_flash_setup(c) (0)
88#define jffs2_nor_ecc_flash_cleanup(c) do {} while (0) 88#define jffs2_nor_ecc_flash_cleanup(c) do {} while (0)
89#define jffs2_dataflash_setup(c) (0)
90#define jffs2_dataflash_cleanup(c) do {} while (0)
89 91
90#else /* NAND and/or ECC'd NOR support present */ 92#else /* NAND and/or ECC'd NOR support present */
91 93
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 081656c1d49e..5b2a83599d73 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -7,7 +7,7 @@
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: readinode.c,v 1.120 2005/07/05 21:03:07 dwmw2 Exp $ 10 * $Id: readinode.c,v 1.125 2005/07/10 13:13:55 dedekind Exp $
11 * 11 *
12 */ 12 */
13 13
@@ -151,6 +151,9 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in
151 151
152 D1(printk(KERN_DEBUG "jffs2_add_full_dnode_to_inode(ino #%u, f %p, fn %p)\n", f->inocache->ino, f, fn)); 152 D1(printk(KERN_DEBUG "jffs2_add_full_dnode_to_inode(ino #%u, f %p, fn %p)\n", f->inocache->ino, f, fn));
153 153
154 if (unlikely(!fn->size))
155 return 0;
156
154 newfrag = jffs2_alloc_node_frag(); 157 newfrag = jffs2_alloc_node_frag();
155 if (unlikely(!newfrag)) 158 if (unlikely(!newfrag))
156 return -ENOMEM; 159 return -ENOMEM;
@@ -158,11 +161,6 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in
158 D2(printk(KERN_DEBUG "adding node %04x-%04x @0x%08x on flash, newfrag *%p\n", 161 D2(printk(KERN_DEBUG "adding node %04x-%04x @0x%08x on flash, newfrag *%p\n",
159 fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag)); 162 fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag));
160 163
161 if (unlikely(!fn->size)) {
162 jffs2_free_node_frag(newfrag);
163 return 0;
164 }
165
166 newfrag->ofs = fn->ofs; 164 newfrag->ofs = fn->ofs;
167 newfrag->size = fn->size; 165 newfrag->size = fn->size;
168 newfrag->node = fn; 166 newfrag->node = fn;
@@ -560,7 +558,6 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
560 } 558 }
561 next_tn: 559 next_tn:
562 BUG_ON(rb->rb_left); 560 BUG_ON(rb->rb_left);
563 repl_rb = NULL;
564 if (rb->rb_parent && rb->rb_parent->rb_left == rb) { 561 if (rb->rb_parent && rb->rb_parent->rb_left == rb) {
565 /* We were then left-hand child of our parent. We need 562 /* We were then left-hand child of our parent. We need
566 to move our own right-hand child into our place. */ 563 to move our own right-hand child into our place. */
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 2cf14cf8b35a..aaf9475cfb6a 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -7,7 +7,7 @@
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: super.c,v 1.106 2005/05/18 11:37:25 dedekind Exp $ 10 * $Id: super.c,v 1.107 2005/07/12 16:37:08 dedekind Exp $
11 * 11 *
12 */ 12 */
13 13
@@ -140,6 +140,15 @@ static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type,
140 D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): New superblock for device %d (\"%s\")\n", 140 D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): New superblock for device %d (\"%s\")\n",
141 mtd->index, mtd->name)); 141 mtd->index, mtd->name));
142 142
143 /* Initialize JFFS2 superblock locks, the further initialization will be
144 * done later */
145 init_MUTEX(&c->alloc_sem);
146 init_MUTEX(&c->erase_free_sem);
147 init_waitqueue_head(&c->erase_wait);
148 init_waitqueue_head(&c->inocache_wq);
149 spin_lock_init(&c->erase_completion_lock);
150 spin_lock_init(&c->inocache_lock);
151
143 sb->s_op = &jffs2_super_operations; 152 sb->s_op = &jffs2_super_operations;
144 sb->s_flags = flags | MS_NOATIME; 153 sb->s_flags = flags | MS_NOATIME;
145 154