PATCH 1/7] ubi: logging feature for ubi

Brijesh Singh brij.singh at samsung.com
Mon Apr 12 04:35:57 EDT 2010


Hi,
    I am sending the patches that add logging support to UBI.

Thanks and Regards,
Brijesh


Note: Media headers and in ram structures files for ubi logging functionality

Signed-off-by: brijesh singh <brij.singh at samsung.com>
---
--- ubi_old/drivers/mtd/ubi/ubi.h	2010-04-09 21:54:13.955581334 +0530
+++ ubi_new/drivers/mtd/ubi/ubi.h	2010-04-09 21:54:02.645580870 +0530
@@ -39,6 +39,9 @@
 #include <linux/notifier.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/ubi.h>
+#ifdef CONFIG_MTD_UBI_LOGGED
+#include <linux/crc32.h>
+#endif

 #include "ubi-media.h"
 #include "scan.h"
@@ -81,6 +84,80 @@
  */
 #define UBI_PROT_QUEUE_LEN 10

+
+#ifdef CONFIG_MTD_UBI_LOGGED
+/*
+ * ubi maintains two copies of super block.
+ * UBI_SB_RESRVD_BUDS: number of reserved buds for sb
+ * UBI_CMT_BUDS_RESRVD: number of reserved buds for cmt.
+ *
+ */
+#define UBIL_SB_BUDS_RESRVD 2
+#define UBIL_CMT_COPIES 2
+
+/*
+ * If ubi has added anything to log after commit, commit is dirty.
+ * If nothing is written to log, commit is not needed.
+ * 0: commit is dirty
+ * 1: commit is clean
+ */
+enum{
+	C_DIRTY = 0,
+	C_CLEAN
+};
+
+/*
+ * Commit status.
+ * 0: not commiting.
+ * 1: commit started
+ * 2: commit Writing
+ * 3: commit finished
+ * 4: commit failed
+ */
+enum{
+	C_FREE = 0,
+	C_STARTED,
+	C_WRITING,
+	C_FINISHED,
+	C_FAILED
+};
+
+/*
+ * error code for node validation.
+ * 100: node is empty, all 0xff
+ * 101: node has bad hdr, error in crc
+ * 102: node has bad data, error data crc
+ * 103: bud is full
+ */
+
+enum {
+	UBIL_NODE_EMPTY = 100,
+	UBIL_NODE_BAD_HDR,
+	UBIL_NODE_BAD_DATA,
+	UBIL_BUD_FULL
+};
+
+/*
+ *  status code in log and commit subsystem.
+ *  1: peb has gone bad
+ *  2: peb needs correction
+ *  3: peb is used
+ *  4: peb is used as special peb. for sb, cmt or ebal
+ *  5: peb is free
+ *  6: peb is pending for erase
+ */
+
+enum {
+	UBIL_PEB_BAD = 1,
+	UBIL_PEB_CORR,
+	UBIL_PEB_USED,
+	UBIL_PEB_USED_SP,
+	UBIL_PEB_FREE,
+	UBIL_PEB_ERASE_PENDING
+};
+
+#endif
+
 /*
  * Error codes returned by the I/O sub-system.
  *
@@ -288,6 +365,24 @@

 struct ubi_wl_entry;

+#ifdef CONFIG_MTD_UBI_LOGGED
+#ifdef CONFIG_MTD_UBIL_COMPR
+/**
+ * struct ubi_compressor - UBI compressor description structure.
+ * @compr_type: compressor type (%UBIFS_COMPR_LZO, etc)
+ * @cc: cryptoapi compressor handle
+ * @name: compressor name
+ * @capi_name: cryptoapi compressor name
+ */
+struct ubi_compressor {
+	int compr_type;
+	struct crypto_comp *cc;
+	const char *name;
+	const char *capi_name;
+};
+#endif
+#endif
+
 /**
  * struct ubi_device - UBI device description structure
  * @dev: UBI device object to use the the Linux device model
@@ -330,12 +425,13 @@
  * @erroneous: RB-tree of erroneous used physical eraseblocks
  * @free: RB-tree of free physical eraseblocks
  * @scrub: RB-tree of physical eraseblocks which need scrubbing
+ * @resvd: RB-tree of physical eraseblocks reserved for cmt or sb or el
  * @pq: protection queue (contain physical eraseblocks which are temporarily
  *      protected from the wear-leveling worker)
  * @pq_head: protection queue head
  * @wl_lock: protects the @used, @free, @pq, @pq_head, @lookuptbl, @move_from,
- * 	     @move_to, @move_to_put @erase_pending, @wl_scheduled, @works,
- * 	     @erroneous, and @erroneous_peb_count fields
+ *	     @move_to, @move_to_put @erase_pending, @wl_scheduled, @works,
+ *	     @erroneous, and @erroneous_peb_count fields
  * @move_mutex: serializes eraseblock moves
  * @work_sem: synchronizes the WL worker with use tasks
  * @wl_scheduled: non-zero if the wear-leveling was scheduled
@@ -375,7 +471,37 @@
  *               not
  * @nor_flash: non-zero if working on top of NOR flash
  * @mtd: MTD device descriptor
- *
+ * --  ubil variables start here --
+ * @peb_lookup: array of peb info. each peb has one entry in this array
+ * @bud_start_offset: offset from where data can be written to bud
+ * @bud_usable_len: usable bud len. This is bud len - bud hdr len
+ * @bud_max_nodes: how many nodes can fit in bud
+ * @node_size: node size. usually it is write size
+ * @sb_node: one inram copy of sb node is always maintained.
+ * @sb_lock: lock protecting sb node
+ * @sb_sqnum: sequence number for sb
+ * @sb_buds: array of sb buds
+ * @sb_active_bud: the bud which is active.
+ * sb is written alternatively in each node.
+ * @sb_mutex: mutex protecting sb log
+ * @sb_offset: corrent log offset
+ * @sb_needs_rcvry: when sb has a flip or bad data recovery is set
+ * @el_mutex: mutex protecting el log.
+ * @el_buds: array of el buds
+ * @el_reservd_buds: how many buds are reserved for el
+ * @el_active_bud: where in el is corrent el
+ * @el_offset: corrent offset in corrent bud
+ * @el_pebs_in_grp: no of pebs in el group.
+ * @el_no_of_grps: no of groups for entire partition
+ * @c_buds: array of cmt buds
+ * @c_reservd_buds: array of buffer reserved buds
+ * @c_previous_status: last commit operation status
+ * @c_max_no_of_rec: maximum commit bud entries
+ * @c_max_data_size: maximum data commit bud contain
+ * @c_dirty: flag invalidating last commit
+ * @schedule_cmt: flag to schedule commit operation
+ * @cmt_lock: lock protecting commit data
+ * @c_status: status of commit operation in progress
  * @peb_buf1: a buffer of PEB size used for different purposes
  * @peb_buf2: another buffer of PEB size used for different purposes
  * @buf_mutex: protects @peb_buf1 and @peb_buf2
@@ -420,6 +546,9 @@
 	struct rb_root erroneous;
 	struct rb_root free;
 	struct rb_root scrub;
+#ifdef CONFIG_MTD_UBI_LOGGED
+	struct rb_root resvd;
+#endif
 	struct list_head pq[UBI_PROT_QUEUE_LEN];
 	int pq_head;
 	spinlock_t wl_lock;
@@ -450,15 +579,56 @@
 	int ro_mode;
 	int leb_size;
 	int leb_start;
+#ifndef CONFIG_MTD_UBI_LOGGED
 	int ec_hdr_alsize;
 	int vid_hdr_alsize;
 	int vid_hdr_offset;
 	int vid_hdr_aloffset;
 	int vid_hdr_shift;
+#endif
 	unsigned int bad_allowed:1;
 	unsigned int nor_flash:1;
 	struct mtd_info *mtd;

+#ifdef CONFIG_MTD_UBI_LOGGED
+	struct peb_info *peb_lookup;
+	int bud_start_offset;
+	int bud_usable_len;
+	int node_size;
+
+	/* sb */
+	struct ubi_sb *sb_node;
+	spinlock_t sb_lock;
+	unsigned long long sb_sqnum;
+	int sb_buds[UBIL_SB_BUDS_RESRVD];
+	int sb_active_bud;
+	struct mutex sb_mutex;
+	int sb_offset;
+	int sb_needs_rcvry;
+
+	/* el */
+	struct mutex el_mutex;
+	int *el_buds;
+	int el_reservd_buds;
+	int el_active_bud;
+	int el_offset;
+	int el_pebs_in_grp;
+	int el_no_of_grps;
+
+	/* cmt */
+	int *c_buds;
+	int c_reservd_buds;
+	int c_previous_status;
+	int c_max_no_of_rec;
+	int c_max_data_size;
+	int c_dirty;
+	int schedule_cmt;
+	spinlock_t cmt_lock;
+	int c_status;
+#ifdef CONFIG_MTD_UBIL_COMPR
+	struct ubi_compressor *compr;
+#endif
+#endif
 	void *peb_buf1;
 	void *peb_buf2;
 	struct mutex buf_mutex;
