diff options
Diffstat (limited to 'drivers/mtd/ubi/ubi.h')
| -rw-r--r-- | drivers/mtd/ubi/ubi.h | 124 |
1 files changed, 74 insertions, 50 deletions
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 5fe62653995e..44803d3329f4 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -1,21 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (c) International Business Machines Corp., 2006 * Copyright (c) Nokia Corporation, 2006, 2007 * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * * Author: Artem Bityutskiy (Битюцкий Артём) */ @@ -39,7 +26,7 @@ #include <linux/notifier.h> #include <linux/mtd/mtd.h> #include <linux/mtd/ubi.h> -#include <asm/pgtable.h> +#include <linux/pgtable.h> #include "ubi-media.h" @@ -95,11 +82,14 @@ void ubi_err(const struct ubi_device *ubi, const char *fmt, ...); #define UBI_DFS_DIR_NAME "ubi%d" #define UBI_DFS_DIR_LEN (3 + 2 + 1) +/* Number of physical eraseblocks reserved for atomic LEB change operation */ +#define EBA_RESERVED_PEBS 1 + /* * Error codes returned by the I/O sub-system. * * UBI_IO_FF: the read region of flash contains only 0xFFs - * UBI_IO_FF_BITFLIPS: the same as %UBI_IO_FF, but also also there was a data + * UBI_IO_FF_BITFLIPS: the same as %UBI_IO_FF, but also there was a data * integrity error reported by the MTD driver * (uncorrectable ECC error in case of NAND) * UBI_IO_BAD_HDR: the EC or VID header is corrupted (bad magic or CRC) @@ -155,17 +145,6 @@ enum { UBI_BAD_FASTMAP, }; -/* - * Flags for emulate_power_cut in ubi_debug_info - * - * POWER_CUT_EC_WRITE: Emulate a power cut when writing an EC header - * POWER_CUT_VID_WRITE: Emulate a power cut when writing a VID header - */ -enum { - POWER_CUT_EC_WRITE = 0x01, - POWER_CUT_VID_WRITE = 0x02, -}; - /** * struct ubi_vid_io_buf - VID buffer used to read/write VID info to/from the * flash. @@ -294,7 +273,7 @@ struct ubi_eba_leb_desc { /** * struct ubi_volume - UBI volume description data structure. - * @dev: device object to make use of the the Linux device model + * @dev: device object to make use of the Linux device model * @cdev: character device object to create character device * @ubi: reference to the UBI device description object * @vol_id: volume ID @@ -327,6 +306,9 @@ struct ubi_eba_leb_desc { * atomic LEB change * * @eba_tbl: EBA table of this volume (LEB->PEB mapping) + * @skip_check: %1 if CRC check of this static volume should be skipped. + * Directly reflects the presence of the + * %UBI_VTBL_SKIP_CRC_CHECK_FLG flag in the vtbl entry * @checked: %1 if this static volume was checked * @corrupted: %1 if the volume is corrupted (static volumes only) * @upd_marker: %1 if the update marker is set for this volume @@ -334,6 +316,9 @@ struct ubi_eba_leb_desc { * @changing_leb: %1 if the atomic LEB change ioctl command is in progress * @direct_writes: %1 if direct writes are enabled for this volume * + * @checkmap: bitmap to remember which PEB->LEB mappings got checked, + * protected by UBI LEB lock tree. + * * The @corrupted field indicates that the volume's contents is corrupted. * Since UBI protects only static volumes, this field is not relevant to * dynamic volumes - it is user's responsibility to assure their data @@ -352,6 +337,7 @@ struct ubi_volume { int writers; int exclusive; int metaonly; + bool is_dead; int reserved_pebs; int vol_type; @@ -371,12 +357,17 @@ struct ubi_volume { void *upd_buf; struct ubi_eba_table *eba_tbl; + unsigned int skip_check:1; unsigned int checked:1; unsigned int corrupted:1; unsigned int upd_marker:1; unsigned int updating:1; unsigned int changing_leb:1; unsigned int direct_writes:1; + +#ifdef CONFIG_MTD_UBI_FASTMAP + unsigned long *checkmap; +#endif }; /** @@ -390,8 +381,6 @@ struct ubi_volume_desc { int mode; }; -struct ubi_wl_entry; - /** * struct ubi_debug_info - debugging information for an UBI device. * @@ -405,6 +394,7 @@ struct ubi_wl_entry; * @power_cut_counter: count down for writes left until emulated power cut * @power_cut_min: minimum number of writes before emulating a power cut * @power_cut_max: maximum number of writes until emulating a power cut + * @emulate_failures: emulate failures for testing purposes * @dfs_dir_name: name of debugfs directory containing files of this UBI device * @dfs_dir: direntry object of the UBI device debugfs directory * @dfs_chk_gen: debugfs knob to enable UBI general extra checks @@ -416,6 +406,7 @@ struct ubi_wl_entry; * @dfs_emulate_power_cut: debugfs knob to emulate power cuts * @dfs_power_cut_min: debugfs knob for minimum writes before power cut * @dfs_power_cut_max: debugfs knob for maximum writes until power cut + * @dfs_emulate_failures: debugfs entry to control the fault injection type */ struct ubi_debug_info { unsigned int chk_gen:1; @@ -428,7 +419,8 @@ struct ubi_debug_info { unsigned int power_cut_counter; unsigned int power_cut_min; unsigned int power_cut_max; - char dfs_dir_name[UBI_DFS_DIR_LEN + 1]; + unsigned int emulate_failures; + char dfs_dir_name[UBI_DFS_DIR_LEN]; struct dentry *dfs_dir; struct dentry *dfs_chk_gen; struct dentry *dfs_chk_io; @@ -439,11 +431,12 @@ struct ubi_debug_info { struct dentry *dfs_emulate_power_cut; struct dentry *dfs_power_cut_min; struct dentry *dfs_power_cut_max; + struct dentry *dfs_emulate_failures; }; /** * struct ubi_device - UBI device description structure - * @dev: UBI device object to use the the Linux device model + * @dev: UBI device object to use the Linux device model * @cdev: character device object to create character device * @ubi_num: UBI device number * @ubi_name: UBI device name @@ -493,6 +486,9 @@ struct ubi_debug_info { * @fm_work: fastmap work queue * @fm_work_scheduled: non-zero if fastmap work was scheduled * @fast_attach: non-zero if UBI was attached by fastmap + * @fm_anchor: The next anchor PEB to use for fastmap + * @fm_do_produce_anchor: If true produce an anchor PEB in wl + * @fm_pool_rsv_cnt: Number of reserved PEBs for filling pool/wl_pool * * @used: RB-tree of used physical eraseblocks * @erroneous: RB-tree of erroneous used physical eraseblocks @@ -566,6 +562,7 @@ struct ubi_device { spinlock_t volumes_lock; int ref_count; int image_seq; + bool is_dead; int rsvd_pebs; int avail_pebs; @@ -601,6 +598,9 @@ struct ubi_device { struct work_struct fm_work; int fm_work_scheduled; int fast_attach; + struct ubi_wl_entry *fm_anchor; + int fm_do_produce_anchor; + int fm_pool_rsv_cnt; /* Wear-leveling sub-system's stuff */ struct rb_root used; @@ -791,7 +791,6 @@ struct ubi_attach_info { * @vol_id: the volume ID on which this erasure is being performed * @lnum: the logical eraseblock number * @torture: if the physical eraseblock has to be tortured - * @anchor: produce a anchor PEB to by used by fastmap * * The @func pointer points to the worker function. If the @shutdown argument is * not zero, the worker has to free the resources and exit immediately as the @@ -807,7 +806,6 @@ struct ubi_work { int vol_id; int lnum; int torture; - int anchor; }; #include "debug.h" @@ -816,7 +814,7 @@ extern struct kmem_cache *ubi_wl_entry_slab; extern const struct file_operations ubi_ctrl_cdev_operations; extern const struct file_operations ubi_cdev_operations; extern const struct file_operations ubi_vol_cdev_operations; -extern struct class ubi_class; +extern const struct class ubi_class; extern struct mutex ubi_devices_mutex; extern struct blocking_notifier_head ubi_notifiers; @@ -833,7 +831,6 @@ void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av); struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi, struct ubi_attach_info *ai); int ubi_attach(struct ubi_device *ubi, int force_scan); -void ubi_destroy_ai(struct ubi_attach_info *ai); /* vtbl.c */ int ubi_change_vtbl_record(struct ubi_device *ubi, int idx, @@ -904,6 +901,7 @@ int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap, struct ubi_attach_info *ai_scan); /* wl.c */ +int ubi_sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, int torture); int ubi_wl_get_peb(struct ubi_device *ubi); int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum, int pnum, int torture); @@ -916,8 +914,9 @@ struct ubi_wl_entry *ubi_wl_get_fm_peb(struct ubi_device *ubi, int anchor); int ubi_wl_put_fm_peb(struct ubi_device *ubi, struct ubi_wl_entry *used_e, int lnum, int torture); int ubi_is_erase_work(struct ubi_work *wrk); -void ubi_refill_pools(struct ubi_device *ubi); +void ubi_refill_pools_and_lock(struct ubi_device *ubi); int ubi_ensure_anchor_pebs(struct ubi_device *ubi); +int ubi_bitflip_check(struct ubi_device *ubi, int pnum, int force_scrub); /* io.c */ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset, @@ -938,7 +937,8 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, /* build.c */ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, - int vid_hdr_offset, int max_beb_per1024); + int vid_hdr_offset, int max_beb_per1024, + bool disable_fm, bool need_resv_pool); int ubi_detach_mtd_dev(int ubi_num, int anyway); struct ubi_device *ubi_get_device(int ubi_num); void ubi_put_device(struct ubi_device *ubi); @@ -949,12 +949,14 @@ int ubi_volume_notify(struct ubi_device *ubi, struct ubi_volume *vol, int ubi_notify_all(struct ubi_device *ubi, int ntype, struct notifier_block *nb); int ubi_enumerate_volumes(struct notifier_block *nb); +void ubi_free_all_volumes(struct ubi_device *ubi); void ubi_free_internal_volumes(struct ubi_device *ubi); /* kapi.c */ void ubi_do_get_device_info(struct ubi_device *ubi, struct ubi_device_info *di); void ubi_do_get_volume_info(struct ubi_device *ubi, struct ubi_volume *vol, struct ubi_volume_info *vi); +int ubi_get_num_by_path(const char *pathname, int *ubi_num, int *vol_id); /* scan.c */ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, int pnum, const struct ubi_vid_hdr *vid_hdr); @@ -965,8 +967,24 @@ size_t ubi_calc_fm_size(struct ubi_device *ubi); int ubi_update_fastmap(struct ubi_device *ubi); int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, struct ubi_attach_info *scan_ai); +int ubi_fastmap_init_checkmap(struct ubi_volume *vol, int leb_count); +void ubi_fastmap_destroy_checkmap(struct ubi_volume *vol); +static inline void ubi_free_fastmap(struct ubi_device *ubi) +{ + if (ubi->fm) { + int i; + + for (i = 0; i < ubi->fm->used_blocks; i++) + kmem_cache_free(ubi_wl_entry_slab, ubi->fm->e[i]); + kfree(ubi->fm); + ubi->fm = NULL; + } +} #else static inline int ubi_update_fastmap(struct ubi_device *ubi) { return 0; } +static inline int ubi_fastmap_init_checkmap(struct ubi_volume *vol, int leb_count) { return 0; } +static inline void ubi_fastmap_destroy_checkmap(struct ubi_volume *vol) {} +static inline void ubi_free_fastmap(struct ubi_device *ubi) { } #endif /* block.c */ @@ -1119,6 +1137,19 @@ static inline struct ubi_vid_hdr *ubi_get_vid_hdr(struct ubi_vid_io_buf *vidb) return vidb->hdr; } +/** + * ubi_ro_mode - switch to read-only mode. + * @ubi: UBI device description object + */ +static inline void ubi_ro_mode(struct ubi_device *ubi) +{ + if (!ubi->ro_mode) { + ubi->ro_mode = 1; + ubi_warn(ubi, "switch to read-only mode"); + dump_stack(); + } +} + /* * This function is equivalent to 'ubi_io_read()', but @offset is relative to * the beginning of the logical eraseblock, not to the beginning of the @@ -1140,20 +1171,13 @@ static inline int ubi_io_write_data(struct ubi_device *ubi, const void *buf, int pnum, int offset, int len) { ubi_assert(offset >= 0); - return ubi_io_write(ubi, buf, pnum, offset + ubi->leb_start, len); -} -/** - * ubi_ro_mode - switch to read-only mode. - * @ubi: UBI device description object - */ -static inline void ubi_ro_mode(struct ubi_device *ubi) -{ - if (!ubi->ro_mode) { - ubi->ro_mode = 1; - ubi_warn(ubi, "switch to read-only mode"); - dump_stack(); + if (ubi_dbg_power_cut(ubi, MASK_POWER_CUT_DATA)) { + ubi_warn(ubi, "XXXXX emulating a power cut when writing data XXXXX"); + ubi_ro_mode(ubi); + return -EROFS; } + return ubi_io_write(ubi, buf, pnum, offset + ubi->leb_start, len); } /** |
