Skip to content

Commit

Permalink
Merge git://git.infradead.org/~dedekind/ubi-2.6
Browse files Browse the repository at this point in the history
  • Loading branch information
dwmw2 committed Feb 3, 2008
2 parents 5eb9103 + 6dc4a87 commit 6208e77
Show file tree
Hide file tree
Showing 13 changed files with 441 additions and 188 deletions.
103 changes: 68 additions & 35 deletions drivers/mtd/ubi/build.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,6 @@ static struct mtd_dev_param mtd_dev_param[UBI_MAX_DEVICES];
/* Root UBI "class" object (corresponds to '/<sysfs>/class/ubi/') */
struct class *ubi_class;

/* Slab cache for lock-tree entries */
struct kmem_cache *ubi_ltree_slab;

/* Slab cache for wear-leveling entries */
struct kmem_cache *ubi_wl_entry_slab;

Expand Down Expand Up @@ -369,9 +366,6 @@ static int uif_init(struct ubi_device *ubi)
int i, err;
dev_t dev;

mutex_init(&ubi->volumes_mutex);
spin_lock_init(&ubi->volumes_lock);

sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num);

/*
Expand Down Expand Up @@ -568,7 +562,7 @@ static int io_init(struct ubi_device *ubi)
}

/* Similar for the data offset */
ubi->leb_start = ubi->vid_hdr_offset + ubi->vid_hdr_alsize;
ubi->leb_start = ubi->vid_hdr_offset + UBI_EC_HDR_SIZE;
ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size);

dbg_msg("vid_hdr_offset %d", ubi->vid_hdr_offset);
Expand Down Expand Up @@ -626,6 +620,58 @@ static int io_init(struct ubi_device *ubi)
return 0;
}

/**
* autoresize - re-size the volume which has the "auto-resize" flag set.
* @ubi: UBI device description object
* @vol_id: ID of the volume to re-size
*
* This function re-sizes the volume marked by the @UBI_VTBL_AUTORESIZE_FLG in
* the volume table to the largest possible size. See comments in ubi-header.h
* for more description of the flag. Returns zero in case of success and a
* negative error code in case of failure.
*/
static int autoresize(struct ubi_device *ubi, int vol_id)
{
struct ubi_volume_desc desc;
struct ubi_volume *vol = ubi->volumes[vol_id];
int err, old_reserved_pebs = vol->reserved_pebs;

/*
* Clear the auto-resize flag in the volume in-memory copy of the
* volume table, and 'ubi_resize_volume()' will propogate this change
* to the flash.
*/
ubi->vtbl[vol_id].flags &= ~UBI_VTBL_AUTORESIZE_FLG;

if (ubi->avail_pebs == 0) {
struct ubi_vtbl_record vtbl_rec;

/*
* No avalilable PEBs to re-size the volume, clear the flag on
* flash and exit.
*/
memcpy(&vtbl_rec, &ubi->vtbl[vol_id],
sizeof(struct ubi_vtbl_record));
err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
if (err)
ubi_err("cannot clean auto-resize flag for volume %d",
vol_id);
} else {
desc.vol = vol;
err = ubi_resize_volume(&desc,
old_reserved_pebs + ubi->avail_pebs);
if (err)
ubi_err("cannot auto-resize volume %d", vol_id);
}

if (err)
return err;

ubi_msg("volume %d (\"%s\") re-sized from %d to %d LEBs", vol_id,
vol->name, old_reserved_pebs, vol->reserved_pebs);
return 0;
}