@@ -483,6 +653,10 @@
 int ubi_vtbl_rename_volumes(struct ubi_device *ubi,
 			    struct list_head *rename_list);
 int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si);
+#ifdef CONFIG_MTD_UBI_LOGGED
+int ubi_vtbl_create_dflt_volume_table(struct ubi_device *ubi);
+int ubi_vtbl_create_dflt_image(struct ubi_device *ubi, int copy, int pnum);
+#endif

 /* vmt.c */
 int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req);
@@ -523,6 +697,10 @@
 int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
 		     struct ubi_vid_hdr *vid_hdr);
 int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si);
+#ifdef CONFIG_MTD_UBI_LOGGED
+int ubi_eba_leb_to_peb(struct ubi_device *ubi, struct ubi_volume *vol,
+		      int lnum);
+#endif

 /* wl.c */
 int ubi_wl_get_peb(struct ubi_device *ubi, int dtype);
@@ -541,17 +719,75 @@
 int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture);
 int ubi_io_is_bad(const struct ubi_device *ubi, int pnum);
 int ubi_io_mark_bad(const struct ubi_device *ubi, int pnum);
+#ifndef CONFIG_MTD_UBI_LOGGED
 int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
 		       struct ubi_ec_hdr *ec_hdr, int verbose);
 int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum,
 			struct ubi_ec_hdr *ec_hdr);
 int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
 			struct ubi_vid_hdr *vid_hdr, int verbose);
