• Zhihao Cheng's avatar
    ubi: fastmap: Fix high cpu usage of ubi_bgt by making sure wl_pool not empty · d09e9a2b
    Zhihao Cheng authored
    There at least 6 PEBs reserved on UBI device:
    1. EBA_RESERVED_PEBS[1]
    2. WL_RESERVED_PEBS[1]
    3. UBI_LAYOUT_VOLUME_EBS[2]
    4. MIN_FASTMAP_RESERVED_PEBS[2]
    
    When all ubi volumes take all their PEBs, there are 3 (EBA_RESERVED_PEBS +
    WL_RESERVED_PEBS + MIN_FASTMAP_RESERVED_PEBS - MIN_FASTMAP_TAKEN_PEBS[1])
    free PEBs. Since commit f9c34bb5 ("ubi: Fix producing anchor PEBs")
    and commit 4b68bf9a ("ubi: Select fastmap anchor PEBs considering
    wear level rules") applied, there is only 1 (3 - FASTMAP_ANCHOR_PEBS[1] -
    FASTMAP_NEXT_ANCHOR_PEBS[1]) free PEB to fill pool and wl_pool, after
    filling pool, wl_pool is always empty. So, UBI could be stuck in an
    infinite loop:
    
    	ubi_thread	   system_wq
    wear_leveling_worker <--------------------------------------------------
      get_peb_for_wl							|
        // fm_wl_pool, used = size = 0					|
        schedule_work(&ubi->fm_work)					|
    									|
    		    update_fastmap_work_fn				|
    		      ubi_update_fastmap				|
    			ubi_refill_pools				|
    			// ubi->free_count - ubi->beb_rsvd_pebs < 5	|
    			// wl_pool is not filled with any PEBs		|
    			schedule_erase(old_fm_anchor)			|
    			ubi_ensure_anchor_pebs				|
    			  __schedule_ubi_work(wear_leveling_worker)	|
    									|
    __erase_worker								|
      ensure_wear_leveling							|
        __schedule_ubi_work(wear_leveling_worker) --------------------------
    
    , which cause high cpu usage of ubi_bgt:
    top - 12:10:42 up 5 min,  2 users,  load average: 1.76, 0.68, 0.27
    Tasks: 123 total,   3 running,  54 sleeping,   0 stopped,   0 zombie
    
      PID USER PR   NI VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
     1589 root 20   0   0      0      0 R  45.0  0.0   0:38.86 ubi_bgt0d
      319 root 20   0   0      0      0 I  15.2  0.0   0:15.29 kworker/0:3-eve
      371 root 20   0   0      0      0 I  14.9  0.0   0:12.85 kworker/3:3-eve
       20 root 20   0   0      0      0 I  11.3  0.0   0:05.33 kworker/1:0-eve
      202 root 20   0   0      0      0 I  11.3  0.0   0:04.93 kworker/2:3-eve
    
    In commit 4b68bf9a ("ubi: Select fastmap anchor PEBs considering
    wear level rules"), there are three key changes:
      1) Choose the fastmap anchor when the most free PEBs are available.
      2) Enable anchor move within the anchor area again as it is useful
         for distributing wear.
      3) Import a candidate fm anchor and check this PEB's erase count during
         wear leveling. If the wear leveling limit is exceeded, use the used
         anchor area PEB with the lowest erase count to replace it.
    
    The anchor candidate can be removed, we can check fm_anchor PEB's erase
    count during wear leveling. Fix it by:
      1) Removing 'fm_next_anchor' and check 'fm_anchor' during wear leveling.
      2) Preferentially filling one free peb into fm_wl_pool in condition of
         ubi->free_count > ubi->beb_rsvd_pebs, then try to reserve enough
         free count for fastmap non anchor pebs after the above prerequisites
         are met.
    Then, there are at least 1 PEB in pool and 1 PEB in wl_pool after calling
    ubi_refill_pools() with all erase works done.
    
    Fetch a reproducer in [Link].
    
    Fixes: 4b68bf9a ("ubi: Select fastmap anchor PEBs ... rules")
    Link: https://bugzilla.kernel.org/show_bug.cgi?id=215407Signed-off-by: default avatarZhihao Cheng <chengzhihao1@huawei.com>
    Signed-off-by: default avatarRichard Weinberger <richard@nod.at>
    d09e9a2b
ubi.h 41.1 KB