xref: /rk3399_rockchip-uboot/fs/ubifs/lpt_commit.c (revision e573bdb324c78fac56655a493bea843842c9d9f8)
19eefe2a2SStefan Roese /*
29eefe2a2SStefan Roese  * This file is part of UBIFS.
39eefe2a2SStefan Roese  *
49eefe2a2SStefan Roese  * Copyright (C) 2006-2008 Nokia Corporation.
59eefe2a2SStefan Roese  *
6ff94bc40SHeiko Schocher  * SPDX-License-Identifier:	GPL-2.0+
79eefe2a2SStefan Roese  *
89eefe2a2SStefan Roese  * Authors: Adrian Hunter
99eefe2a2SStefan Roese  *          Artem Bityutskiy (Битюцкий Артём)
109eefe2a2SStefan Roese  */
119eefe2a2SStefan Roese 
129eefe2a2SStefan Roese /*
139eefe2a2SStefan Roese  * This file implements commit-related functionality of the LEB properties
149eefe2a2SStefan Roese  * subsystem.
159eefe2a2SStefan Roese  */
169eefe2a2SStefan Roese 
17ff94bc40SHeiko Schocher #ifndef __UBOOT__
18ff94bc40SHeiko Schocher #include <linux/crc16.h>
19ff94bc40SHeiko Schocher #include <linux/slab.h>
20ff94bc40SHeiko Schocher #include <linux/random.h>
21ff94bc40SHeiko Schocher #else
22ff94bc40SHeiko Schocher #include <linux/compat.h>
23ff94bc40SHeiko Schocher #include <linux/err.h>
249eefe2a2SStefan Roese #include "crc16.h"
25ff94bc40SHeiko Schocher #endif
269eefe2a2SStefan Roese #include "ubifs.h"
279eefe2a2SStefan Roese 
28ff94bc40SHeiko Schocher #ifndef __UBOOT__
29ff94bc40SHeiko Schocher static int dbg_populate_lsave(struct ubifs_info *c);
30ff94bc40SHeiko Schocher #endif
31ff94bc40SHeiko Schocher 
32ff94bc40SHeiko Schocher /**
33ff94bc40SHeiko Schocher  * first_dirty_cnode - find first dirty cnode.
34ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
35ff94bc40SHeiko Schocher  * @nnode: nnode at which to start
36ff94bc40SHeiko Schocher  *
37ff94bc40SHeiko Schocher  * This function returns the first dirty cnode or %NULL if there is not one.
38ff94bc40SHeiko Schocher  */
first_dirty_cnode(struct ubifs_nnode * nnode)39ff94bc40SHeiko Schocher static struct ubifs_cnode *first_dirty_cnode(struct ubifs_nnode *nnode)
40ff94bc40SHeiko Schocher {
41ff94bc40SHeiko Schocher 	ubifs_assert(nnode);
42ff94bc40SHeiko Schocher 	while (1) {
43ff94bc40SHeiko Schocher 		int i, cont = 0;
44ff94bc40SHeiko Schocher 
45ff94bc40SHeiko Schocher 		for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
46ff94bc40SHeiko Schocher 			struct ubifs_cnode *cnode;
47ff94bc40SHeiko Schocher 
48ff94bc40SHeiko Schocher 			cnode = nnode->nbranch[i].cnode;
49ff94bc40SHeiko Schocher 			if (cnode &&
50ff94bc40SHeiko Schocher 			    test_bit(DIRTY_CNODE, &cnode->flags)) {
51ff94bc40SHeiko Schocher 				if (cnode->level == 0)
52ff94bc40SHeiko Schocher 					return cnode;
53ff94bc40SHeiko Schocher 				nnode = (struct ubifs_nnode *)cnode;
54ff94bc40SHeiko Schocher 				cont = 1;
55ff94bc40SHeiko Schocher 				break;
56ff94bc40SHeiko Schocher 			}
57ff94bc40SHeiko Schocher 		}
58ff94bc40SHeiko Schocher 		if (!cont)
59ff94bc40SHeiko Schocher 			return (struct ubifs_cnode *)nnode;
60ff94bc40SHeiko Schocher 	}
61ff94bc40SHeiko Schocher }
62ff94bc40SHeiko Schocher 
63ff94bc40SHeiko Schocher /**
64ff94bc40SHeiko Schocher  * next_dirty_cnode - find next dirty cnode.
65ff94bc40SHeiko Schocher  * @cnode: cnode from which to begin searching
66ff94bc40SHeiko Schocher  *
67ff94bc40SHeiko Schocher  * This function returns the next dirty cnode or %NULL if there is not one.
68ff94bc40SHeiko Schocher  */
next_dirty_cnode(struct ubifs_cnode * cnode)69ff94bc40SHeiko Schocher static struct ubifs_cnode *next_dirty_cnode(struct ubifs_cnode *cnode)
70ff94bc40SHeiko Schocher {
71ff94bc40SHeiko Schocher 	struct ubifs_nnode *nnode;
72ff94bc40SHeiko Schocher 	int i;
73ff94bc40SHeiko Schocher 
74ff94bc40SHeiko Schocher 	ubifs_assert(cnode);
75ff94bc40SHeiko Schocher 	nnode = cnode->parent;
76ff94bc40SHeiko Schocher 	if (!nnode)
77ff94bc40SHeiko Schocher 		return NULL;
78ff94bc40SHeiko Schocher 	for (i = cnode->iip + 1; i < UBIFS_LPT_FANOUT; i++) {
79ff94bc40SHeiko Schocher 		cnode = nnode->nbranch[i].cnode;
80ff94bc40SHeiko Schocher 		if (cnode && test_bit(DIRTY_CNODE, &cnode->flags)) {
81ff94bc40SHeiko Schocher 			if (cnode->level == 0)
82ff94bc40SHeiko Schocher 				return cnode; /* cnode is a pnode */
83ff94bc40SHeiko Schocher 			/* cnode is a nnode */
84ff94bc40SHeiko Schocher 			return first_dirty_cnode((struct ubifs_nnode *)cnode);
85ff94bc40SHeiko Schocher 		}
86ff94bc40SHeiko Schocher 	}
87ff94bc40SHeiko Schocher 	return (struct ubifs_cnode *)nnode;
88ff94bc40SHeiko Schocher }
89ff94bc40SHeiko Schocher 
90ff94bc40SHeiko Schocher /**
91ff94bc40SHeiko Schocher  * get_cnodes_to_commit - create list of dirty cnodes to commit.
92ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
93ff94bc40SHeiko Schocher  *
94ff94bc40SHeiko Schocher  * This function returns the number of cnodes to commit.
95ff94bc40SHeiko Schocher  */
get_cnodes_to_commit(struct ubifs_info * c)96ff94bc40SHeiko Schocher static int get_cnodes_to_commit(struct ubifs_info *c)
97ff94bc40SHeiko Schocher {
98ff94bc40SHeiko Schocher 	struct ubifs_cnode *cnode, *cnext;
99ff94bc40SHeiko Schocher 	int cnt = 0;
100ff94bc40SHeiko Schocher 
101ff94bc40SHeiko Schocher 	if (!c->nroot)
102ff94bc40SHeiko Schocher 		return 0;
103ff94bc40SHeiko Schocher 
104ff94bc40SHeiko Schocher 	if (!test_bit(DIRTY_CNODE, &c->nroot->flags))
105ff94bc40SHeiko Schocher 		return 0;
106ff94bc40SHeiko Schocher 
107ff94bc40SHeiko Schocher 	c->lpt_cnext = first_dirty_cnode(c->nroot);
108ff94bc40SHeiko Schocher 	cnode = c->lpt_cnext;
109ff94bc40SHeiko Schocher 	if (!cnode)
110ff94bc40SHeiko Schocher 		return 0;
111ff94bc40SHeiko Schocher 	cnt += 1;
112ff94bc40SHeiko Schocher 	while (1) {
113ff94bc40SHeiko Schocher 		ubifs_assert(!test_bit(COW_CNODE, &cnode->flags));
114ff94bc40SHeiko Schocher 		__set_bit(COW_CNODE, &cnode->flags);
115ff94bc40SHeiko Schocher 		cnext = next_dirty_cnode(cnode);
116ff94bc40SHeiko Schocher 		if (!cnext) {
117ff94bc40SHeiko Schocher 			cnode->cnext = c->lpt_cnext;
118ff94bc40SHeiko Schocher 			break;
119ff94bc40SHeiko Schocher 		}
120ff94bc40SHeiko Schocher 		cnode->cnext = cnext;
121ff94bc40SHeiko Schocher 		cnode = cnext;
122ff94bc40SHeiko Schocher 		cnt += 1;
123ff94bc40SHeiko Schocher 	}
124ff94bc40SHeiko Schocher 	dbg_cmt("committing %d cnodes", cnt);
125ff94bc40SHeiko Schocher 	dbg_lp("committing %d cnodes", cnt);
126ff94bc40SHeiko Schocher 	ubifs_assert(cnt == c->dirty_nn_cnt + c->dirty_pn_cnt);
127ff94bc40SHeiko Schocher 	return cnt;
128ff94bc40SHeiko Schocher }
129ff94bc40SHeiko Schocher 
130ff94bc40SHeiko Schocher /**
131ff94bc40SHeiko Schocher  * upd_ltab - update LPT LEB properties.
132ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
133ff94bc40SHeiko Schocher  * @lnum: LEB number
134ff94bc40SHeiko Schocher  * @free: amount of free space
135ff94bc40SHeiko Schocher  * @dirty: amount of dirty space to add
136ff94bc40SHeiko Schocher  */
upd_ltab(struct ubifs_info * c,int lnum,int free,int dirty)137ff94bc40SHeiko Schocher static void upd_ltab(struct ubifs_info *c, int lnum, int free, int dirty)
138ff94bc40SHeiko Schocher {
139ff94bc40SHeiko Schocher 	dbg_lp("LEB %d free %d dirty %d to %d +%d",
140ff94bc40SHeiko Schocher 	       lnum, c->ltab[lnum - c->lpt_first].free,
141ff94bc40SHeiko Schocher 	       c->ltab[lnum - c->lpt_first].dirty, free, dirty);
142ff94bc40SHeiko Schocher 	ubifs_assert(lnum >= c->lpt_first && lnum <= c->lpt_last);
143ff94bc40SHeiko Schocher 	c->ltab[lnum - c->lpt_first].free = free;
144ff94bc40SHeiko Schocher 	c->ltab[lnum - c->lpt_first].dirty += dirty;
145ff94bc40SHeiko Schocher }
146ff94bc40SHeiko Schocher 
147ff94bc40SHeiko Schocher /**
148ff94bc40SHeiko Schocher  * alloc_lpt_leb - allocate an LPT LEB that is empty.
149ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
150ff94bc40SHeiko Schocher  * @lnum: LEB number is passed and returned here
151ff94bc40SHeiko Schocher  *
152ff94bc40SHeiko Schocher  * This function finds the next empty LEB in the ltab starting from @lnum. If a
153ff94bc40SHeiko Schocher  * an empty LEB is found it is returned in @lnum and the function returns %0.
154ff94bc40SHeiko Schocher  * Otherwise the function returns -ENOSPC.  Note however, that LPT is designed
155ff94bc40SHeiko Schocher  * never to run out of space.
156ff94bc40SHeiko Schocher  */
alloc_lpt_leb(struct ubifs_info * c,int * lnum)157ff94bc40SHeiko Schocher static int alloc_lpt_leb(struct ubifs_info *c, int *lnum)
158ff94bc40SHeiko Schocher {
159ff94bc40SHeiko Schocher 	int i, n;
160ff94bc40SHeiko Schocher 
161ff94bc40SHeiko Schocher 	n = *lnum - c->lpt_first + 1;
162ff94bc40SHeiko Schocher 	for (i = n; i < c->lpt_lebs; i++) {
163ff94bc40SHeiko Schocher 		if (c->ltab[i].tgc || c->ltab[i].cmt)
164ff94bc40SHeiko Schocher 			continue;
165ff94bc40SHeiko Schocher 		if (c->ltab[i].free == c->leb_size) {
166ff94bc40SHeiko Schocher 			c->ltab[i].cmt = 1;
167ff94bc40SHeiko Schocher 			*lnum = i + c->lpt_first;
168ff94bc40SHeiko Schocher 			return 0;
169ff94bc40SHeiko Schocher 		}
170ff94bc40SHeiko Schocher 	}
171ff94bc40SHeiko Schocher 
172ff94bc40SHeiko Schocher 	for (i = 0; i < n; i++) {
173ff94bc40SHeiko Schocher 		if (c->ltab[i].tgc || c->ltab[i].cmt)
174ff94bc40SHeiko Schocher 			continue;
175ff94bc40SHeiko Schocher 		if (c->ltab[i].free == c->leb_size) {
176ff94bc40SHeiko Schocher 			c->ltab[i].cmt = 1;
177ff94bc40SHeiko Schocher 			*lnum = i + c->lpt_first;
178ff94bc40SHeiko Schocher 			return 0;
179ff94bc40SHeiko Schocher 		}
180ff94bc40SHeiko Schocher 	}
181ff94bc40SHeiko Schocher 	return -ENOSPC;
182ff94bc40SHeiko Schocher }
183ff94bc40SHeiko Schocher 
184ff94bc40SHeiko Schocher /**
185ff94bc40SHeiko Schocher  * layout_cnodes - layout cnodes for commit.
186ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
187ff94bc40SHeiko Schocher  *
188ff94bc40SHeiko Schocher  * This function returns %0 on success and a negative error code on failure.
189ff94bc40SHeiko Schocher  */
layout_cnodes(struct ubifs_info * c)190ff94bc40SHeiko Schocher static int layout_cnodes(struct ubifs_info *c)
191ff94bc40SHeiko Schocher {
192ff94bc40SHeiko Schocher 	int lnum, offs, len, alen, done_lsave, done_ltab, err;
193ff94bc40SHeiko Schocher 	struct ubifs_cnode *cnode;
194ff94bc40SHeiko Schocher 
195ff94bc40SHeiko Schocher 	err = dbg_chk_lpt_sz(c, 0, 0);
196ff94bc40SHeiko Schocher 	if (err)
197ff94bc40SHeiko Schocher 		return err;
198ff94bc40SHeiko Schocher 	cnode = c->lpt_cnext;
199ff94bc40SHeiko Schocher 	if (!cnode)
200ff94bc40SHeiko Schocher 		return 0;
201ff94bc40SHeiko Schocher 	lnum = c->nhead_lnum;
202ff94bc40SHeiko Schocher 	offs = c->nhead_offs;
203ff94bc40SHeiko Schocher 	/* Try to place lsave and ltab nicely */
204ff94bc40SHeiko Schocher 	done_lsave = !c->big_lpt;
205ff94bc40SHeiko Schocher 	done_ltab = 0;
206ff94bc40SHeiko Schocher 	if (!done_lsave && offs + c->lsave_sz <= c->leb_size) {
207ff94bc40SHeiko Schocher 		done_lsave = 1;
208ff94bc40SHeiko Schocher 		c->lsave_lnum = lnum;
209ff94bc40SHeiko Schocher 		c->lsave_offs = offs;
210ff94bc40SHeiko Schocher 		offs += c->lsave_sz;
211ff94bc40SHeiko Schocher 		dbg_chk_lpt_sz(c, 1, c->lsave_sz);
212ff94bc40SHeiko Schocher 	}
213ff94bc40SHeiko Schocher 
214ff94bc40SHeiko Schocher 	if (offs + c->ltab_sz <= c->leb_size) {
215ff94bc40SHeiko Schocher 		done_ltab = 1;
216ff94bc40SHeiko Schocher 		c->ltab_lnum = lnum;
217ff94bc40SHeiko Schocher 		c->ltab_offs = offs;
218ff94bc40SHeiko Schocher 		offs += c->ltab_sz;
219ff94bc40SHeiko Schocher 		dbg_chk_lpt_sz(c, 1, c->ltab_sz);
220ff94bc40SHeiko Schocher 	}
221ff94bc40SHeiko Schocher 
222ff94bc40SHeiko Schocher 	do {
223ff94bc40SHeiko Schocher 		if (cnode->level) {
224ff94bc40SHeiko Schocher 			len = c->nnode_sz;
225ff94bc40SHeiko Schocher 			c->dirty_nn_cnt -= 1;
226ff94bc40SHeiko Schocher 		} else {
227ff94bc40SHeiko Schocher 			len = c->pnode_sz;
228ff94bc40SHeiko Schocher 			c->dirty_pn_cnt -= 1;
229ff94bc40SHeiko Schocher 		}
230ff94bc40SHeiko Schocher 		while (offs + len > c->leb_size) {
231ff94bc40SHeiko Schocher 			alen = ALIGN(offs, c->min_io_size);
232ff94bc40SHeiko Schocher 			upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
233ff94bc40SHeiko Schocher 			dbg_chk_lpt_sz(c, 2, c->leb_size - offs);
234ff94bc40SHeiko Schocher 			err = alloc_lpt_leb(c, &lnum);
235ff94bc40SHeiko Schocher 			if (err)
236ff94bc40SHeiko Schocher 				goto no_space;
237ff94bc40SHeiko Schocher 			offs = 0;
238ff94bc40SHeiko Schocher 			ubifs_assert(lnum >= c->lpt_first &&
239ff94bc40SHeiko Schocher 				     lnum <= c->lpt_last);
240ff94bc40SHeiko Schocher 			/* Try to place lsave and ltab nicely */
241ff94bc40SHeiko Schocher 			if (!done_lsave) {
242ff94bc40SHeiko Schocher 				done_lsave = 1;
243ff94bc40SHeiko Schocher 				c->lsave_lnum = lnum;
244ff94bc40SHeiko Schocher 				c->lsave_offs = offs;
245ff94bc40SHeiko Schocher 				offs += c->lsave_sz;
246ff94bc40SHeiko Schocher 				dbg_chk_lpt_sz(c, 1, c->lsave_sz);
247ff94bc40SHeiko Schocher 				continue;
248ff94bc40SHeiko Schocher 			}
249ff94bc40SHeiko Schocher 			if (!done_ltab) {
250ff94bc40SHeiko Schocher 				done_ltab = 1;
251ff94bc40SHeiko Schocher 				c->ltab_lnum = lnum;
252ff94bc40SHeiko Schocher 				c->ltab_offs = offs;
253ff94bc40SHeiko Schocher 				offs += c->ltab_sz;
254ff94bc40SHeiko Schocher 				dbg_chk_lpt_sz(c, 1, c->ltab_sz);
255ff94bc40SHeiko Schocher 				continue;
256ff94bc40SHeiko Schocher 			}
257ff94bc40SHeiko Schocher 			break;
258ff94bc40SHeiko Schocher 		}
259ff94bc40SHeiko Schocher 		if (cnode->parent) {
260ff94bc40SHeiko Schocher 			cnode->parent->nbranch[cnode->iip].lnum = lnum;
261ff94bc40SHeiko Schocher 			cnode->parent->nbranch[cnode->iip].offs = offs;
262ff94bc40SHeiko Schocher 		} else {
263ff94bc40SHeiko Schocher 			c->lpt_lnum = lnum;
264ff94bc40SHeiko Schocher 			c->lpt_offs = offs;
265ff94bc40SHeiko Schocher 		}
266ff94bc40SHeiko Schocher 		offs += len;
267ff94bc40SHeiko Schocher 		dbg_chk_lpt_sz(c, 1, len);
268ff94bc40SHeiko Schocher 		cnode = cnode->cnext;
269ff94bc40SHeiko Schocher 	} while (cnode && cnode != c->lpt_cnext);
270ff94bc40SHeiko Schocher 
271ff94bc40SHeiko Schocher 	/* Make sure to place LPT's save table */
272ff94bc40SHeiko Schocher 	if (!done_lsave) {
273ff94bc40SHeiko Schocher 		if (offs + c->lsave_sz > c->leb_size) {
274ff94bc40SHeiko Schocher 			alen = ALIGN(offs, c->min_io_size);
275ff94bc40SHeiko Schocher 			upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
276ff94bc40SHeiko Schocher 			dbg_chk_lpt_sz(c, 2, c->leb_size - offs);
277ff94bc40SHeiko Schocher 			err = alloc_lpt_leb(c, &lnum);
278ff94bc40SHeiko Schocher 			if (err)
279ff94bc40SHeiko Schocher 				goto no_space;
280ff94bc40SHeiko Schocher 			offs = 0;
281ff94bc40SHeiko Schocher 			ubifs_assert(lnum >= c->lpt_first &&
282ff94bc40SHeiko Schocher 				     lnum <= c->lpt_last);
283ff94bc40SHeiko Schocher 		}
284ff94bc40SHeiko Schocher 		done_lsave = 1;
285ff94bc40SHeiko Schocher 		c->lsave_lnum = lnum;
286ff94bc40SHeiko Schocher 		c->lsave_offs = offs;
287ff94bc40SHeiko Schocher 		offs += c->lsave_sz;
288ff94bc40SHeiko Schocher 		dbg_chk_lpt_sz(c, 1, c->lsave_sz);
289ff94bc40SHeiko Schocher 	}
290ff94bc40SHeiko Schocher 
291ff94bc40SHeiko Schocher 	/* Make sure to place LPT's own lprops table */
292ff94bc40SHeiko Schocher 	if (!done_ltab) {
293ff94bc40SHeiko Schocher 		if (offs + c->ltab_sz > c->leb_size) {
294ff94bc40SHeiko Schocher 			alen = ALIGN(offs, c->min_io_size);
295ff94bc40SHeiko Schocher 			upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
296ff94bc40SHeiko Schocher 			dbg_chk_lpt_sz(c, 2, c->leb_size - offs);
297ff94bc40SHeiko Schocher 			err = alloc_lpt_leb(c, &lnum);
298ff94bc40SHeiko Schocher 			if (err)
299ff94bc40SHeiko Schocher 				goto no_space;
300ff94bc40SHeiko Schocher 			offs = 0;
301ff94bc40SHeiko Schocher 			ubifs_assert(lnum >= c->lpt_first &&
302ff94bc40SHeiko Schocher 				     lnum <= c->lpt_last);
303ff94bc40SHeiko Schocher 		}
304ff94bc40SHeiko Schocher 		c->ltab_lnum = lnum;
305ff94bc40SHeiko Schocher 		c->ltab_offs = offs;
306ff94bc40SHeiko Schocher 		offs += c->ltab_sz;
307ff94bc40SHeiko Schocher 		dbg_chk_lpt_sz(c, 1, c->ltab_sz);
308ff94bc40SHeiko Schocher 	}
309ff94bc40SHeiko Schocher 
310ff94bc40SHeiko Schocher 	alen = ALIGN(offs, c->min_io_size);
311ff94bc40SHeiko Schocher 	upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
312ff94bc40SHeiko Schocher 	dbg_chk_lpt_sz(c, 4, alen - offs);
313ff94bc40SHeiko Schocher 	err = dbg_chk_lpt_sz(c, 3, alen);
314ff94bc40SHeiko Schocher 	if (err)
315ff94bc40SHeiko Schocher 		return err;
316ff94bc40SHeiko Schocher 	return 0;
317ff94bc40SHeiko Schocher 
318ff94bc40SHeiko Schocher no_space:
319*0195a7bbSHeiko Schocher 	ubifs_err(c, "LPT out of space at LEB %d:%d needing %d, done_ltab %d, done_lsave %d",
320ff94bc40SHeiko Schocher 		  lnum, offs, len, done_ltab, done_lsave);
321ff94bc40SHeiko Schocher 	ubifs_dump_lpt_info(c);
322ff94bc40SHeiko Schocher 	ubifs_dump_lpt_lebs(c);
323ff94bc40SHeiko Schocher 	dump_stack();
324ff94bc40SHeiko Schocher 	return err;
325ff94bc40SHeiko Schocher }
326ff94bc40SHeiko Schocher 
327ff94bc40SHeiko Schocher #ifndef __UBOOT__
328ff94bc40SHeiko Schocher /**
329ff94bc40SHeiko Schocher  * realloc_lpt_leb - allocate an LPT LEB that is empty.
330ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
331ff94bc40SHeiko Schocher  * @lnum: LEB number is passed and returned here
332ff94bc40SHeiko Schocher  *
333ff94bc40SHeiko Schocher  * This function duplicates exactly the results of the function alloc_lpt_leb.
334ff94bc40SHeiko Schocher  * It is used during end commit to reallocate the same LEB numbers that were
335ff94bc40SHeiko Schocher  * allocated by alloc_lpt_leb during start commit.
336ff94bc40SHeiko Schocher  *
337ff94bc40SHeiko Schocher  * This function finds the next LEB that was allocated by the alloc_lpt_leb
338ff94bc40SHeiko Schocher  * function starting from @lnum. If a LEB is found it is returned in @lnum and
339ff94bc40SHeiko Schocher  * the function returns %0. Otherwise the function returns -ENOSPC.
340ff94bc40SHeiko Schocher  * Note however, that LPT is designed never to run out of space.
341ff94bc40SHeiko Schocher  */
realloc_lpt_leb(struct ubifs_info * c,int * lnum)342ff94bc40SHeiko Schocher static int realloc_lpt_leb(struct ubifs_info *c, int *lnum)
343ff94bc40SHeiko Schocher {
344ff94bc40SHeiko Schocher 	int i, n;
345ff94bc40SHeiko Schocher 
346ff94bc40SHeiko Schocher 	n = *lnum - c->lpt_first + 1;
347ff94bc40SHeiko Schocher 	for (i = n; i < c->lpt_lebs; i++)
348ff94bc40SHeiko Schocher 		if (c->ltab[i].cmt) {
349ff94bc40SHeiko Schocher 			c->ltab[i].cmt = 0;
350ff94bc40SHeiko Schocher 			*lnum = i + c->lpt_first;
351ff94bc40SHeiko Schocher 			return 0;
352ff94bc40SHeiko Schocher 		}
353ff94bc40SHeiko Schocher 
354ff94bc40SHeiko Schocher 	for (i = 0; i < n; i++)
355ff94bc40SHeiko Schocher 		if (c->ltab[i].cmt) {
356ff94bc40SHeiko Schocher 			c->ltab[i].cmt = 0;
357ff94bc40SHeiko Schocher 			*lnum = i + c->lpt_first;
358ff94bc40SHeiko Schocher 			return 0;
359ff94bc40SHeiko Schocher 		}
360ff94bc40SHeiko Schocher 	return -ENOSPC;
361ff94bc40SHeiko Schocher }
362ff94bc40SHeiko Schocher 
363ff94bc40SHeiko Schocher /**
364ff94bc40SHeiko Schocher  * write_cnodes - write cnodes for commit.
365ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
366ff94bc40SHeiko Schocher  *
367ff94bc40SHeiko Schocher  * This function returns %0 on success and a negative error code on failure.
368ff94bc40SHeiko Schocher  */
write_cnodes(struct ubifs_info * c)369ff94bc40SHeiko Schocher static int write_cnodes(struct ubifs_info *c)
370ff94bc40SHeiko Schocher {
371ff94bc40SHeiko Schocher 	int lnum, offs, len, from, err, wlen, alen, done_ltab, done_lsave;
372ff94bc40SHeiko Schocher 	struct ubifs_cnode *cnode;
373ff94bc40SHeiko Schocher 	void *buf = c->lpt_buf;
374ff94bc40SHeiko Schocher 
375ff94bc40SHeiko Schocher 	cnode = c->lpt_cnext;
376ff94bc40SHeiko Schocher 	if (!cnode)
377ff94bc40SHeiko Schocher 		return 0;
378ff94bc40SHeiko Schocher 	lnum = c->nhead_lnum;
379ff94bc40SHeiko Schocher 	offs = c->nhead_offs;
380ff94bc40SHeiko Schocher 	from = offs;
381ff94bc40SHeiko Schocher 	/* Ensure empty LEB is unmapped */
382ff94bc40SHeiko Schocher 	if (offs == 0) {
383ff94bc40SHeiko Schocher 		err = ubifs_leb_unmap(c, lnum);
384ff94bc40SHeiko Schocher 		if (err)
385ff94bc40SHeiko Schocher 			return err;
386ff94bc40SHeiko Schocher 	}
387ff94bc40SHeiko Schocher 	/* Try to place lsave and ltab nicely */
388ff94bc40SHeiko Schocher 	done_lsave = !c->big_lpt;
389ff94bc40SHeiko Schocher 	done_ltab = 0;
390ff94bc40SHeiko Schocher 	if (!done_lsave && offs + c->lsave_sz <= c->leb_size) {
391ff94bc40SHeiko Schocher 		done_lsave = 1;
392ff94bc40SHeiko Schocher 		ubifs_pack_lsave(c, buf + offs, c->lsave);
393ff94bc40SHeiko Schocher 		offs += c->lsave_sz;
394ff94bc40SHeiko Schocher 		dbg_chk_lpt_sz(c, 1, c->lsave_sz);
395ff94bc40SHeiko Schocher 	}
396ff94bc40SHeiko Schocher 
397ff94bc40SHeiko Schocher 	if (offs + c->ltab_sz <= c->leb_size) {
398ff94bc40SHeiko Schocher 		done_ltab = 1;
399ff94bc40SHeiko Schocher 		ubifs_pack_ltab(c, buf + offs, c->ltab_cmt);
400ff94bc40SHeiko Schocher 		offs += c->ltab_sz;
401ff94bc40SHeiko Schocher 		dbg_chk_lpt_sz(c, 1, c->ltab_sz);
402ff94bc40SHeiko Schocher 	}
403ff94bc40SHeiko Schocher 
404ff94bc40SHeiko Schocher 	/* Loop for each cnode */
405ff94bc40SHeiko Schocher 	do {
406ff94bc40SHeiko Schocher 		if (cnode->level)
407ff94bc40SHeiko Schocher 			len = c->nnode_sz;
408ff94bc40SHeiko Schocher 		else
409ff94bc40SHeiko Schocher 			len = c->pnode_sz;
410ff94bc40SHeiko Schocher 		while (offs + len > c->leb_size) {
411ff94bc40SHeiko Schocher 			wlen = offs - from;
412ff94bc40SHeiko Schocher 			if (wlen) {
413ff94bc40SHeiko Schocher 				alen = ALIGN(wlen, c->min_io_size);
414ff94bc40SHeiko Schocher 				memset(buf + offs, 0xff, alen - wlen);
415ff94bc40SHeiko Schocher 				err = ubifs_leb_write(c, lnum, buf + from, from,
416ff94bc40SHeiko Schocher 						       alen);
417ff94bc40SHeiko Schocher 				if (err)
418ff94bc40SHeiko Schocher 					return err;
419ff94bc40SHeiko Schocher 			}
420ff94bc40SHeiko Schocher 			dbg_chk_lpt_sz(c, 2, c->leb_size - offs);
421ff94bc40SHeiko Schocher 			err = realloc_lpt_leb(c, &lnum);
422ff94bc40SHeiko Schocher 			if (err)
423ff94bc40SHeiko Schocher 				goto no_space;
424ff94bc40SHeiko Schocher 			offs = from = 0;
425ff94bc40SHeiko Schocher 			ubifs_assert(lnum >= c->lpt_first &&
426ff94bc40SHeiko Schocher 				     lnum <= c->lpt_last);
427ff94bc40SHeiko Schocher 			err = ubifs_leb_unmap(c, lnum);
428ff94bc40SHeiko Schocher 			if (err)
429ff94bc40SHeiko Schocher 				return err;
430ff94bc40SHeiko Schocher 			/* Try to place lsave and ltab nicely */
431ff94bc40SHeiko Schocher 			if (!done_lsave) {
432ff94bc40SHeiko Schocher 				done_lsave = 1;
433ff94bc40SHeiko Schocher 				ubifs_pack_lsave(c, buf + offs, c->lsave);
434ff94bc40SHeiko Schocher 				offs += c->lsave_sz;
435ff94bc40SHeiko Schocher 				dbg_chk_lpt_sz(c, 1, c->lsave_sz);
436ff94bc40SHeiko Schocher 				continue;
437ff94bc40SHeiko Schocher 			}
438ff94bc40SHeiko Schocher 			if (!done_ltab) {
439ff94bc40SHeiko Schocher 				done_ltab = 1;
440ff94bc40SHeiko Schocher 				ubifs_pack_ltab(c, buf + offs, c->ltab_cmt);
441ff94bc40SHeiko Schocher 				offs += c->ltab_sz;
442ff94bc40SHeiko Schocher 				dbg_chk_lpt_sz(c, 1, c->ltab_sz);
443ff94bc40SHeiko Schocher 				continue;
444ff94bc40SHeiko Schocher 			}
445ff94bc40SHeiko Schocher 			break;
446ff94bc40SHeiko Schocher 		}
447ff94bc40SHeiko Schocher 		if (cnode->level)
448ff94bc40SHeiko Schocher 			ubifs_pack_nnode(c, buf + offs,
449ff94bc40SHeiko Schocher 					 (struct ubifs_nnode *)cnode);
450ff94bc40SHeiko Schocher 		else
451ff94bc40SHeiko Schocher 			ubifs_pack_pnode(c, buf + offs,
452ff94bc40SHeiko Schocher 					 (struct ubifs_pnode *)cnode);
453ff94bc40SHeiko Schocher 		/*
454ff94bc40SHeiko Schocher 		 * The reason for the barriers is the same as in case of TNC.
455ff94bc40SHeiko Schocher 		 * See comment in 'write_index()'. 'dirty_cow_nnode()' and
456ff94bc40SHeiko Schocher 		 * 'dirty_cow_pnode()' are the functions for which this is
457ff94bc40SHeiko Schocher 		 * important.
458ff94bc40SHeiko Schocher 		 */
459ff94bc40SHeiko Schocher 		clear_bit(DIRTY_CNODE, &cnode->flags);
460*0195a7bbSHeiko Schocher 		smp_mb__before_atomic();
461ff94bc40SHeiko Schocher 		clear_bit(COW_CNODE, &cnode->flags);
462*0195a7bbSHeiko Schocher 		smp_mb__after_atomic();
463ff94bc40SHeiko Schocher 		offs += len;
464ff94bc40SHeiko Schocher 		dbg_chk_lpt_sz(c, 1, len);
465ff94bc40SHeiko Schocher 		cnode = cnode->cnext;
466ff94bc40SHeiko Schocher 	} while (cnode && cnode != c->lpt_cnext);
467ff94bc40SHeiko Schocher 
468ff94bc40SHeiko Schocher 	/* Make sure to place LPT's save table */
469ff94bc40SHeiko Schocher 	if (!done_lsave) {
470ff94bc40SHeiko Schocher 		if (offs + c->lsave_sz > c->leb_size) {
471ff94bc40SHeiko Schocher 			wlen = offs - from;
472ff94bc40SHeiko Schocher 			alen = ALIGN(wlen, c->min_io_size);
473ff94bc40SHeiko Schocher 			memset(buf + offs, 0xff, alen - wlen);
474ff94bc40SHeiko Schocher 			err = ubifs_leb_write(c, lnum, buf + from, from, alen);
475ff94bc40SHeiko Schocher 			if (err)
476ff94bc40SHeiko Schocher 				return err;
477ff94bc40SHeiko Schocher 			dbg_chk_lpt_sz(c, 2, c->leb_size - offs);
478ff94bc40SHeiko Schocher 			err = realloc_lpt_leb(c, &lnum);
479ff94bc40SHeiko Schocher 			if (err)
480ff94bc40SHeiko Schocher 				goto no_space;
481ff94bc40SHeiko Schocher 			offs = from = 0;
482ff94bc40SHeiko Schocher 			ubifs_assert(lnum >= c->lpt_first &&
483ff94bc40SHeiko Schocher 				     lnum <= c->lpt_last);
484ff94bc40SHeiko Schocher 			err = ubifs_leb_unmap(c, lnum);
485ff94bc40SHeiko Schocher 			if (err)
486ff94bc40SHeiko Schocher 				return err;
487ff94bc40SHeiko Schocher 		}
488ff94bc40SHeiko Schocher 		done_lsave = 1;
489ff94bc40SHeiko Schocher 		ubifs_pack_lsave(c, buf + offs, c->lsave);
490ff94bc40SHeiko Schocher 		offs += c->lsave_sz;
491ff94bc40SHeiko Schocher 		dbg_chk_lpt_sz(c, 1, c->lsave_sz);
492ff94bc40SHeiko Schocher 	}
493ff94bc40SHeiko Schocher 
494ff94bc40SHeiko Schocher 	/* Make sure to place LPT's own lprops table */
495ff94bc40SHeiko Schocher 	if (!done_ltab) {
496ff94bc40SHeiko Schocher 		if (offs + c->ltab_sz > c->leb_size) {
497ff94bc40SHeiko Schocher 			wlen = offs - from;
498ff94bc40SHeiko Schocher 			alen = ALIGN(wlen, c->min_io_size);
499ff94bc40SHeiko Schocher 			memset(buf + offs, 0xff, alen - wlen);
500ff94bc40SHeiko Schocher 			err = ubifs_leb_write(c, lnum, buf + from, from, alen);
501ff94bc40SHeiko Schocher 			if (err)
502ff94bc40SHeiko Schocher 				return err;
503ff94bc40SHeiko Schocher 			dbg_chk_lpt_sz(c, 2, c->leb_size - offs);
504ff94bc40SHeiko Schocher 			err = realloc_lpt_leb(c, &lnum);
505ff94bc40SHeiko Schocher 			if (err)
506ff94bc40SHeiko Schocher 				goto no_space;
507ff94bc40SHeiko Schocher 			offs = from = 0;
508ff94bc40SHeiko Schocher 			ubifs_assert(lnum >= c->lpt_first &&
509ff94bc40SHeiko Schocher 				     lnum <= c->lpt_last);
510ff94bc40SHeiko Schocher 			err = ubifs_leb_unmap(c, lnum);
511ff94bc40SHeiko Schocher 			if (err)
512ff94bc40SHeiko Schocher 				return err;
513ff94bc40SHeiko Schocher 		}
514ff94bc40SHeiko Schocher 		ubifs_pack_ltab(c, buf + offs, c->ltab_cmt);
515ff94bc40SHeiko Schocher 		offs += c->ltab_sz;
516ff94bc40SHeiko Schocher 		dbg_chk_lpt_sz(c, 1, c->ltab_sz);
517ff94bc40SHeiko Schocher 	}
518ff94bc40SHeiko Schocher 
519ff94bc40SHeiko Schocher 	/* Write remaining data in buffer */
520ff94bc40SHeiko Schocher 	wlen = offs - from;
521ff94bc40SHeiko Schocher 	alen = ALIGN(wlen, c->min_io_size);
522ff94bc40SHeiko Schocher 	memset(buf + offs, 0xff, alen - wlen);
523ff94bc40SHeiko Schocher 	err = ubifs_leb_write(c, lnum, buf + from, from, alen);
524ff94bc40SHeiko Schocher 	if (err)
525ff94bc40SHeiko Schocher 		return err;
526ff94bc40SHeiko Schocher 
527ff94bc40SHeiko Schocher 	dbg_chk_lpt_sz(c, 4, alen - wlen);
528ff94bc40SHeiko Schocher 	err = dbg_chk_lpt_sz(c, 3, ALIGN(offs, c->min_io_size));
529ff94bc40SHeiko Schocher 	if (err)
530ff94bc40SHeiko Schocher 		return err;
531ff94bc40SHeiko Schocher 
532ff94bc40SHeiko Schocher 	c->nhead_lnum = lnum;
533ff94bc40SHeiko Schocher 	c->nhead_offs = ALIGN(offs, c->min_io_size);
534ff94bc40SHeiko Schocher 
535ff94bc40SHeiko Schocher 	dbg_lp("LPT root is at %d:%d", c->lpt_lnum, c->lpt_offs);
536ff94bc40SHeiko Schocher 	dbg_lp("LPT head is at %d:%d", c->nhead_lnum, c->nhead_offs);
537ff94bc40SHeiko Schocher 	dbg_lp("LPT ltab is at %d:%d", c->ltab_lnum, c->ltab_offs);
538ff94bc40SHeiko Schocher 	if (c->big_lpt)
539ff94bc40SHeiko Schocher 		dbg_lp("LPT lsave is at %d:%d", c->lsave_lnum, c->lsave_offs);
540ff94bc40SHeiko Schocher 
541ff94bc40SHeiko Schocher 	return 0;
542ff94bc40SHeiko Schocher 
543ff94bc40SHeiko Schocher no_space:
544*0195a7bbSHeiko Schocher 	ubifs_err(c, "LPT out of space mismatch at LEB %d:%d needing %d, done_ltab %d, done_lsave %d",
545ff94bc40SHeiko Schocher 		  lnum, offs, len, done_ltab, done_lsave);
546ff94bc40SHeiko Schocher 	ubifs_dump_lpt_info(c);
547ff94bc40SHeiko Schocher 	ubifs_dump_lpt_lebs(c);
548ff94bc40SHeiko Schocher 	dump_stack();
549ff94bc40SHeiko Schocher 	return err;
550ff94bc40SHeiko Schocher }
551ff94bc40SHeiko Schocher #endif
552ff94bc40SHeiko Schocher 
553ff94bc40SHeiko Schocher /**
554ff94bc40SHeiko Schocher  * next_pnode_to_dirty - find next pnode to dirty.
555ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
556ff94bc40SHeiko Schocher  * @pnode: pnode
557ff94bc40SHeiko Schocher  *
558ff94bc40SHeiko Schocher  * This function returns the next pnode to dirty or %NULL if there are no more
559ff94bc40SHeiko Schocher  * pnodes.  Note that pnodes that have never been written (lnum == 0) are
560ff94bc40SHeiko Schocher  * skipped.
561ff94bc40SHeiko Schocher  */
next_pnode_to_dirty(struct ubifs_info * c,struct ubifs_pnode * pnode)562ff94bc40SHeiko Schocher static struct ubifs_pnode *next_pnode_to_dirty(struct ubifs_info *c,
563ff94bc40SHeiko Schocher 					       struct ubifs_pnode *pnode)
564ff94bc40SHeiko Schocher {
565ff94bc40SHeiko Schocher 	struct ubifs_nnode *nnode;
566ff94bc40SHeiko Schocher 	int iip;
567ff94bc40SHeiko Schocher 
568ff94bc40SHeiko Schocher 	/* Try to go right */
569ff94bc40SHeiko Schocher 	nnode = pnode->parent;
570ff94bc40SHeiko Schocher 	for (iip = pnode->iip + 1; iip < UBIFS_LPT_FANOUT; iip++) {
571ff94bc40SHeiko Schocher 		if (nnode->nbranch[iip].lnum)
572ff94bc40SHeiko Schocher 			return ubifs_get_pnode(c, nnode, iip);
573ff94bc40SHeiko Schocher 	}
574ff94bc40SHeiko Schocher 
575ff94bc40SHeiko Schocher 	/* Go up while can't go right */
576ff94bc40SHeiko Schocher 	do {
577ff94bc40SHeiko Schocher 		iip = nnode->iip + 1;
578ff94bc40SHeiko Schocher 		nnode = nnode->parent;
579ff94bc40SHeiko Schocher 		if (!nnode)
580ff94bc40SHeiko Schocher 			return NULL;
581ff94bc40SHeiko Schocher 		for (; iip < UBIFS_LPT_FANOUT; iip++) {
582ff94bc40SHeiko Schocher 			if (nnode->nbranch[iip].lnum)
583ff94bc40SHeiko Schocher 				break;
584ff94bc40SHeiko Schocher 		}
585ff94bc40SHeiko Schocher 	} while (iip >= UBIFS_LPT_FANOUT);
586ff94bc40SHeiko Schocher 
587ff94bc40SHeiko Schocher 	/* Go right */
588ff94bc40SHeiko Schocher 	nnode = ubifs_get_nnode(c, nnode, iip);
589ff94bc40SHeiko Schocher 	if (IS_ERR(nnode))
590ff94bc40SHeiko Schocher 		return (void *)nnode;
591ff94bc40SHeiko Schocher 
592ff94bc40SHeiko Schocher 	/* Go down to level 1 */
593ff94bc40SHeiko Schocher 	while (nnode->level > 1) {
594ff94bc40SHeiko Schocher 		for (iip = 0; iip < UBIFS_LPT_FANOUT; iip++) {
595ff94bc40SHeiko Schocher 			if (nnode->nbranch[iip].lnum)
596ff94bc40SHeiko Schocher 				break;
597ff94bc40SHeiko Schocher 		}
598ff94bc40SHeiko Schocher 		if (iip >= UBIFS_LPT_FANOUT) {
599ff94bc40SHeiko Schocher 			/*
600ff94bc40SHeiko Schocher 			 * Should not happen, but we need to keep going
601ff94bc40SHeiko Schocher 			 * if it does.
602ff94bc40SHeiko Schocher 			 */
603ff94bc40SHeiko Schocher 			iip = 0;
604ff94bc40SHeiko Schocher 		}
605ff94bc40SHeiko Schocher 		nnode = ubifs_get_nnode(c, nnode, iip);
606ff94bc40SHeiko Schocher 		if (IS_ERR(nnode))
607ff94bc40SHeiko Schocher 			return (void *)nnode;
608ff94bc40SHeiko Schocher 	}
609ff94bc40SHeiko Schocher 
610ff94bc40SHeiko Schocher 	for (iip = 0; iip < UBIFS_LPT_FANOUT; iip++)
611ff94bc40SHeiko Schocher 		if (nnode->nbranch[iip].lnum)
612ff94bc40SHeiko Schocher 			break;
613ff94bc40SHeiko Schocher 	if (iip >= UBIFS_LPT_FANOUT)
614ff94bc40SHeiko Schocher 		/* Should not happen, but we need to keep going if it does */
615ff94bc40SHeiko Schocher 		iip = 0;
616ff94bc40SHeiko Schocher 	return ubifs_get_pnode(c, nnode, iip);
617ff94bc40SHeiko Schocher }
618ff94bc40SHeiko Schocher 
619ff94bc40SHeiko Schocher /**
620ff94bc40SHeiko Schocher  * pnode_lookup - lookup a pnode in the LPT.
621ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
622ff94bc40SHeiko Schocher  * @i: pnode number (0 to main_lebs - 1)
623ff94bc40SHeiko Schocher  *
624ff94bc40SHeiko Schocher  * This function returns a pointer to the pnode on success or a negative
625ff94bc40SHeiko Schocher  * error code on failure.
626ff94bc40SHeiko Schocher  */
pnode_lookup(struct ubifs_info * c,int i)627ff94bc40SHeiko Schocher static struct ubifs_pnode *pnode_lookup(struct ubifs_info *c, int i)
628ff94bc40SHeiko Schocher {
629ff94bc40SHeiko Schocher 	int err, h, iip, shft;
630ff94bc40SHeiko Schocher 	struct ubifs_nnode *nnode;
631ff94bc40SHeiko Schocher 
632ff94bc40SHeiko Schocher 	if (!c->nroot) {
633ff94bc40SHeiko Schocher 		err = ubifs_read_nnode(c, NULL, 0);
634ff94bc40SHeiko Schocher 		if (err)
635ff94bc40SHeiko Schocher 			return ERR_PTR(err);
636ff94bc40SHeiko Schocher 	}
637ff94bc40SHeiko Schocher 	i <<= UBIFS_LPT_FANOUT_SHIFT;
638ff94bc40SHeiko Schocher 	nnode = c->nroot;
639ff94bc40SHeiko Schocher 	shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT;
640ff94bc40SHeiko Schocher 	for (h = 1; h < c->lpt_hght; h++) {
641ff94bc40SHeiko Schocher 		iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
642ff94bc40SHeiko Schocher 		shft -= UBIFS_LPT_FANOUT_SHIFT;
643ff94bc40SHeiko Schocher 		nnode = ubifs_get_nnode(c, nnode, iip);
644ff94bc40SHeiko Schocher 		if (IS_ERR(nnode))
645ff94bc40SHeiko Schocher 			return ERR_CAST(nnode);
646ff94bc40SHeiko Schocher 	}
647ff94bc40SHeiko Schocher 	iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
648ff94bc40SHeiko Schocher 	return ubifs_get_pnode(c, nnode, iip);
649ff94bc40SHeiko Schocher }
650ff94bc40SHeiko Schocher 
651ff94bc40SHeiko Schocher /**
652ff94bc40SHeiko Schocher  * add_pnode_dirt - add dirty space to LPT LEB properties.
653ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
654ff94bc40SHeiko Schocher  * @pnode: pnode for which to add dirt
655ff94bc40SHeiko Schocher  */
add_pnode_dirt(struct ubifs_info * c,struct ubifs_pnode * pnode)656ff94bc40SHeiko Schocher static void add_pnode_dirt(struct ubifs_info *c, struct ubifs_pnode *pnode)
657ff94bc40SHeiko Schocher {
658ff94bc40SHeiko Schocher 	ubifs_add_lpt_dirt(c, pnode->parent->nbranch[pnode->iip].lnum,
659ff94bc40SHeiko Schocher 			   c->pnode_sz);
660ff94bc40SHeiko Schocher }
661ff94bc40SHeiko Schocher 
662ff94bc40SHeiko Schocher /**
663ff94bc40SHeiko Schocher  * do_make_pnode_dirty - mark a pnode dirty.
664ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
665ff94bc40SHeiko Schocher  * @pnode: pnode to mark dirty
666ff94bc40SHeiko Schocher  */
do_make_pnode_dirty(struct ubifs_info * c,struct ubifs_pnode * pnode)667ff94bc40SHeiko Schocher static void do_make_pnode_dirty(struct ubifs_info *c, struct ubifs_pnode *pnode)
668ff94bc40SHeiko Schocher {
669ff94bc40SHeiko Schocher 	/* Assumes cnext list is empty i.e. not called during commit */
670ff94bc40SHeiko Schocher 	if (!test_and_set_bit(DIRTY_CNODE, &pnode->flags)) {
671ff94bc40SHeiko Schocher 		struct ubifs_nnode *nnode;
672ff94bc40SHeiko Schocher 
673ff94bc40SHeiko Schocher 		c->dirty_pn_cnt += 1;
674ff94bc40SHeiko Schocher 		add_pnode_dirt(c, pnode);
675ff94bc40SHeiko Schocher 		/* Mark parent and ancestors dirty too */
676ff94bc40SHeiko Schocher 		nnode = pnode->parent;
677ff94bc40SHeiko Schocher 		while (nnode) {
678ff94bc40SHeiko Schocher 			if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) {
679ff94bc40SHeiko Schocher 				c->dirty_nn_cnt += 1;
680ff94bc40SHeiko Schocher 				ubifs_add_nnode_dirt(c, nnode);
681ff94bc40SHeiko Schocher 				nnode = nnode->parent;
682ff94bc40SHeiko Schocher 			} else
683ff94bc40SHeiko Schocher 				break;
684ff94bc40SHeiko Schocher 		}
685ff94bc40SHeiko Schocher 	}
686ff94bc40SHeiko Schocher }
687ff94bc40SHeiko Schocher 
688ff94bc40SHeiko Schocher /**
689ff94bc40SHeiko Schocher  * make_tree_dirty - mark the entire LEB properties tree dirty.
690ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
691ff94bc40SHeiko Schocher  *
692ff94bc40SHeiko Schocher  * This function is used by the "small" LPT model to cause the entire LEB
693ff94bc40SHeiko Schocher  * properties tree to be written.  The "small" LPT model does not use LPT
694ff94bc40SHeiko Schocher  * garbage collection because it is more efficient to write the entire tree
695ff94bc40SHeiko Schocher  * (because it is small).
696ff94bc40SHeiko Schocher  *
697ff94bc40SHeiko Schocher  * This function returns %0 on success and a negative error code on failure.
698ff94bc40SHeiko Schocher  */
make_tree_dirty(struct ubifs_info * c)699ff94bc40SHeiko Schocher static int make_tree_dirty(struct ubifs_info *c)
700ff94bc40SHeiko Schocher {
701ff94bc40SHeiko Schocher 	struct ubifs_pnode *pnode;
702ff94bc40SHeiko Schocher 
703ff94bc40SHeiko Schocher 	pnode = pnode_lookup(c, 0);
704ff94bc40SHeiko Schocher 	if (IS_ERR(pnode))
705ff94bc40SHeiko Schocher 		return PTR_ERR(pnode);
706ff94bc40SHeiko Schocher 
707ff94bc40SHeiko Schocher 	while (pnode) {
708ff94bc40SHeiko Schocher 		do_make_pnode_dirty(c, pnode);
709ff94bc40SHeiko Schocher 		pnode = next_pnode_to_dirty(c, pnode);
710ff94bc40SHeiko Schocher 		if (IS_ERR(pnode))
711ff94bc40SHeiko Schocher 			return PTR_ERR(pnode);
712ff94bc40SHeiko Schocher 	}
713ff94bc40SHeiko Schocher 	return 0;
714ff94bc40SHeiko Schocher }
715ff94bc40SHeiko Schocher 
716ff94bc40SHeiko Schocher /**
717ff94bc40SHeiko Schocher  * need_write_all - determine if the LPT area is running out of free space.
718ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
719ff94bc40SHeiko Schocher  *
720ff94bc40SHeiko Schocher  * This function returns %1 if the LPT area is running out of free space and %0
721ff94bc40SHeiko Schocher  * if it is not.
722ff94bc40SHeiko Schocher  */
need_write_all(struct ubifs_info * c)723ff94bc40SHeiko Schocher static int need_write_all(struct ubifs_info *c)
724ff94bc40SHeiko Schocher {
725ff94bc40SHeiko Schocher 	long long free = 0;
726ff94bc40SHeiko Schocher 	int i;
727ff94bc40SHeiko Schocher 
728ff94bc40SHeiko Schocher 	for (i = 0; i < c->lpt_lebs; i++) {
729ff94bc40SHeiko Schocher 		if (i + c->lpt_first == c->nhead_lnum)
730ff94bc40SHeiko Schocher 			free += c->leb_size - c->nhead_offs;
731ff94bc40SHeiko Schocher 		else if (c->ltab[i].free == c->leb_size)
732ff94bc40SHeiko Schocher 			free += c->leb_size;
733ff94bc40SHeiko Schocher 		else if (c->ltab[i].free + c->ltab[i].dirty == c->leb_size)
734ff94bc40SHeiko Schocher 			free += c->leb_size;
735ff94bc40SHeiko Schocher 	}
736ff94bc40SHeiko Schocher 	/* Less than twice the size left */
737ff94bc40SHeiko Schocher 	if (free <= c->lpt_sz * 2)
738ff94bc40SHeiko Schocher 		return 1;
739ff94bc40SHeiko Schocher 	return 0;
740ff94bc40SHeiko Schocher }
741ff94bc40SHeiko Schocher 
742ff94bc40SHeiko Schocher /**
743ff94bc40SHeiko Schocher  * lpt_tgc_start - start trivial garbage collection of LPT LEBs.
744ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
745ff94bc40SHeiko Schocher  *
746ff94bc40SHeiko Schocher  * LPT trivial garbage collection is where a LPT LEB contains only dirty and
747ff94bc40SHeiko Schocher  * free space and so may be reused as soon as the next commit is completed.
748ff94bc40SHeiko Schocher  * This function is called during start commit to mark LPT LEBs for trivial GC.
749ff94bc40SHeiko Schocher  */
lpt_tgc_start(struct ubifs_info * c)750ff94bc40SHeiko Schocher static void lpt_tgc_start(struct ubifs_info *c)
751ff94bc40SHeiko Schocher {
752ff94bc40SHeiko Schocher 	int i;
753ff94bc40SHeiko Schocher 
754ff94bc40SHeiko Schocher 	for (i = 0; i < c->lpt_lebs; i++) {
755ff94bc40SHeiko Schocher 		if (i + c->lpt_first == c->nhead_lnum)
756ff94bc40SHeiko Schocher 			continue;
757ff94bc40SHeiko Schocher 		if (c->ltab[i].dirty > 0 &&
758ff94bc40SHeiko Schocher 		    c->ltab[i].free + c->ltab[i].dirty == c->leb_size) {
759ff94bc40SHeiko Schocher 			c->ltab[i].tgc = 1;
760ff94bc40SHeiko Schocher 			c->ltab[i].free = c->leb_size;
761ff94bc40SHeiko Schocher 			c->ltab[i].dirty = 0;
762ff94bc40SHeiko Schocher 			dbg_lp("LEB %d", i + c->lpt_first);
763ff94bc40SHeiko Schocher 		}
764ff94bc40SHeiko Schocher 	}
765ff94bc40SHeiko Schocher }
766ff94bc40SHeiko Schocher 
767ff94bc40SHeiko Schocher /**
768ff94bc40SHeiko Schocher  * lpt_tgc_end - end trivial garbage collection of LPT LEBs.
769ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
770ff94bc40SHeiko Schocher  *
771ff94bc40SHeiko Schocher  * LPT trivial garbage collection is where a LPT LEB contains only dirty and
772ff94bc40SHeiko Schocher  * free space and so may be reused as soon as the next commit is completed.
773ff94bc40SHeiko Schocher  * This function is called after the commit is completed (master node has been
774ff94bc40SHeiko Schocher  * written) and un-maps LPT LEBs that were marked for trivial GC.
775ff94bc40SHeiko Schocher  */
lpt_tgc_end(struct ubifs_info * c)776ff94bc40SHeiko Schocher static int lpt_tgc_end(struct ubifs_info *c)
777ff94bc40SHeiko Schocher {
778ff94bc40SHeiko Schocher 	int i, err;
779ff94bc40SHeiko Schocher 
780ff94bc40SHeiko Schocher 	for (i = 0; i < c->lpt_lebs; i++)
781ff94bc40SHeiko Schocher 		if (c->ltab[i].tgc) {
782ff94bc40SHeiko Schocher 			err = ubifs_leb_unmap(c, i + c->lpt_first);
783ff94bc40SHeiko Schocher 			if (err)
784ff94bc40SHeiko Schocher 				return err;
785ff94bc40SHeiko Schocher 			c->ltab[i].tgc = 0;
786ff94bc40SHeiko Schocher 			dbg_lp("LEB %d", i + c->lpt_first);
787ff94bc40SHeiko Schocher 		}
788ff94bc40SHeiko Schocher 	return 0;
789ff94bc40SHeiko Schocher }
790ff94bc40SHeiko Schocher 
791ff94bc40SHeiko Schocher /**
792ff94bc40SHeiko Schocher  * populate_lsave - fill the lsave array with important LEB numbers.
793ff94bc40SHeiko Schocher  * @c: the UBIFS file-system description object
794ff94bc40SHeiko Schocher  *
795ff94bc40SHeiko Schocher  * This function is only called for the "big" model. It records a small number
796ff94bc40SHeiko Schocher  * of LEB numbers of important LEBs.  Important LEBs are ones that are (from
797ff94bc40SHeiko Schocher  * most important to least important): empty, freeable, freeable index, dirty
798ff94bc40SHeiko Schocher  * index, dirty or free. Upon mount, we read this list of LEB numbers and bring
799ff94bc40SHeiko Schocher  * their pnodes into memory.  That will stop us from having to scan the LPT
800ff94bc40SHeiko Schocher  * straight away. For the "small" model we assume that scanning the LPT is no
801ff94bc40SHeiko Schocher  * big deal.
802ff94bc40SHeiko Schocher  */
populate_lsave(struct ubifs_info * c)803ff94bc40SHeiko Schocher static void populate_lsave(struct ubifs_info *c)
804ff94bc40SHeiko Schocher {
805ff94bc40SHeiko Schocher 	struct ubifs_lprops *lprops;
806ff94bc40SHeiko Schocher 	struct ubifs_lpt_heap *heap;
807ff94bc40SHeiko Schocher 	int i, cnt = 0;
808ff94bc40SHeiko Schocher 
809ff94bc40SHeiko Schocher 	ubifs_assert(c->big_lpt);
810ff94bc40SHeiko Schocher 	if (!(c->lpt_drty_flgs & LSAVE_DIRTY)) {
811ff94bc40SHeiko Schocher 		c->lpt_drty_flgs |= LSAVE_DIRTY;
812ff94bc40SHeiko Schocher 		ubifs_add_lpt_dirt(c, c->lsave_lnum, c->lsave_sz);
813ff94bc40SHeiko Schocher 	}
814ff94bc40SHeiko Schocher 
815ff94bc40SHeiko Schocher #ifndef __UBOOT__
816ff94bc40SHeiko Schocher 	if (dbg_populate_lsave(c))
817ff94bc40SHeiko Schocher 		return;
818ff94bc40SHeiko Schocher #endif
819ff94bc40SHeiko Schocher 
820ff94bc40SHeiko Schocher 	list_for_each_entry(lprops, &c->empty_list, list) {
821ff94bc40SHeiko Schocher 		c->lsave[cnt++] = lprops->lnum;
822ff94bc40SHeiko Schocher 		if (cnt >= c->lsave_cnt)
823ff94bc40SHeiko Schocher 			return;
824ff94bc40SHeiko Schocher 	}
825ff94bc40SHeiko Schocher 	list_for_each_entry(lprops, &c->freeable_list, list) {
826ff94bc40SHeiko Schocher 		c->lsave[cnt++] = lprops->lnum;
827ff94bc40SHeiko Schocher 		if (cnt >= c->lsave_cnt)
828ff94bc40SHeiko Schocher 			return;
829ff94bc40SHeiko Schocher 	}
830ff94bc40SHeiko Schocher 	list_for_each_entry(lprops, &c->frdi_idx_list, list) {
831ff94bc40SHeiko Schocher 		c->lsave[cnt++] = lprops->lnum;
832ff94bc40SHeiko Schocher 		if (cnt >= c->lsave_cnt)
833ff94bc40SHeiko Schocher 			return;
834ff94bc40SHeiko Schocher 	}
835ff94bc40SHeiko Schocher 	heap = &c->lpt_heap[LPROPS_DIRTY_IDX - 1];
836ff94bc40SHeiko Schocher 	for (i = 0; i < heap->cnt; i++) {
837ff94bc40SHeiko Schocher 		c->lsave[cnt++] = heap->arr[i]->lnum;
838ff94bc40SHeiko Schocher 		if (cnt >= c->lsave_cnt)
839ff94bc40SHeiko Schocher 			return;
840ff94bc40SHeiko Schocher 	}
841ff94bc40SHeiko Schocher 	heap = &c->lpt_heap[LPROPS_DIRTY - 1];
842ff94bc40SHeiko Schocher 	for (i = 0; i < heap->cnt; i++) {
843ff94bc40SHeiko Schocher 		c->lsave[cnt++] = heap->arr[i]->lnum;
844ff94bc40SHeiko Schocher 		if (cnt >= c->lsave_cnt)
845ff94bc40SHeiko Schocher 			return;
846ff94bc40SHeiko Schocher 	}
847ff94bc40SHeiko Schocher 	heap = &c->lpt_heap[LPROPS_FREE - 1];
848ff94bc40SHeiko Schocher 	for (i = 0; i < heap->cnt; i++) {
849ff94bc40SHeiko Schocher 		c->lsave[cnt++] = heap->arr[i]->lnum;
850ff94bc40SHeiko Schocher 		if (cnt >= c->lsave_cnt)
851ff94bc40SHeiko Schocher 			return;
852ff94bc40SHeiko Schocher 	}
853ff94bc40SHeiko Schocher 	/* Fill it up completely */
854ff94bc40SHeiko Schocher 	while (cnt < c->lsave_cnt)
855ff94bc40SHeiko Schocher 		c->lsave[cnt++] = c->main_first;
856ff94bc40SHeiko Schocher }
857ff94bc40SHeiko Schocher 
858ff94bc40SHeiko Schocher /**
859ff94bc40SHeiko Schocher  * nnode_lookup - lookup a nnode in the LPT.
860ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
861ff94bc40SHeiko Schocher  * @i: nnode number
862ff94bc40SHeiko Schocher  *
863ff94bc40SHeiko Schocher  * This function returns a pointer to the nnode on success or a negative
864ff94bc40SHeiko Schocher  * error code on failure.
865ff94bc40SHeiko Schocher  */
nnode_lookup(struct ubifs_info * c,int i)866ff94bc40SHeiko Schocher static struct ubifs_nnode *nnode_lookup(struct ubifs_info *c, int i)
867ff94bc40SHeiko Schocher {
868ff94bc40SHeiko Schocher 	int err, iip;
869ff94bc40SHeiko Schocher 	struct ubifs_nnode *nnode;
870ff94bc40SHeiko Schocher 
871ff94bc40SHeiko Schocher 	if (!c->nroot) {
872ff94bc40SHeiko Schocher 		err = ubifs_read_nnode(c, NULL, 0);
873ff94bc40SHeiko Schocher 		if (err)
874ff94bc40SHeiko Schocher 			return ERR_PTR(err);
875ff94bc40SHeiko Schocher 	}
876ff94bc40SHeiko Schocher 	nnode = c->nroot;
877ff94bc40SHeiko Schocher 	while (1) {
878ff94bc40SHeiko Schocher 		iip = i & (UBIFS_LPT_FANOUT - 1);
879ff94bc40SHeiko Schocher 		i >>= UBIFS_LPT_FANOUT_SHIFT;
880ff94bc40SHeiko Schocher 		if (!i)
881ff94bc40SHeiko Schocher 			break;
882ff94bc40SHeiko Schocher 		nnode = ubifs_get_nnode(c, nnode, iip);
883ff94bc40SHeiko Schocher 		if (IS_ERR(nnode))
884ff94bc40SHeiko Schocher 			return nnode;
885ff94bc40SHeiko Schocher 	}
886ff94bc40SHeiko Schocher 	return nnode;
887ff94bc40SHeiko Schocher }
888ff94bc40SHeiko Schocher 
889ff94bc40SHeiko Schocher /**
890ff94bc40SHeiko Schocher  * make_nnode_dirty - find a nnode and, if found, make it dirty.
891ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
892ff94bc40SHeiko Schocher  * @node_num: nnode number of nnode to make dirty
893ff94bc40SHeiko Schocher  * @lnum: LEB number where nnode was written
894ff94bc40SHeiko Schocher  * @offs: offset where nnode was written
895ff94bc40SHeiko Schocher  *
896ff94bc40SHeiko Schocher  * This function is used by LPT garbage collection.  LPT garbage collection is
897ff94bc40SHeiko Schocher  * used only for the "big" LPT model (c->big_lpt == 1).  Garbage collection
898ff94bc40SHeiko Schocher  * simply involves marking all the nodes in the LEB being garbage-collected as
899ff94bc40SHeiko Schocher  * dirty.  The dirty nodes are written next commit, after which the LEB is free
900ff94bc40SHeiko Schocher  * to be reused.
901ff94bc40SHeiko Schocher  *
902ff94bc40SHeiko Schocher  * This function returns %0 on success and a negative error code on failure.
903ff94bc40SHeiko Schocher  */
make_nnode_dirty(struct ubifs_info * c,int node_num,int lnum,int offs)904ff94bc40SHeiko Schocher static int make_nnode_dirty(struct ubifs_info *c, int node_num, int lnum,
905ff94bc40SHeiko Schocher 			    int offs)
906ff94bc40SHeiko Schocher {
907ff94bc40SHeiko Schocher 	struct ubifs_nnode *nnode;
908ff94bc40SHeiko Schocher 
909ff94bc40SHeiko Schocher 	nnode = nnode_lookup(c, node_num);
910ff94bc40SHeiko Schocher 	if (IS_ERR(nnode))
911ff94bc40SHeiko Schocher 		return PTR_ERR(nnode);
912ff94bc40SHeiko Schocher 	if (nnode->parent) {
913ff94bc40SHeiko Schocher 		struct ubifs_nbranch *branch;
914ff94bc40SHeiko Schocher 
915ff94bc40SHeiko Schocher 		branch = &nnode->parent->nbranch[nnode->iip];
916ff94bc40SHeiko Schocher 		if (branch->lnum != lnum || branch->offs != offs)
917ff94bc40SHeiko Schocher 			return 0; /* nnode is obsolete */
918ff94bc40SHeiko Schocher 	} else if (c->lpt_lnum != lnum || c->lpt_offs != offs)
919ff94bc40SHeiko Schocher 			return 0; /* nnode is obsolete */
920ff94bc40SHeiko Schocher 	/* Assumes cnext list is empty i.e. not called during commit */
921ff94bc40SHeiko Schocher 	if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) {
922ff94bc40SHeiko Schocher 		c->dirty_nn_cnt += 1;
923ff94bc40SHeiko Schocher 		ubifs_add_nnode_dirt(c, nnode);
924ff94bc40SHeiko Schocher 		/* Mark parent and ancestors dirty too */
925ff94bc40SHeiko Schocher 		nnode = nnode->parent;
926ff94bc40SHeiko Schocher 		while (nnode) {
927ff94bc40SHeiko Schocher 			if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) {
928ff94bc40SHeiko Schocher 				c->dirty_nn_cnt += 1;
929ff94bc40SHeiko Schocher 				ubifs_add_nnode_dirt(c, nnode);
930ff94bc40SHeiko Schocher 				nnode = nnode->parent;
931ff94bc40SHeiko Schocher 			} else
932ff94bc40SHeiko Schocher 				break;
933ff94bc40SHeiko Schocher 		}
934ff94bc40SHeiko Schocher 	}
935ff94bc40SHeiko Schocher 	return 0;
936ff94bc40SHeiko Schocher }
937ff94bc40SHeiko Schocher 
938ff94bc40SHeiko Schocher /**
939ff94bc40SHeiko Schocher  * make_pnode_dirty - find a pnode and, if found, make it dirty.
940ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
941ff94bc40SHeiko Schocher  * @node_num: pnode number of pnode to make dirty
942ff94bc40SHeiko Schocher  * @lnum: LEB number where pnode was written
943ff94bc40SHeiko Schocher  * @offs: offset where pnode was written
944ff94bc40SHeiko Schocher  *
945ff94bc40SHeiko Schocher  * This function is used by LPT garbage collection.  LPT garbage collection is
946ff94bc40SHeiko Schocher  * used only for the "big" LPT model (c->big_lpt == 1).  Garbage collection
947ff94bc40SHeiko Schocher  * simply involves marking all the nodes in the LEB being garbage-collected as
948ff94bc40SHeiko Schocher  * dirty.  The dirty nodes are written next commit, after which the LEB is free
949ff94bc40SHeiko Schocher  * to be reused.
950ff94bc40SHeiko Schocher  *
951ff94bc40SHeiko Schocher  * This function returns %0 on success and a negative error code on failure.
952ff94bc40SHeiko Schocher  */
make_pnode_dirty(struct ubifs_info * c,int node_num,int lnum,int offs)953ff94bc40SHeiko Schocher static int make_pnode_dirty(struct ubifs_info *c, int node_num, int lnum,
954ff94bc40SHeiko Schocher 			    int offs)
955ff94bc40SHeiko Schocher {
956ff94bc40SHeiko Schocher 	struct ubifs_pnode *pnode;
957ff94bc40SHeiko Schocher 	struct ubifs_nbranch *branch;
958ff94bc40SHeiko Schocher 
959ff94bc40SHeiko Schocher 	pnode = pnode_lookup(c, node_num);
960ff94bc40SHeiko Schocher 	if (IS_ERR(pnode))
961ff94bc40SHeiko Schocher 		return PTR_ERR(pnode);
962ff94bc40SHeiko Schocher 	branch = &pnode->parent->nbranch[pnode->iip];
963ff94bc40SHeiko Schocher 	if (branch->lnum != lnum || branch->offs != offs)
964ff94bc40SHeiko Schocher 		return 0;
965ff94bc40SHeiko Schocher 	do_make_pnode_dirty(c, pnode);
966ff94bc40SHeiko Schocher 	return 0;
967ff94bc40SHeiko Schocher }
968ff94bc40SHeiko Schocher 
969ff94bc40SHeiko Schocher /**
970ff94bc40SHeiko Schocher  * make_ltab_dirty - make ltab node dirty.
971ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
972ff94bc40SHeiko Schocher  * @lnum: LEB number where ltab was written
973ff94bc40SHeiko Schocher  * @offs: offset where ltab was written
974ff94bc40SHeiko Schocher  *
975ff94bc40SHeiko Schocher  * This function is used by LPT garbage collection.  LPT garbage collection is
976ff94bc40SHeiko Schocher  * used only for the "big" LPT model (c->big_lpt == 1).  Garbage collection
977ff94bc40SHeiko Schocher  * simply involves marking all the nodes in the LEB being garbage-collected as
978ff94bc40SHeiko Schocher  * dirty.  The dirty nodes are written next commit, after which the LEB is free
979ff94bc40SHeiko Schocher  * to be reused.
980ff94bc40SHeiko Schocher  *
981ff94bc40SHeiko Schocher  * This function returns %0 on success and a negative error code on failure.
982ff94bc40SHeiko Schocher  */
make_ltab_dirty(struct ubifs_info * c,int lnum,int offs)983ff94bc40SHeiko Schocher static int make_ltab_dirty(struct ubifs_info *c, int lnum, int offs)
984ff94bc40SHeiko Schocher {
985ff94bc40SHeiko Schocher 	if (lnum != c->ltab_lnum || offs != c->ltab_offs)
986ff94bc40SHeiko Schocher 		return 0; /* This ltab node is obsolete */
987ff94bc40SHeiko Schocher 	if (!(c->lpt_drty_flgs & LTAB_DIRTY)) {
988ff94bc40SHeiko Schocher 		c->lpt_drty_flgs |= LTAB_DIRTY;
989ff94bc40SHeiko Schocher 		ubifs_add_lpt_dirt(c, c->ltab_lnum, c->ltab_sz);
990ff94bc40SHeiko Schocher 	}
991ff94bc40SHeiko Schocher 	return 0;
992ff94bc40SHeiko Schocher }
993ff94bc40SHeiko Schocher 
994ff94bc40SHeiko Schocher /**
995ff94bc40SHeiko Schocher  * make_lsave_dirty - make lsave node dirty.
996ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
997ff94bc40SHeiko Schocher  * @lnum: LEB number where lsave was written
998ff94bc40SHeiko Schocher  * @offs: offset where lsave was written
999ff94bc40SHeiko Schocher  *
1000ff94bc40SHeiko Schocher  * This function is used by LPT garbage collection.  LPT garbage collection is
1001ff94bc40SHeiko Schocher  * used only for the "big" LPT model (c->big_lpt == 1).  Garbage collection
1002ff94bc40SHeiko Schocher  * simply involves marking all the nodes in the LEB being garbage-collected as
1003ff94bc40SHeiko Schocher  * dirty.  The dirty nodes are written next commit, after which the LEB is free
1004ff94bc40SHeiko Schocher  * to be reused.
1005ff94bc40SHeiko Schocher  *
1006ff94bc40SHeiko Schocher  * This function returns %0 on success and a negative error code on failure.
1007ff94bc40SHeiko Schocher  */
make_lsave_dirty(struct ubifs_info * c,int lnum,int offs)1008ff94bc40SHeiko Schocher static int make_lsave_dirty(struct ubifs_info *c, int lnum, int offs)
1009ff94bc40SHeiko Schocher {
1010ff94bc40SHeiko Schocher 	if (lnum != c->lsave_lnum || offs != c->lsave_offs)
1011ff94bc40SHeiko Schocher 		return 0; /* This lsave node is obsolete */
1012ff94bc40SHeiko Schocher 	if (!(c->lpt_drty_flgs & LSAVE_DIRTY)) {
1013ff94bc40SHeiko Schocher 		c->lpt_drty_flgs |= LSAVE_DIRTY;
1014ff94bc40SHeiko Schocher 		ubifs_add_lpt_dirt(c, c->lsave_lnum, c->lsave_sz);
1015ff94bc40SHeiko Schocher 	}
1016ff94bc40SHeiko Schocher 	return 0;
1017ff94bc40SHeiko Schocher }
1018ff94bc40SHeiko Schocher 
1019ff94bc40SHeiko Schocher /**
1020ff94bc40SHeiko Schocher  * make_node_dirty - make node dirty.
1021ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
1022ff94bc40SHeiko Schocher  * @node_type: LPT node type
1023ff94bc40SHeiko Schocher  * @node_num: node number
1024ff94bc40SHeiko Schocher  * @lnum: LEB number where node was written
1025ff94bc40SHeiko Schocher  * @offs: offset where node was written
1026ff94bc40SHeiko Schocher  *
1027ff94bc40SHeiko Schocher  * This function is used by LPT garbage collection.  LPT garbage collection is
1028ff94bc40SHeiko Schocher  * used only for the "big" LPT model (c->big_lpt == 1).  Garbage collection
1029ff94bc40SHeiko Schocher  * simply involves marking all the nodes in the LEB being garbage-collected as
1030ff94bc40SHeiko Schocher  * dirty.  The dirty nodes are written next commit, after which the LEB is free
1031ff94bc40SHeiko Schocher  * to be reused.
1032ff94bc40SHeiko Schocher  *
1033ff94bc40SHeiko Schocher  * This function returns %0 on success and a negative error code on failure.
1034ff94bc40SHeiko Schocher  */
make_node_dirty(struct ubifs_info * c,int node_type,int node_num,int lnum,int offs)1035ff94bc40SHeiko Schocher static int make_node_dirty(struct ubifs_info *c, int node_type, int node_num,
1036ff94bc40SHeiko Schocher 			   int lnum, int offs)
1037ff94bc40SHeiko Schocher {
1038ff94bc40SHeiko Schocher 	switch (node_type) {
1039ff94bc40SHeiko Schocher 	case UBIFS_LPT_NNODE:
1040ff94bc40SHeiko Schocher 		return make_nnode_dirty(c, node_num, lnum, offs);
1041ff94bc40SHeiko Schocher 	case UBIFS_LPT_PNODE:
1042ff94bc40SHeiko Schocher 		return make_pnode_dirty(c, node_num, lnum, offs);
1043ff94bc40SHeiko Schocher 	case UBIFS_LPT_LTAB:
1044ff94bc40SHeiko Schocher 		return make_ltab_dirty(c, lnum, offs);
1045ff94bc40SHeiko Schocher 	case UBIFS_LPT_LSAVE:
1046ff94bc40SHeiko Schocher 		return make_lsave_dirty(c, lnum, offs);
1047ff94bc40SHeiko Schocher 	}
1048ff94bc40SHeiko Schocher 	return -EINVAL;
1049ff94bc40SHeiko Schocher }
1050ff94bc40SHeiko Schocher 
1051ff94bc40SHeiko Schocher /**
1052ff94bc40SHeiko Schocher  * get_lpt_node_len - return the length of a node based on its type.
1053ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
1054ff94bc40SHeiko Schocher  * @node_type: LPT node type
1055ff94bc40SHeiko Schocher  */
get_lpt_node_len(const struct ubifs_info * c,int node_type)1056ff94bc40SHeiko Schocher static int get_lpt_node_len(const struct ubifs_info *c, int node_type)
1057ff94bc40SHeiko Schocher {
1058ff94bc40SHeiko Schocher 	switch (node_type) {
1059ff94bc40SHeiko Schocher 	case UBIFS_LPT_NNODE:
1060ff94bc40SHeiko Schocher 		return c->nnode_sz;
1061ff94bc40SHeiko Schocher 	case UBIFS_LPT_PNODE:
1062ff94bc40SHeiko Schocher 		return c->pnode_sz;
1063ff94bc40SHeiko Schocher 	case UBIFS_LPT_LTAB:
1064ff94bc40SHeiko Schocher 		return c->ltab_sz;
1065ff94bc40SHeiko Schocher 	case UBIFS_LPT_LSAVE:
1066ff94bc40SHeiko Schocher 		return c->lsave_sz;
1067ff94bc40SHeiko Schocher 	}
1068ff94bc40SHeiko Schocher 	return 0;
1069ff94bc40SHeiko Schocher }
1070ff94bc40SHeiko Schocher 
1071ff94bc40SHeiko Schocher /**
1072ff94bc40SHeiko Schocher  * get_pad_len - return the length of padding in a buffer.
1073ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
1074ff94bc40SHeiko Schocher  * @buf: buffer
1075ff94bc40SHeiko Schocher  * @len: length of buffer
1076ff94bc40SHeiko Schocher  */
get_pad_len(const struct ubifs_info * c,uint8_t * buf,int len)1077ff94bc40SHeiko Schocher static int get_pad_len(const struct ubifs_info *c, uint8_t *buf, int len)
1078ff94bc40SHeiko Schocher {
1079ff94bc40SHeiko Schocher 	int offs, pad_len;
1080ff94bc40SHeiko Schocher 
1081ff94bc40SHeiko Schocher 	if (c->min_io_size == 1)
1082ff94bc40SHeiko Schocher 		return 0;
1083ff94bc40SHeiko Schocher 	offs = c->leb_size - len;
1084ff94bc40SHeiko Schocher 	pad_len = ALIGN(offs, c->min_io_size) - offs;
1085ff94bc40SHeiko Schocher 	return pad_len;
1086ff94bc40SHeiko Schocher }
1087ff94bc40SHeiko Schocher 
1088ff94bc40SHeiko Schocher /**
1089ff94bc40SHeiko Schocher  * get_lpt_node_type - return type (and node number) of a node in a buffer.
1090ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
1091ff94bc40SHeiko Schocher  * @buf: buffer
1092ff94bc40SHeiko Schocher  * @node_num: node number is returned here
1093ff94bc40SHeiko Schocher  */
get_lpt_node_type(const struct ubifs_info * c,uint8_t * buf,int * node_num)1094ff94bc40SHeiko Schocher static int get_lpt_node_type(const struct ubifs_info *c, uint8_t *buf,
1095ff94bc40SHeiko Schocher 			     int *node_num)
1096ff94bc40SHeiko Schocher {
1097ff94bc40SHeiko Schocher 	uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
1098ff94bc40SHeiko Schocher 	int pos = 0, node_type;
1099ff94bc40SHeiko Schocher 
1100ff94bc40SHeiko Schocher 	node_type = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_TYPE_BITS);
1101ff94bc40SHeiko Schocher 	*node_num = ubifs_unpack_bits(&addr, &pos, c->pcnt_bits);
1102ff94bc40SHeiko Schocher 	return node_type;
1103ff94bc40SHeiko Schocher }
1104ff94bc40SHeiko Schocher 
1105ff94bc40SHeiko Schocher /**
1106ff94bc40SHeiko Schocher  * is_a_node - determine if a buffer contains a node.
1107ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
1108ff94bc40SHeiko Schocher  * @buf: buffer
1109ff94bc40SHeiko Schocher  * @len: length of buffer
1110ff94bc40SHeiko Schocher  *
1111ff94bc40SHeiko Schocher  * This function returns %1 if the buffer contains a node or %0 if it does not.
1112ff94bc40SHeiko Schocher  */
is_a_node(const struct ubifs_info * c,uint8_t * buf,int len)1113ff94bc40SHeiko Schocher static int is_a_node(const struct ubifs_info *c, uint8_t *buf, int len)
1114ff94bc40SHeiko Schocher {
1115ff94bc40SHeiko Schocher 	uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
1116ff94bc40SHeiko Schocher 	int pos = 0, node_type, node_len;
1117ff94bc40SHeiko Schocher 	uint16_t crc, calc_crc;
1118ff94bc40SHeiko Schocher 
1119ff94bc40SHeiko Schocher 	if (len < UBIFS_LPT_CRC_BYTES + (UBIFS_LPT_TYPE_BITS + 7) / 8)
1120ff94bc40SHeiko Schocher 		return 0;
1121ff94bc40SHeiko Schocher 	node_type = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_TYPE_BITS);
1122ff94bc40SHeiko Schocher 	if (node_type == UBIFS_LPT_NOT_A_NODE)
1123ff94bc40SHeiko Schocher 		return 0;
1124ff94bc40SHeiko Schocher 	node_len = get_lpt_node_len(c, node_type);
1125ff94bc40SHeiko Schocher 	if (!node_len || node_len > len)
1126ff94bc40SHeiko Schocher 		return 0;
1127ff94bc40SHeiko Schocher 	pos = 0;
1128ff94bc40SHeiko Schocher 	addr = buf;
1129ff94bc40SHeiko Schocher 	crc = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_CRC_BITS);
1130ff94bc40SHeiko Schocher 	calc_crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
1131ff94bc40SHeiko Schocher 			 node_len - UBIFS_LPT_CRC_BYTES);
1132ff94bc40SHeiko Schocher 	if (crc != calc_crc)
1133ff94bc40SHeiko Schocher 		return 0;
1134ff94bc40SHeiko Schocher 	return 1;
1135ff94bc40SHeiko Schocher }
1136ff94bc40SHeiko Schocher 
1137ff94bc40SHeiko Schocher /**
1138ff94bc40SHeiko Schocher  * lpt_gc_lnum - garbage collect a LPT LEB.
1139ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
1140ff94bc40SHeiko Schocher  * @lnum: LEB number to garbage collect
1141ff94bc40SHeiko Schocher  *
1142ff94bc40SHeiko Schocher  * LPT garbage collection is used only for the "big" LPT model
1143ff94bc40SHeiko Schocher  * (c->big_lpt == 1).  Garbage collection simply involves marking all the nodes
1144ff94bc40SHeiko Schocher  * in the LEB being garbage-collected as dirty.  The dirty nodes are written
1145ff94bc40SHeiko Schocher  * next commit, after which the LEB is free to be reused.
1146ff94bc40SHeiko Schocher  *
1147ff94bc40SHeiko Schocher  * This function returns %0 on success and a negative error code on failure.
1148ff94bc40SHeiko Schocher  */
lpt_gc_lnum(struct ubifs_info * c,int lnum)1149ff94bc40SHeiko Schocher static int lpt_gc_lnum(struct ubifs_info *c, int lnum)
1150ff94bc40SHeiko Schocher {
1151ff94bc40SHeiko Schocher 	int err, len = c->leb_size, node_type, node_num, node_len, offs;
1152ff94bc40SHeiko Schocher 	void *buf = c->lpt_buf;
1153ff94bc40SHeiko Schocher 
1154ff94bc40SHeiko Schocher 	dbg_lp("LEB %d", lnum);
1155ff94bc40SHeiko Schocher 
1156ff94bc40SHeiko Schocher 	err = ubifs_leb_read(c, lnum, buf, 0, c->leb_size, 1);
1157ff94bc40SHeiko Schocher 	if (err)
1158ff94bc40SHeiko Schocher 		return err;
1159ff94bc40SHeiko Schocher 
1160ff94bc40SHeiko Schocher 	while (1) {
1161ff94bc40SHeiko Schocher 		if (!is_a_node(c, buf, len)) {
1162ff94bc40SHeiko Schocher 			int pad_len;
1163ff94bc40SHeiko Schocher 
1164ff94bc40SHeiko Schocher 			pad_len = get_pad_len(c, buf, len);
1165ff94bc40SHeiko Schocher 			if (pad_len) {
1166ff94bc40SHeiko Schocher 				buf += pad_len;
1167ff94bc40SHeiko Schocher 				len -= pad_len;
1168ff94bc40SHeiko Schocher 				continue;
1169ff94bc40SHeiko Schocher 			}
1170ff94bc40SHeiko Schocher 			return 0;
1171ff94bc40SHeiko Schocher 		}
1172ff94bc40SHeiko Schocher 		node_type = get_lpt_node_type(c, buf, &node_num);
1173ff94bc40SHeiko Schocher 		node_len = get_lpt_node_len(c, node_type);
1174ff94bc40SHeiko Schocher 		offs = c->leb_size - len;
1175ff94bc40SHeiko Schocher 		ubifs_assert(node_len != 0);
1176ff94bc40SHeiko Schocher 		mutex_lock(&c->lp_mutex);
1177ff94bc40SHeiko Schocher 		err = make_node_dirty(c, node_type, node_num, lnum, offs);
1178ff94bc40SHeiko Schocher 		mutex_unlock(&c->lp_mutex);
1179ff94bc40SHeiko Schocher 		if (err)
1180ff94bc40SHeiko Schocher 			return err;
1181ff94bc40SHeiko Schocher 		buf += node_len;
1182ff94bc40SHeiko Schocher 		len -= node_len;
1183ff94bc40SHeiko Schocher 	}
1184ff94bc40SHeiko Schocher 	return 0;
1185ff94bc40SHeiko Schocher }
1186ff94bc40SHeiko Schocher 
1187ff94bc40SHeiko Schocher /**
1188ff94bc40SHeiko Schocher  * lpt_gc - LPT garbage collection.
1189ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
1190ff94bc40SHeiko Schocher  *
1191ff94bc40SHeiko Schocher  * Select a LPT LEB for LPT garbage collection and call 'lpt_gc_lnum()'.
1192ff94bc40SHeiko Schocher  * Returns %0 on success and a negative error code on failure.
1193ff94bc40SHeiko Schocher  */
lpt_gc(struct ubifs_info * c)1194ff94bc40SHeiko Schocher static int lpt_gc(struct ubifs_info *c)
1195ff94bc40SHeiko Schocher {
1196ff94bc40SHeiko Schocher 	int i, lnum = -1, dirty = 0;
1197ff94bc40SHeiko Schocher 
1198ff94bc40SHeiko Schocher 	mutex_lock(&c->lp_mutex);
1199ff94bc40SHeiko Schocher 	for (i = 0; i < c->lpt_lebs; i++) {
1200ff94bc40SHeiko Schocher 		ubifs_assert(!c->ltab[i].tgc);
1201ff94bc40SHeiko Schocher 		if (i + c->lpt_first == c->nhead_lnum ||
1202ff94bc40SHeiko Schocher 		    c->ltab[i].free + c->ltab[i].dirty == c->leb_size)
1203ff94bc40SHeiko Schocher 			continue;
1204ff94bc40SHeiko Schocher 		if (c->ltab[i].dirty > dirty) {
1205ff94bc40SHeiko Schocher 			dirty = c->ltab[i].dirty;
1206ff94bc40SHeiko Schocher 			lnum = i + c->lpt_first;
1207ff94bc40SHeiko Schocher 		}
1208ff94bc40SHeiko Schocher 	}
1209ff94bc40SHeiko Schocher 	mutex_unlock(&c->lp_mutex);
1210ff94bc40SHeiko Schocher 	if (lnum == -1)
1211ff94bc40SHeiko Schocher 		return -ENOSPC;
1212ff94bc40SHeiko Schocher 	return lpt_gc_lnum(c, lnum);
1213ff94bc40SHeiko Schocher }
1214ff94bc40SHeiko Schocher 
1215ff94bc40SHeiko Schocher /**
1216ff94bc40SHeiko Schocher  * ubifs_lpt_start_commit - UBIFS commit starts.
1217ff94bc40SHeiko Schocher  * @c: the UBIFS file-system description object
1218ff94bc40SHeiko Schocher  *
1219ff94bc40SHeiko Schocher  * This function has to be called when UBIFS starts the commit operation.
1220ff94bc40SHeiko Schocher  * This function "freezes" all currently dirty LEB properties and does not
1221ff94bc40SHeiko Schocher  * change them anymore. Further changes are saved and tracked separately
1222ff94bc40SHeiko Schocher  * because they are not part of this commit. This function returns zero in case
1223ff94bc40SHeiko Schocher  * of success and a negative error code in case of failure.
1224ff94bc40SHeiko Schocher  */
ubifs_lpt_start_commit(struct ubifs_info * c)1225ff94bc40SHeiko Schocher int ubifs_lpt_start_commit(struct ubifs_info *c)
1226ff94bc40SHeiko Schocher {
1227ff94bc40SHeiko Schocher 	int err, cnt;
1228ff94bc40SHeiko Schocher 
1229ff94bc40SHeiko Schocher 	dbg_lp("");
1230ff94bc40SHeiko Schocher 
1231ff94bc40SHeiko Schocher 	mutex_lock(&c->lp_mutex);
1232ff94bc40SHeiko Schocher 	err = dbg_chk_lpt_free_spc(c);
1233ff94bc40SHeiko Schocher 	if (err)
1234ff94bc40SHeiko Schocher 		goto out;
1235ff94bc40SHeiko Schocher 	err = dbg_check_ltab(c);
1236ff94bc40SHeiko Schocher 	if (err)
1237ff94bc40SHeiko Schocher 		goto out;
1238ff94bc40SHeiko Schocher 
1239ff94bc40SHeiko Schocher 	if (c->check_lpt_free) {
1240ff94bc40SHeiko Schocher 		/*
1241ff94bc40SHeiko Schocher 		 * We ensure there is enough free space in
1242ff94bc40SHeiko Schocher 		 * ubifs_lpt_post_commit() by marking nodes dirty. That
1243ff94bc40SHeiko Schocher 		 * information is lost when we unmount, so we also need
1244ff94bc40SHeiko Schocher 		 * to check free space once after mounting also.
1245ff94bc40SHeiko Schocher 		 */
1246ff94bc40SHeiko Schocher 		c->check_lpt_free = 0;
1247ff94bc40SHeiko Schocher 		while (need_write_all(c)) {
1248ff94bc40SHeiko Schocher 			mutex_unlock(&c->lp_mutex);
1249ff94bc40SHeiko Schocher 			err = lpt_gc(c);
1250ff94bc40SHeiko Schocher 			if (err)
1251ff94bc40SHeiko Schocher 				return err;
1252ff94bc40SHeiko Schocher 			mutex_lock(&c->lp_mutex);
1253ff94bc40SHeiko Schocher 		}
1254ff94bc40SHeiko Schocher 	}
1255ff94bc40SHeiko Schocher 
1256ff94bc40SHeiko Schocher 	lpt_tgc_start(c);
1257ff94bc40SHeiko Schocher 
1258ff94bc40SHeiko Schocher 	if (!c->dirty_pn_cnt) {
1259ff94bc40SHeiko Schocher 		dbg_cmt("no cnodes to commit");
1260ff94bc40SHeiko Schocher 		err = 0;
1261ff94bc40SHeiko Schocher 		goto out;
1262ff94bc40SHeiko Schocher 	}
1263ff94bc40SHeiko Schocher 
1264ff94bc40SHeiko Schocher 	if (!c->big_lpt && need_write_all(c)) {
1265ff94bc40SHeiko Schocher 		/* If needed, write everything */
1266ff94bc40SHeiko Schocher 		err = make_tree_dirty(c);
1267ff94bc40SHeiko Schocher 		if (err)
1268ff94bc40SHeiko Schocher 			goto out;
1269ff94bc40SHeiko Schocher 		lpt_tgc_start(c);
1270ff94bc40SHeiko Schocher 	}
1271ff94bc40SHeiko Schocher 
1272ff94bc40SHeiko Schocher 	if (c->big_lpt)
1273ff94bc40SHeiko Schocher 		populate_lsave(c);
1274ff94bc40SHeiko Schocher 
1275ff94bc40SHeiko Schocher 	cnt = get_cnodes_to_commit(c);
1276ff94bc40SHeiko Schocher 	ubifs_assert(cnt != 0);
1277ff94bc40SHeiko Schocher 
1278ff94bc40SHeiko Schocher 	err = layout_cnodes(c);
1279ff94bc40SHeiko Schocher 	if (err)
1280ff94bc40SHeiko Schocher 		goto out;
1281ff94bc40SHeiko Schocher 
1282ff94bc40SHeiko Schocher 	/* Copy the LPT's own lprops for end commit to write */
1283ff94bc40SHeiko Schocher 	memcpy(c->ltab_cmt, c->ltab,
1284ff94bc40SHeiko Schocher 	       sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs);
1285ff94bc40SHeiko Schocher 	c->lpt_drty_flgs &= ~(LTAB_DIRTY | LSAVE_DIRTY);
1286ff94bc40SHeiko Schocher 
1287ff94bc40SHeiko Schocher out:
1288ff94bc40SHeiko Schocher 	mutex_unlock(&c->lp_mutex);
1289ff94bc40SHeiko Schocher 	return err;
1290ff94bc40SHeiko Schocher }
1291ff94bc40SHeiko Schocher 
12929eefe2a2SStefan Roese /**
12939eefe2a2SStefan Roese  * free_obsolete_cnodes - free obsolete cnodes for commit end.
12949eefe2a2SStefan Roese  * @c: UBIFS file-system description object
12959eefe2a2SStefan Roese  */
free_obsolete_cnodes(struct ubifs_info * c)12969eefe2a2SStefan Roese static void free_obsolete_cnodes(struct ubifs_info *c)
12979eefe2a2SStefan Roese {
12989eefe2a2SStefan Roese 	struct ubifs_cnode *cnode, *cnext;
12999eefe2a2SStefan Roese 
13009eefe2a2SStefan Roese 	cnext = c->lpt_cnext;
13019eefe2a2SStefan Roese 	if (!cnext)
13029eefe2a2SStefan Roese 		return;
13039eefe2a2SStefan Roese 	do {
13049eefe2a2SStefan Roese 		cnode = cnext;
13059eefe2a2SStefan Roese 		cnext = cnode->cnext;
13069eefe2a2SStefan Roese 		if (test_bit(OBSOLETE_CNODE, &cnode->flags))
13079eefe2a2SStefan Roese 			kfree(cnode);
13089eefe2a2SStefan Roese 		else
13099eefe2a2SStefan Roese 			cnode->cnext = NULL;
13109eefe2a2SStefan Roese 	} while (cnext != c->lpt_cnext);
13119eefe2a2SStefan Roese 	c->lpt_cnext = NULL;
13129eefe2a2SStefan Roese }
13139eefe2a2SStefan Roese 
1314ff94bc40SHeiko Schocher #ifndef __UBOOT__
1315ff94bc40SHeiko Schocher /**
1316ff94bc40SHeiko Schocher  * ubifs_lpt_end_commit - finish the commit operation.
1317ff94bc40SHeiko Schocher  * @c: the UBIFS file-system description object
1318ff94bc40SHeiko Schocher  *
1319ff94bc40SHeiko Schocher  * This function has to be called when the commit operation finishes. It
1320ff94bc40SHeiko Schocher  * flushes the changes which were "frozen" by 'ubifs_lprops_start_commit()' to
1321ff94bc40SHeiko Schocher  * the media. Returns zero in case of success and a negative error code in case
1322ff94bc40SHeiko Schocher  * of failure.
1323ff94bc40SHeiko Schocher  */
ubifs_lpt_end_commit(struct ubifs_info * c)1324ff94bc40SHeiko Schocher int ubifs_lpt_end_commit(struct ubifs_info *c)
1325ff94bc40SHeiko Schocher {
1326ff94bc40SHeiko Schocher 	int err;
1327ff94bc40SHeiko Schocher 
1328ff94bc40SHeiko Schocher 	dbg_lp("");
1329ff94bc40SHeiko Schocher 
1330ff94bc40SHeiko Schocher 	if (!c->lpt_cnext)
1331ff94bc40SHeiko Schocher 		return 0;
1332ff94bc40SHeiko Schocher 
1333ff94bc40SHeiko Schocher 	err = write_cnodes(c);
1334ff94bc40SHeiko Schocher 	if (err)
1335ff94bc40SHeiko Schocher 		return err;
1336ff94bc40SHeiko Schocher 
1337ff94bc40SHeiko Schocher 	mutex_lock(&c->lp_mutex);
1338ff94bc40SHeiko Schocher 	free_obsolete_cnodes(c);
1339ff94bc40SHeiko Schocher 	mutex_unlock(&c->lp_mutex);
1340ff94bc40SHeiko Schocher 
1341ff94bc40SHeiko Schocher 	return 0;
1342ff94bc40SHeiko Schocher }
1343ff94bc40SHeiko Schocher #endif
1344ff94bc40SHeiko Schocher 
1345ff94bc40SHeiko Schocher /**
1346ff94bc40SHeiko Schocher  * ubifs_lpt_post_commit - post commit LPT trivial GC and LPT GC.
1347ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
1348ff94bc40SHeiko Schocher  *
1349ff94bc40SHeiko Schocher  * LPT trivial GC is completed after a commit. Also LPT GC is done after a
1350ff94bc40SHeiko Schocher  * commit for the "big" LPT model.
1351ff94bc40SHeiko Schocher  */
ubifs_lpt_post_commit(struct ubifs_info * c)1352ff94bc40SHeiko Schocher int ubifs_lpt_post_commit(struct ubifs_info *c)
1353ff94bc40SHeiko Schocher {
1354ff94bc40SHeiko Schocher 	int err;
1355ff94bc40SHeiko Schocher 
1356ff94bc40SHeiko Schocher 	mutex_lock(&c->lp_mutex);
1357ff94bc40SHeiko Schocher 	err = lpt_tgc_end(c);
1358ff94bc40SHeiko Schocher 	if (err)
1359ff94bc40SHeiko Schocher 		goto out;
1360ff94bc40SHeiko Schocher 	if (c->big_lpt)
1361ff94bc40SHeiko Schocher 		while (need_write_all(c)) {
1362ff94bc40SHeiko Schocher 			mutex_unlock(&c->lp_mutex);
1363ff94bc40SHeiko Schocher 			err = lpt_gc(c);
1364ff94bc40SHeiko Schocher 			if (err)
1365ff94bc40SHeiko Schocher 				return err;
1366ff94bc40SHeiko Schocher 			mutex_lock(&c->lp_mutex);
1367ff94bc40SHeiko Schocher 		}
1368ff94bc40SHeiko Schocher out:
1369ff94bc40SHeiko Schocher 	mutex_unlock(&c->lp_mutex);
1370ff94bc40SHeiko Schocher 	return err;
1371ff94bc40SHeiko Schocher }
1372ff94bc40SHeiko Schocher 
13739eefe2a2SStefan Roese /**
13749eefe2a2SStefan Roese  * first_nnode - find the first nnode in memory.
13759eefe2a2SStefan Roese  * @c: UBIFS file-system description object
13769eefe2a2SStefan Roese  * @hght: height of tree where nnode found is returned here
13779eefe2a2SStefan Roese  *
13789eefe2a2SStefan Roese  * This function returns a pointer to the nnode found or %NULL if no nnode is
13799eefe2a2SStefan Roese  * found. This function is a helper to 'ubifs_lpt_free()'.
13809eefe2a2SStefan Roese  */
first_nnode(struct ubifs_info * c,int * hght)13819eefe2a2SStefan Roese static struct ubifs_nnode *first_nnode(struct ubifs_info *c, int *hght)
13829eefe2a2SStefan Roese {
13839eefe2a2SStefan Roese 	struct ubifs_nnode *nnode;
13849eefe2a2SStefan Roese 	int h, i, found;
13859eefe2a2SStefan Roese 
13869eefe2a2SStefan Roese 	nnode = c->nroot;
13879eefe2a2SStefan Roese 	*hght = 0;
13889eefe2a2SStefan Roese 	if (!nnode)
13899eefe2a2SStefan Roese 		return NULL;
13909eefe2a2SStefan Roese 	for (h = 1; h < c->lpt_hght; h++) {
13919eefe2a2SStefan Roese 		found = 0;
13929eefe2a2SStefan Roese 		for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
13939eefe2a2SStefan Roese 			if (nnode->nbranch[i].nnode) {
13949eefe2a2SStefan Roese 				found = 1;
13959eefe2a2SStefan Roese 				nnode = nnode->nbranch[i].nnode;
13969eefe2a2SStefan Roese 				*hght = h;
13979eefe2a2SStefan Roese 				break;
13989eefe2a2SStefan Roese 			}
13999eefe2a2SStefan Roese 		}
14009eefe2a2SStefan Roese 		if (!found)
14019eefe2a2SStefan Roese 			break;
14029eefe2a2SStefan Roese 	}
14039eefe2a2SStefan Roese 	return nnode;
14049eefe2a2SStefan Roese }
14059eefe2a2SStefan Roese 
14069eefe2a2SStefan Roese /**
14079eefe2a2SStefan Roese  * next_nnode - find the next nnode in memory.
14089eefe2a2SStefan Roese  * @c: UBIFS file-system description object
14099eefe2a2SStefan Roese  * @nnode: nnode from which to start.
14109eefe2a2SStefan Roese  * @hght: height of tree where nnode is, is passed and returned here
14119eefe2a2SStefan Roese  *
14129eefe2a2SStefan Roese  * This function returns a pointer to the nnode found or %NULL if no nnode is
14139eefe2a2SStefan Roese  * found. This function is a helper to 'ubifs_lpt_free()'.
14149eefe2a2SStefan Roese  */
next_nnode(struct ubifs_info * c,struct ubifs_nnode * nnode,int * hght)14159eefe2a2SStefan Roese static struct ubifs_nnode *next_nnode(struct ubifs_info *c,
14169eefe2a2SStefan Roese 				      struct ubifs_nnode *nnode, int *hght)
14179eefe2a2SStefan Roese {
14189eefe2a2SStefan Roese 	struct ubifs_nnode *parent;
14199eefe2a2SStefan Roese 	int iip, h, i, found;
14209eefe2a2SStefan Roese 
14219eefe2a2SStefan Roese 	parent = nnode->parent;
14229eefe2a2SStefan Roese 	if (!parent)
14239eefe2a2SStefan Roese 		return NULL;
14249eefe2a2SStefan Roese 	if (nnode->iip == UBIFS_LPT_FANOUT - 1) {
14259eefe2a2SStefan Roese 		*hght -= 1;
14269eefe2a2SStefan Roese 		return parent;
14279eefe2a2SStefan Roese 	}
14289eefe2a2SStefan Roese 	for (iip = nnode->iip + 1; iip < UBIFS_LPT_FANOUT; iip++) {
14299eefe2a2SStefan Roese 		nnode = parent->nbranch[iip].nnode;
14309eefe2a2SStefan Roese 		if (nnode)
14319eefe2a2SStefan Roese 			break;
14329eefe2a2SStefan Roese 	}
14339eefe2a2SStefan Roese 	if (!nnode) {
14349eefe2a2SStefan Roese 		*hght -= 1;
14359eefe2a2SStefan Roese 		return parent;
14369eefe2a2SStefan Roese 	}
14379eefe2a2SStefan Roese 	for (h = *hght + 1; h < c->lpt_hght; h++) {
14389eefe2a2SStefan Roese 		found = 0;
14399eefe2a2SStefan Roese 		for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
14409eefe2a2SStefan Roese 			if (nnode->nbranch[i].nnode) {
14419eefe2a2SStefan Roese 				found = 1;
14429eefe2a2SStefan Roese 				nnode = nnode->nbranch[i].nnode;
14439eefe2a2SStefan Roese 				*hght = h;
14449eefe2a2SStefan Roese 				break;
14459eefe2a2SStefan Roese 			}
14469eefe2a2SStefan Roese 		}
14479eefe2a2SStefan Roese 		if (!found)
14489eefe2a2SStefan Roese 			break;
14499eefe2a2SStefan Roese 	}
14509eefe2a2SStefan Roese 	return nnode;
14519eefe2a2SStefan Roese }
14529eefe2a2SStefan Roese 
14539eefe2a2SStefan Roese /**
14549eefe2a2SStefan Roese  * ubifs_lpt_free - free resources owned by the LPT.
14559eefe2a2SStefan Roese  * @c: UBIFS file-system description object
14569eefe2a2SStefan Roese  * @wr_only: free only resources used for writing
14579eefe2a2SStefan Roese  */
ubifs_lpt_free(struct ubifs_info * c,int wr_only)14589eefe2a2SStefan Roese void ubifs_lpt_free(struct ubifs_info *c, int wr_only)
14599eefe2a2SStefan Roese {
14609eefe2a2SStefan Roese 	struct ubifs_nnode *nnode;
14619eefe2a2SStefan Roese 	int i, hght;
14629eefe2a2SStefan Roese 
14639eefe2a2SStefan Roese 	/* Free write-only things first */
14649eefe2a2SStefan Roese 
14659eefe2a2SStefan Roese 	free_obsolete_cnodes(c); /* Leftover from a failed commit */
14669eefe2a2SStefan Roese 
14679eefe2a2SStefan Roese 	vfree(c->ltab_cmt);
14689eefe2a2SStefan Roese 	c->ltab_cmt = NULL;
14699eefe2a2SStefan Roese 	vfree(c->lpt_buf);
14709eefe2a2SStefan Roese 	c->lpt_buf = NULL;
14719eefe2a2SStefan Roese 	kfree(c->lsave);
14729eefe2a2SStefan Roese 	c->lsave = NULL;
14739eefe2a2SStefan Roese 
14749eefe2a2SStefan Roese 	if (wr_only)
14759eefe2a2SStefan Roese 		return;
14769eefe2a2SStefan Roese 
14779eefe2a2SStefan Roese 	/* Now free the rest */
14789eefe2a2SStefan Roese 
14799eefe2a2SStefan Roese 	nnode = first_nnode(c, &hght);
14809eefe2a2SStefan Roese 	while (nnode) {
14819eefe2a2SStefan Roese 		for (i = 0; i < UBIFS_LPT_FANOUT; i++)
14829eefe2a2SStefan Roese 			kfree(nnode->nbranch[i].nnode);
14839eefe2a2SStefan Roese 		nnode = next_nnode(c, nnode, &hght);
14849eefe2a2SStefan Roese 	}
14859eefe2a2SStefan Roese 	for (i = 0; i < LPROPS_HEAP_CNT; i++)
14869eefe2a2SStefan Roese 		kfree(c->lpt_heap[i].arr);
14879eefe2a2SStefan Roese 	kfree(c->dirty_idx.arr);
14889eefe2a2SStefan Roese 	kfree(c->nroot);
14899eefe2a2SStefan Roese 	vfree(c->ltab);
14909eefe2a2SStefan Roese 	kfree(c->lpt_nod_buf);
14919eefe2a2SStefan Roese }
1492ff94bc40SHeiko Schocher 
1493ff94bc40SHeiko Schocher #ifndef __UBOOT__
1494ff94bc40SHeiko Schocher /*
1495ff94bc40SHeiko Schocher  * Everything below is related to debugging.
1496ff94bc40SHeiko Schocher  */
1497ff94bc40SHeiko Schocher 
1498ff94bc40SHeiko Schocher /**
1499ff94bc40SHeiko Schocher  * dbg_is_all_ff - determine if a buffer contains only 0xFF bytes.
1500ff94bc40SHeiko Schocher  * @buf: buffer
1501ff94bc40SHeiko Schocher  * @len: buffer length
1502ff94bc40SHeiko Schocher  */
dbg_is_all_ff(uint8_t * buf,int len)1503ff94bc40SHeiko Schocher static int dbg_is_all_ff(uint8_t *buf, int len)
1504ff94bc40SHeiko Schocher {
1505ff94bc40SHeiko Schocher 	int i;
1506ff94bc40SHeiko Schocher 
1507ff94bc40SHeiko Schocher 	for (i = 0; i < len; i++)
1508ff94bc40SHeiko Schocher 		if (buf[i] != 0xff)
1509ff94bc40SHeiko Schocher 			return 0;
1510ff94bc40SHeiko Schocher 	return 1;
1511ff94bc40SHeiko Schocher }
1512ff94bc40SHeiko Schocher 
1513ff94bc40SHeiko Schocher /**
1514ff94bc40SHeiko Schocher  * dbg_is_nnode_dirty - determine if a nnode is dirty.
1515ff94bc40SHeiko Schocher  * @c: the UBIFS file-system description object
1516ff94bc40SHeiko Schocher  * @lnum: LEB number where nnode was written
1517ff94bc40SHeiko Schocher  * @offs: offset where nnode was written
1518ff94bc40SHeiko Schocher  */
dbg_is_nnode_dirty(struct ubifs_info * c,int lnum,int offs)1519ff94bc40SHeiko Schocher static int dbg_is_nnode_dirty(struct ubifs_info *c, int lnum, int offs)
1520ff94bc40SHeiko Schocher {
1521ff94bc40SHeiko Schocher 	struct ubifs_nnode *nnode;
1522ff94bc40SHeiko Schocher 	int hght;
1523ff94bc40SHeiko Schocher 
1524ff94bc40SHeiko Schocher 	/* Entire tree is in memory so first_nnode / next_nnode are OK */
1525ff94bc40SHeiko Schocher 	nnode = first_nnode(c, &hght);
1526ff94bc40SHeiko Schocher 	for (; nnode; nnode = next_nnode(c, nnode, &hght)) {
1527ff94bc40SHeiko Schocher 		struct ubifs_nbranch *branch;
1528ff94bc40SHeiko Schocher 
1529ff94bc40SHeiko Schocher 		cond_resched();
1530ff94bc40SHeiko Schocher 		if (nnode->parent) {
1531ff94bc40SHeiko Schocher 			branch = &nnode->parent->nbranch[nnode->iip];
1532ff94bc40SHeiko Schocher 			if (branch->lnum != lnum || branch->offs != offs)
1533ff94bc40SHeiko Schocher 				continue;
1534ff94bc40SHeiko Schocher 			if (test_bit(DIRTY_CNODE, &nnode->flags))
1535ff94bc40SHeiko Schocher 				return 1;
1536ff94bc40SHeiko Schocher 			return 0;
1537ff94bc40SHeiko Schocher 		} else {
1538ff94bc40SHeiko Schocher 			if (c->lpt_lnum != lnum || c->lpt_offs != offs)
1539ff94bc40SHeiko Schocher 				continue;
1540ff94bc40SHeiko Schocher 			if (test_bit(DIRTY_CNODE, &nnode->flags))
1541ff94bc40SHeiko Schocher 				return 1;
1542ff94bc40SHeiko Schocher 			return 0;
1543ff94bc40SHeiko Schocher 		}
1544ff94bc40SHeiko Schocher 	}
1545ff94bc40SHeiko Schocher 	return 1;
1546ff94bc40SHeiko Schocher }
1547ff94bc40SHeiko Schocher 
1548ff94bc40SHeiko Schocher /**
1549ff94bc40SHeiko Schocher  * dbg_is_pnode_dirty - determine if a pnode is dirty.
1550ff94bc40SHeiko Schocher  * @c: the UBIFS file-system description object
1551ff94bc40SHeiko Schocher  * @lnum: LEB number where pnode was written
1552ff94bc40SHeiko Schocher  * @offs: offset where pnode was written
1553ff94bc40SHeiko Schocher  */
dbg_is_pnode_dirty(struct ubifs_info * c,int lnum,int offs)1554ff94bc40SHeiko Schocher static int dbg_is_pnode_dirty(struct ubifs_info *c, int lnum, int offs)
1555ff94bc40SHeiko Schocher {
1556ff94bc40SHeiko Schocher 	int i, cnt;
1557ff94bc40SHeiko Schocher 
1558ff94bc40SHeiko Schocher 	cnt = DIV_ROUND_UP(c->main_lebs, UBIFS_LPT_FANOUT);
1559ff94bc40SHeiko Schocher 	for (i = 0; i < cnt; i++) {
1560ff94bc40SHeiko Schocher 		struct ubifs_pnode *pnode;
1561ff94bc40SHeiko Schocher 		struct ubifs_nbranch *branch;
1562ff94bc40SHeiko Schocher 
1563ff94bc40SHeiko Schocher 		cond_resched();
1564ff94bc40SHeiko Schocher 		pnode = pnode_lookup(c, i);
1565ff94bc40SHeiko Schocher 		if (IS_ERR(pnode))
1566ff94bc40SHeiko Schocher 			return PTR_ERR(pnode);
1567ff94bc40SHeiko Schocher 		branch = &pnode->parent->nbranch[pnode->iip];
1568ff94bc40SHeiko Schocher 		if (branch->lnum != lnum || branch->offs != offs)
1569ff94bc40SHeiko Schocher 			continue;
1570ff94bc40SHeiko Schocher 		if (test_bit(DIRTY_CNODE, &pnode->flags))
1571ff94bc40SHeiko Schocher 			return 1;
1572ff94bc40SHeiko Schocher 		return 0;
1573ff94bc40SHeiko Schocher 	}
1574ff94bc40SHeiko Schocher 	return 1;
1575ff94bc40SHeiko Schocher }
1576ff94bc40SHeiko Schocher 
1577ff94bc40SHeiko Schocher /**
1578ff94bc40SHeiko Schocher  * dbg_is_ltab_dirty - determine if a ltab node is dirty.
1579ff94bc40SHeiko Schocher  * @c: the UBIFS file-system description object
1580ff94bc40SHeiko Schocher  * @lnum: LEB number where ltab node was written
1581ff94bc40SHeiko Schocher  * @offs: offset where ltab node was written
1582ff94bc40SHeiko Schocher  */
dbg_is_ltab_dirty(struct ubifs_info * c,int lnum,int offs)1583ff94bc40SHeiko Schocher static int dbg_is_ltab_dirty(struct ubifs_info *c, int lnum, int offs)
1584ff94bc40SHeiko Schocher {
1585ff94bc40SHeiko Schocher 	if (lnum != c->ltab_lnum || offs != c->ltab_offs)
1586ff94bc40SHeiko Schocher 		return 1;
1587ff94bc40SHeiko Schocher 	return (c->lpt_drty_flgs & LTAB_DIRTY) != 0;
1588ff94bc40SHeiko Schocher }
1589ff94bc40SHeiko Schocher 
1590ff94bc40SHeiko Schocher /**
1591ff94bc40SHeiko Schocher  * dbg_is_lsave_dirty - determine if a lsave node is dirty.
1592ff94bc40SHeiko Schocher  * @c: the UBIFS file-system description object
1593ff94bc40SHeiko Schocher  * @lnum: LEB number where lsave node was written
1594ff94bc40SHeiko Schocher  * @offs: offset where lsave node was written
1595ff94bc40SHeiko Schocher  */
dbg_is_lsave_dirty(struct ubifs_info * c,int lnum,int offs)1596ff94bc40SHeiko Schocher static int dbg_is_lsave_dirty(struct ubifs_info *c, int lnum, int offs)
1597ff94bc40SHeiko Schocher {
1598ff94bc40SHeiko Schocher 	if (lnum != c->lsave_lnum || offs != c->lsave_offs)
1599ff94bc40SHeiko Schocher 		return 1;
1600ff94bc40SHeiko Schocher 	return (c->lpt_drty_flgs & LSAVE_DIRTY) != 0;
1601ff94bc40SHeiko Schocher }
1602ff94bc40SHeiko Schocher 
1603ff94bc40SHeiko Schocher /**
1604ff94bc40SHeiko Schocher  * dbg_is_node_dirty - determine if a node is dirty.
1605ff94bc40SHeiko Schocher  * @c: the UBIFS file-system description object
1606ff94bc40SHeiko Schocher  * @node_type: node type
1607ff94bc40SHeiko Schocher  * @lnum: LEB number where node was written
1608ff94bc40SHeiko Schocher  * @offs: offset where node was written
1609ff94bc40SHeiko Schocher  */
dbg_is_node_dirty(struct ubifs_info * c,int node_type,int lnum,int offs)1610ff94bc40SHeiko Schocher static int dbg_is_node_dirty(struct ubifs_info *c, int node_type, int lnum,
1611ff94bc40SHeiko Schocher 			     int offs)
1612ff94bc40SHeiko Schocher {
1613ff94bc40SHeiko Schocher 	switch (node_type) {
1614ff94bc40SHeiko Schocher 	case UBIFS_LPT_NNODE:
1615ff94bc40SHeiko Schocher 		return dbg_is_nnode_dirty(c, lnum, offs);
1616ff94bc40SHeiko Schocher 	case UBIFS_LPT_PNODE:
1617ff94bc40SHeiko Schocher 		return dbg_is_pnode_dirty(c, lnum, offs);
1618ff94bc40SHeiko Schocher 	case UBIFS_LPT_LTAB:
1619ff94bc40SHeiko Schocher 		return dbg_is_ltab_dirty(c, lnum, offs);
1620ff94bc40SHeiko Schocher 	case UBIFS_LPT_LSAVE:
1621ff94bc40SHeiko Schocher 		return dbg_is_lsave_dirty(c, lnum, offs);
1622ff94bc40SHeiko Schocher 	}
1623ff94bc40SHeiko Schocher 	return 1;
1624ff94bc40SHeiko Schocher }
1625ff94bc40SHeiko Schocher 
1626ff94bc40SHeiko Schocher /**
1627ff94bc40SHeiko Schocher  * dbg_check_ltab_lnum - check the ltab for a LPT LEB number.
1628ff94bc40SHeiko Schocher  * @c: the UBIFS file-system description object
1629ff94bc40SHeiko Schocher  * @lnum: LEB number where node was written
1630ff94bc40SHeiko Schocher  * @offs: offset where node was written
1631ff94bc40SHeiko Schocher  *
1632ff94bc40SHeiko Schocher  * This function returns %0 on success and a negative error code on failure.
1633ff94bc40SHeiko Schocher  */
dbg_check_ltab_lnum(struct ubifs_info * c,int lnum)1634ff94bc40SHeiko Schocher static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum)
1635ff94bc40SHeiko Schocher {
1636ff94bc40SHeiko Schocher 	int err, len = c->leb_size, dirty = 0, node_type, node_num, node_len;
1637ff94bc40SHeiko Schocher 	int ret;
1638ff94bc40SHeiko Schocher 	void *buf, *p;
1639ff94bc40SHeiko Schocher 
1640ff94bc40SHeiko Schocher 	if (!dbg_is_chk_lprops(c))
1641ff94bc40SHeiko Schocher 		return 0;
1642ff94bc40SHeiko Schocher 
1643ff94bc40SHeiko Schocher 	buf = p = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL);
1644ff94bc40SHeiko Schocher 	if (!buf) {
1645*0195a7bbSHeiko Schocher 		ubifs_err(c, "cannot allocate memory for ltab checking");
1646ff94bc40SHeiko Schocher 		return 0;
1647ff94bc40SHeiko Schocher 	}
1648ff94bc40SHeiko Schocher 
1649ff94bc40SHeiko Schocher 	dbg_lp("LEB %d", lnum);
1650ff94bc40SHeiko Schocher 
1651ff94bc40SHeiko Schocher 	err = ubifs_leb_read(c, lnum, buf, 0, c->leb_size, 1);
1652ff94bc40SHeiko Schocher 	if (err)
1653ff94bc40SHeiko Schocher 		goto out;
1654ff94bc40SHeiko Schocher 
1655ff94bc40SHeiko Schocher 	while (1) {
1656ff94bc40SHeiko Schocher 		if (!is_a_node(c, p, len)) {
1657ff94bc40SHeiko Schocher 			int i, pad_len;
1658ff94bc40SHeiko Schocher 
1659ff94bc40SHeiko Schocher 			pad_len = get_pad_len(c, p, len);
1660ff94bc40SHeiko Schocher 			if (pad_len) {
1661ff94bc40SHeiko Schocher 				p += pad_len;
1662ff94bc40SHeiko Schocher 				len -= pad_len;
1663ff94bc40SHeiko Schocher 				dirty += pad_len;
1664ff94bc40SHeiko Schocher 				continue;
1665ff94bc40SHeiko Schocher 			}
1666ff94bc40SHeiko Schocher 			if (!dbg_is_all_ff(p, len)) {
1667*0195a7bbSHeiko Schocher 				ubifs_err(c, "invalid empty space in LEB %d at %d",
1668ff94bc40SHeiko Schocher 					  lnum, c->leb_size - len);
1669ff94bc40SHeiko Schocher 				err = -EINVAL;
1670ff94bc40SHeiko Schocher 			}
1671ff94bc40SHeiko Schocher 			i = lnum - c->lpt_first;
1672ff94bc40SHeiko Schocher 			if (len != c->ltab[i].free) {
1673*0195a7bbSHeiko Schocher 				ubifs_err(c, "invalid free space in LEB %d (free %d, expected %d)",
1674ff94bc40SHeiko Schocher 					  lnum, len, c->ltab[i].free);
1675ff94bc40SHeiko Schocher 				err = -EINVAL;
1676ff94bc40SHeiko Schocher 			}
1677ff94bc40SHeiko Schocher 			if (dirty != c->ltab[i].dirty) {
1678*0195a7bbSHeiko Schocher 				ubifs_err(c, "invalid dirty space in LEB %d (dirty %d, expected %d)",
1679ff94bc40SHeiko Schocher 					  lnum, dirty, c->ltab[i].dirty);
1680ff94bc40SHeiko Schocher 				err = -EINVAL;
1681ff94bc40SHeiko Schocher 			}
1682ff94bc40SHeiko Schocher 			goto out;
1683ff94bc40SHeiko Schocher 		}
1684ff94bc40SHeiko Schocher 		node_type = get_lpt_node_type(c, p, &node_num);
1685ff94bc40SHeiko Schocher 		node_len = get_lpt_node_len(c, node_type);
1686ff94bc40SHeiko Schocher 		ret = dbg_is_node_dirty(c, node_type, lnum, c->leb_size - len);
1687ff94bc40SHeiko Schocher 		if (ret == 1)
1688ff94bc40SHeiko Schocher 			dirty += node_len;
1689ff94bc40SHeiko Schocher 		p += node_len;
1690ff94bc40SHeiko Schocher 		len -= node_len;
1691ff94bc40SHeiko Schocher 	}
1692ff94bc40SHeiko Schocher 
1693ff94bc40SHeiko Schocher 	err = 0;
1694ff94bc40SHeiko Schocher out:
1695ff94bc40SHeiko Schocher 	vfree(buf);
1696ff94bc40SHeiko Schocher 	return err;
1697ff94bc40SHeiko Schocher }
1698ff94bc40SHeiko Schocher 
1699ff94bc40SHeiko Schocher /**
1700ff94bc40SHeiko Schocher  * dbg_check_ltab - check the free and dirty space in the ltab.
1701ff94bc40SHeiko Schocher  * @c: the UBIFS file-system description object
1702ff94bc40SHeiko Schocher  *
1703ff94bc40SHeiko Schocher  * This function returns %0 on success and a negative error code on failure.
1704ff94bc40SHeiko Schocher  */
dbg_check_ltab(struct ubifs_info * c)1705ff94bc40SHeiko Schocher int dbg_check_ltab(struct ubifs_info *c)
1706ff94bc40SHeiko Schocher {
1707ff94bc40SHeiko Schocher 	int lnum, err, i, cnt;
1708ff94bc40SHeiko Schocher 
1709ff94bc40SHeiko Schocher 	if (!dbg_is_chk_lprops(c))
1710ff94bc40SHeiko Schocher 		return 0;
1711ff94bc40SHeiko Schocher 
1712ff94bc40SHeiko Schocher 	/* Bring the entire tree into memory */
1713ff94bc40SHeiko Schocher 	cnt = DIV_ROUND_UP(c->main_lebs, UBIFS_LPT_FANOUT);
1714ff94bc40SHeiko Schocher 	for (i = 0; i < cnt; i++) {
1715ff94bc40SHeiko Schocher 		struct ubifs_pnode *pnode;
1716ff94bc40SHeiko Schocher 
1717ff94bc40SHeiko Schocher 		pnode = pnode_lookup(c, i);
1718ff94bc40SHeiko Schocher 		if (IS_ERR(pnode))
1719ff94bc40SHeiko Schocher 			return PTR_ERR(pnode);
1720ff94bc40SHeiko Schocher 		cond_resched();
1721ff94bc40SHeiko Schocher 	}
1722ff94bc40SHeiko Schocher 
1723ff94bc40SHeiko Schocher 	/* Check nodes */
1724ff94bc40SHeiko Schocher 	err = dbg_check_lpt_nodes(c, (struct ubifs_cnode *)c->nroot, 0, 0);
1725ff94bc40SHeiko Schocher 	if (err)
1726ff94bc40SHeiko Schocher 		return err;
1727ff94bc40SHeiko Schocher 
1728ff94bc40SHeiko Schocher 	/* Check each LEB */
1729ff94bc40SHeiko Schocher 	for (lnum = c->lpt_first; lnum <= c->lpt_last; lnum++) {
1730ff94bc40SHeiko Schocher 		err = dbg_check_ltab_lnum(c, lnum);
1731ff94bc40SHeiko Schocher 		if (err) {
1732*0195a7bbSHeiko Schocher 			ubifs_err(c, "failed at LEB %d", lnum);
1733ff94bc40SHeiko Schocher 			return err;
1734ff94bc40SHeiko Schocher 		}
1735ff94bc40SHeiko Schocher 	}
1736ff94bc40SHeiko Schocher 
1737ff94bc40SHeiko Schocher 	dbg_lp("succeeded");
1738ff94bc40SHeiko Schocher 	return 0;
1739ff94bc40SHeiko Schocher }
1740ff94bc40SHeiko Schocher 
1741ff94bc40SHeiko Schocher /**
1742ff94bc40SHeiko Schocher  * dbg_chk_lpt_free_spc - check LPT free space is enough to write entire LPT.
1743ff94bc40SHeiko Schocher  * @c: the UBIFS file-system description object
1744ff94bc40SHeiko Schocher  *
1745ff94bc40SHeiko Schocher  * This function returns %0 on success and a negative error code on failure.
1746ff94bc40SHeiko Schocher  */
dbg_chk_lpt_free_spc(struct ubifs_info * c)1747ff94bc40SHeiko Schocher int dbg_chk_lpt_free_spc(struct ubifs_info *c)
1748ff94bc40SHeiko Schocher {
1749ff94bc40SHeiko Schocher 	long long free = 0;
1750ff94bc40SHeiko Schocher 	int i;
1751ff94bc40SHeiko Schocher 
1752ff94bc40SHeiko Schocher 	if (!dbg_is_chk_lprops(c))
1753ff94bc40SHeiko Schocher 		return 0;
1754ff94bc40SHeiko Schocher 
1755ff94bc40SHeiko Schocher 	for (i = 0; i < c->lpt_lebs; i++) {
1756ff94bc40SHeiko Schocher 		if (c->ltab[i].tgc || c->ltab[i].cmt)
1757ff94bc40SHeiko Schocher 			continue;
1758ff94bc40SHeiko Schocher 		if (i + c->lpt_first == c->nhead_lnum)
1759ff94bc40SHeiko Schocher 			free += c->leb_size - c->nhead_offs;
1760ff94bc40SHeiko Schocher 		else if (c->ltab[i].free == c->leb_size)
1761ff94bc40SHeiko Schocher 			free += c->leb_size;
1762ff94bc40SHeiko Schocher 	}
1763ff94bc40SHeiko Schocher 	if (free < c->lpt_sz) {
1764*0195a7bbSHeiko Schocher 		ubifs_err(c, "LPT space error: free %lld lpt_sz %lld",
1765ff94bc40SHeiko Schocher 			  free, c->lpt_sz);
1766ff94bc40SHeiko Schocher 		ubifs_dump_lpt_info(c);
1767ff94bc40SHeiko Schocher 		ubifs_dump_lpt_lebs(c);
1768ff94bc40SHeiko Schocher 		dump_stack();
1769ff94bc40SHeiko Schocher 		return -EINVAL;
1770ff94bc40SHeiko Schocher 	}
1771ff94bc40SHeiko Schocher 	return 0;
1772ff94bc40SHeiko Schocher }
1773ff94bc40SHeiko Schocher 
1774ff94bc40SHeiko Schocher /**
1775ff94bc40SHeiko Schocher  * dbg_chk_lpt_sz - check LPT does not write more than LPT size.
1776ff94bc40SHeiko Schocher  * @c: the UBIFS file-system description object
1777ff94bc40SHeiko Schocher  * @action: what to do
1778ff94bc40SHeiko Schocher  * @len: length written
1779ff94bc40SHeiko Schocher  *
1780ff94bc40SHeiko Schocher  * This function returns %0 on success and a negative error code on failure.
1781ff94bc40SHeiko Schocher  * The @action argument may be one of:
1782ff94bc40SHeiko Schocher  *   o %0 - LPT debugging checking starts, initialize debugging variables;
1783ff94bc40SHeiko Schocher  *   o %1 - wrote an LPT node, increase LPT size by @len bytes;
1784ff94bc40SHeiko Schocher  *   o %2 - switched to a different LEB and wasted @len bytes;
1785ff94bc40SHeiko Schocher  *   o %3 - check that we've written the right number of bytes.
1786ff94bc40SHeiko Schocher  *   o %4 - wasted @len bytes;
1787ff94bc40SHeiko Schocher  */
dbg_chk_lpt_sz(struct ubifs_info * c,int action,int len)1788ff94bc40SHeiko Schocher int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
1789ff94bc40SHeiko Schocher {
1790ff94bc40SHeiko Schocher 	struct ubifs_debug_info *d = c->dbg;
1791ff94bc40SHeiko Schocher 	long long chk_lpt_sz, lpt_sz;
1792ff94bc40SHeiko Schocher 	int err = 0;
1793ff94bc40SHeiko Schocher 
1794ff94bc40SHeiko Schocher 	if (!dbg_is_chk_lprops(c))
1795ff94bc40SHeiko Schocher 		return 0;
1796ff94bc40SHeiko Schocher 
1797ff94bc40SHeiko Schocher 	switch (action) {
1798ff94bc40SHeiko Schocher 	case 0:
1799ff94bc40SHeiko Schocher 		d->chk_lpt_sz = 0;
1800ff94bc40SHeiko Schocher 		d->chk_lpt_sz2 = 0;
1801ff94bc40SHeiko Schocher 		d->chk_lpt_lebs = 0;
1802ff94bc40SHeiko Schocher 		d->chk_lpt_wastage = 0;
1803ff94bc40SHeiko Schocher 		if (c->dirty_pn_cnt > c->pnode_cnt) {
1804*0195a7bbSHeiko Schocher 			ubifs_err(c, "dirty pnodes %d exceed max %d",
1805ff94bc40SHeiko Schocher 				  c->dirty_pn_cnt, c->pnode_cnt);
1806ff94bc40SHeiko Schocher 			err = -EINVAL;
1807ff94bc40SHeiko Schocher 		}
1808ff94bc40SHeiko Schocher 		if (c->dirty_nn_cnt > c->nnode_cnt) {
1809*0195a7bbSHeiko Schocher 			ubifs_err(c, "dirty nnodes %d exceed max %d",
1810ff94bc40SHeiko Schocher 				  c->dirty_nn_cnt, c->nnode_cnt);
1811ff94bc40SHeiko Schocher 			err = -EINVAL;
1812ff94bc40SHeiko Schocher 		}
1813ff94bc40SHeiko Schocher 		return err;
1814ff94bc40SHeiko Schocher 	case 1:
1815ff94bc40SHeiko Schocher 		d->chk_lpt_sz += len;
1816ff94bc40SHeiko Schocher 		return 0;
1817ff94bc40SHeiko Schocher 	case 2:
1818ff94bc40SHeiko Schocher 		d->chk_lpt_sz += len;
1819ff94bc40SHeiko Schocher 		d->chk_lpt_wastage += len;
1820ff94bc40SHeiko Schocher 		d->chk_lpt_lebs += 1;
1821ff94bc40SHeiko Schocher 		return 0;
1822ff94bc40SHeiko Schocher 	case 3:
1823ff94bc40SHeiko Schocher 		chk_lpt_sz = c->leb_size;
1824ff94bc40SHeiko Schocher 		chk_lpt_sz *= d->chk_lpt_lebs;
1825ff94bc40SHeiko Schocher 		chk_lpt_sz += len - c->nhead_offs;
1826ff94bc40SHeiko Schocher 		if (d->chk_lpt_sz != chk_lpt_sz) {
1827*0195a7bbSHeiko Schocher 			ubifs_err(c, "LPT wrote %lld but space used was %lld",
1828ff94bc40SHeiko Schocher 				  d->chk_lpt_sz, chk_lpt_sz);
1829ff94bc40SHeiko Schocher 			err = -EINVAL;
1830ff94bc40SHeiko Schocher 		}
1831ff94bc40SHeiko Schocher 		if (d->chk_lpt_sz > c->lpt_sz) {
1832*0195a7bbSHeiko Schocher 			ubifs_err(c, "LPT wrote %lld but lpt_sz is %lld",
1833ff94bc40SHeiko Schocher 				  d->chk_lpt_sz, c->lpt_sz);
1834ff94bc40SHeiko Schocher 			err = -EINVAL;
1835ff94bc40SHeiko Schocher 		}
1836ff94bc40SHeiko Schocher 		if (d->chk_lpt_sz2 && d->chk_lpt_sz != d->chk_lpt_sz2) {
1837*0195a7bbSHeiko Schocher 			ubifs_err(c, "LPT layout size %lld but wrote %lld",
1838ff94bc40SHeiko Schocher 				  d->chk_lpt_sz, d->chk_lpt_sz2);
1839ff94bc40SHeiko Schocher 			err = -EINVAL;
1840ff94bc40SHeiko Schocher 		}
1841ff94bc40SHeiko Schocher 		if (d->chk_lpt_sz2 && d->new_nhead_offs != len) {
1842*0195a7bbSHeiko Schocher 			ubifs_err(c, "LPT new nhead offs: expected %d was %d",
1843ff94bc40SHeiko Schocher 				  d->new_nhead_offs, len);
1844ff94bc40SHeiko Schocher 			err = -EINVAL;
1845ff94bc40SHeiko Schocher 		}
1846ff94bc40SHeiko Schocher 		lpt_sz = (long long)c->pnode_cnt * c->pnode_sz;
1847ff94bc40SHeiko Schocher 		lpt_sz += (long long)c->nnode_cnt * c->nnode_sz;
1848ff94bc40SHeiko Schocher 		lpt_sz += c->ltab_sz;
1849ff94bc40SHeiko Schocher 		if (c->big_lpt)
1850ff94bc40SHeiko Schocher 			lpt_sz += c->lsave_sz;
1851ff94bc40SHeiko Schocher 		if (d->chk_lpt_sz - d->chk_lpt_wastage > lpt_sz) {
1852*0195a7bbSHeiko Schocher 			ubifs_err(c, "LPT chk_lpt_sz %lld + waste %lld exceeds %lld",
1853ff94bc40SHeiko Schocher 				  d->chk_lpt_sz, d->chk_lpt_wastage, lpt_sz);
1854ff94bc40SHeiko Schocher 			err = -EINVAL;
1855ff94bc40SHeiko Schocher 		}
1856ff94bc40SHeiko Schocher 		if (err) {
1857ff94bc40SHeiko Schocher 			ubifs_dump_lpt_info(c);
1858ff94bc40SHeiko Schocher 			ubifs_dump_lpt_lebs(c);
1859ff94bc40SHeiko Schocher 			dump_stack();
1860ff94bc40SHeiko Schocher 		}
1861ff94bc40SHeiko Schocher 		d->chk_lpt_sz2 = d->chk_lpt_sz;
1862ff94bc40SHeiko Schocher 		d->chk_lpt_sz = 0;
1863ff94bc40SHeiko Schocher 		d->chk_lpt_wastage = 0;
1864ff94bc40SHeiko Schocher 		d->chk_lpt_lebs = 0;
1865ff94bc40SHeiko Schocher 		d->new_nhead_offs = len;
1866ff94bc40SHeiko Schocher 		return err;
1867ff94bc40SHeiko Schocher 	case 4:
1868ff94bc40SHeiko Schocher 		d->chk_lpt_sz += len;
1869ff94bc40SHeiko Schocher 		d->chk_lpt_wastage += len;
1870ff94bc40SHeiko Schocher 		return 0;
1871ff94bc40SHeiko Schocher 	default:
1872ff94bc40SHeiko Schocher 		return -EINVAL;
1873ff94bc40SHeiko Schocher 	}
1874ff94bc40SHeiko Schocher }
1875ff94bc40SHeiko Schocher 
1876ff94bc40SHeiko Schocher /**
1877ff94bc40SHeiko Schocher  * ubifs_dump_lpt_leb - dump an LPT LEB.
1878ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
1879ff94bc40SHeiko Schocher  * @lnum: LEB number to dump
1880ff94bc40SHeiko Schocher  *
1881ff94bc40SHeiko Schocher  * This function dumps an LEB from LPT area. Nodes in this area are very
1882ff94bc40SHeiko Schocher  * different to nodes in the main area (e.g., they do not have common headers,
1883ff94bc40SHeiko Schocher  * they do not have 8-byte alignments, etc), so we have a separate function to
1884ff94bc40SHeiko Schocher  * dump LPT area LEBs. Note, LPT has to be locked by the caller.
1885ff94bc40SHeiko Schocher  */
dump_lpt_leb(const struct ubifs_info * c,int lnum)1886ff94bc40SHeiko Schocher static void dump_lpt_leb(const struct ubifs_info *c, int lnum)
1887ff94bc40SHeiko Schocher {
1888ff94bc40SHeiko Schocher 	int err, len = c->leb_size, node_type, node_num, node_len, offs;
1889ff94bc40SHeiko Schocher 	void *buf, *p;
1890ff94bc40SHeiko Schocher 
1891ff94bc40SHeiko Schocher 	pr_err("(pid %d) start dumping LEB %d\n", current->pid, lnum);
1892ff94bc40SHeiko Schocher 	buf = p = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL);
1893ff94bc40SHeiko Schocher 	if (!buf) {
1894*0195a7bbSHeiko Schocher 		ubifs_err(c, "cannot allocate memory to dump LPT");
1895ff94bc40SHeiko Schocher 		return;
1896ff94bc40SHeiko Schocher 	}
1897ff94bc40SHeiko Schocher 
1898ff94bc40SHeiko Schocher 	err = ubifs_leb_read(c, lnum, buf, 0, c->leb_size, 1);
1899ff94bc40SHeiko Schocher 	if (err)
1900ff94bc40SHeiko Schocher 		goto out;
1901ff94bc40SHeiko Schocher 
1902ff94bc40SHeiko Schocher 	while (1) {
1903ff94bc40SHeiko Schocher 		offs = c->leb_size - len;
1904ff94bc40SHeiko Schocher 		if (!is_a_node(c, p, len)) {
1905ff94bc40SHeiko Schocher 			int pad_len;
1906ff94bc40SHeiko Schocher 
1907ff94bc40SHeiko Schocher 			pad_len = get_pad_len(c, p, len);
1908ff94bc40SHeiko Schocher 			if (pad_len) {
1909ff94bc40SHeiko Schocher 				pr_err("LEB %d:%d, pad %d bytes\n",
1910ff94bc40SHeiko Schocher 				       lnum, offs, pad_len);
1911ff94bc40SHeiko Schocher 				p += pad_len;
1912ff94bc40SHeiko Schocher 				len -= pad_len;
1913ff94bc40SHeiko Schocher 				continue;
1914ff94bc40SHeiko Schocher 			}
1915ff94bc40SHeiko Schocher 			if (len)
1916ff94bc40SHeiko Schocher 				pr_err("LEB %d:%d, free %d bytes\n",
1917ff94bc40SHeiko Schocher 				       lnum, offs, len);
1918ff94bc40SHeiko Schocher 			break;
1919ff94bc40SHeiko Schocher 		}
1920ff94bc40SHeiko Schocher 
1921ff94bc40SHeiko Schocher 		node_type = get_lpt_node_type(c, p, &node_num);
1922ff94bc40SHeiko Schocher 		switch (node_type) {
1923ff94bc40SHeiko Schocher 		case UBIFS_LPT_PNODE:
1924ff94bc40SHeiko Schocher 		{
1925ff94bc40SHeiko Schocher 			node_len = c->pnode_sz;
1926ff94bc40SHeiko Schocher 			if (c->big_lpt)
1927ff94bc40SHeiko Schocher 				pr_err("LEB %d:%d, pnode num %d\n",
1928ff94bc40SHeiko Schocher 				       lnum, offs, node_num);
1929ff94bc40SHeiko Schocher 			else
1930ff94bc40SHeiko Schocher 				pr_err("LEB %d:%d, pnode\n", lnum, offs);
1931ff94bc40SHeiko Schocher 			break;
1932ff94bc40SHeiko Schocher 		}
1933ff94bc40SHeiko Schocher 		case UBIFS_LPT_NNODE:
1934ff94bc40SHeiko Schocher 		{
1935ff94bc40SHeiko Schocher 			int i;
1936ff94bc40SHeiko Schocher 			struct ubifs_nnode nnode;
1937ff94bc40SHeiko Schocher 
1938ff94bc40SHeiko Schocher 			node_len = c->nnode_sz;
1939ff94bc40SHeiko Schocher 			if (c->big_lpt)
1940ff94bc40SHeiko Schocher 				pr_err("LEB %d:%d, nnode num %d, ",
1941ff94bc40SHeiko Schocher 				       lnum, offs, node_num);
1942ff94bc40SHeiko Schocher 			else
1943ff94bc40SHeiko Schocher 				pr_err("LEB %d:%d, nnode, ",
1944ff94bc40SHeiko Schocher 				       lnum, offs);
1945ff94bc40SHeiko Schocher 			err = ubifs_unpack_nnode(c, p, &nnode);
1946*0195a7bbSHeiko Schocher 			if (err) {
1947*0195a7bbSHeiko Schocher 				pr_err("failed to unpack_node, error %d\n",
1948*0195a7bbSHeiko Schocher 				       err);
1949*0195a7bbSHeiko Schocher 				break;
1950*0195a7bbSHeiko Schocher 			}
1951ff94bc40SHeiko Schocher 			for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
1952ff94bc40SHeiko Schocher 				pr_cont("%d:%d", nnode.nbranch[i].lnum,
1953ff94bc40SHeiko Schocher 				       nnode.nbranch[i].offs);
1954ff94bc40SHeiko Schocher 				if (i != UBIFS_LPT_FANOUT - 1)
1955ff94bc40SHeiko Schocher 					pr_cont(", ");
1956ff94bc40SHeiko Schocher 			}
1957ff94bc40SHeiko Schocher 			pr_cont("\n");
1958ff94bc40SHeiko Schocher 			break;
1959ff94bc40SHeiko Schocher 		}
1960ff94bc40SHeiko Schocher 		case UBIFS_LPT_LTAB:
1961ff94bc40SHeiko Schocher 			node_len = c->ltab_sz;
1962ff94bc40SHeiko Schocher 			pr_err("LEB %d:%d, ltab\n", lnum, offs);
1963ff94bc40SHeiko Schocher 			break;
1964ff94bc40SHeiko Schocher 		case UBIFS_LPT_LSAVE:
1965ff94bc40SHeiko Schocher 			node_len = c->lsave_sz;
1966ff94bc40SHeiko Schocher 			pr_err("LEB %d:%d, lsave len\n", lnum, offs);
1967ff94bc40SHeiko Schocher 			break;
1968ff94bc40SHeiko Schocher 		default:
1969*0195a7bbSHeiko Schocher 			ubifs_err(c, "LPT node type %d not recognized", node_type);
1970ff94bc40SHeiko Schocher 			goto out;
1971ff94bc40SHeiko Schocher 		}
1972ff94bc40SHeiko Schocher 
1973ff94bc40SHeiko Schocher 		p += node_len;
1974ff94bc40SHeiko Schocher 		len -= node_len;
1975ff94bc40SHeiko Schocher 	}
1976ff94bc40SHeiko Schocher 
1977ff94bc40SHeiko Schocher 	pr_err("(pid %d) finish dumping LEB %d\n", current->pid, lnum);
1978ff94bc40SHeiko Schocher out:
1979ff94bc40SHeiko Schocher 	vfree(buf);
1980ff94bc40SHeiko Schocher 	return;
1981ff94bc40SHeiko Schocher }
1982ff94bc40SHeiko Schocher 
1983ff94bc40SHeiko Schocher /**
1984ff94bc40SHeiko Schocher  * ubifs_dump_lpt_lebs - dump LPT lebs.
1985ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
1986ff94bc40SHeiko Schocher  *
1987ff94bc40SHeiko Schocher  * This function dumps all LPT LEBs. The caller has to make sure the LPT is
1988ff94bc40SHeiko Schocher  * locked.
1989ff94bc40SHeiko Schocher  */
ubifs_dump_lpt_lebs(const struct ubifs_info * c)1990ff94bc40SHeiko Schocher void ubifs_dump_lpt_lebs(const struct ubifs_info *c)
1991ff94bc40SHeiko Schocher {
1992ff94bc40SHeiko Schocher 	int i;
1993ff94bc40SHeiko Schocher 
1994ff94bc40SHeiko Schocher 	pr_err("(pid %d) start dumping all LPT LEBs\n", current->pid);
1995ff94bc40SHeiko Schocher 	for (i = 0; i < c->lpt_lebs; i++)
1996ff94bc40SHeiko Schocher 		dump_lpt_leb(c, i + c->lpt_first);
1997ff94bc40SHeiko Schocher 	pr_err("(pid %d) finish dumping all LPT LEBs\n", current->pid);
1998ff94bc40SHeiko Schocher }
1999ff94bc40SHeiko Schocher 
2000ff94bc40SHeiko Schocher /**
2001ff94bc40SHeiko Schocher  * dbg_populate_lsave - debugging version of 'populate_lsave()'
2002ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
2003ff94bc40SHeiko Schocher  *
2004ff94bc40SHeiko Schocher  * This is a debugging version for 'populate_lsave()' which populates lsave
2005ff94bc40SHeiko Schocher  * with random LEBs instead of useful LEBs, which is good for test coverage.
2006ff94bc40SHeiko Schocher  * Returns zero if lsave has not been populated (this debugging feature is
2007ff94bc40SHeiko Schocher  * disabled) an non-zero if lsave has been populated.
2008ff94bc40SHeiko Schocher  */
dbg_populate_lsave(struct ubifs_info * c)2009ff94bc40SHeiko Schocher static int dbg_populate_lsave(struct ubifs_info *c)
2010ff94bc40SHeiko Schocher {
2011ff94bc40SHeiko Schocher 	struct ubifs_lprops *lprops;
2012ff94bc40SHeiko Schocher 	struct ubifs_lpt_heap *heap;
2013ff94bc40SHeiko Schocher 	int i;
2014ff94bc40SHeiko Schocher 
2015ff94bc40SHeiko Schocher 	if (!dbg_is_chk_gen(c))
2016ff94bc40SHeiko Schocher 		return 0;
2017ff94bc40SHeiko Schocher 	if (prandom_u32() & 3)
2018ff94bc40SHeiko Schocher 		return 0;
2019ff94bc40SHeiko Schocher 
2020ff94bc40SHeiko Schocher 	for (i = 0; i < c->lsave_cnt; i++)
2021ff94bc40SHeiko Schocher 		c->lsave[i] = c->main_first;
2022ff94bc40SHeiko Schocher 
2023ff94bc40SHeiko Schocher 	list_for_each_entry(lprops, &c->empty_list, list)
2024ff94bc40SHeiko Schocher 		c->lsave[prandom_u32() % c->lsave_cnt] = lprops->lnum;
2025ff94bc40SHeiko Schocher 	list_for_each_entry(lprops, &c->freeable_list, list)
2026ff94bc40SHeiko Schocher 		c->lsave[prandom_u32() % c->lsave_cnt] = lprops->lnum;
2027ff94bc40SHeiko Schocher 	list_for_each_entry(lprops, &c->frdi_idx_list, list)
2028ff94bc40SHeiko Schocher 		c->lsave[prandom_u32() % c->lsave_cnt] = lprops->lnum;
2029ff94bc40SHeiko Schocher 
2030ff94bc40SHeiko Schocher 	heap = &c->lpt_heap[LPROPS_DIRTY_IDX - 1];
2031ff94bc40SHeiko Schocher 	for (i = 0; i < heap->cnt; i++)
2032ff94bc40SHeiko Schocher 		c->lsave[prandom_u32() % c->lsave_cnt] = heap->arr[i]->lnum;
2033ff94bc40SHeiko Schocher 	heap = &c->lpt_heap[LPROPS_DIRTY - 1];
2034ff94bc40SHeiko Schocher 	for (i = 0; i < heap->cnt; i++)
2035ff94bc40SHeiko Schocher 		c->lsave[prandom_u32() % c->lsave_cnt] = heap->arr[i]->lnum;
2036ff94bc40SHeiko Schocher 	heap = &c->lpt_heap[LPROPS_FREE - 1];
2037ff94bc40SHeiko Schocher 	for (i = 0; i < heap->cnt; i++)
2038ff94bc40SHeiko Schocher 		c->lsave[prandom_u32() % c->lsave_cnt] = heap->arr[i]->lnum;
2039ff94bc40SHeiko Schocher 
2040ff94bc40SHeiko Schocher 	return 1;
2041ff94bc40SHeiko Schocher }
2042ff94bc40SHeiko Schocher #endif
2043