+#endif
 int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
 			 struct ubi_vid_hdr *vid_hdr);
+#ifdef CONFIG_MTD_UBI_LOGGED
+int ubi_read_node(struct ubi_device *ubi, struct node_t *node, int pnum,
+			int offset, int len);
+int ubi_write_node(struct ubi_device *ubi, struct node_t *node, int pnum,
+			int offset, int len);
+
+/* super.c */
+struct ubi_sb *ubi_sb_get_node(struct ubi_device *ubi);
+void ubi_sb_put_node(struct ubi_device *ubi);
+int ubi_sb_sync_node(struct ubi_device *ubi);
+int ubi_get_sb(struct ubi_device *ubi);
+int ubi_sb_init(struct ubi_device *ubi);
+int ubi_sb_create_dflt(struct ubi_device *ubi, int copy, int pnum);
+int ubi_sb_close(struct ubi_device *ubi);
+
+/* el.c */
+int ubi_el_read_ec_hdr(struct ubi_device *ubi, int pnum);
+int ubi_el_write_ec_hdr(struct ubi_device *ubi, int pnum, int ec);
+int ubi_el_write_ec_hdr_no_sync(struct ubi_device *ubi, int pnum, int ec);
+int ubi_el_mark_pending(struct ubi_device *ubi, int pnum);
+int ubi_el_read_vid_hdr(struct ubi_device *ubi, int pnum,
+			struct ubi_vid_hdr *vid_hdr, int verbose);
+int ubi_el_write_vid_hdr(struct ubi_device *ubi, int pnum,
+			 struct ubi_vid_hdr *vid_hdr);
+int  ubi_el_init(struct ubi_device *ubi);
+void  ubi_el_close(struct ubi_device *ubi);
+int  ubi_el_scan(struct ubi_device *ubi);
+int  ubi_el_create_dflt(struct ubi_device *ubi, int copy, int pnum);
+
+/* commit.c */
+
+int ubi_ensure_cmt(struct ubi_device *ubi);
+void ubi_schedule_cmt(struct ubi_device *ubi);
+int ubi_cmt_progress(struct ubi_device *ubi);
+int ubi_cmt_init(struct ubi_device *ubi);
+int ubi_cmt_ubinize_write(struct ubi_device *ubi);
+int ubi_cmt_read(struct ubi_device *ubi);
+int ubi_cmt_sb_init(struct ubi_device *ubi);
+#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+int paranoid_check_special(struct ubi_device *ubi, int in_pnum);
+int paranoid_check_reservd_status(struct ubi_device *ubi);
+#else
+#define paronoid_check_special(ubi, in_pnum) 0
+#define paronoid_check_reservd_status(ubi) 0
+#endif
+int ubi_cmt_close(struct ubi_device *ubi);
+int ubi_cmt(struct ubi_device *ubi);
+int ubi_cmt_put_resvd_peb(struct ubi_device *ubi);
+
+
+#endif

 /* build.c */
