diff mbox series

[RFC,12/17] ubifs: Extract a helper function to create lpt

Message ID 20231228014112.2836317-13-chengzhihao1@huawei.com
State Changes Requested
Headers show
Series ubifs: Add filesystem repair support | expand

Commit Message

Zhihao Cheng Dec. 28, 2023, 1:41 a.m. UTC
Abstract a helper function to create lpt, this is a preparation to
add lpt creation support in ubifs_repair.

Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
---
 fs/ubifs/lpt.c    | 140 ++++++++++++++++++++++++++--------------------
 fs/ubifs/repair.h |  11 +---
 fs/ubifs/ubifs.h  |  18 ++++++
 3 files changed, 98 insertions(+), 71 deletions(-)
diff mbox series

Patch

diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c
index 778a22bf9a92..fa50ad5106d4 100644
--- a/fs/ubifs/lpt.c
+++ b/fs/ubifs/lpt.c
@@ -586,20 +586,21 @@  static int calc_pnode_num_from_parent(const struct ubifs_info *c,
 }
 
 /**
- * ubifs_create_dflt_lpt - create default LPT.
+ * ubifs_create_lpt - create lpt acccording to lprops array.
  * @c: UBIFS file-system description object
- * @main_lebs: number of main area LEBs is passed and returned here
- * @lpt_first: LEB number of first LPT LEB
- * @lpt_lebs: number of LEBs for LPT is passed and returned here
- * @big_lpt: use big LPT model is passed and returned here
+ * @lps: lprops array to record logical eraseblock properties
+ * @lp_cnt: the length of @lps
  * @hash: hash of the LPT is returned here
  *
- * This function returns %0 on success and a negative error code on failure.
+ * This function creates lpt, the pnode will be initialized based on
+ * corresponding elements in @lps. If there are no corresponding lprops
+ * (eg. @lp_cnt is smaller than @c->main_lebs), the LEB property is set
+ * as free state.
  */
-int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
-			  int *lpt_lebs, int *big_lpt, u8 *hash)
+int ubifs_create_lpt(struct ubifs_info *c, struct lprops *lps, int lp_cnt,
+		     u8 *hash)
 {
-	int lnum, err = 0, node_sz, iopos, i, j, cnt, len, alen, row;
+	int lnum, err = 0, i, j, cnt, len, alen, row;
 	int blnum, boffs, bsz, bcnt;
 	struct ubifs_pnode *pnode = NULL;
 	struct ubifs_nnode *nnode = NULL;
@@ -608,18 +609,6 @@  int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
 	int *lsave = NULL;
 	struct shash_desc *desc;
 
-	err = calc_dflt_lpt_geom(c, main_lebs, big_lpt);
-	if (err)
-		return err;
-	*lpt_lebs = c->lpt_lebs;
-
-	/* Needed by 'ubifs_pack_nnode()' and 'set_ltab()' */
-	c->lpt_first = lpt_first;
-	/* Needed by 'set_ltab()' */
-	c->lpt_last = lpt_first + c->lpt_lebs - 1;
-	/* Needed by 'ubifs_pack_lsave()' */
-	c->main_first = c->leb_cnt - *main_lebs;
-
 	desc = ubifs_hash_get_desc(c);
 	if (IS_ERR(desc))
 		return PTR_ERR(desc);
@@ -646,47 +635,12 @@  int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
 		ltab[i].cmt = 0;
 	}
 
-	lnum = lpt_first;
+	lnum = c->lpt_first;
 	p = buf;
+	len = 0;
 	/* Number of leaf nodes (pnodes) */
 	cnt = c->pnode_cnt;
 
