Skip to content

Commit

Permalink
Merge tag 'ubifs-for-linus-6.7-rc1' of git://git.kernel.org/pub/scm/l…
Browse files Browse the repository at this point in the history
…inux/kernel/git/rw/ubifs

Pull UBI and UBIFS updates from Richard Weinberger:

 - UBI Fastmap improvements

 - Minor issues found by static analysis bots in both UBI and UBIFS

 - Fix for wrong dentry length UBIFS in fscrypt mode

* tag 'ubifs-for-linus-6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs:
  ubifs: ubifs_link: Fix wrong name len calculating when UBIFS is encrypted
  ubi: block: Fix use-after-free in ubiblock_cleanup
  ubifs: fix possible dereference after free
  ubi: fastmap: Add control in 'UBI_IOCATT' ioctl to reserve PEBs for filling pools
  ubi: fastmap: Add module parameter to control reserving filling pool PEBs
  ubi: fastmap: Fix lapsed wear leveling for first 64 PEBs
  ubi: fastmap: Get wl PEB even ec beyonds the 'max' if free PEBs are run out
  ubi: fastmap: may_reserve_for_fm: Don't reserve PEB if fm_anchor exists
  ubi: fastmap: Remove unneeded break condition while filling pools
  ubi: fastmap: Wait until there are enough free PEBs before filling pools
  ubi: fastmap: Use free pebs reserved for bad block handling
  ubi: Replace erase_block() with sync_erase()
  ubi: fastmap: Allocate memory with GFP_NOFS in ubi_update_fastmap
  ubi: fastmap: erase_block: Get erase counter from wl_entry rather than flash
  ubi: fastmap: Fix missed ec updating after erasing old fastmap data block
  ubifs: Fix missing error code err
  ubifs: Fix memory leak of bud->log_hash
  ubifs: Fix some kernel-doc comments
  • Loading branch information
torvalds committed Nov 5, 2023
2 parents 1c41041 + 7569049 commit 2153fc3
Show file tree
Hide file tree
Showing 15 changed files with 179 additions and 116 deletions.
4 changes: 3 additions & 1 deletion drivers/mtd/ubi/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -447,13 +447,15 @@ int ubiblock_create(struct ubi_volume_info *vi)

static void ubiblock_cleanup(struct ubiblock *dev)
{
int id = dev->gd->first_minor;

/* Stop new requests to arrive */
del_gendisk(dev->gd);
/* Finally destroy the blk queue */
dev_info(disk_to_dev(dev->gd), "released");
put_disk(dev->gd);
blk_mq_free_tag_set(&dev->tag_set);
idr_remove(&ubiblock_minor_idr, dev->gd->first_minor);
idr_remove(&ubiblock_minor_idr, id);
}

int ubiblock_remove(struct ubi_volume_info *vi)
Expand Down
25 changes: 22 additions & 3 deletions drivers/mtd/ubi/build.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
#define MTD_PARAM_LEN_MAX 64

/* Maximum number of comma-separated items in the 'mtd=' parameter */
#define MTD_PARAM_MAX_COUNT 5
#define MTD_PARAM_MAX_COUNT 6

/* Maximum value for the number of bad PEBs per 1024 PEBs */
#define MAX_MTD_UBI_BEB_LIMIT 768
Expand All @@ -54,13 +54,15 @@
* @vid_hdr_offs: VID header offset
* @max_beb_per1024: maximum expected number of bad PEBs per 1024 PEBs
* @enable_fm: enable fastmap when value is non-zero
* @need_resv_pool: reserve pool->max_size pebs when value is none-zero
*/
struct mtd_dev_param {
char name[MTD_PARAM_LEN_MAX];
int ubi_num;
int vid_hdr_offs;
int max_beb_per1024;
int enable_fm;
int need_resv_pool;
};

