Lines Matching +full:- +full:c
4 * Copyright (C) 2006-2008 Nokia Corporation.
6 * SPDX-License-Identifier: GPL-2.0+
24 static int dbg_check_bud_bytes(struct ubifs_info *c);
27 * ubifs_search_bud - search bud LEB.
28 * @c: UBIFS file-system description object
34 struct ubifs_bud *ubifs_search_bud(struct ubifs_info *c, int lnum) in ubifs_search_bud() argument
39 spin_lock(&c->buds_lock); in ubifs_search_bud()
40 p = c->buds.rb_node; in ubifs_search_bud()
43 if (lnum < bud->lnum) in ubifs_search_bud()
44 p = p->rb_left; in ubifs_search_bud()
45 else if (lnum > bud->lnum) in ubifs_search_bud()
46 p = p->rb_right; in ubifs_search_bud()
48 spin_unlock(&c->buds_lock); in ubifs_search_bud()
52 spin_unlock(&c->buds_lock); in ubifs_search_bud()
57 * ubifs_get_wbuf - get the wbuf associated with a LEB, if there is one.
58 * @c: UBIFS file-system description object
63 struct ubifs_wbuf *ubifs_get_wbuf(struct ubifs_info *c, int lnum) in ubifs_get_wbuf() argument
69 if (!c->jheads) in ubifs_get_wbuf()
72 spin_lock(&c->buds_lock); in ubifs_get_wbuf()
73 p = c->buds.rb_node; in ubifs_get_wbuf()
76 if (lnum < bud->lnum) in ubifs_get_wbuf()
77 p = p->rb_left; in ubifs_get_wbuf()
78 else if (lnum > bud->lnum) in ubifs_get_wbuf()
79 p = p->rb_right; in ubifs_get_wbuf()
81 jhead = bud->jhead; in ubifs_get_wbuf()
82 spin_unlock(&c->buds_lock); in ubifs_get_wbuf()
83 return &c->jheads[jhead].wbuf; in ubifs_get_wbuf()
86 spin_unlock(&c->buds_lock); in ubifs_get_wbuf()
91 * empty_log_bytes - calculate amount of empty space in the log.
92 * @c: UBIFS file-system description object
94 static inline long long empty_log_bytes(const struct ubifs_info *c) in empty_log_bytes() argument
98 h = (long long)c->lhead_lnum * c->leb_size + c->lhead_offs; in empty_log_bytes()
99 t = (long long)c->ltail_lnum * c->leb_size; in empty_log_bytes()
102 return c->log_bytes - h + t; in empty_log_bytes()
104 return t - h; in empty_log_bytes()
105 else if (c->lhead_lnum != c->ltail_lnum) in empty_log_bytes()
108 return c->log_bytes; in empty_log_bytes()
112 * ubifs_add_bud - add bud LEB to the tree of buds and its journal head list.
113 * @c: UBIFS file-system description object
116 void ubifs_add_bud(struct ubifs_info *c, struct ubifs_bud *bud) in ubifs_add_bud() argument
122 spin_lock(&c->buds_lock); in ubifs_add_bud()
123 p = &c->buds.rb_node; in ubifs_add_bud()
127 ubifs_assert(bud->lnum != b->lnum); in ubifs_add_bud()
128 if (bud->lnum < b->lnum) in ubifs_add_bud()
129 p = &(*p)->rb_left; in ubifs_add_bud()
131 p = &(*p)->rb_right; in ubifs_add_bud()
134 rb_link_node(&bud->rb, parent, p); in ubifs_add_bud()
135 rb_insert_color(&bud->rb, &c->buds); in ubifs_add_bud()
136 if (c->jheads) { in ubifs_add_bud()
137 jhead = &c->jheads[bud->jhead]; in ubifs_add_bud()
138 list_add_tail(&bud->list, &jhead->buds_list); in ubifs_add_bud()
140 ubifs_assert(c->replaying && c->ro_mount); in ubifs_add_bud()
148 c->bud_bytes += c->leb_size - bud->start; in ubifs_add_bud()
150 dbg_log("LEB %d:%d, jhead %s, bud_bytes %lld", bud->lnum, in ubifs_add_bud()
151 bud->start, dbg_jhead(bud->jhead), c->bud_bytes); in ubifs_add_bud()
152 spin_unlock(&c->buds_lock); in ubifs_add_bud()
156 * ubifs_add_bud_to_log - add a new bud to the log.
157 * @c: UBIFS file-system description object
164 * exceed the 'c->max_bud_bytes' limit. Returns zero in case of success,
165 * %-EAGAIN if commit is required, and a negative error codes in case of
168 int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs) in ubifs_add_bud_to_log() argument
176 return -ENOMEM; in ubifs_add_bud_to_log()
177 ref = kzalloc(c->ref_node_alsz, GFP_NOFS); in ubifs_add_bud_to_log()
180 return -ENOMEM; in ubifs_add_bud_to_log()
183 mutex_lock(&c->log_mutex); in ubifs_add_bud_to_log()
184 ubifs_assert(!c->ro_media && !c->ro_mount); in ubifs_add_bud_to_log()
185 if (c->ro_error) { in ubifs_add_bud_to_log()
186 err = -EROFS; in ubifs_add_bud_to_log()
191 if (empty_log_bytes(c) - c->ref_node_alsz < c->min_log_bytes) { in ubifs_add_bud_to_log()
192 dbg_log("not enough log space - %lld, required %d", in ubifs_add_bud_to_log()
193 empty_log_bytes(c), c->min_log_bytes); in ubifs_add_bud_to_log()
194 ubifs_commit_required(c); in ubifs_add_bud_to_log()
195 err = -EAGAIN; in ubifs_add_bud_to_log()
201 * 'c->max_bud_bytes' limit, because we want to guarantee mount time in ubifs_add_bud_to_log()
204 * It is not necessary to hold @c->buds_lock when reading @c->bud_bytes in ubifs_add_bud_to_log()
205 * because we are holding @c->log_mutex. All @c->bud_bytes take place in ubifs_add_bud_to_log()
206 * when both @c->log_mutex and @c->bud_bytes are locked. in ubifs_add_bud_to_log()
208 if (c->bud_bytes + c->leb_size - offs > c->max_bud_bytes) { in ubifs_add_bud_to_log()
210 c->bud_bytes, c->max_bud_bytes); in ubifs_add_bud_to_log()
211 ubifs_commit_required(c); in ubifs_add_bud_to_log()
212 err = -EAGAIN; in ubifs_add_bud_to_log()
217 * If the journal is full enough - start background commit. Note, it is in ubifs_add_bud_to_log()
218 * OK to read 'c->cmt_state' without spinlock because integer reads in ubifs_add_bud_to_log()
221 if (c->bud_bytes >= c->bg_bud_bytes && in ubifs_add_bud_to_log()
222 c->cmt_state == COMMIT_RESTING) { in ubifs_add_bud_to_log()
224 c->bud_bytes, c->max_bud_bytes); in ubifs_add_bud_to_log()
225 ubifs_request_bg_commit(c); in ubifs_add_bud_to_log()
228 bud->lnum = lnum; in ubifs_add_bud_to_log()
229 bud->start = offs; in ubifs_add_bud_to_log()
230 bud->jhead = jhead; in ubifs_add_bud_to_log()
232 ref->ch.node_type = UBIFS_REF_NODE; in ubifs_add_bud_to_log()
233 ref->lnum = cpu_to_le32(bud->lnum); in ubifs_add_bud_to_log()
234 ref->offs = cpu_to_le32(bud->start); in ubifs_add_bud_to_log()
235 ref->jhead = cpu_to_le32(jhead); in ubifs_add_bud_to_log()
237 if (c->lhead_offs > c->leb_size - c->ref_node_alsz) { in ubifs_add_bud_to_log()
238 c->lhead_lnum = ubifs_next_log_lnum(c, c->lhead_lnum); in ubifs_add_bud_to_log()
239 ubifs_assert(c->lhead_lnum != c->ltail_lnum); in ubifs_add_bud_to_log()
240 c->lhead_offs = 0; in ubifs_add_bud_to_log()
243 if (c->lhead_offs == 0) { in ubifs_add_bud_to_log()
245 err = ubifs_leb_unmap(c, c->lhead_lnum); in ubifs_add_bud_to_log()
250 if (bud->start == 0) { in ubifs_add_bud_to_log()
258 err = ubifs_leb_map(c, bud->lnum); in ubifs_add_bud_to_log()
264 c->lhead_lnum, c->lhead_offs); in ubifs_add_bud_to_log()
265 err = ubifs_write_node(c, ref, UBIFS_REF_NODE_SZ, c->lhead_lnum, in ubifs_add_bud_to_log()
266 c->lhead_offs); in ubifs_add_bud_to_log()
270 c->lhead_offs += c->ref_node_alsz; in ubifs_add_bud_to_log()
272 ubifs_add_bud(c, bud); in ubifs_add_bud_to_log()
274 mutex_unlock(&c->log_mutex); in ubifs_add_bud_to_log()
279 mutex_unlock(&c->log_mutex); in ubifs_add_bud_to_log()
286 * remove_buds - remove used buds.
287 * @c: UBIFS file-system description object
292 static void remove_buds(struct ubifs_info *c) in remove_buds() argument
296 ubifs_assert(list_empty(&c->old_buds)); in remove_buds()
297 c->cmt_bud_bytes = 0; in remove_buds()
298 spin_lock(&c->buds_lock); in remove_buds()
299 p = rb_first(&c->buds); in remove_buds()
307 wbuf = &c->jheads[bud->jhead].wbuf; in remove_buds()
309 if (wbuf->lnum == bud->lnum) { in remove_buds()
312 * heads (non-closed buds). in remove_buds()
314 c->cmt_bud_bytes += wbuf->offs - bud->start; in remove_buds()
316 bud->lnum, bud->start, dbg_jhead(bud->jhead), in remove_buds()
317 wbuf->offs - bud->start, c->cmt_bud_bytes); in remove_buds()
318 bud->start = wbuf->offs; in remove_buds()
320 c->cmt_bud_bytes += c->leb_size - bud->start; in remove_buds()
322 bud->lnum, bud->start, dbg_jhead(bud->jhead), in remove_buds()
323 c->leb_size - bud->start, c->cmt_bud_bytes); in remove_buds()
324 rb_erase(p1, &c->buds); in remove_buds()
332 list_move(&bud->list, &c->old_buds); in remove_buds()
335 spin_unlock(&c->buds_lock); in remove_buds()
339 * ubifs_log_start_commit - start commit.
340 * @c: UBIFS file-system description object
351 int ubifs_log_start_commit(struct ubifs_info *c, int *ltail_lnum) in ubifs_log_start_commit() argument
358 err = dbg_check_bud_bytes(c); in ubifs_log_start_commit()
362 max_len = UBIFS_CS_NODE_SZ + c->jhead_cnt * UBIFS_REF_NODE_SZ; in ubifs_log_start_commit()
363 max_len = ALIGN(max_len, c->min_io_size); in ubifs_log_start_commit()
366 return -ENOMEM; in ubifs_log_start_commit()
368 cs->ch.node_type = UBIFS_CS_NODE; in ubifs_log_start_commit()
369 cs->cmt_no = cpu_to_le64(c->cmt_no); in ubifs_log_start_commit()
370 ubifs_prepare_node(c, cs, UBIFS_CS_NODE_SZ, 0); in ubifs_log_start_commit()
373 * Note, we do not lock 'c->log_mutex' because this is the commit start in ubifs_log_start_commit()
375 * write-buffer because nobody can write to the file-system at this in ubifs_log_start_commit()
380 for (i = 0; i < c->jhead_cnt; i++) { in ubifs_log_start_commit()
381 int lnum = c->jheads[i].wbuf.lnum; in ubifs_log_start_commit()
382 int offs = c->jheads[i].wbuf.offs; in ubifs_log_start_commit()
384 if (lnum == -1 || offs == c->leb_size) in ubifs_log_start_commit()
390 ref->ch.node_type = UBIFS_REF_NODE; in ubifs_log_start_commit()
391 ref->lnum = cpu_to_le32(lnum); in ubifs_log_start_commit()
392 ref->offs = cpu_to_le32(offs); in ubifs_log_start_commit()
393 ref->jhead = cpu_to_le32(i); in ubifs_log_start_commit()
395 ubifs_prepare_node(c, ref, UBIFS_REF_NODE_SZ, 0); in ubifs_log_start_commit()
399 ubifs_pad(c, buf + len, ALIGN(len, c->min_io_size) - len); in ubifs_log_start_commit()
402 if (c->lhead_offs) { in ubifs_log_start_commit()
403 c->lhead_lnum = ubifs_next_log_lnum(c, c->lhead_lnum); in ubifs_log_start_commit()
404 ubifs_assert(c->lhead_lnum != c->ltail_lnum); in ubifs_log_start_commit()
405 c->lhead_offs = 0; in ubifs_log_start_commit()
409 err = ubifs_leb_unmap(c, c->lhead_lnum); in ubifs_log_start_commit()
413 len = ALIGN(len, c->min_io_size); in ubifs_log_start_commit()
414 dbg_log("writing commit start at LEB %d:0, len %d", c->lhead_lnum, len); in ubifs_log_start_commit()
415 err = ubifs_leb_write(c, c->lhead_lnum, cs, 0, len); in ubifs_log_start_commit()
419 *ltail_lnum = c->lhead_lnum; in ubifs_log_start_commit()
421 c->lhead_offs += len; in ubifs_log_start_commit()
422 if (c->lhead_offs == c->leb_size) { in ubifs_log_start_commit()
423 c->lhead_lnum = ubifs_next_log_lnum(c, c->lhead_lnum); in ubifs_log_start_commit()
424 c->lhead_offs = 0; in ubifs_log_start_commit()
427 remove_buds(c); in ubifs_log_start_commit()
433 c->min_log_bytes = 0; in ubifs_log_start_commit()
441 * ubifs_log_end_commit - end commit.
442 * @c: UBIFS file-system description object
450 int ubifs_log_end_commit(struct ubifs_info *c, int ltail_lnum) in ubifs_log_end_commit() argument
455 * At this phase we have to lock 'c->log_mutex' because UBIFS allows FS in ubifs_log_end_commit()
459 mutex_lock(&c->log_mutex); in ubifs_log_end_commit()
462 c->ltail_lnum, ltail_lnum); in ubifs_log_end_commit()
464 c->ltail_lnum = ltail_lnum; in ubifs_log_end_commit()
469 c->min_log_bytes = c->leb_size; in ubifs_log_end_commit()
471 spin_lock(&c->buds_lock); in ubifs_log_end_commit()
472 c->bud_bytes -= c->cmt_bud_bytes; in ubifs_log_end_commit()
473 spin_unlock(&c->buds_lock); in ubifs_log_end_commit()
475 err = dbg_check_bud_bytes(c); in ubifs_log_end_commit()
479 err = ubifs_write_master(c); in ubifs_log_end_commit()
482 mutex_unlock(&c->log_mutex); in ubifs_log_end_commit()
487 * ubifs_log_post_commit - things to do after commit is completed.
488 * @c: UBIFS file-system description object
499 int ubifs_log_post_commit(struct ubifs_info *c, int old_ltail_lnum) in ubifs_log_post_commit() argument
503 while (!list_empty(&c->old_buds)) { in ubifs_log_post_commit()
506 bud = list_entry(c->old_buds.next, struct ubifs_bud, list); in ubifs_log_post_commit()
507 err = ubifs_return_leb(c, bud->lnum); in ubifs_log_post_commit()
510 list_del(&bud->list); in ubifs_log_post_commit()
513 mutex_lock(&c->log_mutex); in ubifs_log_post_commit()
514 for (lnum = old_ltail_lnum; lnum != c->ltail_lnum; in ubifs_log_post_commit()
515 lnum = ubifs_next_log_lnum(c, lnum)) { in ubifs_log_post_commit()
517 err = ubifs_leb_unmap(c, lnum); in ubifs_log_post_commit()
522 mutex_unlock(&c->log_mutex); in ubifs_log_post_commit()
527 * struct done_ref - references that have been done.
528 * @rb: rb-tree node
537 * done_already - determine if a reference has been done already.
538 * @done_tree: rb-tree to store references that have been done
546 struct rb_node **p = &done_tree->rb_node, *parent = NULL; in done_already()
552 if (lnum < dr->lnum) in done_already()
553 p = &(*p)->rb_left; in done_already()
554 else if (lnum > dr->lnum) in done_already()
555 p = &(*p)->rb_right; in done_already()
562 return -ENOMEM; in done_already()
564 dr->lnum = lnum; in done_already()
566 rb_link_node(&dr->rb, parent, p); in done_already()
567 rb_insert_color(&dr->rb, done_tree); in done_already()
573 * destroy_done_tree - destroy the done tree.
585 * add_node - add a node to the consolidated log.
586 * @c: UBIFS file-system description object
594 static int add_node(struct ubifs_info *c, void *buf, int *lnum, int *offs, in add_node() argument
598 int len = le32_to_cpu(ch->len), remains = c->leb_size - *offs; in add_node()
601 int sz = ALIGN(*offs, c->min_io_size), err; in add_node()
603 ubifs_pad(c, buf + *offs, sz - *offs); in add_node()
604 err = ubifs_leb_change(c, *lnum, buf, sz); in add_node()
607 *lnum = ubifs_next_log_lnum(c, *lnum); in add_node()
616 * ubifs_consolidate_log - consolidate the log.
617 * @c: UBIFS file-system description object
625 int ubifs_consolidate_log(struct ubifs_info *c) in ubifs_consolidate_log() argument
633 dbg_rcvry("log tail LEB %d, log head LEB %d", c->ltail_lnum, in ubifs_consolidate_log()
634 c->lhead_lnum); in ubifs_consolidate_log()
635 buf = vmalloc(c->leb_size); in ubifs_consolidate_log()
637 return -ENOMEM; in ubifs_consolidate_log()
638 lnum = c->ltail_lnum; in ubifs_consolidate_log()
641 sleb = ubifs_scan(c, lnum, 0, c->sbuf, 0); in ubifs_consolidate_log()
646 list_for_each_entry(snod, &sleb->nodes, list) { in ubifs_consolidate_log()
647 switch (snod->type) { in ubifs_consolidate_log()
649 struct ubifs_ref_node *ref = snod->node; in ubifs_consolidate_log()
650 int ref_lnum = le32_to_cpu(ref->lnum); in ubifs_consolidate_log()
656 err = add_node(c, buf, &write_lnum, in ubifs_consolidate_log()
657 &offs, snod->node); in ubifs_consolidate_log()
666 err = add_node(c, buf, &write_lnum, &offs, in ubifs_consolidate_log()
667 snod->node); in ubifs_consolidate_log()
675 if (lnum == c->lhead_lnum) in ubifs_consolidate_log()
677 lnum = ubifs_next_log_lnum(c, lnum); in ubifs_consolidate_log()
680 int sz = ALIGN(offs, c->min_io_size); in ubifs_consolidate_log()
682 ubifs_pad(c, buf + offs, sz - offs); in ubifs_consolidate_log()
683 err = ubifs_leb_change(c, write_lnum, buf, sz); in ubifs_consolidate_log()
686 offs = ALIGN(offs, c->min_io_size); in ubifs_consolidate_log()
690 if (write_lnum == c->lhead_lnum) { in ubifs_consolidate_log()
691 ubifs_err(c, "log is too full"); in ubifs_consolidate_log()
692 return -EINVAL; in ubifs_consolidate_log()
697 lnum = ubifs_next_log_lnum(c, lnum); in ubifs_consolidate_log()
698 err = ubifs_leb_unmap(c, lnum); in ubifs_consolidate_log()
701 } while (lnum != c->lhead_lnum); in ubifs_consolidate_log()
702 c->lhead_lnum = write_lnum; in ubifs_consolidate_log()
703 c->lhead_offs = offs; in ubifs_consolidate_log()
704 dbg_rcvry("new log head at %d:%d", c->lhead_lnum, c->lhead_offs); in ubifs_consolidate_log()
716 * dbg_check_bud_bytes - make sure bud bytes calculation are all right.
717 * @c: UBIFS file-system description object
720 * ('c->bud_bytes' is correct). Returns zero in case of success and %-EINVAL in
723 static int dbg_check_bud_bytes(struct ubifs_info *c) in dbg_check_bud_bytes() argument
729 if (!dbg_is_chk_gen(c)) in dbg_check_bud_bytes()
732 spin_lock(&c->buds_lock); in dbg_check_bud_bytes()
733 for (i = 0; i < c->jhead_cnt; i++) in dbg_check_bud_bytes()
734 list_for_each_entry(bud, &c->jheads[i].buds_list, list) in dbg_check_bud_bytes()
735 bud_bytes += c->leb_size - bud->start; in dbg_check_bud_bytes()
737 if (c->bud_bytes != bud_bytes) { in dbg_check_bud_bytes()
738 ubifs_err(c, "bad bud_bytes %lld, calculated %lld", in dbg_check_bud_bytes()
739 c->bud_bytes, bud_bytes); in dbg_check_bud_bytes()
740 err = -EINVAL; in dbg_check_bud_bytes()
742 spin_unlock(&c->buds_lock); in dbg_check_bud_bytes()