-	/*
-	 * The first pnode contains the LEB properties for the LEBs that contain
-	 * the root inode node and the root index node of the index tree.
-	 */
-	node_sz = ALIGN(ubifs_idx_node_sz(c, 1), 8);
-	iopos = ALIGN(node_sz, c->min_io_size);
-	pnode->lprops[0].free = c->leb_size - iopos;
-	pnode->lprops[0].dirty = iopos - node_sz;
-	pnode->lprops[0].flags = LPROPS_INDEX;
-
-	node_sz = UBIFS_INO_NODE_SZ;
-	iopos = ALIGN(node_sz, c->min_io_size);
-	pnode->lprops[1].free = c->leb_size - iopos;
-	pnode->lprops[1].dirty = iopos - node_sz;
-
-	for (i = 2; i < UBIFS_LPT_FANOUT; i++)
-		pnode->lprops[i].free = c->leb_size;
-
-	/* Add first pnode */
-	ubifs_pack_pnode(c, p, pnode);
-	err = ubifs_shash_update(c, desc, p, c->pnode_sz);
-	if (err)
-		goto out;
-
-	p += c->pnode_sz;
-	len = c->pnode_sz;
-	pnode->num += 1;
-
-	/* Reset pnode values for remaining pnodes */
-	pnode->lprops[0].free = c->leb_size;
-	pnode->lprops[0].dirty = 0;
-	pnode->lprops[0].flags = 0;
-
-	pnode->lprops[1].free = c->leb_size;
-	pnode->lprops[1].dirty = 0;
-
 	/*
 	 * To calculate the internal node branches, we keep information about
 	 * the level below.
@@ -696,8 +650,8 @@  int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
 	bcnt = cnt; /* Number of nodes in level below */
 	bsz = c->pnode_sz; /* Size of nodes in level below */
 