/* Numbers of elements set in the @mtd_dev_param array */
Expand Down Expand Up @@ -825,6 +827,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
* @vid_hdr_offset: VID header offset
* @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs
* @disable_fm: whether disable fastmap
* @need_resv_pool: whether reserve pebs to fill fm_pool
*
* This function attaches MTD device @mtd_dev to UBI and assign @ubi_num number
* to the newly created UBI device, unless @ubi_num is %UBI_DEV_NUM_AUTO, in
Expand All @@ -840,7 +843,8 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
* @ubi_devices_mutex.
*/
int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
int vid_hdr_offset, int max_beb_per1024, bool disable_fm)
int vid_hdr_offset, int max_beb_per1024, bool disable_fm,
bool need_resv_pool)
{
struct ubi_device *ubi;
int i, err;
Expand Down Expand Up @@ -951,6 +955,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
UBI_FM_MIN_POOL_SIZE);

ubi->fm_wl_pool.max_size = ubi->fm_pool.max_size / 2;
ubi->fm_pool_rsv_cnt = need_resv_pool ? ubi->fm_pool.max_size : 0;
ubi->fm_disabled = (!fm_autoconvert || disable_fm) ? 1 : 0;
if (fm_debug)
ubi_enable_dbg_chk_fastmap(ubi);
Expand Down Expand Up @@ -1273,7 +1278,8 @@ static int __init ubi_init(void)
mutex_lock(&ubi_devices_mutex);
err = ubi_attach_mtd_dev(mtd, p->ubi_num,
p->vid_hdr_offs, p->max_beb_per1024,
p->enable_fm == 0);
p->enable_fm == 0,
p->need_resv_pool != 0);
mutex_unlock(&ubi_devices_mutex);
if (err < 0) {
pr_err("UBI error: cannot attach mtd%d\n",
Expand Down Expand Up @@ -1482,6 +1488,18 @@ static int ubi_mtd_param_parse(const char *val, const struct kernel_param *kp)
} else
p->enable_fm = 0;

token = tokens[5];
if (token) {
int err = kstrtoint(token, 10, &p->need_resv_pool);

if (err) {
pr_err("UBI error: bad value for need_resv_pool parameter: %s\n",
token);
return -EINVAL;
}
} else
p->need_resv_pool = 0;

mtd_devs += 1;
return 0;
}
Expand All @@ -1495,6 +1513,7 @@ MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=<name|num|pa
__stringify(CONFIG_MTD_UBI_BEB_LIMIT) ") if 0)\n"
"Optional \"ubi_num\" parameter specifies UBI device number which have to be assigned to the newly created UBI device (assigned automatically by default)\n"
"Optional \"enable_fm\" parameter determines whether to enable fastmap during attach. If the value is non-zero, fastmap is enabled. Default value is 0.\n"
"Optional \"need_resv_pool\" parameter determines whether to reserve pool->max_size pebs during attach. If the value is non-zero, peb reservation is enabled. Default value is 0.\n"
"\n"
"Example 1: mtd=/dev/mtd0 - attach MTD device /dev/mtd0.\n"
"Example 2: mtd=content,1984 mtd=4 - attach MTD device with name \"content\" using VID header offset 1984, and MTD device number 4 with default VID header offset.\n"
Expand Down
3 changes: 2 additions & 1 deletion drivers/mtd/ubi/cdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1041,7 +1041,8 @@ static long ctrl_cdev_ioctl(struct file *file, unsigned int cmd,
*/
mutex_lock(&ubi_devices_mutex);
err = ubi_attach_mtd_dev(mtd, req.ubi_num, req.vid_hdr_offset,
req.max_beb_per1024, !!req.disable_fm);
req.max_beb_per1024, !!req.disable_fm,
!!req.need_resv_pool);
mutex_unlock(&ubi_devices_mutex);
if (err < 0)
put_mtd_device(mtd);
Expand Down
3 changes: 0 additions & 3 deletions drivers/mtd/ubi/eba.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@
#include <linux/err.h>
#include "ubi.h"