+
+#ifdef CONFIG_MTD_UBI_LOGGED
+int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int ubinize);
+#else
 int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset);
+#endif
 int ubi_detach_mtd_dev(int ubi_num, int anyway);
 struct ubi_device *ubi_get_device(int ubi_num);
 void ubi_put_device(struct ubi_device *ubi);
@@ -595,8 +831,11 @@
 ubi_zalloc_vid_hdr(const struct ubi_device *ubi, gfp_t gfp_flags)
 {
 	void *vid_hdr;
-
+#ifndef CONFIG_MTD_UBI_LOGGED
 	vid_hdr = kzalloc(ubi->vid_hdr_alsize, gfp_flags);
+#else
+	vid_hdr = kzalloc(sizeof(struct ubi_vid_hdr), gfp_flags);
+#endif
 	if (!vid_hdr)
 		return NULL;

@@ -604,7 +843,12 @@
 	 * VID headers may be stored at un-aligned flash offsets, so we shift
 	 * the pointer.
 	 */
+
+#ifndef CONFIG_MTD_UBI_LOGGED
 	return vid_hdr + ubi->vid_hdr_shift;
+#else
+	return vid_hdr;
+#endif
 }

 /**
@@ -620,7 +864,11 @@
 	if (!p)
 		return;

+#ifndef CONFIG_MTD_UBI_LOGGED
 	kfree(p - ubi->vid_hdr_shift);
+#else
+	kfree(p);
+#endif
 }

 /*
@@ -685,4 +933,115 @@
 		return idx;
 }

+#ifdef CONFIG_MTD_UBI_LOGGED
+
+/*
+ *  alloc_nodes - allocate nodes
+ *  @ubi: ubi decription object
+ *  @nodes: no of nodes
+ *  returns NULL for failure else ptr.
+ */
+static inline void *alloc_nodes(struct ubi_device *ubi, int nodes)
+{
+	return kmalloc(ubi->node_size * nodes, GFP_KERNEL);
+}
+
+/*
+ *  free_nodes - free nodes
+ *  @p: node pointer
+ */
+static inline void free_nodes(void *p)
+{
+	kfree(p);
+}
+
+#define node2lnode(f) (&f->lh)
+
+/**
+ * check_pattern - check if buffer contains only a certain byte pattern.
+ * @buf: buffer to check
+ * @patt: the pattern to check
+ * @size: buffer size in bytes
+ *
+ * This function returns %1 in there are only @patt bytes in @buf, and %0 if
+ * something else was also found.
+ */
+static inline int check_pattern(const void *buf, uint8_t patt, int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++)
+		if (((const uint8_t *)buf)[i] != patt)
+			return 0;
+	return 1;
+}
+
+/**
+ * verify_node - verify node header
+ * @ubi_device: UBI device description object
+ * @lh: node to verify
+ * @type: expected type of node.
+ *
+ * this function verifies the consistency of a generic node.
+ * node_type is validated against passed value.
+ *
+ * returns 0 on success, error code on failure.
+ */
+static inline int verify_node(struct ubi_device *ubi,
+				struct node_t *lh, int type) {
+	int data_size, node_type;
+	int magic, crc, stored_crc;
+
+	magic = be32_to_cpu(lh->magic);
+	if (magic != UBIL_NODE_MAGIC) {
+		/* bad magic. Check for all 0xFF pattern i.e. empty node.*/
+		if (check_pattern(lh, 0xFF, ubi->node_size)) {
+			/* the physical eraseblock is supposedly empty */
+			return UBIL_NODE_EMPTY;
+		}
+
+		/* this is not a valid node. */
+		ubi_err("bad magic in node");
+		return UBIL_NODE_BAD_HDR;
+	}
+
+	/* check node type */
+	node_type =  be32_to_cpu(lh->node_type);
+	if (node_type != type) {
+		ubi_err("bad node type");
+		return -EBADMSG;
+	}
+
+
+	/* validate header crc */
+	stored_crc = be32_to_cpu(lh->hdr_crc);
+	crc = crc32(UBI_CRC32_INIT, lh, UBIL_NODE_SIZE_CRC);
+
+	if (stored_crc != crc) {
+		ubi_err("bad header crc");
+		dbg_bld("crc error: stored %d calculated %d", stored_crc, crc);
+		return UBIL_NODE_BAD_HDR;
+	}
+
+
+	/* validate data crc */
+	data_size = be32_to_cpu(lh->data_size);
+	if (data_size > ubi->node_size) {
+		ubi_err("bad data size");
+		return -EBADMSG;
+	}
+
+	/* check for data crc */
+	stored_crc = be32_to_cpu(lh->data_crc);
+	crc = crc32(UBI_CRC32_INIT, lh->data, data_size);
+
+	if (crc != stored_crc) {
+		ubi_err("bad data crc");
+		dbg_bld("crc error: stored %d calculated %d", stored_crc, crc);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+#endif	/* ! CONFIG_MTD_UBI_LOGGED */
 #endif /* !__UBI_UBI_H__ */
--- ubi-2.6/include/mtd/ubi-user.h	2010-04-11 13:19:21.516404100 +0530
+++ myubi-2.6/include/mtd/ubi-user.h	2010-04-11 13:17:44.063914743 +0530
@@ -209,6 +209,9 @@
 	UBI_LONGTERM  = 1,
 	UBI_SHORTTERM = 2,
 	UBI_UNKNOWN   = 3,
+#ifdef CONFIG_MTD_UBI_LOGGED
+	UBIL_RESVD    = 4,
+#endif
 };

 /*
@@ -237,6 +240,7 @@
  * @ubi_num: UBI device number to create
  * @mtd_num: MTD device number to attach
  * @vid_hdr_offset: VID header offset (use defaults if %0)
+ * @ubinize: ubinize the partition
  * @padding: reserved for future, not used, has to be zeroed
  *
  * This data structure is used to specify MTD device UBI has to attach and the
@@ -251,6 +255,9 @@
  * 512 in case of a 512 bytes page NAND flash with no sub-page support. Or
  * it will be 512 in case of a 2KiB page NAND flash with 4 512-byte sub-pages.
  *
+ * ubinize option is selected in first instance of ubi.this will be used when
+ * applications want the mtd partition to be ubinized.
+ *
  * But in rare cases, if this optimizes things, the VID header may be placed to
  * a different offset. For example, the boot-loader might do things faster if
  * the VID header sits at the end of the first 2KiB NAND page with 4 sub-pages.
@@ -264,7 +271,11 @@
 struct ubi_attach_req {
 	__s32 ubi_num;
 	__s32 mtd_num;
+#ifdef CONFIG_MTD_UBI_LOGGED
+	__s32 ubinize;
+#else
 	__s32 vid_hdr_offset;
+#endif
 	__s8 padding[12];
 };

--- ubi_old/drivers/mtd/ubi/ubi-media.h	2010-04-09 21:54:13.955581334 +0530
+++ ubi_new/drivers/mtd/ubi/ubi-media.h	2010-04-09 21:54:02.635580892 +0530
@@ -36,7 +36,15 @@
 #define UBI_VERSION 1

 /* The highest erase counter value supported by this implementation */
+
+#ifdef CONFIG_MTD_UBI_LOGGED
+/* UBIL takes 32 bit ec values. */
+#define UBI_MAX_ERASECOUNTER 0x7FFF
+/* default ec count to start with */
+#define UBIL_EC_START 0x0001
+#else
 #define UBI_MAX_ERASECOUNTER 0x7FFFFFFF
+#endif

 /* The initial CRC32 value used when calculating CRC checksums */
 #define UBI_CRC32_INIT 0xFFFFFFFFU
@@ -46,6 +54,69 @@
 /* Volume identifier header magic number (ASCII "UBI!") */
 #define UBI_VID_HDR_MAGIC 0x55424921

+#ifdef CONFIG_MTD_UBI_LOGGED
+/*
+ * UBI expects sub page size >=512. If not it will still work with size= 512
+ * TODO Try to fix UBIL for NOR. Single peb_info log entry should be possible.
+ */
+#define UBIL_MIN_SUB_PAGE_SIZE 512
+/* Offset where sb, el or cmt bud header will start */
+#define UBIL_BUD_HDR_OFFSET	0
+
+/* Version numbers of subsystem implementation */
+#define UBIL_EL_VERSION	1
+#define UBIL_CMT_VERSION 1
+#define UBIL_SB_VERSION 1
+
+/* UBI magic: (ASCII "UBIU") */
+#define UBI_MAGIC  0x55424955
+/* UBIL Node magic: (ASCII "UBIN")*/
+#define UBIL_NODE_MAGIC 0x5542494E
+/* UBIL sb bud hdr magic: (ASCII "UBIS") */
+#define UBIL_SB_BUD_MAGIC 0x55424953
+/* UBIL sb magic: (ASCII "UBIs")*/
+#define UBIL_SB_MAGIC  0x55424973
+/* UBIL EL bud header magic:(ASCII "UBIE" */
+#define UBIL_EL_BUD_HDR_MAGIC  0x55424945
+/* UBIL EL magic: (ASCII "UBIe" */
+#define UBIL_EL_MAGIC 0x55424965
+/* UBIL CMT Bud header magic: (ASCII "UBIC") */
+#define UBIL_CMT_BUD_HDR_MAGIC  0x55424943
+
+/* size of each eba log record */
+#define UBIL_EL_REC_SIZE sizeof(struct peb_info)
+/* size of each eba log node */
+#define UBIL_EL_NODE_HDR_SIZE sizeof(struct el_node)
+/* size of each UBIL node */
+#define UBIL_NODE_HDR_SIZE sizeof(struct node_t)
+
+/* size of each UBIL node excluding crc */
+#define UBIL_NODE_SIZE_CRC  (UBIL_NODE_HDR_SIZE  - sizeof(__be32))
+
+/* last commit status success or faild in between */
+#define UBIL_CMT_WRITE_SUCCESS 0x1
+#define UBIL_CMT_INVALID 0x0
+
+/**
+ * type of node.node is generic and could be any of following types
+ * UBIL_SB_BUD_HDR_T: sb bud hdr node type
+ * UBIL_EL_BUD_HDR_T: el bud hdr node type
+ * UBIL_CMT_BUD_HDR_T: cmt bud hdr node type
+ * UBIL_SB_NODE_T: sb node type
+ * UBIL_EL_NODE_T: el node type
+ * UBIL_CMT_NODE_T: cmt node type
+ */
+enum{
+	UBIL_SB_BUD_HDR_T  = 1,
+	UBIL_EL_BUD_HDR_T,
+	UBIL_CMT_BUD_HDR_T,
+	UBIL_SB_NODE_T,
+	UBIL_EL_NODE_T,
+	UBIL_CMT_NODE_T
+};
+
+#endif
+
 /*
  * Volume type constants used in the volume identifier header.
  *
@@ -204,7 +275,7 @@
  *
  * 1. Because UBI may erase physical eraseblocks asynchronously, the following
  * situation is possible: L is asynchronously erased, so P is scheduled for
- * erasure, then L is written to,i.e. mapped to another physical eraseblock P1,
+ * erasure, then L is written to, i.e. mapped to another physical
eraseblock P1,
  * so P1 is written to, then an unclean reboot happens. Result - there are 2
  * physical eraseblocks P and P1 corresponding to the same logical eraseblock
  * L. But P1 has greater sequence number, so UBI picks P1 when it attaches the
@@ -294,6 +365,212 @@
 	__be32  hdr_crc;
 } __attribute__ ((packed));

+#ifdef CONFIG_MTD_UBI_LOGGED
+
+/* media headers for UBIL start here */
+
+/**
+ * struct node_t: variable size stuctur to be used for sb, el, cmt
+ * @magic: node magic
+ * @node_type: identification expressing which type node it is
+ * @node_id:   unique identification to be used by node implementation.
+ * @data_size:	size of data this node contains
+ * @sqnum: sequence number of node, optional to use
+ * @padding2[32]: padding.
+ * @data_crc: data crc for node
+ * @hdr_crc: hdr crc
+ * @data: node data, variable size array. data_size shows the size.
+ *
+ * node_t is variable size of node, generic enough to be used for el node or sb
+ * node. node magic will remain same as NODE_MAGIC.
+ * node_type will decide which type of node it is, it can be
+ *	UBIL_SB_BUD_HDR_T: sb bud hdr node type
+ *	UBIL_EL_BUD_HDR_T: el bud hdr node type
+ *	UBIL_CMT_BUD_HDR_T: cmt bud hdr node type
+ *	UBIL_SB_NODE_T: sb node type
+ *	UBIL_EL_NODE_T: el node type
+ *	UBIL_CMT_NODE_T: cmt node type
+ * node_id can be used for node identification by implementation. el uses it
+ * to store the group id.
+ * data_size shows the size of node excluding the size of hdr. This helps for
+ * variable size node.
+ * TODO NOR: padding2 can be removed and if peb_info fits in 32 bytes, each
+ * group may contain one peb_info.
+ */
+
+struct node_t{
+	__be32	magic;
+	__be32	node_type;
+	__be32	node_id;
+	__be32	data_size;
+	__be64	sqnum;
+	__u8	padding[32];
+	__be32	data_crc;
+	__be32	hdr_crc;
+	__u8	data[0];
+} __attribute__((packed));
+
+/**
+ * struct sb_bud_hdr:  sb bud hdr type node
+ * @lh: this is node derived from generic node. Ref to generic node.
+ * @MAGIC: node magic
+ * @ubi_version: ubi version
+ * @log_version: el version
+ * @cmt_version: cmt version
+ * @rsvd_pebs: reserved pebs at the time of ubinize
+ * @beb_rsvd_pebs: reserved pebs for bad block
+ * @beb_rsvd_level: bad erase block level
+ * @flash_size: flash size at ubinize time
+ * @sqnum:
+ * @peb_count: peb count for the partition at ubinize time
+ * @peb_size: peb size
+ * @min_io_size: min io size at ubinize
+ * @hdrs_min_io_size: hdr min io size at ubinize
+ * @bad_allowed: is bad allowed?
+ *
+ * sb_bud_hdr is main structur of UBIL. This structer is calculated at ubinize.
+ * For each mount it is verified. UBIL does not handle resized mtd partition
+ * after ubinizing. This struct is footprint for UBIL. If mtd partition is not
+ * ubinized, user will need to do it explicitely.
+ */
+struct sb_bud_hdr{
+	struct node_t lh;
+	__be32 MAGIC;
+	__be32 ubi_version;
+	__be32 el_version;
+	__be32 cmt_version;
+
+	__be32 rsvd_pebs;
+	__be32 beb_rsvd_pebs;
+	__be32 beb_rsvd_level;
+	__be64 flash_size;
+	__be64 sqnum;
+	__be32 peb_count;
+	__be32 peb_size;
+	__be32 min_io_size;
+	__be32 hdrs_min_io_size;
+	__be32 bad_allowed;
+} __attribute__((packed));
+
+/**
+ * struct el_bud_hdr:  el bud hdr type node
+ * @lh: this is node derived from generic node. Ref to generic node.
+ * @MAGIC: node magic
+ * @el_version: el version
+ * @padding: padding 56 bytes
+ */
+
+struct el_bud_hdr{
+	struct node_t lh;
+	__be32 MAGIC;
+	__be32 log_version;
+	__u8 padding[56];
+} __attribute__((packed));
+
+/**
+ * struct ubil_vid_t on-flash UBIL volume identifier header.
+ * @vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC)
+ * @copy_flag: if this logical eraseblock was copied from another physical
+ *             eraseblock (for wear-leveling reasons)
+ * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE,
+ *          %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
+ * @vol_id: ID of this volume
+ * @lnum: logical eraseblock number
+ * @data_size: how many bytes of data this logical eraseblock contains
+ * @used_ebs: total number of used logical eraseblocks in this volume
+ * @data_crc: CRC checksum of the data stored in this logical eraseblock
+ * @sqnum: sequence number
+ */
+
+struct ubil_vid_t{
+	__u8    vol_type;
+	__u8    copy_flag;
+	__u8    compat;
+
+	__be32  vol_id;
+	__be32  lnum;
+	__be32  data_size;
+	__be32  used_ebs;
+	__be32  data_crc;
+	__be64  sqnum;
+} __attribute__((packed));
+
+/**
+ * struct peb_info- on-flash UBIL peb information.
+ * @status: status of peb
+ * @v: volume header of peb
+ * @ec: ec count of peb
+ *
+ * status of peb helps in knowing the peb state. If a peb is marked pending,
+ * it's inram status is made PENDING. If the group is written this state will
+ * be synced to flash. This will help in reducing sqnum calculation for such
+ * pebs.
+ */
+struct peb_info{
+	__u8 status;
+	struct ubi_vid_hdr v;
+	__be32 ec;
+} __attribute__((packed));
+
+/**
+ * struct el_node:  el node type node
+ * @lh: this is node derived from generic node. Ref to generic node.
+ * @peb_info recs: array of peb_info in that group.
+ *
+ * el_node groups multiple peb records in it. For NAND as minimum write size is
+ * much more that size needed for one peb, they are grouped in this node.
+ */
+
+struct el_node{
+	struct node_t lh;
+	struct peb_info recs[0];
+} __attribute__((packed));
+
+/**
+ * struct ubi_sb:  ubi_sb type node
+ * @lh: this is node derived from generic node. Ref to generic node.
+ * @version: sb version
+ * @el_resrvd_buds: how many pebs are reserved for el?
+ * @vtbl_peb[2]: pebs used for vtbl.
+ * @cmt_status: status of commit.
+ * @cmt_resrvd_buds: how many pebs are reserved for cmt
+ * @cmt_next_buds: the buds where next cmt was getting written
+ * @buds: array of buds where peb location is stored. el, cmt checks
+ * these location. this is variable array. It has EL buds, then cmt
+ * buds and then cmt_next_buds.
+ */
+
+struct ubi_sb{
+	struct node_t lh;
+	__be32 version;
+	__be32 cmt_status;
+	__be32 el_resrvd_buds;
+	__be32 cmt_resrvd_buds;
+	__be32 cmt_next_buds;
+	__be32 vtbl_peb[2];
+	__be32 buds[0];
+} __attribute__((packed));
+
+
+/**
+ * struct cmt_bud_hdr:  commit type node
+ * @lh: this is node derived from generic node. Ref to generic node.
+ * @MAGIC: magic of cmt bud
+ * @cmt_version: cmt version
+ * @padding: padding to align the header to 128 bytes.
+ */
+
+struct cmt_bud_hdr{
+	struct node_t lh;
+	__be32 MAGIC;
+	__be32 cmt_version;
+	__be32 data_size;
+	__u8 padding[48];
+	__be32 data_crc;
+} __attribute__((packed));
+
+#endif
+
 /* Internal UBI volumes count */
 #define UBI_INT_VOL_COUNT 1



More information about the linux-mtd mailing list