diff options
Diffstat (limited to 'fs/ubifs/recovery.c')
-rw-r--r-- | fs/ubifs/recovery.c | 44 |
1 files changed, 31 insertions, 13 deletions
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index 77e9b874b6c2..936f2cbfe6b6 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c | |||
@@ -28,6 +28,23 @@ | |||
28 | * UBIFS always cleans away all remnants of an unclean un-mount, so that | 28 | * UBIFS always cleans away all remnants of an unclean un-mount, so that |
29 | * errors do not accumulate. However UBIFS defers recovery if it is mounted | 29 | * errors do not accumulate. However UBIFS defers recovery if it is mounted |
30 | * read-only, and the flash is not modified in that case. | 30 | * read-only, and the flash is not modified in that case. |
31 | * | ||
32 | * The general UBIFS approach to the recovery is that it recovers from | ||
33 | * corruptions which could be caused by power cuts, but it refuses to recover | ||
34 | * from corruption caused by other reasons. And UBIFS tries to distinguish | ||
35 | * between these 2 reasons of corruptions and silently recover in the former | ||
36 | * case and loudly complain in the latter case. | ||
37 | * | ||
38 | * UBIFS writes only to erased LEBs, so it writes only to the flash space | ||
39 | * containing only 0xFFs. UBIFS also always writes strictly from the beginning | ||
40 | * of the LEB to the end. And UBIFS assumes that the underlying flash media | ||
41 | * writes in @c->max_write_size bytes at a time. | ||
42 | * | ||
43 | * Hence, if UBIFS finds a corrupted node at offset X, it expects only the min. | ||
44 | * I/O unit corresponding to offset X to contain corrupted data, all the | ||
45 | * following min. I/O units have to contain empty space (all 0xFFs). If this is | ||
46 | * not true, the corruption cannot be the result of a power cut, and UBIFS | ||
47 | * refuses to mount. | ||
31 | */ | 48 | */ |
32 | 49 | ||
33 | #include <linux/crc32.h> | 50 | #include <linux/crc32.h> |
@@ -362,8 +379,9 @@ int ubifs_write_rcvrd_mst_node(struct ubifs_info *c) | |||
362 | * @offs: offset to check | 379 | * @offs: offset to check |
363 | * | 380 | * |
364 | * This function returns %1 if @offs was in the last write to the LEB whose data | 381 | * This function returns %1 if @offs was in the last write to the LEB whose data |
365 | * is in @buf, otherwise %0 is returned. The determination is made by checking | 382 | * is in @buf, otherwise %0 is returned. The determination is made by checking |
366 | * for subsequent empty space starting from the next @c->min_io_size boundary. | 383 | * for subsequent empty space starting from the next @c->max_write_size |
384 | * boundary. | ||
367 | */ | 385 | */ |
368 | static int is_last_write(const struct ubifs_info *c, void *buf, int offs) | 386 | static int is_last_write(const struct ubifs_info *c, void *buf, int offs) |
369 | { | 387 | { |
@@ -371,10 +389,10 @@ static int is_last_write(const struct ubifs_info *c, void *buf, int offs) | |||
371 | uint8_t *p; | 389 | uint8_t *p; |
372 | 390 | ||
373 | /* | 391 | /* |
374 | * Round up to the next @c->min_io_size boundary i.e. @offs is in the | 392 | * Round up to the next @c->max_write_size boundary i.e. @offs is in |
375 | * last wbuf written. After that should be empty space. | 393 | * the last wbuf written. After that should be empty space. |
376 | */ | 394 | */ |
377 | empty_offs = ALIGN(offs + 1, c->min_io_size); | 395 | empty_offs = ALIGN(offs + 1, c->max_write_size); |
378 | check_len = c->leb_size - empty_offs; | 396 | check_len = c->leb_size - empty_offs; |
379 | p = buf + empty_offs - offs; | 397 | p = buf + empty_offs - offs; |
380 | return is_empty(p, check_len); | 398 | return is_empty(p, check_len); |
@@ -429,7 +447,7 @@ static int no_more_nodes(const struct ubifs_info *c, void *buf, int len, | |||
429 | int skip, dlen = le32_to_cpu(ch->len); | 447 | int skip, dlen = le32_to_cpu(ch->len); |
430 | 448 | ||
431 | /* Check for empty space after the corrupt node's common header */ | 449 | /* Check for empty space after the corrupt node's common header */ |
432 | skip = ALIGN(offs + UBIFS_CH_SZ, c->min_io_size) - offs; | 450 | skip = ALIGN(offs + UBIFS_CH_SZ, c->max_write_size) - offs; |
433 | if (is_empty(buf + skip, len - skip)) | 451 | if (is_empty(buf + skip, len - skip)) |
434 | return 1; | 452 | return 1; |
435 | /* | 453 | /* |
@@ -441,7 +459,7 @@ static int no_more_nodes(const struct ubifs_info *c, void *buf, int len, | |||
441 | return 0; | 459 | return 0; |
442 | } | 460 | } |
443 | /* Now we know the corrupt node's length we can skip over it */ | 461 | /* Now we know the corrupt node's length we can skip over it */ |
444 | skip = ALIGN(offs + dlen, c->min_io_size) - offs; | 462 | skip = ALIGN(offs + dlen, c->max_write_size) - offs; |
445 | /* After which there should be empty space */ | 463 | /* After which there should be empty space */ |
446 | if (is_empty(buf + skip, len - skip)) | 464 | if (is_empty(buf + skip, len - skip)) |
447 | return 1; | 465 | return 1; |
@@ -671,10 +689,14 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, | |||
671 | } else { | 689 | } else { |
672 | int corruption = first_non_ff(buf, len); | 690 | int corruption = first_non_ff(buf, len); |
673 | 691 | ||
692 | /* | ||
693 | * See header comment for this file for more | ||
694 | * explanations about the reasons we have this check. | ||
695 | */ | ||
674 | ubifs_err("corrupt empty space LEB %d:%d, corruption " | 696 | ubifs_err("corrupt empty space LEB %d:%d, corruption " |
675 | "starts at %d", lnum, offs, corruption); | 697 | "starts at %d", lnum, offs, corruption); |
676 | /* Make sure we dump interesting non-0xFF data */ | 698 | /* Make sure we dump interesting non-0xFF data */ |
677 | offs = corruption; | 699 | offs += corruption; |
678 | buf += corruption; | 700 | buf += corruption; |
679 | goto corrupted; | 701 | goto corrupted; |
680 | } | 702 | } |
@@ -836,12 +858,8 @@ struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum, | |||
836 | static int recover_head(const struct ubifs_info *c, int lnum, int offs, | 858 | static int recover_head(const struct ubifs_info *c, int lnum, int offs, |
837 | void *sbuf) | 859 | void *sbuf) |
838 | { | 860 | { |
839 | int len, err; | 861 | int len = c->max_write_size, err; |
840 | 862 | ||
841 | if (c->min_io_size > 1) | ||
842 | len = c->min_io_size; | ||
843 | else | ||
844 | len = 512; | ||
845 | if (offs + len > c->leb_size) | 863 | if (offs + len > c->leb_size) |
846 | len = c->leb_size - offs; | 864 | len = c->leb_size - offs; |
847 | 865 | ||