/**
* ubi_attach_mtd_dev - attach an MTD device.
* @mtd_dev: MTD device description object
Expand Down Expand Up @@ -702,6 +748,12 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
ubi->mtd = mtd;
ubi->ubi_num = ubi_num;
ubi->vid_hdr_offset = vid_hdr_offset;
ubi->autoresize_vol_id = -1;

mutex_init(&ubi->buf_mutex);
mutex_init(&ubi->ckvol_mutex);
mutex_init(&ubi->volumes_mutex);
spin_lock_init(&ubi->volumes_lock);

dbg_msg("attaching mtd%d to ubi%d: VID header offset %d",
mtd->index, ubi_num, vid_hdr_offset);
Expand All @@ -710,8 +762,6 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
if (err)
goto out_free;

mutex_init(&ubi->buf_mutex);
mutex_init(&ubi->ckvol_mutex);
ubi->peb_buf1 = vmalloc(ubi->peb_size);
if (!ubi->peb_buf1)
goto out_free;
Expand All @@ -733,6 +783,12 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
goto out_free;
}

if (ubi->autoresize_vol_id != -1) {
err = autoresize(ubi, ubi->autoresize_vol_id);
if (err)
goto out_detach;
}

err = uif_init(ubi);
if (err)
goto out_detach;
Expand Down Expand Up @@ -857,20 +913,6 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
return 0;
}

/**
* ltree_entry_ctor - lock tree entries slab cache constructor.
* @obj: the lock-tree entry to construct
* @cache: the lock tree entry slab cache
* @flags: constructor flags
*/
static void ltree_entry_ctor(struct kmem_cache *cache, void *obj)
{
struct ubi_ltree_entry *le = obj;

le->users = 0;
init_rwsem(&le->mutex);
}

/**
* find_mtd_device - open an MTD device by its name or number.
* @mtd_dev: name or number of the device
Expand Down Expand Up @@ -933,17 +975,11 @@ static int __init ubi_init(void)
goto out_version;
}

ubi_ltree_slab = kmem_cache_create("ubi_ltree_slab",
sizeof(struct ubi_ltree_entry), 0,
0, &ltree_entry_ctor);
if (!ubi_ltree_slab)
goto out_dev_unreg;

ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab",
sizeof(struct ubi_wl_entry),
0, 0, NULL);
if (!ubi_wl_entry_slab)
goto out_ltree;
goto out_dev_unreg;

/* Attach MTD devices */
for (i = 0; i < mtd_devs; i++) {
Expand Down Expand Up @@ -980,8 +1016,6 @@ static int __init ubi_init(void)
mutex_unlock(&ubi_devices_mutex);
}
kmem_cache_destroy(ubi_wl_entry_slab);
out_ltree:
kmem_cache_destroy(ubi_ltree_slab);
out_dev_unreg:
misc_deregister(&ubi_ctrl_cdev);
out_version:
Expand All @@ -1005,7 +1039,6 @@ static void __exit ubi_exit(void)
mutex_unlock(&ubi_devices_mutex);
}
kmem_cache_destroy(ubi_wl_entry_slab);
kmem_cache_destroy(ubi_ltree_slab);
misc_deregister(&ubi_ctrl_cdev);
class_remove_file(ubi_class, &ubi_version);
class_destroy(ubi_class);
Expand Down Expand Up @@ -1066,7 +1099,7 @@ static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp)
struct mtd_dev_param *p;
char buf[MTD_PARAM_LEN_MAX];
char *pbuf = &buf[0];
char *tokens[3] = {NULL, NULL, NULL};
char *tokens[2] = {NULL, NULL};

if (!val)
return -EINVAL;
Expand Down Expand Up @@ -1096,7 +1129,7 @@ static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp)
if (buf[len - 1] == '\n')
buf[len - 1] = '\0';

for (i = 0; i < 3; i++)
for (i = 0; i < 2; i++)
tokens[i] = strsep(&pbuf, ",");

if (pbuf) {
Expand Down
82 changes: 64 additions & 18 deletions drivers/mtd/ubi/cdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,15 @@ static int vol_cdev_release(struct inode *inode, struct file *file)
if (vol->updating) {
ubi_warn("update of volume %d not finished, volume is damaged",
vol->vol_id);
ubi_assert(!vol->changing_leb);
vol->updating = 0;
vfree(vol->upd_buf);
} else if (vol->changing_leb) {
dbg_msg("only %lld of %lld bytes received for atomic LEB change"
" for volume %d:%d, cancel", vol->upd_received,
vol->upd_bytes, vol->ubi->ubi_num, vol->vol_id);
vol->changing_leb = 0;
vfree(vol->upd_buf);
}

ubi_close_volume(desc);
Expand Down Expand Up @@ -184,13 +191,13 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
struct ubi_volume_desc *desc = file->private_data;
struct ubi_volume *vol = desc->vol;
struct ubi_device *ubi = vol->ubi;
int err, lnum, off, len, vol_id = desc->vol->vol_id, tbuf_size;
int err, lnum, off, len, tbuf_size;
size_t count_save = count;
void *tbuf;
uint64_t tmp;

dbg_msg("read %zd bytes from offset %lld of volume %d",
count, *offp, vol_id);
count, *offp, vol->vol_id);

if (vol->updating) {
dbg_err("updating");
Expand All @@ -204,7 +211,7 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
return 0;

if (vol->corrupted)
dbg_msg("read from corrupted volume %d", vol_id);
dbg_msg("read from corrupted volume %d", vol->vol_id);

if (*offp + count > vol->used_bytes)
count_save = count = vol->used_bytes - *offp;
Expand Down Expand Up @@ -274,7 +281,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
uint64_t tmp;

dbg_msg("requested: write %zd bytes to offset %lld of volume %u",
count, *offp, desc->vol->vol_id);
count, *offp, vol->vol_id);

if (vol->vol_type == UBI_STATIC_VOLUME)
return -EROFS;
Expand Down Expand Up @@ -351,23 +358,32 @@ static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
struct ubi_volume *vol = desc->vol;
struct ubi_device *ubi = vol->ubi;

if (!vol->updating)
if (!vol->updating && !vol->changing_leb)
return vol_cdev_direct_write(file, buf, count, offp);

err = ubi_more_update_data(ubi, vol->vol_id, buf, count);
if (vol->updating)
err = ubi_more_update_data(ubi, vol, buf, count);
else
err = ubi_more_leb_change_data(ubi, vol, buf, count);

if (err < 0) {
ubi_err("cannot write %zd bytes of update data, error %d",
ubi_err("cannot accept more %zd bytes of data, error %d",
count, err);
return err;
}

if (err) {
/*
* Update is finished, @err contains number of actually written
* bytes now.
* The operation is finished, @err contains number of actually
* written bytes.
*/
count = err;

if (vol->changing_leb) {
revoke_exclusive(desc, UBI_READWRITE);
return count;
}

err = ubi_check_volume(ubi, vol->vol_id);
if (err < 0)
return err;
Expand All @@ -382,7 +398,6 @@ static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
revoke_exclusive(desc, UBI_READWRITE);
}

*offp += count;
return count;
}

Expand Down Expand Up @@ -427,11 +442,46 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
if (err < 0)
break;

err = ubi_start_update(ubi, vol->vol_id, bytes);
err = ubi_start_update(ubi, vol, bytes);
if (bytes == 0)
revoke_exclusive(desc, UBI_READWRITE);
break;
}

/* Atomic logical eraseblock change command */
case UBI_IOCEBCH:
{
struct ubi_leb_change_req req;

err = copy_from_user(&req, argp,
sizeof(struct ubi_leb_change_req));
if (err) {
err = -EFAULT;
break;
}

if (desc->mode == UBI_READONLY ||
vol->vol_type == UBI_STATIC_VOLUME) {
err = -EROFS;
break;
}

/* Validate the request */
err = -EINVAL;
if (req.lnum < 0 || req.lnum >= vol->reserved_pebs ||
req.bytes < 0 || req.lnum >= vol->usable_leb_size)
break;
if (req.dtype != UBI_LONGTERM && req.dtype != UBI_SHORTTERM &&
req.dtype != UBI_UNKNOWN)
break;

err = get_exclusive(desc);
if (err < 0)
break;

file->f_pos = 0;
err = ubi_start_leb_change(ubi, vol, &req);
if (req.bytes == 0)
revoke_exclusive(desc, UBI_READWRITE);
break;
}

Expand All @@ -447,7 +497,8 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
break;
}

if (desc->mode == UBI_READONLY) {
if (desc->mode == UBI_READONLY ||
vol->vol_type == UBI_STATIC_VOLUME) {
err = -EROFS;
break;
}
Expand All @@ -457,11 +508,6 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
break;
}

if (vol->vol_type != UBI_DYNAMIC_VOLUME) {
err = -EROFS;
break;
}

dbg_msg("erase LEB %d:%d", vol->vol_id, lnum);
err = ubi_eba_unmap_leb(ubi, vol, lnum);
if (err)
Expand Down
Loading

0 comments on commit 6208e77

Please sign in to comment.