]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - fs/ubifs/scan.c
Merge branch 'master' of git://git.denx.de/u-boot-arc
[karo-tx-uboot.git] / fs / ubifs / scan.c
index 0ed82479b44b4daca156a80107fee1b040ec10a7..5523d4e6608f39d16e98641eb584128fc67a6e09 100644 (file)
@@ -3,18 +3,7 @@
  *
  * Copyright (C) 2006-2008 Nokia Corporation
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * SPDX-License-Identifier:    GPL-2.0+
  *
  * Authors: Adrian Hunter
  *          Artem Bityutskiy (Битюцкий Артём)
  * debugging functions.
  */
 
+#define __UBOOT__
+#ifdef __UBOOT__
+#include <linux/err.h>
+#endif
 #include "ubifs.h"
 
 /**
@@ -75,7 +68,7 @@ int ubifs_scan_a_node(const struct ubifs_info *c, void *buf, int len, int lnum,
        magic = le32_to_cpu(ch->magic);
 
        if (magic == 0xFFFFFFFF) {
-               dbg_scan("hit empty space");
+               dbg_scan("hit empty space at LEB %d:%d", lnum, offs);
                return SCANNED_EMPTY_SPACE;
        }
 
@@ -85,7 +78,8 @@ int ubifs_scan_a_node(const struct ubifs_info *c, void *buf, int len, int lnum,
        if (len < UBIFS_CH_SZ)
                return SCANNED_GARBAGE;
 
-       dbg_scan("scanning %s", dbg_ntype(ch->node_type));
+       dbg_scan("scanning %s at LEB %d:%d",
+                dbg_ntype(ch->node_type), lnum, offs);
 
        if (ubifs_check_node(c, buf, lnum, offs, quiet, 1))
                return SCANNED_A_CORRUPT_NODE;
@@ -101,22 +95,21 @@ int ubifs_scan_a_node(const struct ubifs_info *c, void *buf, int len, int lnum,
                        if (!quiet) {
                                ubifs_err("bad pad node at LEB %d:%d",
                                          lnum, offs);
-                               dbg_dump_node(c, pad);
+                               ubifs_dump_node(c, pad);
                        }
                        return SCANNED_A_BAD_PAD_NODE;
                }
 
                /* Make the node pads to 8-byte boundary */
                if ((node_len + pad_len) & 7) {
-                       if (!quiet) {
-                               dbg_err("bad padding length %d - %d",
-                                       offs, offs + node_len + pad_len);
-                       }
+                       if (!quiet)
+                               ubifs_err("bad padding length %d - %d",
+                                         offs, offs + node_len + pad_len);
                        return SCANNED_A_BAD_PAD_NODE;
                }
 
-               dbg_scan("%d bytes padded, offset now %d",
-                        pad_len, ALIGN(offs + node_len + pad_len, 8));
+               dbg_scan("%d bytes padded at LEB %d:%d, offset now %d", pad_len,
+                        lnum, offs, ALIGN(offs + node_len + pad_len, 8));
 
                return node_len + pad_len;
        }
