UBI: prepare attach and detach functions
Prepare the attach and detach functions to by used outside of module initialization: * detach function checks reference count before detaching * it kills the background thread as well Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
This commit is contained in:
parent
e73f4459d9
commit
cdfa788acd
|
@ -40,6 +40,7 @@
|
||||||
#include <linux/stat.h>
|
#include <linux/stat.h>
|
||||||
#include <linux/miscdevice.h>
|
#include <linux/miscdevice.h>
|
||||||
#include <linux/log2.h>
|
#include <linux/log2.h>
|
||||||
|
#include <linux/kthread.h>
|
||||||
#include "ubi.h"
|
#include "ubi.h"
|
||||||
|
|
||||||
/* Maximum length of the 'mtd=' parameter */
|
/* Maximum length of the 'mtd=' parameter */
|
||||||
|
@ -83,6 +84,9 @@ static struct miscdevice ubi_ctrl_cdev = {
|
||||||
/* All UBI devices in system */
|
/* All UBI devices in system */
|
||||||
static struct ubi_device *ubi_devices[UBI_MAX_DEVICES];
|
static struct ubi_device *ubi_devices[UBI_MAX_DEVICES];
|
||||||
|
|
||||||
|
/* Serializes UBI devices creations and removals */
|
||||||
|
DEFINE_MUTEX(ubi_devices_mutex);
|
||||||
|
|
||||||
/* Protects @ubi_devices and @ubi->ref_count */
|
/* Protects @ubi_devices and @ubi->ref_count */
|
||||||
static DEFINE_SPINLOCK(ubi_devices_lock);
|
static DEFINE_SPINLOCK(ubi_devices_lock);
|
||||||
|
|
||||||
|
@ -192,7 +196,7 @@ struct ubi_device *ubi_get_by_major(int major)
|
||||||
* @major: major number
|
* @major: major number
|
||||||
*
|
*
|
||||||
* This function searches UBI device number object by its major number. If UBI
|
* This function searches UBI device number object by its major number. If UBI
|
||||||
* device was not found, this function returns -ENODEV, othewise the UBI device
|
* device was not found, this function returns -ENODEV, otherwise the UBI device
|
||||||
* number is returned.
|
* number is returned.
|
||||||
*/
|
*/
|
||||||
int ubi_major2num(int major)
|
int ubi_major2num(int major)
|
||||||
|
@ -485,9 +489,9 @@ out_si:
|
||||||
* assumed:
|
* assumed:
|
||||||
* o EC header is always at offset zero - this cannot be changed;
|
* o EC header is always at offset zero - this cannot be changed;
|
||||||
* o VID header starts just after the EC header at the closest address
|
* o VID header starts just after the EC header at the closest address
|
||||||
* aligned to @io->@hdrs_min_io_size;
|
* aligned to @io->hdrs_min_io_size;
|
||||||
* o data starts just after the VID header at the closest address aligned to
|
* o data starts just after the VID header at the closest address aligned to
|
||||||
* @io->@min_io_size
|
* @io->min_io_size
|
||||||
*
|
*
|
||||||
* 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.
|
||||||
|
@ -508,6 +512,9 @@ static int io_init(struct ubi_device *ubi)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ubi->vid_hdr_offset < 0 || ubi->leb_start < ubi->vid_hdr_offset)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note, in this implementation we support MTD devices with 0x7FFFFFFF
|
* Note, in this implementation we support MTD devices with 0x7FFFFFFF
|
||||||
* physical eraseblocks maximum.
|
* physical eraseblocks maximum.
|
||||||
|
@ -616,84 +623,62 @@ static int io_init(struct ubi_device *ubi)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* attach_mtd_dev - attach an MTD device.
|
* ubi_attach_mtd_dev - attach an MTD device.
|
||||||
* @mtd_dev: MTD device name or number string
|
* @mtd_dev: MTD device description object
|
||||||
* @vid_hdr_offset: VID header offset
|
* @vid_hdr_offset: VID header offset
|
||||||
* @data_offset: data offset
|
* @data_offset: data offset
|
||||||
*
|
*
|
||||||
* This function attaches an MTD device to UBI. It first treats @mtd_dev as the
|
* This function attaches an MTD device to UBI. It first treats @mtd_dev as the
|
||||||
* MTD device name, and tries to open it by this name. If it is unable to open,
|
* MTD device name, and tries to open it by this name. If it is unable to open,
|
||||||
* it tries to convert @mtd_dev to an integer and open the MTD device by its
|
* it tries to convert @mtd_dev to an integer and open the MTD device by its
|
||||||
* number. Returns zero in case of success and a negative error code in case of
|
* number. Returns new UBI device's number in case of success and a negative
|
||||||
* failure.
|
* error code in case of failure.
|
||||||
|
*
|
||||||
|
* Note, the invocations of this function has to be serialized by the
|
||||||
|
* @ubi_devices_mutex.
|
||||||
*/
|
*/
|
||||||
static int attach_mtd_dev(const char *mtd_dev, int vid_hdr_offset,
|
int ubi_attach_mtd_dev(struct mtd_info *mtd, int vid_hdr_offset,
|
||||||
int data_offset)
|
int data_offset)
|
||||||
{
|
{
|
||||||
struct ubi_device *ubi;
|
struct ubi_device *ubi;
|
||||||
struct mtd_info *mtd;
|
|
||||||
int i, err;
|
int i, err;
|
||||||
|
|
||||||
mtd = get_mtd_device_nm(mtd_dev);
|
/*
|
||||||
if (IS_ERR(mtd)) {
|
* Check if we already have the same MTD device attached.
|
||||||
int mtd_num;
|
*
|
||||||
char *endp;
|
* Note, this function assumes that UBI devices creations and deletions
|
||||||
|
* are serialized, so it does not take the &ubi_devices_lock.
|
||||||
if (PTR_ERR(mtd) != -ENODEV)
|
*/
|
||||||
return PTR_ERR(mtd);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Probably this is not MTD device name but MTD device number -
|
|
||||||
* check this out.
|
|
||||||
*/
|
|
||||||
mtd_num = simple_strtoul(mtd_dev, &endp, 0);
|
|
||||||
if (*endp != '\0' || mtd_dev == endp) {
|
|
||||||
ubi_err("incorrect MTD device: \"%s\"", mtd_dev);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
mtd = get_mtd_device(NULL, mtd_num);
|
|
||||||
if (IS_ERR(mtd))
|
|
||||||
return PTR_ERR(mtd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if we already have the same MTD device attached */
|
|
||||||
for (i = 0; i < UBI_MAX_DEVICES; i++)
|
for (i = 0; i < UBI_MAX_DEVICES; i++)
|
||||||
ubi = ubi_devices[i];
|
ubi = ubi_devices[i];
|
||||||
if (ubi && ubi->mtd->index == mtd->index) {
|
if (ubi && mtd->index == ubi->mtd->index) {
|
||||||
ubi_err("mtd%d is already attached to ubi%d",
|
ubi_err("mtd%d is already attached to ubi%d",
|
||||||
mtd->index, i);
|
mtd->index, i);
|
||||||
err = -EINVAL;
|
return -EINVAL;
|
||||||
goto out_mtd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ubi = kzalloc(sizeof(struct ubi_device), GFP_KERNEL);
|
|
||||||
if (!ubi) {
|
|
||||||
err = -ENOMEM;
|
|
||||||
goto out_mtd;
|
|
||||||
}
|
|
||||||
|
|
||||||
ubi->mtd = mtd;
|
|
||||||
|
|
||||||
/* Search for an empty slot in the @ubi_devices array */
|
/* Search for an empty slot in the @ubi_devices array */
|
||||||
ubi->ubi_num = -1;
|
|
||||||
for (i = 0; i < UBI_MAX_DEVICES; i++)
|
for (i = 0; i < UBI_MAX_DEVICES; i++)
|
||||||
if (!ubi_devices[i]) {
|
if (!ubi_devices[i])
|
||||||
ubi->ubi_num = i;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
if (ubi->ubi_num == -1) {
|
if (i == UBI_MAX_DEVICES) {
|
||||||
ubi_err("only %d UBI devices may be created", UBI_MAX_DEVICES);
|
ubi_err("only %d UBI devices may be created", UBI_MAX_DEVICES);
|
||||||
err = -ENFILE;
|
return -ENFILE;
|
||||||
goto out_free;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg_msg("attaching mtd%d to ubi%d: VID header offset %d data offset %d",
|
ubi = kzalloc(sizeof(struct ubi_device), GFP_KERNEL);
|
||||||
ubi->mtd->index, ubi->ubi_num, vid_hdr_offset, data_offset);
|
if (!ubi)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ubi->mtd = mtd;
|
||||||
|
ubi->ubi_num = i;
|
||||||
ubi->vid_hdr_offset = vid_hdr_offset;
|
ubi->vid_hdr_offset = vid_hdr_offset;
|
||||||
ubi->leb_start = data_offset;
|
ubi->leb_start = data_offset;
|
||||||
|
|
||||||
|
dbg_msg("attaching mtd%d to ubi%d: VID header offset %d data offset %d",
|
||||||
|
mtd->index, ubi->ubi_num, vid_hdr_offset, data_offset);
|
||||||
|
|
||||||
err = io_init(ubi);
|
err = io_init(ubi);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
@ -724,8 +709,16 @@ static int attach_mtd_dev(const char *mtd_dev, int vid_hdr_offset,
|
||||||
if (err)
|
if (err)
|
||||||
goto out_detach;
|
goto out_detach;
|
||||||
|
|
||||||
ubi_msg("attached mtd%d to ubi%d", ubi->mtd->index, ubi->ubi_num);
|
ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name);
|
||||||
ubi_msg("MTD device name: \"%s\"", ubi->mtd->name);
|
if (IS_ERR(ubi->bgt_thread)) {
|
||||||
|
err = PTR_ERR(ubi->bgt_thread);
|
||||||
|
ubi_err("cannot spawn \"%s\", error %d", ubi->bgt_name,
|
||||||
|
err);
|
||||||
|
goto out_uif;
|
||||||
|
}
|
||||||
|
|
||||||
|
ubi_msg("attached mtd%d to ubi%d", mtd->index, ubi->ubi_num);
|
||||||
|
ubi_msg("MTD device name: \"%s\"", mtd->name);
|
||||||
ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20);
|
ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20);
|
||||||
ubi_msg("physical eraseblock size: %d bytes (%d KiB)",
|
ubi_msg("physical eraseblock size: %d bytes (%d KiB)",
|
||||||
ubi->peb_size, ubi->peb_size >> 10);
|
ubi->peb_size, ubi->peb_size >> 10);
|
||||||
|
@ -754,8 +747,10 @@ static int attach_mtd_dev(const char *mtd_dev, int vid_hdr_offset,
|
||||||
}
|
}
|
||||||
|
|
||||||
ubi_devices[ubi->ubi_num] = ubi;
|
ubi_devices[ubi->ubi_num] = ubi;
|
||||||
return 0;
|
return ubi->ubi_num;
|
||||||
|
|
||||||
|
out_uif:
|
||||||
|
uif_close(ubi);
|
||||||
out_detach:
|
out_detach:
|
||||||
ubi_eba_close(ubi);
|
ubi_eba_close(ubi);
|
||||||
ubi_wl_close(ubi);
|
ubi_wl_close(ubi);
|
||||||
|
@ -767,21 +762,57 @@ out_free:
|
||||||
vfree(ubi->dbg_peb_buf);
|
vfree(ubi->dbg_peb_buf);
|
||||||
#endif
|
#endif
|
||||||
kfree(ubi);
|
kfree(ubi);
|
||||||
out_mtd:
|
|
||||||
put_mtd_device(mtd);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* detach_mtd_dev - detach an MTD device.
|
* ubi_detach_mtd_dev - detach an MTD device.
|
||||||
* @ubi: UBI device description object
|
* @ubi_num: UBI device number to detach from
|
||||||
|
* @anyway: detach MTD even if device reference count is not zero
|
||||||
|
*
|
||||||
|
* This function destroys an UBI device number @ubi_num and detaches the
|
||||||
|
* underlying MTD device. Returns zero in case of success and %-EBUSY if the
|
||||||
|
* UBI device is busy and cannot be destroyed, and %-EINVAL if it does not
|
||||||
|
* exist.
|
||||||
|
*
|
||||||
|
* Note, the invocations of this function has to be serialized by the
|
||||||
|
* @ubi_devices_mutex.
|
||||||
*/
|
*/
|
||||||
static void detach_mtd_dev(struct ubi_device *ubi)
|
int ubi_detach_mtd_dev(int ubi_num, int anyway)
|
||||||
{
|
{
|
||||||
int ubi_num = ubi->ubi_num, mtd_num = ubi->mtd->index;
|
struct ubi_device *ubi;
|
||||||
|
|
||||||
|
if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
spin_lock(&ubi_devices_lock);
|
||||||
|
ubi = ubi_devices[ubi_num];
|
||||||
|
if (!ubi) {
|
||||||
|
spin_lock(&ubi_devices_lock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ubi->ref_count) {
|
||||||
|
if (!anyway) {
|
||||||
|
spin_lock(&ubi_devices_lock);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
/* This may only happen if there is a bug */
|
||||||
|
ubi_err("%s reference count %d, destroy anyway",
|
||||||
|
ubi->ubi_name, ubi->ref_count);
|
||||||
|
}
|
||||||
|
ubi_devices[ubi->ubi_num] = NULL;
|
||||||
|
spin_unlock(&ubi_devices_lock);
|
||||||
|
|
||||||
|
dbg_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi->ubi_num);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Before freeing anything, we have to stop the background thread to
|
||||||
|
* prevent it from doing anything on this device while we are freeing.
|
||||||
|
*/
|
||||||
|
if (ubi->bgt_thread)
|
||||||
|
kthread_stop(ubi->bgt_thread);
|
||||||
|
|
||||||
dbg_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi_num);
|
|
||||||
ubi_assert(ubi->ref_count == 0);
|
|
||||||
uif_close(ubi);
|
uif_close(ubi);
|
||||||
ubi_eba_close(ubi);
|
ubi_eba_close(ubi);
|
||||||
ubi_wl_close(ubi);
|
ubi_wl_close(ubi);
|
||||||
|
@ -792,9 +823,9 @@ static void detach_mtd_dev(struct ubi_device *ubi)
|
||||||
#ifdef CONFIG_MTD_UBI_DEBUG
|
#ifdef CONFIG_MTD_UBI_DEBUG
|
||||||
vfree(ubi->dbg_peb_buf);
|
vfree(ubi->dbg_peb_buf);
|
||||||
#endif
|
#endif
|
||||||
kfree(ubi_devices[ubi_num]);
|
ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num);
|
||||||
ubi_devices[ubi_num] = NULL;
|
kfree(ubi);
|
||||||
ubi_msg("mtd%d is detached from ubi%d", mtd_num, ubi_num);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -811,6 +842,46 @@ static void ltree_entry_ctor(struct kmem_cache *cache, void *obj)
|
||||||
init_rwsem(&le->mutex);
|
init_rwsem(&le->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find_mtd_device - open an MTD device by its name or number.
|
||||||
|
* @mtd_dev: name or number of the device
|
||||||
|
*
|
||||||
|
* This function tries to open and MTD device with name @mtd_dev, and if it
|
||||||
|
* fails, then it tries to interpret the @mtd_dev string as an ASCII-coded
|
||||||
|
* integer and open an MTD device with this number. Returns MTD device
|
||||||
|
* description object in case of success and a negative error code in case of
|
||||||
|
* failure.
|
||||||
|
*/
|
||||||
|
static struct mtd_info * __init open_mtd_device(const char *mtd_dev)
|
||||||
|
{
|
||||||
|
struct mtd_info *mtd;
|
||||||
|
|
||||||
|
mtd = get_mtd_device_nm(mtd_dev);
|
||||||
|
if (IS_ERR(mtd)) {
|
||||||
|
int mtd_num;
|
||||||
|
char *endp;
|
||||||
|
|
||||||
|
if (PTR_ERR(mtd) != -ENODEV)
|
||||||
|
return mtd;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Probably this is not MTD device name but MTD device number -
|
||||||
|
* check this out.
|
||||||
|
*/
|
||||||
|
mtd_num = simple_strtoul(mtd_dev, &endp, 0);
|
||||||
|
if (*endp != '\0' || mtd_dev == endp) {
|
||||||
|
ubi_err("incorrect MTD device: \"%s\"", mtd_dev);
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
}
|
||||||
|
|
||||||
|
mtd = get_mtd_device(NULL, mtd_num);
|
||||||
|
if (IS_ERR(mtd))
|
||||||
|
return mtd;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mtd;
|
||||||
|
}
|
||||||
|
|
||||||
static int __init ubi_init(void)
|
static int __init ubi_init(void)
|
||||||
{
|
{
|
||||||
int err, i, k;
|
int err, i, k;
|
||||||
|
@ -860,10 +931,21 @@ static int __init ubi_init(void)
|
||||||
/* Attach MTD devices */
|
/* Attach MTD devices */
|
||||||
for (i = 0; i < mtd_devs; i++) {
|
for (i = 0; i < mtd_devs; i++) {
|
||||||
struct mtd_dev_param *p = &mtd_dev_param[i];
|
struct mtd_dev_param *p = &mtd_dev_param[i];
|
||||||
|
struct mtd_info *mtd;
|
||||||
|
|
||||||
cond_resched();
|
cond_resched();
|
||||||
err = attach_mtd_dev(p->name, p->vid_hdr_offs, p->data_offs);
|
|
||||||
if (err) {
|
mtd = open_mtd_device(p->name);
|
||||||
|
if (IS_ERR(mtd)) {
|
||||||
|
err = PTR_ERR(mtd);
|
||||||
|
goto out_detach;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_lock(&ubi_devices_mutex);
|
||||||
|
err = ubi_attach_mtd_dev(mtd, p->vid_hdr_offs, p->data_offs);
|
||||||
|
mutex_unlock(&ubi_devices_mutex);
|
||||||
|
if (err < 0) {
|
||||||
|
put_mtd_device(mtd);
|
||||||
printk(KERN_ERR "UBI error: cannot attach %s\n",
|
printk(KERN_ERR "UBI error: cannot attach %s\n",
|
||||||
p->name);
|
p->name);
|
||||||
goto out_detach;
|
goto out_detach;
|
||||||
|
@ -874,7 +956,11 @@ static int __init ubi_init(void)
|
||||||
|
|
||||||
out_detach:
|
out_detach:
|
||||||
for (k = 0; k < i; k++)
|
for (k = 0; k < i; k++)
|
||||||
detach_mtd_dev(ubi_devices[k]);
|
if (ubi_devices[k]) {
|
||||||
|
mutex_lock(&ubi_devices_mutex);
|
||||||
|
ubi_detach_mtd_dev(ubi_devices[k]->ubi_num, 1);
|
||||||
|
mutex_unlock(&ubi_devices_mutex);
|
||||||
|
}
|
||||||
kmem_cache_destroy(ubi_wl_entry_slab);
|
kmem_cache_destroy(ubi_wl_entry_slab);
|
||||||
out_ltree:
|
out_ltree:
|
||||||
kmem_cache_destroy(ubi_ltree_slab);
|
kmem_cache_destroy(ubi_ltree_slab);
|
||||||
|
@ -895,8 +981,11 @@ static void __exit ubi_exit(void)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < UBI_MAX_DEVICES; i++)
|
for (i = 0; i < UBI_MAX_DEVICES; i++)
|
||||||
if (ubi_devices[i])
|
if (ubi_devices[i]) {
|
||||||
detach_mtd_dev(ubi_devices[i]);
|
mutex_lock(&ubi_devices_mutex);
|
||||||
|
ubi_detach_mtd_dev(ubi_devices[i]->ubi_num, 1);
|
||||||
|
mutex_unlock(&ubi_devices_mutex);
|
||||||
|
}
|
||||||
kmem_cache_destroy(ubi_wl_entry_slab);
|
kmem_cache_destroy(ubi_wl_entry_slab);
|
||||||
kmem_cache_destroy(ubi_ltree_slab);
|
kmem_cache_destroy(ubi_ltree_slab);
|
||||||
misc_deregister(&ubi_ctrl_cdev);
|
misc_deregister(&ubi_ctrl_cdev);
|
||||||
|
|
|
@ -404,6 +404,7 @@ extern struct file_operations ubi_ctrl_cdev_operations;
|
||||||
extern struct file_operations ubi_cdev_operations;
|
extern struct file_operations ubi_cdev_operations;
|
||||||
extern struct file_operations ubi_vol_cdev_operations;
|
extern struct file_operations ubi_vol_cdev_operations;
|
||||||
extern struct class *ubi_class;
|
extern struct class *ubi_class;
|
||||||
|
extern struct mutex ubi_devices_mutex;
|
||||||
|
|
||||||
/* vtbl.c */
|
/* vtbl.c */
|
||||||
int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
|
int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
|
||||||
|
@ -462,6 +463,7 @@ int ubi_wl_flush(struct ubi_device *ubi);
|
||||||
int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum);
|
int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum);
|
||||||
int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si);
|
int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si);
|
||||||
void ubi_wl_close(struct ubi_device *ubi);
|
void ubi_wl_close(struct ubi_device *ubi);
|
||||||
|
int ubi_thread(void *u);
|
||||||
|
|
||||||
/* io.c */
|
/* io.c */
|
||||||
int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
|
int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
|
||||||
|
@ -481,6 +483,9 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
|
||||||
struct ubi_vid_hdr *vid_hdr);
|
struct ubi_vid_hdr *vid_hdr);
|
||||||
|
|
||||||
/* build.c */
|
/* build.c */
|
||||||
|
int ubi_attach_mtd_dev(struct mtd_info *mtd, int vid_hdr_offset,
|
||||||
|
int data_offset);
|
||||||
|
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);
|
||||||
struct ubi_device *ubi_get_by_major(int major);
|
struct ubi_device *ubi_get_by_major(int major);
|
||||||
|
|
|
@ -1356,7 +1356,7 @@ static void tree_destroy(struct rb_root *root)
|
||||||
* ubi_thread - UBI background thread.
|
* ubi_thread - UBI background thread.
|
||||||
* @u: the UBI device description object pointer
|
* @u: the UBI device description object pointer
|
||||||
*/
|
*/
|
||||||
static int ubi_thread(void *u)
|
int ubi_thread(void *u)
|
||||||
{
|
{
|
||||||
int failures = 0;
|
int failures = 0;
|
||||||
struct ubi_device *ubi = u;
|
struct ubi_device *ubi = u;
|
||||||
|
@ -1454,18 +1454,10 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
|
||||||
|
|
||||||
sprintf(ubi->bgt_name, UBI_BGT_NAME_PATTERN, ubi->ubi_num);
|
sprintf(ubi->bgt_name, UBI_BGT_NAME_PATTERN, ubi->ubi_num);
|
||||||
|
|
||||||
ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name);
|
|
||||||
if (IS_ERR(ubi->bgt_thread)) {
|
|
||||||
err = PTR_ERR(ubi->bgt_thread);
|
|
||||||
ubi_err("cannot spawn \"%s\", error %d", ubi->bgt_name,
|
|
||||||
err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
ubi->lookuptbl = kzalloc(ubi->peb_count * sizeof(void *), GFP_KERNEL);
|
ubi->lookuptbl = kzalloc(ubi->peb_count * sizeof(void *), GFP_KERNEL);
|
||||||
if (!ubi->lookuptbl)
|
if (!ubi->lookuptbl)
|
||||||
goto out_free;
|
return err;
|
||||||
|
|
||||||
list_for_each_entry_safe(seb, tmp, &si->erase, u.list) {
|
list_for_each_entry_safe(seb, tmp, &si->erase, u.list) {
|
||||||
cond_resched();
|
cond_resched();
|
||||||
|
@ -1598,10 +1590,6 @@ static void protection_trees_destroy(struct ubi_device *ubi)
|
||||||
*/
|
*/
|
||||||
void ubi_wl_close(struct ubi_device *ubi)
|
void ubi_wl_close(struct ubi_device *ubi)
|
||||||
{
|
{
|
||||||
dbg_wl("disable \"%s\"", ubi->bgt_name);
|
|
||||||
if (ubi->bgt_thread)
|
|
||||||
kthread_stop(ubi->bgt_thread);
|
|
||||||
|
|
||||||
dbg_wl("close the UBI wear-leveling unit");
|
dbg_wl("close the UBI wear-leveling unit");
|
||||||
|
|
||||||
cancel_pending(ubi);
|
cancel_pending(ubi);
|
||||||
|
|
Loading…
Reference in New Issue