When developping NAND controller drivers or when debugging filesystem
corruptions, it is quite common to need hacking locally into the
MTD/NAND core in order to get access to the content of the bad
blocks. Instead of having multiple implementations out there let's
provide a simple yet effective specific MTD-wide debugfs entry to fully
disable these checks on purpose.
A warning is added to inform the user when this mode gets enabled.
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20211118114659.1282855-1-miquel.raynal@bootlin.com
        return ret ? ERR_PTR(ret) : bdi;
 }
 
+char *mtd_expert_analysis_warning =
+       "Bad block checks have been entirely disabled.\n"
+       "This is only reserved for post-mortem forensics and debug purposes.\n"
+       "Never enable this mode if you do not know what you are doing!\n";
+EXPORT_SYMBOL_GPL(mtd_expert_analysis_warning);
+bool mtd_expert_analysis_mode;
+EXPORT_SYMBOL_GPL(mtd_expert_analysis_mode);
+
 static struct proc_dir_entry *proc_mtd;
 
 static int __init init_mtd(void)
                goto out_procfs;
 
        dfs_dir_mtd = debugfs_create_dir("mtd", NULL);
+       debugfs_create_bool("expert_analysis_mode", 0600, dfs_dir_mtd,
+                           &mtd_expert_analysis_mode);
 
        return 0;
 
 
  */
 bool nanddev_isbad(struct nand_device *nand, const struct nand_pos *pos)
 {
+       if (WARN_ONCE(mtd_expert_analysis_mode, mtd_expert_analysis_warning))
+               return false;
+
        if (nanddev_bbt_is_initialized(nand)) {
                unsigned int entry;
                int status;
 
        if (nand_region_is_secured(chip, ofs, mtd->erasesize))
                return -EIO;
 
+       if (WARN_ONCE(mtd_expert_analysis_mode, mtd_expert_analysis_warning))
+               return 0;
+
        if (chip->legacy.block_bad)
                return chip->legacy.block_bad(chip, ofs);
 
 
        pr_debug("nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
                 (unsigned int)offs, block, res);
 
+       if (WARN_ONCE(mtd_expert_analysis_mode, mtd_expert_analysis_warning))
+               return 0;
+
        switch (res) {
        case BBT_BLOCK_GOOD:
                return 0;
 
 
 unsigned mtd_mmap_capabilities(struct mtd_info *mtd);
 
+extern char *mtd_expert_analysis_warning;
+extern bool mtd_expert_analysis_mode;
+
 #endif /* __MTD_MTD_H__ */