diff mbox

[11/16] UBI: Fastmap: Store pool sizes in fastmap

Message ID 1340812676-14460-12-git-send-email-richard@nod.at
State New, archived
Headers show

Commit Message

Richard Weinberger June 27, 2012, 3:57 p.m. UTC
Later this can be used by ubinize to allow custom
pool sizes.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/mtd/ubi/attach.c    |    8 ++++
 drivers/mtd/ubi/build.c     |    4 +-
 drivers/mtd/ubi/fastmap.c   |   84 ++++++++++++++++++++++++++++--------------
 drivers/mtd/ubi/ubi-media.h |    4 ++-
 drivers/mtd/ubi/ubi.h       |    6 +++
 5 files changed, 75 insertions(+), 31 deletions(-)
diff mbox

Patch

diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
index 1ac58ec..7552d25 100644
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -1261,6 +1261,14 @@  int ubi_attach(struct ubi_device *ubi, int force_scan)
 	if (err)
 		goto out_ai;
 
+	if (ubi->fm) {
+		ubi->fm_pool.max_size = ubi->fm->max_pool_size;
+		ubi->fm_wl_pool.max_size = ubi->fm->max_wl_pool_size;
+
+		ubi_msg("fastmap pool size: %d", ubi->fm_pool.max_size);
+		ubi_msg("fastmap WL pool size: %d", ubi->fm_wl_pool.max_size);
+	}
+
 	err = ubi_wl_init(ubi, ai);
 	if (err)
 		goto out_vtbl;
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index d00101e..7094550 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -900,8 +900,8 @@  int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
 
 	ubi->fm_wl_pool.max_size = UBI_FM_WL_POOL_SIZE;
 
-	ubi_msg("fastmap pool size: %d", ubi->fm_pool.max_size);
-	ubi_msg("fastmap WL pool size: %d", ubi->fm_wl_pool.max_size);
+	ubi_msg("default fastmap pool size: %d", ubi->fm_pool.max_size);
+	ubi_msg("default fastmap WL pool size: %d", ubi->fm_wl_pool.max_size);
 
 	mutex_init(&ubi->buf_mutex);
 	mutex_init(&ubi->ckvol_mutex);
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index c234d94..e285e3b 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -506,15 +506,14 @@  static int count_fastmap_pebs(struct ubi_attach_info *ai)
  * ubi_attach_fastmap - creates ubi_attach_info from a fastmap.
  * @ubi: UBI device object
  * @ai: UBI attach info object