/* Number of physical eraseblocks reserved for atomic LEB change operation */
#define EBA_RESERVED_PEBS 1

/**
* struct ubi_eba_entry - structure encoding a single LEB -> PEB association
* @pnum: the physical eraseblock number attached to the LEB
Expand Down
112 changes: 88 additions & 24 deletions drivers/mtd/ubi/fastmap-wl.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ struct ubi_wl_entry *ubi_wl_get_fm_peb(struct ubi_device *ubi, int anchor)
{
struct ubi_wl_entry *e = NULL;

if (!ubi->free.rb_node || (ubi->free_count - ubi->beb_rsvd_pebs < 1))
if (!ubi->free.rb_node)
goto out;

if (anchor)
Expand All @@ -98,43 +98,104 @@ struct ubi_wl_entry *ubi_wl_get_fm_peb(struct ubi_device *ubi, int anchor)
}

/*
* has_enough_free_count - whether ubi has enough free pebs to fill fm pools
* wait_free_pebs_for_pool - wait until there enough free pebs
* @ubi: UBI device description object
*
* Wait and execute do_work until there are enough free pebs, fill pool
* as much as we can. This will reduce pool refilling times, which can
* reduce the fastmap updating frequency.
*/
static void wait_free_pebs_for_pool(struct ubi_device *ubi)
{
struct ubi_fm_pool *wl_pool = &ubi->fm_wl_pool;
struct ubi_fm_pool *pool = &ubi->fm_pool;
int free, expect_free, executed;
/*
* There are at least following free pebs which reserved by UBI:
* 1. WL_RESERVED_PEBS[1]
* 2. EBA_RESERVED_PEBS[1]
* 3. fm pebs - 1: Twice fastmap size deducted by fastmap and fm_anchor
* 4. beb_rsvd_pebs: This value should be get under lock ubi->wl_lock
*/
int reserved = WL_RESERVED_PEBS + EBA_RESERVED_PEBS +
ubi->fm_size / ubi->leb_size - 1 + ubi->fm_pool_rsv_cnt;

do {
spin_lock(&ubi->wl_lock);
free = ubi->free_count;
free += pool->size - pool->used + wl_pool->size - wl_pool->used;
expect_free = reserved + ubi->beb_rsvd_pebs;
spin_unlock(&ubi->wl_lock);

/*
* Break out if there are no works or work is executed failure,
* given the fact that erase_worker will schedule itself when
* -EBUSY is returned from mtd layer caused by system shutdown.
*/
if (do_work(ubi, &executed) || !executed)
break;
} while (free < expect_free);
}

/*
* left_free_count - returns the number of free pebs to fill fm pools
* @ubi: UBI device description object
* @is_wl_pool: whether UBI is filling wear leveling pool
*
* This helper function checks whether there are enough free pebs (deducted
* by fastmap pebs) to fill fm_pool and fm_wl_pool, above rule works after
* there is at least one of free pebs is filled into fm_wl_pool.
* For wear leveling pool, UBI should also reserve free pebs for bad pebs
* handling, because there maybe no enough free pebs for user volumes after
* producing new bad pebs.
* This helper function returns the number of free pebs (deducted
* by fastmap pebs) to fill fm_pool and fm_wl_pool.
*/
static bool has_enough_free_count(struct ubi_device *ubi, bool is_wl_pool)
static int left_free_count(struct ubi_device *ubi)
{
int fm_used = 0; // fastmap non anchor pebs.
int beb_rsvd_pebs;

if (!ubi->free.rb_node)
return false;
return 0;

beb_rsvd_pebs = is_wl_pool ? ubi->beb_rsvd_pebs : 0;
if (ubi->fm_wl_pool.size > 0 && !(ubi->ro_mode || ubi->fm_disabled))
if (!ubi->ro_mode && !ubi->fm_disabled)
fm_used = ubi->fm_size / ubi->leb_size - 1;

return ubi->free_count - beb_rsvd_pebs > fm_used;
return ubi->free_count - fm_used;
}

