STRUCT UBI_DEVICE(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’… struct ubi_device(9) πŸ’…

okay bestie, so this is the manual page for struct ubi_device β€” literally the UBI device description structure in the Linux kernel, and it's a lot, but we're gonna get through it together 🫢


✨ NAME ✨

struct ubi_device β€” the UBI device description structure, no cap, it's the whole vibe of a UBI device


πŸŽ€ SYNOPSIS πŸŽ€

struct ubi_device {
    struct cdev cdev;
    struct device dev;
    int ubi_num;
    char ubi_name[sizeof(UBI_NAME_STR)+5];
    int vol_count;
    struct ubi_volume *volumes[UBI_MAX_VOLUMES+UBI_INT_VOL_COUNT];
    spinlock_t volumes_lock;
    int ref_count;
    int image_seq;
    bool is_dead;
    int rsvd_pebs;
    int avail_pebs;
    int beb_rsvd_pebs;
    int beb_rsvd_level;
    int bad_peb_limit;
    int autoresize_vol_id;
    int vtbl_slots;
    int vtbl_size;
    struct ubi_vtbl_record *vtbl;
    struct mutex device_mutex;
    int max_ec;
    int mean_ec;
    unsigned long long global_sqnum;
    spinlock_t ltree_lock;
    struct rb_root ltree;
    struct mutex alc_mutex;
    int fm_disabled;
    struct ubi_fastmap_layout *fm;
    struct ubi_fm_pool fm_pool;
    struct ubi_fm_pool fm_wl_pool;
    struct rw_semaphore fm_eba_sem;
    struct rw_semaphore fm_protect;
    void *fm_buf;
    size_t fm_size;
    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;
    struct rb_root used;
    struct rb_root erroneous;
    struct rb_root free;
    int free_count;
    struct rb_root scrub;
    struct list_head pq[UBI_PROT_QUEUE_LEN];
    int pq_head;
    spinlock_t wl_lock;
    struct mutex move_mutex;
    struct rw_semaphore work_sem;
    int wl_scheduled;
    struct ubi_wl_entry **lookuptbl;
    struct ubi_wl_entry *move_from;
    struct ubi_wl_entry *move_to;
    int move_to_put;
    struct list_head works;
    int works_count;
    struct task_struct *bgt_thread;
    int thread_enabled;
    char bgt_name[sizeof(UBI_BGT_NAME_PATTERN)+2];
    int wl_threshold;
    int wl_free_max_diff;
    long long flash_size;
    int peb_count;
    int peb_size;
    int bad_peb_count;
    int good_peb_count;
    int corr_peb_count;
    int erroneous_peb_count;
    int max_erroneous;
    int min_io_size;
    int hdrs_min_io_size;
    int ro_mode;
    int leb_size;
    int leb_start;
    int ec_hdr_alsize;
    int vid_hdr_alsize;
    int vid_hdr_offset;
    int vid_hdr_aloffset;
    int vid_hdr_shift;
    unsigned int bad_allowed:1;
    unsigned int nor_flash:1;
    int max_write_size;
    struct mtd_info *mtd;
    void *peb_buf;
    struct mutex buf_mutex;
    struct mutex ckvol_mutex;
    struct ubi_debug_info dbg;
};

like, that's the whole struct, periodt πŸ’…


🌸 DESCRIPTION 🌸

so this struct is literally the main character energy of a UBI device β€” it holds every single thing the kernel needs to know about one UBI device. we're talking volumes, eraseblocks, wear-leveling, fastmap, debug info… the whole situation ✨


πŸ‘‘ Members πŸ‘‘

here's the tea on every single field, bestie, buckle up:

  • cdev β€” character device object to create character device πŸ’–
  • dev β€” UBI device object to use the Linux device model
  • ubi_num β€” UBI device number
  • ubi_name β€” UBI device name
  • vol_count β€” number of volumes in this UBI device
  • volumes β€” volumes of this UBI device
  • volumes_lock β€” protects volumes, rsvd_pebs, avail_pebs, beb_rsvd_pebs, beb_rsvd_level, bad_peb_count, good_peb_count, vol_count, vol->readers, vol->writers, vol->exclusive, vol->metaonly, vol->ref_count, vol->mapping and vol->eba_tbl. lowkey that's a lot but okay 🫢
  • ref_count β€” count of references on the UBI device
  • image_seq β€” image sequence number recorded on EC headers
  • rsvd_pebs β€” count of reserved physical eraseblocks
  • avail_pebs β€” count of available physical eraseblocks
  • beb_rsvd_pebs β€” how many physical eraseblocks are reserved for bad PEB handling
  • beb_rsvd_level β€” normal level of PEBs reserved for bad PEB handling
  • bad_peb_limit β€” top limit of expected bad physical eraseblocks
  • autoresize_vol_id β€” ID of the volume which has to be auto-resized at the end of UBI initialization
  • vtbl_slots β€” how many slots are available in the volume table
  • vtbl_size β€” size of the volume table in bytes
  • vtbl β€” in-RAM volume table copy
  • device_mutex β€” protects on-flash volume table and serializes volume creation, deletion, update, re-size, re-name and set property. it's giving "one at a time please" 😌
  • max_ec β€” current highest erase counter value
  • mean_ec β€” current mean erase counter value
  • global_sqnum β€” global sequence number
  • ltree_lock β€” protects the lock tree and global_sqnum
  • ltree β€” the lock tree
  • alc_mutex β€” serializes "atomic LEB change" operations
  • fm_disabled β€” non-zero if fastmap is disabled (default)
  • fm β€” in-memory data structure of the currently used fastmap
  • fm_pool β€” in-memory data structure of the fastmap pool
  • fm_wl_pool β€” in-memory data structure of the fastmap pool used by the WL sub-system
  • fm_eba_sem β€” allows ubi_update_fastmap to block EBA table changes
  • fm_protect β€” serializes ubi_update_fastmap, protects fm_buf and makes sure that critical sections cannot be interrupted by ubi_update_fastmap
  • fm_buf β€” vmalloc'd buffer which holds the raw fastmap
  • fm_size β€” fastmap size in bytes
  • 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
  • free β€” RB-tree of free physical eraseblocks
  • free_count β€” contains the number of elements in free
  • scrub β€” RB-tree of physical eraseblocks which need scrubbing 🧚
  • pq β€” protection queue (contain physical eraseblocks which are temporarily protected from the wear-leveling worker)
  • pq_head β€” protection queue head
  • wl_lock β€” protects the used, free, pq, pq_head, lookuptbl, move_from, move_to, move_to_put erase_pending, wl_scheduled, works, erroneous, erroneous_peb_count, fm_work_scheduled, fm_pool, and fm_wl_pool fields. like, it protects everything, it's the bodyguard of the struct πŸ’€
  • move_mutex β€” serializes eraseblock moves
  • work_sem β€” used to wait for all the scheduled works to finish and prevent new works from being submitted
  • wl_scheduled β€” non-zero if the wear-leveling was scheduled
  • lookuptbl β€” a table to quickly find a struct ubi_wl_entry object for any physical eraseblock
  • move_from β€” physical eraseblock from where the data is being moved
  • move_to β€” physical eraseblock where the data is being moved to
  • move_to_put β€” if the "to" PEB was put
  • works β€” list of pending works
  • works_count β€” count of pending works
  • bgt_thread β€” background thread description object
  • thread_enabled β€” if the background thread is enabled
  • bgt_name β€” background thread name
  • wl_threshold β€” maximum difference between two erase counters. if this threshold is exceeded, the WL sub-system starts moving data from used physical eraseblocks with low erase counter to free physical eraseblocks with high erase counter. it's giving "balance is key" βš–οΈ
  • wl_free_max_diff β€” okay so when a physical eraseblock is moved, the WL sub-system has to pick the target physical eraseblock to move to. the simplest way would be just to pick the one with the highest erase counter. but in certain workloads this could lead to an unlimited wear of one or few physical eraseblock. indeed, imagine a situation when the picked physical eraseblock is constantly erased after the data is written to it. so, we have a constant which limits the highest erase counter of the free physical eraseblock to pick. namely, the WL sub-system does not pick eraseblocks with erase counter greater than the lowest erase counter plus wl_free_max_diff. ngl that's a whole paragraph but it's important, don't skip it bestie 😭
  • flash_size β€” underlying MTD device size (in bytes)
  • peb_count β€” count of physical eraseblocks on the MTD device
  • peb_size β€” physical eraseblock size
  • bad_peb_count β€” count of bad physical eraseblocks
  • good_peb_count β€” count of good physical eraseblocks
  • corr_peb_count β€” count of corrupted physical eraseblocks (preserved and not used by UBI)
  • erroneous_peb_count β€” count of erroneous physical eraseblocks in erroneous
  • max_erroneous β€” maximum allowed amount of erroneous physical eraseblocks
  • min_io_size β€” minimal input/output unit size of the underlying MTD device
  • hdrs_min_io_size β€” minimal I/O unit size used for VID and EC headers
  • ro_mode β€” if the UBI device is in read-only mode
  • leb_size β€” logical eraseblock size
  • leb_start β€” starting offset of logical eraseblocks within physical eraseblocks
  • ec_hdr_alsize β€” size of the EC header aligned to hdrs_min_io_size
  • vid_hdr_alsize β€” size of the VID header aligned to hdrs_min_io_size
  • vid_hdr_offset β€” starting offset of the volume identifier header (might be unaligned)
  • vid_hdr_aloffset β€” starting offset of the VID header aligned to hdrs_min_io_size
  • vid_hdr_shift β€” contains vid_hdr_offset - vid_hdr_aloffset
  • bad_allowed β€” whether the MTD device admits bad physical eraseblocks or not
  • nor_flash β€” non-zero if working on top of NOR flash
  • max_write_size β€” maximum amount of bytes the underlying flash can write at a time (MTD write buffer size)
  • mtd β€” MTD device descriptor
  • peb_buf β€” a buffer of PEB size used for different purposes
  • buf_mutex β€” protects peb_buf
  • ckvol_mutex β€” serializes static volume checking when opening
  • dbg β€” debugging information for this UBI device

honestly, that's the whole list, and every single field is here, no gatekeeping πŸ’œ


πŸ¦‹ SEE ALSO πŸ¦‹

bestie, there's a whole squad of related kernel file things, go check them out iykyk:

Kernel file ./drivers/mtd/ubi/ubi.h struct ubi_vid_io_buf(9), struct ubi_wl_entry(9), struct ubi_ltree_entry(9), struct ubi_rename_entry(9), struct ubi_fastmap_layout(9), struct ubi_fm_pool(9), struct ubi_eba_leb_desc(9), struct ubi_volume(9), struct ubi_volume_desc(9), struct ubi_debug_info(9), struct ubi_ainf_peb(9), struct ubi_ainf_volume(9), struct ubi_attach_info(9), struct ubi_work(9), ubi_init_vid_buf(9), ubi_free_vid_buf(9), ubi_get_vid_hdr(9), ubi_ro_mode(9), vol_id2idx(9), idx2vol_id(9), ubi_is_fm_vol(9), ubi_find_fm_block(9)


and that's the whole manual page, bestie! every single field, every single detail, no cap. you're now officially obsessed with struct ubi_device whether you like it or not πŸ’…βœ¨

signed off with love from ./drivers/mtd/ubi, October 2026 β€” stay iconic, kernel queen πŸ‘‘πŸ’–

πŸ“¦ where this page comes from