- * @fm_raw: the fastmap it self as byte array
- * @fm_size: size of the fastmap in bytes
+ * @fm: the fastmap to be attached
  *
  * Returns 0 on success, UBI_BAD_FASTMAP if the found fastmap was unusable.
  * < 0 indicates an internal error.
  */
 static int ubi_attach_fastmap(struct ubi_device *ubi,
 			      struct ubi_attach_info *ai,
-			      void *fm_raw, size_t fm_size)
+			      struct ubi_fastmap_layout *fm)
 {
 	struct list_head used, eba_orphans, free;
 	struct ubi_ainf_volume *av;
@@ -526,9 +525,10 @@  static int ubi_attach_fastmap(struct ubi_device *ubi,
 	struct ubi_fm_ec *fmec;
 	struct ubi_fm_volhdr *fmvhdr;
 	struct ubi_fm_eba *fm_eba;
-	int ret, i, j;
-	size_t fm_pos = 0;
+	int ret, i, j, pool_size, wl_pool_size;
+	size_t fm_pos = 0, fm_size = fm->size;
 	unsigned long long max_sqnum = 0;
+	void *fm_raw = fm->raw;
 
 	INIT_LIST_HEAD(&used);
 	INIT_LIST_HEAD(&free);
@@ -585,6 +585,34 @@  static int ubi_attach_fastmap(struct ubi_device *ubi,
 		goto fail_bad;
 	}
 
+	pool_size = be16_to_cpu(fmpl1->size);
+	wl_pool_size = be16_to_cpu(fmpl2->size);
+	fm->max_pool_size = be16_to_cpu(fmpl1->max_size);
+	fm->max_wl_pool_size = be16_to_cpu(fmpl2->max_size);
+
+	if (pool_size > UBI_FM_MAX_POOL_SIZE || pool_size < 0) {
+		ubi_err("bad pool size: %i", pool_size);
+		goto fail_bad;
+	}
+
+	if (wl_pool_size > UBI_FM_MAX_POOL_SIZE || wl_pool_size < 0) {
+		ubi_err("bad WL pool size: %i", wl_pool_size);
+		goto fail_bad;
+	}
+
+
+	if (fm->max_pool_size > UBI_FM_MAX_POOL_SIZE ||
+	    fm->max_pool_size < 0) {
+		ubi_err("bad maximal pool size: %i", fm->max_pool_size);
+		goto fail_bad;
+	}
+
+	if (fm->max_wl_pool_size > UBI_FM_MAX_POOL_SIZE ||
+	    fm->max_wl_pool_size < 0) {
+		ubi_err("bad maximal WL pool size: %i", fm->max_wl_pool_size);
+		goto fail_bad;
+	}
+
 	/* read EC values from free list */
 	for (i = 0; i < be32_to_cpu(fmhdr->free_peb_count); i++) {
 		fmec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
@@ -754,13 +782,13 @@  static int ubi_attach_fastmap(struct ubi_device *ubi,
 		kfree(ech);
 	}
 
-	ret = scan_pool(ubi, ai, fmpl1->pebs, be32_to_cpu(fmpl1->size),
-			&max_sqnum, &eba_orphans, &free);
+	ret = scan_pool(ubi, ai, fmpl1->pebs, pool_size, &max_sqnum,
+			&eba_orphans, &free);
 	if (ret)
 		goto fail;
 
-	ret = scan_pool(ubi, ai, fmpl2->pebs, be32_to_cpu(fmpl2->size),
-			&max_sqnum, &eba_orphans, &free);
+	ret = scan_pool(ubi, ai, fmpl2->pebs, wl_pool_size, &max_sqnum,
+			&eba_orphans, &free);
 	if (ret)
 		goto fail;
 
@@ -772,6 +800,16 @@  static int ubi_attach_fastmap(struct ubi_device *ubi,
 		list_add_tail(&tmp_aeb->u.list, &ai->free);
 	}
 
+	/*
+	 * If fastmap is leaking PEBs (must not happen), raise a
+	 * fat warning and fall back to scanning mode.
+	 * We do this here because in ubi_wl_init() it's too late
+	 * and we cannot fall back to scanning.
+	 */
+	if (WARN_ON(count_fastmap_pebs(ai) != ubi->peb_count -
+		    ai->bad_peb_count - fm->used_blocks))
+		goto fail_bad;
+
 	return 0;
 
 fail_bad:
@@ -1026,7 +1064,11 @@  int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
 
 	fmsb->sqnum = sqnum;
 
-	ret = ubi_attach_fastmap(ubi, ai, fm_raw, fm_size);
+	fm->size = fm_size;
+	fm->used_blocks = used_blocks;
+	fm->raw = fm_raw;
+
+	ret = ubi_attach_fastmap(ubi, ai, fm);
 	if (ret) {
 		if (ret > 0)
 			ret = UBI_BAD_FASTMAP;
@@ -1034,22 +1076,6 @@  int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
 		goto free_hdr;
 	}
 
-	/*
-	 * If fastmap is leaking PEBs (must not happen), raise a
-	 * fat warning and fall back to scanning mode.
-	 * We do this here because in ubi_wl_init() it's too late
-	 * and we cannot fall back to scanning.
-	 */
-	if (WARN_ON(count_fastmap_pebs(ai) != ubi->peb_count -
-		    ai->bad_peb_count - used_blocks)) {
-		ret = UBI_BAD_FASTMAP;
-		kfree(fm);
-		goto free_hdr;
-	}
-
-	fm->size = fm_size;
-	fm->used_blocks = used_blocks;
-
 	for (i = 0; i < used_blocks; i++) {
 		struct ubi_wl_entry *e;
 
@@ -1153,7 +1179,8 @@  static int ubi_write_fastmap(struct ubi_device *ubi,
 	fmpl1 = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
 	fm_pos += sizeof(*fmpl1);
 	fmpl1->magic = cpu_to_be32(UBI_FM_POOL_MAGIC);
-	fmpl1->size = cpu_to_be32(ubi->fm_pool.size);
+	fmpl1->size = cpu_to_be16(ubi->fm_pool.size);
+	fmpl1->max_size = cpu_to_be16(ubi->fm_pool.max_size);
 
 	for (i = 0; i < ubi->fm_pool.size; i++)
 		fmpl1->pebs[i] = cpu_to_be32(ubi->fm_pool.pebs[i]);
@@ -1161,7 +1188,8 @@  static int ubi_write_fastmap(struct ubi_device *ubi,
 	fmpl2 = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
 	fm_pos += sizeof(*fmpl2);
 	fmpl2->magic = cpu_to_be32(UBI_FM_POOL_MAGIC);
-	fmpl2->size = cpu_to_be32(ubi->fm_wl_pool.size);
+	fmpl2->size = cpu_to_be16(ubi->fm_wl_pool.size);
+	fmpl2->max_size = cpu_to_be16(ubi->fm_wl_pool.max_size);
 
 	for (i = 0; i < ubi->fm_wl_pool.size; i++)
 		fmpl2->pebs[i] = cpu_to_be32(ubi->fm_wl_pool.pebs[i]);
diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h
index eaf81a2..f1b85a4f 100644
--- a/drivers/mtd/ubi/ubi-media.h
+++ b/drivers/mtd/ubi/ubi-media.h
@@ -455,11 +455,13 @@  struct ubi_fm_hdr {
  * struct ubi_fm_scan_pool - Fastmap pool PEBs to be scanned while attaching
  * @magic: pool magic numer (%UBI_FM_POOL_MAGIC)
  * @size: current pool size
+ * @max_size: maximal pool size
  * @pebs: an array containing the location of all PEBs in this pool
  */
 struct ubi_fm_scan_pool {
 	__be32 magic;
-	__be32 size;
+	__be16 size;
+	__be16 max_size;
 	__be32 pebs[UBI_FM_MAX_POOL_SIZE];
 	__be32 padding[4];
 } __packed;
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index b60818d..8e2592d 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -218,12 +218,18 @@  struct ubi_volume_desc;
  * @to_be_tortured: if non-zero tortured this PEB
  * @size: size of the fastmap in bytes
  * @used_blocks: number of used PEBs
+ * @max_pool_size: maximal size of the user pool
+ * @max_wl_pool_size: maximal size of the pooly used by the WL sub-system
+ * @raw: the fastmap itself as byte array (only valid while attaching)
  */
 struct ubi_fastmap_layout {
 	struct ubi_wl_entry *e[UBI_FM_MAX_BLOCKS];
 	int to_be_tortured[UBI_FM_MAX_BLOCKS];
 	size_t size;
 	int used_blocks;
+	int max_pool_size;
+	int max_wl_pool_size;
+	void *raw;
 };
 
 /**