aboutsummaryrefslogtreecommitdiff
path: root/ubifs-utils/libubifs
diff options
context:
space:
mode:
Diffstat (limited to 'ubifs-utils/libubifs')
-rw-r--r--ubifs-utils/libubifs/orphan.c42
-rw-r--r--ubifs-utils/libubifs/ubifs.h1
2 files changed, 40 insertions, 3 deletions
diff --git a/ubifs-utils/libubifs/orphan.c b/ubifs-utils/libubifs/orphan.c
index 26668cb..baa4db7 100644
--- a/ubifs-utils/libubifs/orphan.c
+++ b/ubifs-utils/libubifs/orphan.c
@@ -423,6 +423,7 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
ubifs_dump_node(c, snod->node,
c->leb_size - snod->offs);
err = -EINVAL;
+ set_failure_reason_callback(c, FR_DATA_CORRUPTED);
goto out_free;
}
@@ -452,6 +453,7 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
ubifs_dump_node(c, snod->node,
c->leb_size - snod->offs);
err = -EINVAL;
+ set_failure_reason_callback(c, FR_DATA_CORRUPTED);
goto out_free;
}
dbg_rcvry("out of date LEB %d", sleb->lnum);
@@ -471,8 +473,19 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
ino_key_init(c, &key, inum);
err = ubifs_tnc_lookup(c, &key, ino);
- if (err && err != -ENOENT)
+ if (err && err != -ENOENT) {
+ unsigned int reason;
+
+ reason = get_failure_reason_callback(c);
+ if (reason & FR_DATA_CORRUPTED) {
+ test_and_clear_failure_reason_callback(c, FR_DATA_CORRUPTED);
+ if (handle_failure_callback(c, FR_H_TNC_DATA_CORRUPTED, NULL)) {
+ /* Leave the inode to be deleted by subsequent steps */
+ continue;
+ }
+ }
goto out_free;
+ }
/*
* Check whether an inode can really get deleted.
@@ -483,8 +496,11 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
(unsigned long)inum);
err = ubifs_tnc_remove_ino(c, inum);
- if (err)
+ if (err) {
+ if (c->program_type == FSCK_PROGRAM_TYPE)
+ goto out_free;
goto out_ro;
+ }
}
}
@@ -553,13 +569,33 @@ static int kill_orphans(struct ubifs_info *c)
c->sbuf, -1);
}
if (IS_ERR(sleb)) {
+ if (test_and_clear_failure_reason_callback(c, FR_DATA_CORRUPTED) &&
+ handle_failure_callback(c, FR_H_ORPHAN_CORRUPTED, &lnum)) {
+ /* Skip the orphan LEB. */
+ continue;
+ }
err = PTR_ERR(sleb);
break;
}
}
err = do_kill_orphans(c, sleb, &last_cmt_no, &outofdate,
&last_flagged);
- if (err || outofdate) {
+ if (err) {
+ unsigned int reason = get_failure_reason_callback(c);
+
+ if (reason & FR_DATA_CORRUPTED) {
+ test_and_clear_failure_reason_callback(c, FR_DATA_CORRUPTED);
+ if (handle_failure_callback(c, FR_H_ORPHAN_CORRUPTED, &lnum)) {
+ err = 0;
+ /* Skip the orphan LEB. */
+ ubifs_scan_destroy(sleb);
+ continue;
+ }
+ }
+ ubifs_scan_destroy(sleb);
+ break;
+ }
+ if (outofdate) {
ubifs_scan_destroy(sleb);
break;
}
diff --git a/ubifs-utils/libubifs/ubifs.h b/ubifs-utils/libubifs/ubifs.h
index ae812ff..8a506a8 100644
--- a/ubifs-utils/libubifs/ubifs.h
+++ b/ubifs-utils/libubifs/ubifs.h
@@ -1546,6 +1546,7 @@ enum {
enum {
FR_H_BUD_CORRUPTED = 0, /* Bud LEB is corrupted */
FR_H_TNC_DATA_CORRUPTED, /* Data searched from TNC is corrupted */
+ FR_H_ORPHAN_CORRUPTED, /* Orphan LEB is corrupted */
};
/* Callback functions for failure(which can be handled by fsck) happens. */
static inline void set_failure_reason_callback(const struct ubifs_info *c,