Commit 2153fc3d authored by Linus Torvalds's avatar Linus Torvalds

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
parents 1c410411 75690493
...@@ -447,13 +447,15 @@ int ubiblock_create(struct ubi_volume_info *vi) ...@@ -447,13 +447,15 @@ int ubiblock_create(struct ubi_volume_info *vi)
static void ubiblock_cleanup(struct ubiblock *dev) static void ubiblock_cleanup(struct ubiblock *dev)
{ {
int id = dev->gd->first_minor;
/* Stop new requests to arrive */ /* Stop new requests to arrive */
del_gendisk(dev->gd); del_gendisk(dev->gd);
/* Finally destroy the blk queue */ /* Finally destroy the blk queue */
dev_info(disk_to_dev(dev->gd), "released"); dev_info(disk_to_dev(dev->gd), "released");
put_disk(dev->gd); put_disk(dev->gd);
blk_mq_free_tag_set(&dev->tag_set); 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) int ubiblock_remove(struct ubi_volume_info *vi)
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#define MTD_PARAM_LEN_MAX 64 #define MTD_PARAM_LEN_MAX 64
/* Maximum number of comma-separated items in the 'mtd=' parameter */ /* 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 */ /* Maximum value for the number of bad PEBs per 1024 PEBs */
#define MAX_MTD_UBI_BEB_LIMIT 768 #define MAX_MTD_UBI_BEB_LIMIT 768
...@@ -54,6 +54,7 @@ ...@@ -54,6 +54,7 @@
* @vid_hdr_offs: VID header offset * @vid_hdr_offs: VID header offset
* @max_beb_per1024: maximum expected number of bad PEBs per 1024 PEBs * @max_beb_per1024: maximum expected number of bad PEBs per 1024 PEBs
* @enable_fm: enable fastmap when value is non-zero * @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 { struct mtd_dev_param {
char name[MTD_PARAM_LEN_MAX]; char name[MTD_PARAM_LEN_MAX];
...@@ -61,6 +62,7 @@ struct mtd_dev_param { ...@@ -61,6 +62,7 @@ struct mtd_dev_param {
int vid_hdr_offs; int vid_hdr_offs;
int max_beb_per1024; int max_beb_per1024;
int enable_fm; int enable_fm;
int need_resv_pool;
}; };
/* Numbers of elements set in the @mtd_dev_param array */ /* Numbers of elements set in the @mtd_dev_param array */
...@@ -825,6 +827,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id) ...@@ -825,6 +827,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
* @vid_hdr_offset: VID header offset * @vid_hdr_offset: VID header offset
* @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs * @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs
* @disable_fm: whether disable fastmap * @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 * 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 * 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) ...@@ -840,7 +843,8 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
* @ubi_devices_mutex. * @ubi_devices_mutex.
*/ */
int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, 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; struct ubi_device *ubi;
int i, err; int i, err;
...@@ -951,6 +955,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, ...@@ -951,6 +955,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
UBI_FM_MIN_POOL_SIZE); UBI_FM_MIN_POOL_SIZE);
ubi->fm_wl_pool.max_size = ubi->fm_pool.max_size / 2; 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; ubi->fm_disabled = (!fm_autoconvert || disable_fm) ? 1 : 0;
if (fm_debug) if (fm_debug)
ubi_enable_dbg_chk_fastmap(ubi); ubi_enable_dbg_chk_fastmap(ubi);
...@@ -1273,7 +1278,8 @@ static int __init ubi_init(void) ...@@ -1273,7 +1278,8 @@ static int __init ubi_init(void)
mutex_lock(&ubi_devices_mutex); mutex_lock(&ubi_devices_mutex);
err = ubi_attach_mtd_dev(mtd, p->ubi_num, err = ubi_attach_mtd_dev(mtd, p->ubi_num,
p->vid_hdr_offs, p->max_beb_per1024, 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); mutex_unlock(&ubi_devices_mutex);
if (err < 0) { if (err < 0) {
pr_err("UBI error: cannot attach mtd%d\n", 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) ...@@ -1482,6 +1488,18 @@ static int ubi_mtd_param_parse(const char *val, const struct kernel_param *kp)
} else } else
p->enable_fm = 0; 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; mtd_devs += 1;
return 0; return 0;
} }
...@@ -1495,6 +1513,7 @@ MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=<name|num|pa ...@@ -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" __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 \"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 \"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" "\n"
"Example 1: mtd=/dev/mtd0 - attach MTD device /dev/mtd0.\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" "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, ...@@ -1041,7 +1041,8 @@ static long ctrl_cdev_ioctl(struct file *file, unsigned int cmd,
*/ */
mutex_lock(&ubi_devices_mutex); mutex_lock(&ubi_devices_mutex);
err = ubi_attach_mtd_dev(mtd, req.ubi_num, req.vid_hdr_offset, 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); mutex_unlock(&ubi_devices_mutex);
if (err < 0) if (err < 0)
put_mtd_device(mtd); put_mtd_device(mtd);
......
...@@ -33,9 +33,6 @@ ...@@ -33,9 +33,6 @@
#include <linux/err.h> #include <linux/err.h>
#include "ubi.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 * struct ubi_eba_entry - structure encoding a single LEB -> PEB association
* @pnum: the physical eraseblock number attached to the LEB * @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) ...@@ -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; 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; goto out;
if (anchor) if (anchor)
...@@ -98,43 +98,104 @@ struct ubi_wl_entry *ubi_wl_get_fm_peb(struct ubi_device *ubi, int anchor) ...@@ -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 * @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 * This helper function returns the number of free pebs (deducted
* by fastmap pebs) to fill fm_pool and fm_wl_pool, above rule works after * by fastmap pebs) to fill fm_pool and fm_wl_pool.
* 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.
*/ */
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 fm_used = 0; // fastmap non anchor pebs.
int beb_rsvd_pebs;
if (!ubi->free.rb_node) if (!ubi->free.rb_node)
return false; return 0;
beb_rsvd_pebs = is_wl_pool ? ubi->beb_rsvd_pebs : 0; if (!ubi->ro_mode && !ubi->fm_disabled)
if (ubi->fm_wl_pool.size > 0 && !(ubi->ro_mode || ubi->fm_disabled))
fm_used = ubi->fm_size / ubi->leb_size - 1; 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 * @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 *wl_pool = &ubi->fm_wl_pool;
struct ubi_fm_pool *pool = &ubi->fm_pool; struct ubi_fm_pool *pool = &ubi->fm_pool;
struct ubi_wl_entry *e; struct ubi_wl_entry *e;
int enough; 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); spin_lock(&ubi->wl_lock);
return_unused_pool_pebs(ubi, wl_pool); return_unused_pool_pebs(ubi, wl_pool);
...@@ -159,7 +220,7 @@ void ubi_refill_pools(struct ubi_device *ubi) ...@@ -159,7 +220,7 @@ void ubi_refill_pools(struct ubi_device *ubi)
for (;;) { for (;;) {
enough = 0; enough = 0;
if (pool->size < pool->max_size) { if (pool->size < pool->max_size) {
if (!has_enough_free_count(ubi, false)) if (left_free_count(ubi) <= 0)
break; break;
e = wl_get_wle(ubi); e = wl_get_wle(ubi);
...@@ -172,10 +233,13 @@ void ubi_refill_pools(struct ubi_device *ubi) ...@@ -172,10 +233,13 @@ void ubi_refill_pools(struct ubi_device *ubi)
enough++; enough++;
if (wl_pool->size < wl_pool->max_size) { 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; 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); self_check_in_wl_tree(ubi, e, &ubi->free);
rb_erase(&e->u.rb, &ubi->free); rb_erase(&e->u.rb, &ubi->free);
ubi->free_count--; ubi->free_count--;
...@@ -210,7 +274,7 @@ static int produce_free_peb(struct ubi_device *ubi) ...@@ -210,7 +274,7 @@ static int produce_free_peb(struct ubi_device *ubi)
while (!ubi->free.rb_node && ubi->works_count) { while (!ubi->free.rb_node && ubi->works_count) {
dbg_wl("do one work synchronously"); dbg_wl("do one work synchronously");
err = do_work(ubi); err = do_work(ubi, NULL);
if (err) if (err)
return err; return err;
...@@ -315,12 +379,12 @@ static bool need_wear_leveling(struct ubi_device *ubi) ...@@ -315,12 +379,12 @@ static bool need_wear_leveling(struct ubi_device *ubi)
if (!e) { if (!e) {
if (!ubi->free.rb_node) if (!ubi->free.rb_node)
return false; 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; ec = e->ec;
} else { } else {
ec = e->ec; ec = e->ec;
if (ubi->free.rb_node) { 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); ec = max(ec, e->ec);
} }
} }
...@@ -481,7 +545,7 @@ static void ubi_fastmap_close(struct ubi_device *ubi) ...@@ -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, static struct ubi_wl_entry *may_reserve_for_fm(struct ubi_device *ubi,
struct ubi_wl_entry *e, struct ubi_wl_entry *e,
struct rb_root *root) { 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->pnum < UBI_FM_MAX_START)
e = rb_entry(rb_next(root->rb_node), e = rb_entry(rb_next(root->rb_node),
struct ubi_wl_entry, u.rb); struct ubi_wl_entry, u.rb);
......
...@@ -20,7 +20,7 @@ static inline unsigned long *init_seen(struct ubi_device *ubi) ...@@ -20,7 +20,7 @@ static inline unsigned long *init_seen(struct ubi_device *ubi)
if (!ubi_dbg_chk_fastmap(ubi)) if (!ubi_dbg_chk_fastmap(ubi))
return NULL; return NULL;
ret = bitmap_zalloc(ubi->peb_count, GFP_KERNEL); ret = bitmap_zalloc(ubi->peb_count, GFP_NOFS);
if (!ret) if (!ret)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
...@@ -105,7 +105,7 @@ static struct ubi_vid_io_buf *new_fm_vbuf(struct ubi_device *ubi, int vol_id) ...@@ -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_io_buf *new;
struct ubi_vid_hdr *vh; struct ubi_vid_hdr *vh;
new = ubi_alloc_vid_buf(ubi, GFP_KERNEL); new = ubi_alloc_vid_buf(ubi, GFP_NOFS);
if (!new) if (!new)
goto out; goto out;
...@@ -1389,53 +1389,6 @@ static int ubi_write_fastmap(struct ubi_device *ubi, ...@@ -1389,53 +1389,6 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
return ret; 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. * invalidate_fastmap - destroys a fastmap.
* @ubi: UBI device object * @ubi: UBI device object
...@@ -1462,7 +1415,7 @@ static int invalidate_fastmap(struct ubi_device *ubi) ...@@ -1462,7 +1415,7 @@ static int invalidate_fastmap(struct ubi_device *ubi)
ubi->fm = NULL; ubi->fm = NULL;
ret = -ENOMEM; ret = -ENOMEM;
fm = kzalloc(sizeof(*fm), GFP_KERNEL); fm = kzalloc(sizeof(*fm), GFP_NOFS);
if (!fm) if (!fm)
goto out; goto out;
...@@ -1538,11 +1491,7 @@ int ubi_update_fastmap(struct ubi_device *ubi) ...@@ -1538,11 +1491,7 @@ int ubi_update_fastmap(struct ubi_device *ubi)
struct ubi_fastmap_layout *new_fm, *old_fm; struct ubi_fastmap_layout *new_fm, *old_fm;
struct ubi_wl_entry *tmp_e; struct ubi_wl_entry *tmp_e;
down_write(&ubi->fm_protect); ubi_refill_pools_and_lock(ubi);
down_write(&ubi->work_sem);
down_write(&ubi->fm_eba_sem);
ubi_refill_pools(ubi);
if (ubi->ro_mode || ubi->fm_disabled) { if (ubi->ro_mode || ubi->fm_disabled) {
up_write(&ubi->fm_eba_sem); up_write(&ubi->fm_eba_sem);
...@@ -1551,7 +1500,7 @@ int ubi_update_fastmap(struct ubi_device *ubi) ...@@ -1551,7 +1500,7 @@ int ubi_update_fastmap(struct ubi_device *ubi)
return 0; return 0;
} }
new_fm = kzalloc(sizeof(*new_fm), GFP_KERNEL); new_fm = kzalloc(sizeof(*new_fm), GFP_NOFS);
if (!new_fm) { if (!new_fm) {
up_write(&ubi->fm_eba_sem); up_write(&ubi->fm_eba_sem);
up_write(&ubi->work_sem); up_write(&ubi->work_sem);
...@@ -1576,7 +1525,7 @@ int ubi_update_fastmap(struct ubi_device *ubi) ...@@ -1576,7 +1525,7 @@ int ubi_update_fastmap(struct ubi_device *ubi)
if (!tmp_e) { if (!tmp_e) {
if (old_fm && old_fm->e[i]) { 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) { if (ret < 0) {
ubi_err(ubi, "could not erase old fastmap PEB"); ubi_err(ubi, "could not erase old fastmap PEB");
...@@ -1628,7 +1577,7 @@ int ubi_update_fastmap(struct ubi_device *ubi) ...@@ -1628,7 +1577,7 @@ int ubi_update_fastmap(struct ubi_device *ubi)
if (old_fm) { if (old_fm) {
/* no fresh anchor PEB was found, reuse the old one */ /* no fresh anchor PEB was found, reuse the old one */
if (!tmp_e) { 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) { if (ret < 0) {
ubi_err(ubi, "could not erase old anchor PEB"); ubi_err(ubi, "could not erase old anchor PEB");
...@@ -1640,7 +1589,6 @@ int ubi_update_fastmap(struct ubi_device *ubi) ...@@ -1640,7 +1589,6 @@ int ubi_update_fastmap(struct ubi_device *ubi)
goto err; goto err;
} }
new_fm->e[0] = old_fm->e[0]; new_fm->e[0] = old_fm->e[0];
new_fm->e[0]->ec = ret;
old_fm->e[0] = NULL; old_fm->e[0] = NULL;
} else { } else {
/* we've got a new anchor PEB, return the old one */ /* 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, ...); ...@@ -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_NAME "ubi%d"
#define UBI_DFS_DIR_LEN (3 + 2 + 1) #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. * Error codes returned by the I/O sub-system.
* *
...@@ -491,6 +494,7 @@ struct ubi_debug_info { ...@@ -491,6 +494,7 @@ struct ubi_debug_info {
* @fast_attach: non-zero if UBI was attached by fastmap * @fast_attach: non-zero if UBI was attached by fastmap
* @fm_anchor: The next anchor PEB to use for fastmap * @fm_anchor: The next anchor PEB to use for fastmap
* @fm_do_produce_anchor: If true produce an anchor PEB in wl * @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 * @used: RB-tree of used physical eraseblocks
* @erroneous: RB-tree of erroneous used physical eraseblocks * @erroneous: RB-tree of erroneous used physical eraseblocks
...@@ -601,6 +605,7 @@ struct ubi_device { ...@@ -601,6 +605,7 @@ struct ubi_device {
int fast_attach; int fast_attach;
struct ubi_wl_entry *fm_anchor; struct ubi_wl_entry *fm_anchor;
int fm_do_produce_anchor; int fm_do_produce_anchor;
int fm_pool_rsv_cnt;
/* Wear-leveling sub-system's stuff */ /* Wear-leveling sub-system's stuff */
struct rb_root used; struct rb_root used;
...@@ -902,6 +907,7 @@ int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap, ...@@ -902,6 +907,7 @@ int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap,
struct ubi_attach_info *ai_scan); struct ubi_attach_info *ai_scan);
/* wl.c */ /* 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_get_peb(struct ubi_device *ubi);
int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum, int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum,
int pnum, int torture); int pnum, int torture);
...@@ -914,7 +920,7 @@ struct ubi_wl_entry *ubi_wl_get_fm_peb(struct ubi_device *ubi, int anchor); ...@@ -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 ubi_wl_put_fm_peb(struct ubi_device *ubi, struct ubi_wl_entry *used_e,
int lnum, int torture); int lnum, int torture);
int ubi_is_erase_work(struct ubi_work *wrk); 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_ensure_anchor_pebs(struct ubi_device *ubi);
int ubi_bitflip_check(struct ubi_device *ubi, int pnum, int force_scrub); 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, ...@@ -938,7 +944,7 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
/* build.c */ /* build.c */
int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, 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 disable_fm, bool need_resv_pool);
int ubi_detach_mtd_dev(int ubi_num, int anyway); int ubi_detach_mtd_dev(int ubi_num, int anyway);
struct ubi_device *ubi_get_device(int ubi_num); struct ubi_device *ubi_get_device(int ubi_num);
void ubi_put_device(struct ubi_device *ubi); 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) ...@@ -181,11 +181,13 @@ static void wl_entry_destroy(struct ubi_device *ubi, struct ubi_wl_entry *e)
/** /**
* do_work - do one pending work. * do_work - do one pending work.
* @ubi: UBI device description object * @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 * 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; int err;
struct ubi_work *wrk; struct ubi_work *wrk;
...@@ -203,9 +205,13 @@ static int do_work(struct ubi_device *ubi) ...@@ -203,9 +205,13 @@ static int do_work(struct ubi_device *ubi)
if (list_empty(&ubi->works)) { if (list_empty(&ubi->works)) {
spin_unlock(&ubi->wl_lock); spin_unlock(&ubi->wl_lock);
up_read(&ubi->work_sem); up_read(&ubi->work_sem);
if (executed)
*executed = 0;
return 0; return 0;
} }
if (executed)
*executed = 1;
wrk = list_entry(ubi->works.next, struct ubi_work, list); wrk = list_entry(ubi->works.next, struct ubi_work, list);
list_del(&wrk->list); list_del(&wrk->list);
ubi->works_count -= 1; ubi->works_count -= 1;
...@@ -311,12 +317,14 @@ static void prot_queue_add(struct ubi_device *ubi, struct ubi_wl_entry *e) ...@@ -311,12 +317,14 @@ static void prot_queue_add(struct ubi_device *ubi, struct ubi_wl_entry *e)
* @ubi: UBI device description object * @ubi: UBI device description object
* @root: the RB-tree where to look for * @root: the RB-tree where to look for
* @diff: maximum possible difference from the smallest erase counter * @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 * This function looks for a wear leveling entry with erase counter closest to
* min + @diff, where min is the smallest erase counter. * min + @diff, where min is the smallest erase counter.
*/ */
static struct ubi_wl_entry *find_wl_entry(struct ubi_device *ubi, 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 rb_node *p;
struct ubi_wl_entry *e; struct ubi_wl_entry *e;
...@@ -330,9 +338,11 @@ static struct ubi_wl_entry *find_wl_entry(struct ubi_device *ubi, ...@@ -330,9 +338,11 @@ static struct ubi_wl_entry *find_wl_entry(struct ubi_device *ubi,
struct ubi_wl_entry *e1; struct ubi_wl_entry *e1;
e1 = rb_entry(p, struct ubi_wl_entry, u.rb); 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; p = p->rb_left;
else { } else {
p = p->rb_right; p = p->rb_right;
e = e1; e = e1;
} }
...@@ -361,12 +371,15 @@ static struct ubi_wl_entry *find_mean_wl_entry(struct ubi_device *ubi, ...@@ -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) { if (last->ec - first->ec < WL_FREE_MAX_DIFF) {
e = rb_entry(root->rb_node, struct ubi_wl_entry, u.rb); 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 * If no fastmap has been written and fm_anchor is not
* WL entry such that fastmap can use the anchor PEB later. */ * 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); e = may_reserve_for_fm(ubi, e, root);
} else } 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; return e;
} }
...@@ -427,7 +440,7 @@ static int prot_queue_del(struct ubi_device *ubi, int pnum) ...@@ -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 * @ubi: UBI device description object
* @e: the physical eraseblock to erase * @e: the physical eraseblock to erase
* @torture: if the physical eraseblock has to be tortured * @torture: if the physical eraseblock has to be tortured
...@@ -435,8 +448,7 @@ static int prot_queue_del(struct ubi_device *ubi, int pnum) ...@@ -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 * This function returns zero in case of success and a negative error code in
* case of failure. * case of failure.
*/ */
static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, int ubi_sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, int torture)
int torture)
{ {
int err; int err;
struct ubi_ec_hdr *ec_hdr; struct ubi_ec_hdr *ec_hdr;
...@@ -1040,7 +1052,7 @@ static int ensure_wear_leveling(struct ubi_device *ubi, int nested) ...@@ -1040,7 +1052,7 @@ static int ensure_wear_leveling(struct ubi_device *ubi, int nested)
* %UBI_WL_THRESHOLD. * %UBI_WL_THRESHOLD.
*/ */
e1 = rb_entry(rb_first(&ubi->used), struct ubi_wl_entry, u.rb); 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)) if (!(e2->ec - e1->ec >= UBI_WL_THRESHOLD))
goto out_unlock; goto out_unlock;
...@@ -1094,7 +1106,7 @@ static int __erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk) ...@@ -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", dbg_wl("erase PEB %d EC %d LEB %d:%d",
pnum, e->ec, wl_wrk->vol_id, wl_wrk->lnum); 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) { if (!err) {
spin_lock(&ubi->wl_lock); spin_lock(&ubi->wl_lock);
...@@ -1686,7 +1698,7 @@ int ubi_thread(void *u) ...@@ -1686,7 +1698,7 @@ int ubi_thread(void *u)
} }
spin_unlock(&ubi->wl_lock); spin_unlock(&ubi->wl_lock);
err = do_work(ubi); err = do_work(ubi, NULL);
if (err) { if (err) {
ubi_err(ubi, "%s: work failed with error code %d", ubi_err(ubi, "%s: work failed with error code %d",
ubi->bgt_name, err); ubi->bgt_name, err);
...@@ -1749,7 +1761,7 @@ static int erase_aeb(struct ubi_device *ubi, struct ubi_ainf_peb *aeb, bool sync ...@@ -1749,7 +1761,7 @@ static int erase_aeb(struct ubi_device *ubi, struct ubi_ainf_peb *aeb, bool sync
ubi->lookuptbl[e->pnum] = e; ubi->lookuptbl[e->pnum] = e;
if (sync) { if (sync) {
err = sync_erase(ubi, e, false); err = ubi_sync_erase(ubi, e, false);
if (err) if (err)
goto out_free; goto out_free;
...@@ -2071,7 +2083,7 @@ static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi) ...@@ -2071,7 +2083,7 @@ static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi)
{ {
struct ubi_wl_entry *e; 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); self_check_in_wl_tree(ubi, e, &ubi->free);
ubi->free_count--; ubi->free_count--;
ubi_assert(ubi->free_count >= 0); ubi_assert(ubi->free_count >= 0);
...@@ -2097,7 +2109,7 @@ static int produce_free_peb(struct ubi_device *ubi) ...@@ -2097,7 +2109,7 @@ static int produce_free_peb(struct ubi_device *ubi)
spin_unlock(&ubi->wl_lock); spin_unlock(&ubi->wl_lock);
dbg_wl("do one work synchronously"); dbg_wl("do one work synchronously");
err = do_work(ubi); err = do_work(ubi, NULL);
spin_lock(&ubi->wl_lock); spin_lock(&ubi->wl_lock);
if (err) if (err)
......
...@@ -10,8 +10,10 @@ static bool need_wear_leveling(struct ubi_device *ubi); ...@@ -10,8 +10,10 @@ static bool need_wear_leveling(struct ubi_device *ubi);
static void ubi_fastmap_close(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) static inline void ubi_fastmap_init(struct ubi_device *ubi, int *count)
{ {
/* Reserve enough LEBs to store two fastmaps. */ if (ubi->fm_disabled)
*count += (ubi->fm_size / ubi->leb_size) * 2; 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); INIT_WORK(&ubi->fm_work, update_fastmap_work_fn);
} }
static struct ubi_wl_entry *may_reserve_for_fm(struct ubi_device *ubi, 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, ...@@ -725,7 +725,7 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
struct inode *inode = d_inode(old_dentry); struct inode *inode = d_inode(old_dentry);
struct ubifs_inode *ui = ubifs_inode(inode); struct ubifs_inode *ui = ubifs_inode(inode);
struct ubifs_inode *dir_ui = ubifs_inode(dir); 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, struct ubifs_budget_req req = { .new_dent = 1, .dirtied_ino = 2,
.dirtied_ino_d = ALIGN(ui->data_len, 8) }; .dirtied_ino_d = ALIGN(ui->data_len, 8) };
struct fscrypt_name nm; struct fscrypt_name nm;
...@@ -749,6 +749,8 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir, ...@@ -749,6 +749,8 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
if (err) if (err)
return err; return err;
sz_change = CALC_DENT_SIZE(fname_len(&nm));
err = dbg_check_synced_i_size(c, inode); err = dbg_check_synced_i_size(c, inode);
if (err) if (err)
goto out_fname; goto out_fname;
......
...@@ -1375,6 +1375,9 @@ static inline int mctime_update_needed(const struct inode *inode, ...@@ -1375,6 +1375,9 @@ static inline int mctime_update_needed(const struct inode *inode,
/** /**
* ubifs_update_time - update time of inode. * ubifs_update_time - update time of inode.
* @inode: inode to update * @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. * This function updates time of the inode.
*/ */
......
...@@ -1607,6 +1607,7 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *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)", ubifs_err(c, "bad data node (block %u, inode %lu)",
blk, inode->i_ino); blk, inode->i_ino);
ubifs_dump_node(c, dn, dn_size); ubifs_dump_node(c, dn, dn_size);
err = -EUCLEAN;
goto out_free; goto out_free;
} }
......
...@@ -919,8 +919,10 @@ static void free_buds(struct ubifs_info *c) ...@@ -919,8 +919,10 @@ static void free_buds(struct ubifs_info *c)
{ {
struct ubifs_bud *bud, *n; 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); kfree(bud);
}
} }
/** /**
...@@ -1189,6 +1191,7 @@ static void destroy_journal(struct ubifs_info *c) ...@@ -1189,6 +1191,7 @@ static void destroy_journal(struct ubifs_info *c)
bud = list_entry(c->old_buds.next, struct ubifs_bud, list); bud = list_entry(c->old_buds.next, struct ubifs_bud, list);
list_del(&bud->list); list_del(&bud->list);
kfree(bud->log_hash);
kfree(bud); kfree(bud);
} }
ubifs_destroy_idx_gc(c); ubifs_destroy_idx_gc(c);
......
...@@ -65,6 +65,7 @@ static void do_insert_old_idx(struct ubifs_info *c, ...@@ -65,6 +65,7 @@ static void do_insert_old_idx(struct ubifs_info *c,
else { else {
ubifs_err(c, "old idx added twice!"); ubifs_err(c, "old idx added twice!");
kfree(old_idx); kfree(old_idx);
return;
} }
} }
rb_link_node(&old_idx->rb, parent, p); rb_link_node(&old_idx->rb, parent, p);
......
...@@ -248,6 +248,7 @@ enum { ...@@ -248,6 +248,7 @@ enum {
* @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs * @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs
* @padding: reserved for future, not used, has to be zeroed * @padding: reserved for future, not used, has to be zeroed
* @disable_fm: whether disable fastmap * @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 * 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 * parameters it has to use. The number which should be assigned to the new UBI
...@@ -293,7 +294,8 @@ struct ubi_attach_req { ...@@ -293,7 +294,8 @@ struct ubi_attach_req {
__s32 vid_hdr_offset; __s32 vid_hdr_offset;
__s16 max_beb_per1024; __s16 max_beb_per1024;
__s8 disable_fm; __s8 disable_fm;
__s8 padding[9]; __s8 need_resv_pool;
__s8 padding[8];
}; };
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment