summaryrefslogtreecommitdiff
path: root/drivers/mtd/ubi/kapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/ubi/kapi.c')
-rw-r--r--drivers/mtd/ubi/kapi.c119
1 files changed, 98 insertions, 21 deletions
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c
index fd2bbd64f1..06b93147f1 100644
--- a/drivers/mtd/ubi/kapi.c
+++ b/drivers/mtd/ubi/kapi.c
@@ -132,7 +132,7 @@ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode)
return ERR_PTR(-EINVAL);
if (mode != UBI_READONLY && mode != UBI_READWRITE &&
- mode != UBI_EXCLUSIVE)
+ mode != UBI_EXCLUSIVE && mode != UBI_METAONLY)
return ERR_PTR(-EINVAL);
/*
@@ -177,10 +177,17 @@ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode)
break;
case UBI_EXCLUSIVE:
- if (vol->exclusive || vol->writers || vol->readers)
+ if (vol->exclusive || vol->writers || vol->readers ||
+ vol->metaonly)
goto out_unlock;
vol->exclusive = 1;
break;
+
+ case UBI_METAONLY:
+ if (vol->metaonly || vol->exclusive)
+ goto out_unlock;
+ vol->metaonly = 1;
+ break;
}
get_device(&vol->dev);
vol->ref_count += 1;
@@ -199,7 +206,7 @@ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode)
return ERR_PTR(err);
}
if (err == 1) {
- ubi_warn("volume %d on UBI device %d is corrupted",
+ ubi_warn(ubi, "volume %d on UBI device %d is corrupted",
vol_id, ubi->ubi_num);
vol->corrupted = 1;
}
@@ -216,7 +223,7 @@ out_free:
kfree(desc);
out_put_ubi:
ubi_put_device(ubi);
- ubi_err("cannot open device %d, volume %d, error %d",
+ ubi_err(ubi, "cannot open device %d, volume %d, error %d",
ubi_num, vol_id, err);
return ERR_PTR(err);
}
@@ -303,7 +310,7 @@ struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode)
if (error)
return ERR_PTR(error);
- inode = path.dentry->d_inode;
+ inode = d_backing_inode(path.dentry);
mod = inode->i_mode;
ubi_num = ubi_major2num(imajor(inode));
vol_id = iminor(inode) - 1;
@@ -340,6 +347,10 @@ void ubi_close_volume(struct ubi_volume_desc *desc)
break;
case UBI_EXCLUSIVE:
vol->exclusive = 0;
+ break;
+ case UBI_METAONLY:
+ vol->metaonly = 0;
+ break;
}
vol->ref_count -= 1;
spin_unlock(&ubi->volumes_lock);
@@ -352,6 +363,43 @@ void ubi_close_volume(struct ubi_volume_desc *desc)
EXPORT_SYMBOL_GPL(ubi_close_volume);
/**
+ * leb_read_sanity_check - does sanity checks on read requests.
+ * @desc: volume descriptor
+ * @lnum: logical eraseblock number to read from
+ * @offset: offset within the logical eraseblock to read from
+ * @len: how many bytes to read
+ *
+ * This function is used by ubi_leb_read() and ubi_leb_read_sg()
+ * to perform sanity checks.
+ */
+static int leb_read_sanity_check(struct ubi_volume_desc *desc, int lnum,
+ int offset, int len)
+{
+ struct ubi_volume *vol = desc->vol;
+ struct ubi_device *ubi = vol->ubi;
+ int vol_id = vol->vol_id;
+
+ if (vol_id < 0 || vol_id >= ubi->vtbl_slots || lnum < 0 ||
+ lnum >= vol->used_ebs || offset < 0 || len < 0 ||
+ offset + len > vol->usable_leb_size)
+ return -EINVAL;
+
+ if (vol->vol_type == UBI_STATIC_VOLUME) {
+ if (vol->used_ebs == 0)
+ /* Empty static UBI volume */
+ return 0;
+ if (lnum == vol->used_ebs - 1 &&
+ offset + len > vol->last_eb_bytes)
+ return -EINVAL;
+ }
+
+ if (vol->upd_marker)
+ return -EBADF;
+
+ return 0;
+}
+
+/**
* ubi_leb_read - read data.
* @desc: volume descriptor
* @lnum: logical eraseblock number to read from
@@ -387,28 +435,16 @@ int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset);
- if (vol_id < 0 || vol_id >= ubi->vtbl_slots || lnum < 0 ||
- lnum >= vol->used_ebs || offset < 0 || len < 0 ||
- offset + len > vol->usable_leb_size)
- return -EINVAL;
-
- if (vol->vol_type == UBI_STATIC_VOLUME) {
- if (vol->used_ebs == 0)
- /* Empty static UBI volume */
- return 0;
- if (lnum == vol->used_ebs - 1 &&
- offset + len > vol->last_eb_bytes)
- return -EINVAL;
- }
+ err = leb_read_sanity_check(desc, lnum, offset, len);
+ if (err < 0)
+ return err;
- if (vol->upd_marker)
- return -EBADF;
if (len == 0)
return 0;
err = ubi_eba_read_leb(ubi, vol, lnum, buf, offset, len, check);
if (err && mtd_is_eccerr(err) && vol->vol_type == UBI_STATIC_VOLUME) {
- ubi_warn("mark volume %d as corrupted", vol_id);
+ ubi_warn(ubi, "mark volume %d as corrupted", vol_id);
vol->corrupted = 1;
}
@@ -416,6 +452,47 @@ int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
}
EXPORT_SYMBOL_GPL(ubi_leb_read);
+#ifndef __UBOOT__
+/**
+ * ubi_leb_read_sg - read data into a scatter gather list.
+ * @desc: volume descriptor
+ * @lnum: logical eraseblock number to read from
+ * @buf: buffer where to store the read data
+ * @offset: offset within the logical eraseblock to read from
+ * @len: how many bytes to read
+ * @check: whether UBI has to check the read data's CRC or not.
+ *
+ * This function works exactly like ubi_leb_read_sg(). But instead of
+ * storing the read data into a buffer it writes to an UBI scatter gather
+ * list.
+ */
+int ubi_leb_read_sg(struct ubi_volume_desc *desc, int lnum, struct ubi_sgl *sgl,
+ int offset, int len, int check)
+{
+ struct ubi_volume *vol = desc->vol;
+ struct ubi_device *ubi = vol->ubi;
+ int err, vol_id = vol->vol_id;
+
+ dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset);
+
+ err = leb_read_sanity_check(desc, lnum, offset, len);
+ if (err < 0)
+ return err;
+
+ if (len == 0)
+ return 0;
+
+ err = ubi_eba_read_leb_sg(ubi, vol, sgl, lnum, offset, len, check);
+ if (err && mtd_is_eccerr(err) && vol->vol_type == UBI_STATIC_VOLUME) {
+ ubi_warn(ubi, "mark volume %d as corrupted", vol_id);
+ vol->corrupted = 1;
+ }
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(ubi_leb_read_sg);
+#endif
+
/**
* ubi_leb_write - write data.
* @desc: volume descriptor