]> git.sur5r.net Git - u-boot/blobdiff - drivers/mtd/ubi/kapi.c
Merge git://git.denx.de/u-boot-net
[u-boot] / drivers / mtd / ubi / kapi.c
index fd2bbd64f13835d67e25ad5275d550b3a1ca8058..06b93147f1c57c2bacbd720628dac9115732ed5b 100644 (file)
@@ -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);
@@ -351,6 +362,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
@@ -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