/*
* can_fill_pools - whether free PEBs will be left after filling pools
* @ubi: UBI device description object
* @free: current number of free PEBs
*
* Return %1 if there are still left free PEBs after filling pools,
* otherwise %0 is returned.
*/
static int can_fill_pools(struct ubi_device *ubi, int free)
{
struct ubi_fm_pool *wl_pool = &ubi->fm_wl_pool;
struct ubi_fm_pool *pool = &ubi->fm_pool;
int pool_need = pool->max_size - pool->size +
wl_pool->max_size - wl_pool->size;

if (free - pool_need < 1)
return 0;

return 1;
}

/**
* ubi_refill_pools - refills all fastmap PEB pools.
* ubi_refill_pools_and_lock - refills all fastmap PEB pools and takes fm locks.
* @ubi: UBI device description object
*/
void ubi_refill_pools(struct ubi_device *ubi)
void ubi_refill_pools_and_lock(struct ubi_device *ubi)
{
struct ubi_fm_pool *wl_pool = &ubi->fm_wl_pool;
struct ubi_fm_pool *pool = &ubi->fm_pool;
struct ubi_wl_entry *e;
int enough;

if (!ubi->ro_mode && !ubi->fm_disabled)
wait_free_pebs_for_pool(ubi);

down_write(&ubi->fm_protect);
down_write(&ubi->work_sem);
down_write(&ubi->fm_eba_sem);

spin_lock(&ubi->wl_lock);

return_unused_pool_pebs(ubi, wl_pool);
Expand All @@ -159,7 +220,7 @@ void ubi_refill_pools(struct ubi_device *ubi)
for (;;) {
enough = 0;
if (pool->size < pool->max_size) {
if (!has_enough_free_count(ubi, false))
if (left_free_count(ubi) <= 0)
break;

e = wl_get_wle(ubi);
Expand All @@ -172,10 +233,13 @@ void ubi_refill_pools(struct ubi_device *ubi)
enough++;

if (wl_pool->size < wl_pool->max_size) {
if (!has_enough_free_count(ubi, true))
int left_free = left_free_count(ubi);

if (left_free <= 0)
break;

e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF);
e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF,
!can_fill_pools(ubi, left_free));
self_check_in_wl_tree(ubi, e, &ubi->free);
rb_erase(&e->u.rb, &ubi->free);
ubi->free_count--;
Expand Down Expand Up @@ -210,7 +274,7 @@ static int produce_free_peb(struct ubi_device *ubi)

while (!ubi->free.rb_node && ubi->works_count) {
dbg_wl("do one work synchronously");
err = do_work(ubi);
err = do_work(ubi, NULL);

if (err)
return err;
Expand Down Expand Up @@ -315,12 +379,12 @@ static bool need_wear_leveling(struct ubi_device *ubi)
if (!e) {
if (!ubi->free.rb_node)
return false;
e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF);
e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF, 0);
ec = e->ec;
} else {
ec = e->ec;
if (ubi->free.rb_node) {
e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF);
e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF, 0);
ec = max(ec, e->ec);
}
}
Expand Down Expand Up @@ -481,7 +545,7 @@ static void ubi_fastmap_close(struct ubi_device *ubi)
static struct ubi_wl_entry *may_reserve_for_fm(struct ubi_device *ubi,
struct ubi_wl_entry *e,
struct rb_root *root) {
if (e && !ubi->fm_disabled && !ubi->fm &&
if (e && !ubi->fm_disabled && !ubi->fm && !ubi->fm_anchor &&
e->pnum < UBI_FM_MAX_START)
e = rb_entry(rb_next(root->rb_node),
struct ubi_wl_entry, u.rb);
Expand Down
Loading

0 comments on commit 2153fc3

Please sign in to comment.