diff options
Diffstat (limited to 'fs/ubifs/master.c')
-rw-r--r-- | fs/ubifs/master.c | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/fs/ubifs/master.c b/fs/ubifs/master.c index a88f33801b98..28beaeedadc0 100644 --- a/fs/ubifs/master.c +++ b/fs/ubifs/master.c | |||
@@ -29,7 +29,8 @@ | |||
29 | * @c: UBIFS file-system description object | 29 | * @c: UBIFS file-system description object |
30 | * | 30 | * |
31 | * This function scans the master node LEBs and search for the latest master | 31 | * This function scans the master node LEBs and search for the latest master |
32 | * node. Returns zero in case of success and a negative error code in case of | 32 | * node. Returns zero in case of success, %-EUCLEAN if there master area is |
33 | * corrupted and requires recovery, and a negative error code in case of | ||
33 | * failure. | 34 | * failure. |
34 | */ | 35 | */ |
35 | static int scan_for_master(struct ubifs_info *c) | 36 | static int scan_for_master(struct ubifs_info *c) |
@@ -40,7 +41,7 @@ static int scan_for_master(struct ubifs_info *c) | |||
40 | 41 | ||
41 | lnum = UBIFS_MST_LNUM; | 42 | lnum = UBIFS_MST_LNUM; |
42 | 43 | ||
43 | sleb = ubifs_scan(c, lnum, 0, c->sbuf); | 44 | sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1); |
44 | if (IS_ERR(sleb)) | 45 | if (IS_ERR(sleb)) |
45 | return PTR_ERR(sleb); | 46 | return PTR_ERR(sleb); |
46 | nodes_cnt = sleb->nodes_cnt; | 47 | nodes_cnt = sleb->nodes_cnt; |
@@ -48,7 +49,7 @@ static int scan_for_master(struct ubifs_info *c) | |||
48 | snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, | 49 | snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, |
49 | list); | 50 | list); |
50 | if (snod->type != UBIFS_MST_NODE) | 51 | if (snod->type != UBIFS_MST_NODE) |
51 | goto out; | 52 | goto out_dump; |
52 | memcpy(c->mst_node, snod->node, snod->len); | 53 | memcpy(c->mst_node, snod->node, snod->len); |
53 | offs = snod->offs; | 54 | offs = snod->offs; |
54 | } | 55 | } |
@@ -56,7 +57,7 @@ static int scan_for_master(struct ubifs_info *c) | |||
56 | 57 | ||
57 | lnum += 1; | 58 | lnum += 1; |
58 | 59 | ||
59 | sleb = ubifs_scan(c, lnum, 0, c->sbuf); | 60 | sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1); |
60 | if (IS_ERR(sleb)) | 61 | if (IS_ERR(sleb)) |
61 | return PTR_ERR(sleb); | 62 | return PTR_ERR(sleb); |
62 | if (sleb->nodes_cnt != nodes_cnt) | 63 | if (sleb->nodes_cnt != nodes_cnt) |
@@ -65,7 +66,7 @@ static int scan_for_master(struct ubifs_info *c) | |||
65 | goto out; | 66 | goto out; |
66 | snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, list); | 67 | snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, list); |
67 | if (snod->type != UBIFS_MST_NODE) | 68 | if (snod->type != UBIFS_MST_NODE) |
68 | goto out; | 69 | goto out_dump; |
69 | if (snod->offs != offs) | 70 | if (snod->offs != offs) |
70 | goto out; | 71 | goto out; |
71 | if (memcmp((void *)c->mst_node + UBIFS_CH_SZ, | 72 | if (memcmp((void *)c->mst_node + UBIFS_CH_SZ, |
@@ -78,6 +79,12 @@ static int scan_for_master(struct ubifs_info *c) | |||
78 | 79 | ||
79 | out: | 80 | out: |
80 | ubifs_scan_destroy(sleb); | 81 | ubifs_scan_destroy(sleb); |
82 | return -EUCLEAN; | ||
83 | |||
84 | out_dump: | ||
85 | ubifs_err("unexpected node type %d master LEB %d:%d", | ||
86 | snod->type, lnum, snod->offs); | ||
87 | ubifs_scan_destroy(sleb); | ||
81 | return -EINVAL; | 88 | return -EINVAL; |
82 | } | 89 | } |
83 | 90 | ||
@@ -256,7 +263,8 @@ int ubifs_read_master(struct ubifs_info *c) | |||
256 | 263 | ||
257 | err = scan_for_master(c); | 264 | err = scan_for_master(c); |
258 | if (err) { | 265 | if (err) { |
259 | err = ubifs_recover_master_node(c); | 266 | if (err == -EUCLEAN) |
267 | err = ubifs_recover_master_node(c); | ||
260 | if (err) | 268 | if (err) |
261 | /* | 269 | /* |
262 | * Note, we do not free 'c->mst_node' here because the | 270 | * Note, we do not free 'c->mst_node' here because the |