mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-23 20:24:12 +08:00
This pull request contains updates for UBI and UBIFS
- UBI Fastmap improvements - Minor issues found by static analysis bots in both UBI and UBIFS - Fix for wrong dentry length UBIFS in fscrypt mode -----BEGIN PGP SIGNATURE----- iQJKBAABCAA0FiEEdgfidid8lnn52cLTZvlZhesYu8EFAmVHbHYWHHJpY2hhcmRA c2lnbWEtc3Rhci5hdAAKCRBm+VmF6xi7wSdwEACWV8rZGKamOgnidf5WR8ycQUFd mPnTwPaRAZNjCq5LgeoMPcV1osucWb+vN+dO7o3KQSk2N/UF1iC6Lhs6giMj8MuU ZJ4v6bfPB0m0d5cQy+X8D1NH/yTQ7vzJrpuu3xDJeywLZFt7P6bSJRlX36Zr6WWC BVmVKeiqaB0qnlkpTf4BkIbgXR8Pcv/pXkYjsRcHnSJzpLQD6ByBErQwL2LKGUkE 3ULajJW2oRs8FA6YWfzTcARS3BOpIPJtUyA8RFi8uWKWks16R1Vg4FFfjMVoTzf9 Fe6f2KB+SQxX4dzhGMuVQTGgJuRVacktiL6fLHzvpE2mcKY7E5/b0F39P3BnFhID 2QtojZMXtgFpqz/Vg2W1vNrvHrN++e0sVgqIoxrN8PaE4ciP0yhkhoTEQwx1HWu5 qIxNH8j6USMnfybLgyphVDIoLXzOzhQqY5RWzIYN454jsFg9PeNPkqB3SH9h63j+ nZZ8v+PHeq2wxyYTg4vV+GPKcAlQ/XdKzM9w2Hh+Gp+XIgcO9i4Ag5Qku2lnjPY3 HvKq9t19YSDZkwMnmqeUY/hPB5OK9c0ukirsipQ6ACcQYj0h5hpVHlBGhX8r2cc2 EhdPNP11FhnxR3EcjBDBtSYAKmBs/LDT7gYrjo0013ciMZpVHFREx8G8Icp97366 spp8j/xwAAOyvw6/xA== =fJhk -----END PGP SIGNATURE----- Merge tag 'ubifs-for-linus-6.7-rc1' of git://git.kernel.org/pub/scm/linux/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
This commit is contained in:
commit
2153fc3d68
@ -447,13 +447,15 @@ out_unlock:
|
||||
|
||||
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)
|
||||
|
@ -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
|
||||
@ -54,6 +54,7 @@
|
||||
* @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];
|
||||
@ -61,6 +62,7 @@ struct mtd_dev_param {
|
||||
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 */
|
||||
@ -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
|
||||
@ -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;
|
||||
@ -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);
|
||||
@ -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",
|
||||
@ -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;
|
||||
}
|
||||
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
@ -98,43 +98,104 @@ out:
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
* @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.
|
||||
* 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 bool has_enough_free_count(struct ubi_device *ubi, bool is_wl_pool)
|
||||
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
|
||||
*
|
||||
* This helper function returns the number of free pebs (deducted
|
||||
* by fastmap pebs) to fill fm_pool and fm_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);
|
||||
@ -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);
|
||||
@ -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--;
|
||||
@ -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;
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
|
@ -20,7 +20,7 @@ static inline unsigned long *init_seen(struct ubi_device *ubi)
|
||||
if (!ubi_dbg_chk_fastmap(ubi))
|
||||
return NULL;
|
||||
|
||||
ret = bitmap_zalloc(ubi->peb_count, GFP_KERNEL);
|
||||
ret = bitmap_zalloc(ubi->peb_count, GFP_NOFS);
|
||||
if (!ret)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
@ -105,7 +105,7 @@ static struct ubi_vid_io_buf *new_fm_vbuf(struct ubi_device *ubi, int vol_id)
|
||||
struct ubi_vid_io_buf *new;
|
||||
struct ubi_vid_hdr *vh;
|
||||
|
||||
new = ubi_alloc_vid_buf(ubi, GFP_KERNEL);
|
||||
new = ubi_alloc_vid_buf(ubi, GFP_NOFS);
|
||||
if (!new)
|
||||
goto out;
|
||||
|
||||
@ -1389,53 +1389,6 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* erase_block - Manually erase a PEB.
|
||||
* @ubi: UBI device object
|
||||
* @pnum: PEB to be erased
|
||||
*
|
||||
* Returns the new EC value on success, < 0 indicates an internal error.
|
||||
*/
|
||||
static int erase_block(struct ubi_device *ubi, int pnum)
|
||||
{
|
||||
int ret;
|
||||
struct ubi_ec_hdr *ec_hdr;
|
||||
long long ec;
|
||||
|
||||
ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
|
||||
if (!ec_hdr)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = ubi_io_read_ec_hdr(ubi, pnum, ec_hdr, 0);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
else if (ret && ret != UBI_IO_BITFLIPS) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ubi_io_sync_erase(ubi, pnum, 0);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ec = be64_to_cpu(ec_hdr->ec);
|
||||
ec += ret;
|
||||
if (ec > UBI_MAX_ERASECOUNTER) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ec_hdr->ec = cpu_to_be64(ec);
|
||||
ret = ubi_io_write_ec_hdr(ubi, pnum, ec_hdr);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = ec;
|
||||
out:
|
||||
kfree(ec_hdr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* invalidate_fastmap - destroys a fastmap.
|
||||
* @ubi: UBI device object
|
||||
@ -1462,7 +1415,7 @@ static int invalidate_fastmap(struct ubi_device *ubi)
|
||||
ubi->fm = NULL;
|
||||
|
||||
ret = -ENOMEM;
|
||||
fm = kzalloc(sizeof(*fm), GFP_KERNEL);
|
||||
fm = kzalloc(sizeof(*fm), GFP_NOFS);
|
||||
if (!fm)
|
||||
goto out;
|
||||
|
||||
@ -1538,11 +1491,7 @@ int ubi_update_fastmap(struct ubi_device *ubi)
|
||||
struct ubi_fastmap_layout *new_fm, *old_fm;
|
||||
struct ubi_wl_entry *tmp_e;
|
||||
|
||||
down_write(&ubi->fm_protect);
|
||||
down_write(&ubi->work_sem);
|
||||
down_write(&ubi->fm_eba_sem);
|
||||
|
||||
ubi_refill_pools(ubi);
|
||||
ubi_refill_pools_and_lock(ubi);
|
||||
|
||||
if (ubi->ro_mode || ubi->fm_disabled) {
|
||||
up_write(&ubi->fm_eba_sem);
|
||||
@ -1551,7 +1500,7 @@ int ubi_update_fastmap(struct ubi_device *ubi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
new_fm = kzalloc(sizeof(*new_fm), GFP_KERNEL);
|
||||
new_fm = kzalloc(sizeof(*new_fm), GFP_NOFS);
|
||||
if (!new_fm) {
|
||||
up_write(&ubi->fm_eba_sem);
|
||||
up_write(&ubi->work_sem);
|
||||
@ -1576,7 +1525,7 @@ int ubi_update_fastmap(struct ubi_device *ubi)
|
||||
|
||||
if (!tmp_e) {
|
||||
if (old_fm && old_fm->e[i]) {
|
||||
ret = erase_block(ubi, old_fm->e[i]->pnum);
|
||||
ret = ubi_sync_erase(ubi, old_fm->e[i], 0);
|
||||
if (ret < 0) {
|
||||
ubi_err(ubi, "could not erase old fastmap PEB");
|
||||
|
||||
@ -1628,7 +1577,7 @@ int ubi_update_fastmap(struct ubi_device *ubi)
|
||||
if (old_fm) {
|
||||
/* no fresh anchor PEB was found, reuse the old one */
|
||||
if (!tmp_e) {
|
||||
ret = erase_block(ubi, old_fm->e[0]->pnum);
|
||||
ret = ubi_sync_erase(ubi, old_fm->e[0], 0);
|
||||
if (ret < 0) {
|
||||
ubi_err(ubi, "could not erase old anchor PEB");
|
||||
|
||||
@ -1640,7 +1589,6 @@ int ubi_update_fastmap(struct ubi_device *ubi)
|
||||
goto err;
|
||||
}
|
||||
new_fm->e[0] = old_fm->e[0];
|
||||
new_fm->e[0]->ec = ret;
|
||||
old_fm->e[0] = NULL;
|
||||
} else {
|
||||
/* we've got a new anchor PEB, return the old one */
|
||||
|
@ -82,6 +82,9 @@ 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.
|
||||
*
|
||||
@ -491,6 +494,7 @@ struct ubi_debug_info {
|
||||
* @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
|
||||
@ -601,6 +605,7 @@ struct ubi_device {
|
||||
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;
|
||||
@ -902,6 +907,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);
|
||||
@ -914,7 +920,7 @@ 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);
|
||||
|
||||
@ -938,7 +944,7 @@ 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,
|
||||
bool disable_fm);
|
||||
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);
|
||||
|
@ -181,11 +181,13 @@ static void wl_entry_destroy(struct ubi_device *ubi, struct ubi_wl_entry *e)
|
||||
/**
|
||||
* do_work - do one pending work.
|
||||
* @ubi: UBI device description object
|
||||
* @executed: whether there is one work is executed
|
||||
*
|
||||
* This function returns zero in case of success and a negative error code in
|
||||
* case of failure.
|
||||
* case of failure. If @executed is not NULL and there is one work executed,
|
||||
* @executed is set as %1, otherwise @executed is set as %0.
|
||||
*/
|
||||
static int do_work(struct ubi_device *ubi)
|
||||
static int do_work(struct ubi_device *ubi, int *executed)
|
||||
{
|
||||
int err;
|
||||
struct ubi_work *wrk;
|
||||
@ -203,9 +205,13 @@ static int do_work(struct ubi_device *ubi)
|
||||
if (list_empty(&ubi->works)) {
|
||||
spin_unlock(&ubi->wl_lock);
|
||||
up_read(&ubi->work_sem);
|
||||
if (executed)
|
||||
*executed = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (executed)
|
||||
*executed = 1;
|
||||
wrk = list_entry(ubi->works.next, struct ubi_work, list);
|
||||
list_del(&wrk->list);
|
||||
ubi->works_count -= 1;
|
||||
@ -311,12 +317,14 @@ static void prot_queue_add(struct ubi_device *ubi, struct ubi_wl_entry *e)
|
||||
* @ubi: UBI device description object
|
||||
* @root: the RB-tree where to look for
|
||||
* @diff: maximum possible difference from the smallest erase counter
|
||||
* @pick_max: pick PEB even its erase counter beyonds 'min_ec + @diff'
|
||||
*
|
||||
* This function looks for a wear leveling entry with erase counter closest to
|
||||
* min + @diff, where min is the smallest erase counter.
|
||||
*/
|
||||
static struct ubi_wl_entry *find_wl_entry(struct ubi_device *ubi,
|
||||
struct rb_root *root, int diff)
|
||||
struct rb_root *root, int diff,
|
||||
int pick_max)
|
||||
{
|
||||
struct rb_node *p;
|
||||
struct ubi_wl_entry *e;
|
||||
@ -330,9 +338,11 @@ static struct ubi_wl_entry *find_wl_entry(struct ubi_device *ubi,
|
||||
struct ubi_wl_entry *e1;
|
||||
|
||||
e1 = rb_entry(p, struct ubi_wl_entry, u.rb);
|
||||
if (e1->ec >= max)
|
||||
if (e1->ec >= max) {
|
||||
if (pick_max)
|
||||
e = e1;
|
||||
p = p->rb_left;
|
||||
else {
|
||||
} else {
|
||||
p = p->rb_right;
|
||||
e = e1;
|
||||
}
|
||||
@ -361,12 +371,15 @@ static struct ubi_wl_entry *find_mean_wl_entry(struct ubi_device *ubi,
|
||||
if (last->ec - first->ec < WL_FREE_MAX_DIFF) {
|
||||
e = rb_entry(root->rb_node, struct ubi_wl_entry, u.rb);
|
||||
|
||||
/* If no fastmap has been written and this WL entry can be used
|
||||
* as anchor PEB, hold it back and return the second best
|
||||
* WL entry such that fastmap can use the anchor PEB later. */
|
||||
/*
|
||||
* If no fastmap has been written and fm_anchor is not
|
||||
* reserved and this WL entry can be used as anchor PEB
|
||||
* hold it back and return the second best WL entry such
|
||||
* that fastmap can use the anchor PEB later.
|
||||
*/
|
||||
e = may_reserve_for_fm(ubi, e, root);
|
||||
} else
|
||||
e = find_wl_entry(ubi, root, WL_FREE_MAX_DIFF/2);
|
||||
e = find_wl_entry(ubi, root, WL_FREE_MAX_DIFF/2, 0);
|
||||
|
||||
return e;
|
||||
}
|
||||
@ -427,7 +440,7 @@ static int prot_queue_del(struct ubi_device *ubi, int pnum)
|
||||
}
|
||||
|
||||
/**
|
||||
* sync_erase - synchronously erase a physical eraseblock.
|
||||
* ubi_sync_erase - synchronously erase a physical eraseblock.
|
||||
* @ubi: UBI device description object
|
||||
* @e: the physical eraseblock to erase
|
||||
* @torture: if the physical eraseblock has to be tortured
|
||||
@ -435,8 +448,7 @@ static int prot_queue_del(struct ubi_device *ubi, int pnum)
|
||||
* This function returns zero in case of success and a negative error code in
|
||||
* case of failure.
|
||||
*/
|
||||
static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
|
||||
int torture)
|
||||
int ubi_sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, int torture)
|
||||
{
|
||||
int err;
|
||||
struct ubi_ec_hdr *ec_hdr;
|
||||
@ -1040,7 +1052,7 @@ static int ensure_wear_leveling(struct ubi_device *ubi, int nested)
|
||||
* %UBI_WL_THRESHOLD.
|
||||
*/
|
||||
e1 = rb_entry(rb_first(&ubi->used), struct ubi_wl_entry, u.rb);
|
||||
e2 = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF);
|
||||
e2 = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF, 0);
|
||||
|
||||
if (!(e2->ec - e1->ec >= UBI_WL_THRESHOLD))
|
||||
goto out_unlock;
|
||||
@ -1094,7 +1106,7 @@ static int __erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk)
|
||||
dbg_wl("erase PEB %d EC %d LEB %d:%d",
|
||||
pnum, e->ec, wl_wrk->vol_id, wl_wrk->lnum);
|
||||
|
||||
err = sync_erase(ubi, e, wl_wrk->torture);
|
||||
err = ubi_sync_erase(ubi, e, wl_wrk->torture);
|
||||
if (!err) {
|
||||
spin_lock(&ubi->wl_lock);
|
||||
|
||||
@ -1686,7 +1698,7 @@ int ubi_thread(void *u)
|
||||
}
|
||||
spin_unlock(&ubi->wl_lock);
|
||||
|
||||
err = do_work(ubi);
|
||||
err = do_work(ubi, NULL);
|
||||
if (err) {
|
||||
ubi_err(ubi, "%s: work failed with error code %d",
|
||||
ubi->bgt_name, err);
|
||||
@ -1749,7 +1761,7 @@ static int erase_aeb(struct ubi_device *ubi, struct ubi_ainf_peb *aeb, bool sync
|
||||
ubi->lookuptbl[e->pnum] = e;
|
||||
|
||||
if (sync) {
|
||||
err = sync_erase(ubi, e, false);
|
||||
err = ubi_sync_erase(ubi, e, false);
|
||||
if (err)
|
||||
goto out_free;
|
||||
|
||||
@ -2071,7 +2083,7 @@ static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi)
|
||||
{
|
||||
struct ubi_wl_entry *e;
|
||||
|
||||
e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF);
|
||||
e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF, 0);
|
||||
self_check_in_wl_tree(ubi, e, &ubi->free);
|
||||
ubi->free_count--;
|
||||
ubi_assert(ubi->free_count >= 0);
|
||||
@ -2097,7 +2109,7 @@ static int produce_free_peb(struct ubi_device *ubi)
|
||||
spin_unlock(&ubi->wl_lock);
|
||||
|
||||
dbg_wl("do one work synchronously");
|
||||
err = do_work(ubi);
|
||||
err = do_work(ubi, NULL);
|
||||
|
||||
spin_lock(&ubi->wl_lock);
|
||||
if (err)
|
||||
|
@ -10,8 +10,10 @@ static bool need_wear_leveling(struct ubi_device *ubi);
|
||||
static void ubi_fastmap_close(struct ubi_device *ubi);
|
||||
static inline void ubi_fastmap_init(struct ubi_device *ubi, int *count)
|
||||
{
|
||||
/* Reserve enough LEBs to store two fastmaps. */
|
||||
*count += (ubi->fm_size / ubi->leb_size) * 2;
|
||||
if (ubi->fm_disabled)
|
||||
ubi->fm_pool_rsv_cnt = 0;
|
||||
/* Reserve enough LEBs to store two fastmaps and to fill pools. */
|
||||
*count += (ubi->fm_size / ubi->leb_size) * 2 + ubi->fm_pool_rsv_cnt;
|
||||
INIT_WORK(&ubi->fm_work, update_fastmap_work_fn);
|
||||
}
|
||||
static struct ubi_wl_entry *may_reserve_for_fm(struct ubi_device *ubi,
|
||||
|
@ -725,7 +725,7 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
|
||||
struct inode *inode = d_inode(old_dentry);
|
||||
struct ubifs_inode *ui = ubifs_inode(inode);
|
||||
struct ubifs_inode *dir_ui = ubifs_inode(dir);
|
||||
int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len);
|
||||
int err, sz_change;
|
||||
struct ubifs_budget_req req = { .new_dent = 1, .dirtied_ino = 2,
|
||||
.dirtied_ino_d = ALIGN(ui->data_len, 8) };
|
||||
struct fscrypt_name nm;
|
||||
@ -749,6 +749,8 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
sz_change = CALC_DENT_SIZE(fname_len(&nm));
|
||||
|
||||
err = dbg_check_synced_i_size(c, inode);
|
||||
if (err)
|
||||
goto out_fname;
|
||||
|
@ -1375,6 +1375,9 @@ static inline int mctime_update_needed(const struct inode *inode,
|
||||
/**
|
||||
* ubifs_update_time - update time of inode.
|
||||
* @inode: inode to update
|
||||
* @time: timespec structure to hold the current time value
|
||||
* @flags: time updating control flag determines updating
|
||||
* which time fields of @inode
|
||||
*
|
||||
* This function updates time of the inode.
|
||||
*/
|
||||
|
@ -1607,6 +1607,7 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode,
|
||||
ubifs_err(c, "bad data node (block %u, inode %lu)",
|
||||
blk, inode->i_ino);
|
||||
ubifs_dump_node(c, dn, dn_size);
|
||||
err = -EUCLEAN;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
|
@ -919,8 +919,10 @@ static void free_buds(struct ubifs_info *c)
|
||||
{
|
||||
struct ubifs_bud *bud, *n;
|
||||
|
||||
rbtree_postorder_for_each_entry_safe(bud, n, &c->buds, rb)
|
||||
rbtree_postorder_for_each_entry_safe(bud, n, &c->buds, rb) {
|
||||
kfree(bud->log_hash);
|
||||
kfree(bud);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1189,6 +1191,7 @@ static void destroy_journal(struct ubifs_info *c)
|
||||
|
||||
bud = list_entry(c->old_buds.next, struct ubifs_bud, list);
|
||||
list_del(&bud->list);
|
||||
kfree(bud->log_hash);
|
||||
kfree(bud);
|
||||
}
|
||||
ubifs_destroy_idx_gc(c);
|
||||
|
@ -65,6 +65,7 @@ static void do_insert_old_idx(struct ubifs_info *c,
|
||||
else {
|
||||
ubifs_err(c, "old idx added twice!");
|
||||
kfree(old_idx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
rb_link_node(&old_idx->rb, parent, p);
|
||||
|
@ -248,6 +248,7 @@ enum {
|
||||
* @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs
|
||||
* @padding: reserved for future, not used, has to be zeroed
|
||||
* @disable_fm: whether disable fastmap
|
||||
* @need_resv_pool: whether reserve free pebs for filling pool/wl_pool
|
||||
*
|
||||
* This data structure is used to specify MTD device UBI has to attach and the
|
||||
* parameters it has to use. The number which should be assigned to the new UBI
|
||||
@ -293,7 +294,8 @@ struct ubi_attach_req {
|
||||
__s32 vid_hdr_offset;
|
||||
__s16 max_beb_per1024;
|
||||
__s8 disable_fm;
|
||||
__s8 padding[9];
|
||||
__s8 need_resv_pool;
|
||||
__s8 padding[8];
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user