@@ -149,10 +142,10 @@ struct ubifs_scan_leb *ubifs_start_scan(const struct ubifs_info *c, int lnum,
        INIT_LIST_HEAD(&sleb->nodes);
        sleb->buf = sbuf;
 
-       err = ubi_read(c->ubi, lnum, sbuf + offs, offs, c->leb_size - offs);
+       err = ubifs_leb_read(c, lnum, sbuf + offs, offs, c->leb_size - offs, 0);
        if (err && err != -EBADMSG) {
-               ubifs_err("cannot read %d bytes from LEB %d:%d,"
-                         " error %d", c->leb_size - offs, lnum, offs, err);
+               ubifs_err("cannot read %d bytes from LEB %d:%d, error %d",
+                         c->leb_size - offs, lnum, offs, err);
                kfree(sleb);
                return ERR_PTR(err);
        }
@@ -198,7 +191,7 @@ int ubifs_add_snod(const struct ubifs_info *c, struct ubifs_scan_leb *sleb,
        struct ubifs_ino_node *ino = buf;
        struct ubifs_scan_node *snod;
 
-       snod = kzalloc(sizeof(struct ubifs_scan_node), GFP_NOFS);
+       snod = kmalloc(sizeof(struct ubifs_scan_node), GFP_NOFS);
        if (!snod)
                return -ENOMEM;
 
@@ -213,13 +206,15 @@ int ubifs_add_snod(const struct ubifs_info *c, struct ubifs_scan_leb *sleb,
        case UBIFS_DENT_NODE:
        case UBIFS_XENT_NODE:
        case UBIFS_DATA_NODE:
-       case UBIFS_TRUN_NODE:
                /*
                 * The key is in the same place in all keyed
                 * nodes.
                 */
                key_read(c, &ino->key, &snod->key);
                break;
+       default:
+               invalid_key_init(c, &snod->key);
+               break;
        }
        list_add_tail(&snod->list, &sleb->nodes);
        sleb->nodes_cnt += 1;
@@ -238,13 +233,11 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs,
 {
        int len;
 
-       ubifs_err("corrupted data at LEB %d:%d", lnum, offs);
-       if (dbg_failure_mode)
-               return;
+       ubifs_err("corruption at LEB %d:%d", lnum, offs);
        len = c->leb_size - offs;
-       if (len > 4096)
-               len = 4096;
-       dbg_err("first %d bytes from LEB %d:%d", len, lnum, offs);
+       if (len > 8192)
+               len = 8192;
+       ubifs_err("first %d bytes from LEB %d:%d", len, lnum, offs);
        print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1);
 }
 
@@ -253,13 +246,19 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs,
  * @c: UBIFS file-system description object
  * @lnum: logical eraseblock number
  * @offs: offset to start at (usually zero)
- * @sbuf: scan buffer (must be c->leb_size)
+ * @sbuf: scan buffer (must be of @c->leb_size bytes in size)
+ * @quiet: print no messages
  *
  * This function scans LEB number @lnum and returns complete information about
- * its contents. Returns an error code in case of failure.
+ * its contents. Returns the scaned information in case of success and,
+ * %-EUCLEAN if the LEB neads recovery, and other negative error codes in case
+ * of failure.
+ *
+ * If @quiet is non-zero, this function does not print large and scary
+ * error messages and flash dumps in case of errors.
  */
 struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
-                                 int offs, void *sbuf)
+                                 int offs, void *sbuf, int quiet)
 {
        void *buf = sbuf + offs;
        int err, len = c->leb_size - offs;
@@ -278,8 +277,7 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
 
                cond_resched();
 
-               ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 0);
-
+               ret = ubifs_scan_a_node(c, buf, len, lnum, offs, quiet);
                if (ret > 0) {
                        /* Padding bytes or a valid padding node */
                        offs += ret;
@@ -294,17 +292,18 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
 
                switch (ret) {
                case SCANNED_GARBAGE:
-                       dbg_err("garbage");
+                       ubifs_err("garbage");
                        goto corrupted;
                case SCANNED_A_NODE:
                        break;
                case SCANNED_A_CORRUPT_NODE:
                case SCANNED_A_BAD_PAD_NODE:
-                       dbg_err("bad node");
+                       ubifs_err("bad node");
                        goto corrupted;
                default:
-                       dbg_err("unknown");
-                       goto corrupted;
+                       ubifs_err("unknown");
+                       err = -EINVAL;
+                       goto error;
                }
 
                err = ubifs_add_snod(c, sleb, buf, offs);
@@ -317,8 +316,12 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
                len -= node_len;
        }
 
-       if (offs % c->min_io_size)
+       if (offs % c->min_io_size) {
+               if (!quiet)
+                       ubifs_err("empty space starts at non-aligned offset %d",
+                                 offs);
                goto corrupted;
+       }
 
        ubifs_end_scan(c, sleb, lnum, offs);
 
@@ -327,18 +330,25 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
                        break;
        for (; len; offs++, buf++, len--)
                if (*(uint8_t *)buf != 0xff) {
-                       ubifs_err("corrupt empty space at LEB %d:%d",
-                                 lnum, offs);
+                       if (!quiet)
+                               ubifs_err("corrupt empty space at LEB %d:%d",
+                                         lnum, offs);
                        goto corrupted;
                }
 
        return sleb;
 
 corrupted:
-       ubifs_scanned_corruption(c, lnum, offs, buf);
+       if (!quiet) {
+               ubifs_scanned_corruption(c, lnum, offs, buf);
+               ubifs_err("LEB %d scanning failed", lnum);
+       }
        err = -EUCLEAN;
+       ubifs_scan_destroy(sleb);
+       return ERR_PTR(err);
+
 error:
-       ubifs_err("LEB %d scanning failed", lnum);
+       ubifs_err("LEB %d scanning failed, error %d", lnum, err);
        ubifs_scan_destroy(sleb);
        return ERR_PTR(err);
 }