-	/* Add all remaining pnodes */
-	for (i = 1; i < cnt; i++) {
+	/* Add all pnodes */
+	for (i = 0; i < cnt; i++) {
 		if (len + c->pnode_sz > c->leb_size) {
 			alen = ALIGN(len, c->min_io_size);
 			set_ltab(c, lnum, c->leb_size - alen, alen - len);
@@ -708,6 +662,20 @@  int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
 			p = buf;
 			len = 0;
 		}
+		/* Fill in the pnode */
+		for (j = 0; j < UBIFS_LPT_FANOUT; j++) {
+			int k = (i << UBIFS_LPT_FANOUT_SHIFT) + j;
+
+			if (k < lp_cnt) {
+				pnode->lprops[j].free = lps[k].free;
+				pnode->lprops[j].dirty = lps[k].dirty;
+				pnode->lprops[j].flags = lps[k].flags;
+			} else {
+				pnode->lprops[j].free = c->leb_size;
+				pnode->lprops[j].dirty = 0;
+				pnode->lprops[j].flags = 0;
+			}
+		}
 		ubifs_pack_pnode(c, p, pnode);
 		err = ubifs_shash_update(c, desc, p, c->pnode_sz);
 		if (err)
@@ -777,7 +745,7 @@  int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
 		row -= 1;
 	}
 
-	if (*big_lpt) {
+	if (c->big_lpt) {
 		/* Need to add LPT's save table */
 		if (len + c->lsave_sz > c->leb_size) {
 			alen = ALIGN(len, c->min_io_size);
@@ -793,7 +761,7 @@  int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
 		c->lsave_lnum = lnum;
 		c->lsave_offs = len;
 
-		for (i = 0; i < c->lsave_cnt && i < *main_lebs; i++)
+		for (i = 0; i < c->lsave_cnt && i < c->main_lebs; i++)
 			lsave[i] = c->main_first + i;
 		for (; i < c->lsave_cnt; i++)
 			lsave[i] = c->main_first;
@@ -868,6 +836,54 @@  int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
 	return err;
 }
 
+/**
+ * ubifs_create_dflt_lpt - create default LPT.
+ * @c: UBIFS file-system description object
+ * @main_lebs: number of main area LEBs is passed and returned here
+ * @lpt_first: LEB number of first LPT LEB
+ * @lpt_lebs: number of LEBs for LPT is passed and returned here
+ * @big_lpt: use big LPT model is passed and returned here
+ * @hash: hash of the LPT is returned here
+ *
+ * This function returns %0 on success and a negative error code on failure.
+ */
+int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
+			  int *lpt_lebs, int *big_lpt, u8 *hash)
+{
+	int node_sz, iopos, err = 0;
+	struct lprops lps[2];
+
+	err = calc_dflt_lpt_geom(c, main_lebs, big_lpt);
+	if (err)
+		return err;
+	*lpt_lebs = c->lpt_lebs;
+
+	/* Needed by 'ubifs_pack_nnode()' and 'set_ltab()' */
+	c->lpt_first = lpt_first;
+	/* Needed by 'set_ltab()' */
+	c->lpt_last = lpt_first + c->lpt_lebs - 1;
+	/* Needed by 'ubifs_pack_lsave()' */
+	c->main_first = c->leb_cnt - *main_lebs;
+
+	/*
+	 * The first pnode contains the LEB properties for the LEBs that contain
+	 * the root inode node and the root index node of the index tree.
+	 */
+	node_sz = ALIGN(ubifs_idx_node_sz(c, 1), 8);
+	iopos = ALIGN(node_sz, c->min_io_size);
+	lps[0].free = c->leb_size - iopos;
+	lps[0].dirty = iopos - node_sz;
+	lps[0].flags = LPROPS_INDEX;
+
+	node_sz = UBIFS_INO_NODE_SZ;
+	iopos = ALIGN(node_sz, c->min_io_size);
+	lps[1].free = c->leb_size - iopos;
+	lps[1].dirty = iopos - node_sz;
+	lps[1].flags = 0;
+
+	return ubifs_create_lpt(c, lps, 2, hash);
+}
+
 /**
  * update_cats - add LEB properties of a pnode to LEB category lists and heaps.
  * @c: UBIFS file-system description object
diff --git a/fs/ubifs/repair.h b/fs/ubifs/repair.h
index e3b879b3f999..f8d18f07e324 100644
--- a/fs/ubifs/repair.h
+++ b/fs/ubifs/repair.h
@@ -151,15 +151,6 @@  struct scanned_file {
 	struct rb_root data_nodes;
 };
 
-
-/**
- * lprops - logical eraseblock properties.
- * @end: the end postition of LEB calculated by the last node
- */
-struct lprops {
-	int end;
-};
-
 /**
  * ubifs_repair_info - per-FS repairing information.
  * @usen_lebs: a bitmap used for recording used lebs
@@ -168,6 +159,7 @@  struct lprops {
  * @write_buf: write buffer for LEB @head_lnum
  * @head_lnum: current writing LEB number
  * @head_offs: current writing position in LEB @head_lnum
+ * @need_update_lpt: whether to update lpt while writing index nodes
  */
 struct ubifs_repair_info {
 	unsigned long *used_lebs;
@@ -176,6 +168,7 @@  struct ubifs_repair_info {
 	void *write_buf;
 	int head_lnum;
 	int head_offs;
+	bool need_update_lpt;
 };
 
 #endif /* !__UBIFS_REPAIR_H__ */
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 7d66440623cb..5fe28980d151 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -495,6 +495,22 @@  struct ubifs_lprops {
 	};
 };
 
+/**
+ * struct lprops - logical eraseblock properties.
+ * @free: amount of free space in bytes
+ * @dirty: amount of dirty space in bytes
+ * @used: amount of used space in bytes
+ * @flags: LEB properties flags
+ * @end: the end postition of LEB calculated by the last node
+ */
+struct lprops {
+	int free;
+	int dirty;
+	int used;
+	int flags;
+	int end;
+};
+
 /**
  * struct ubifs_lpt_lprops - LPT logical eraseblock properties.
  * @free: amount of free space in bytes
@@ -2020,6 +2036,8 @@  int ubifs_clear_orphans(struct ubifs_info *c);
 
 /* lpt.c */
 int ubifs_calc_lpt_geom(struct ubifs_info *c);
+int ubifs_create_lpt(struct ubifs_info *c, struct lprops *lps, int lp_cnt,
+		     u8 *hash);
 int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
 			  int *lpt_lebs, int *big_lpt, u8 *hash);
 int ubifs_lpt_init(struct ubifs_info *c, int rd, int wr);