lpt_commit.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /*
  2. * This file is part of UBIFS.
  3. *
  4. * Copyright (C) 2006-2008 Nokia Corporation.
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License version 2 as published by
  8. * the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along with
  16. * this program; if not, write to the Free Software Foundation, Inc., 51
  17. * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  18. *
  19. * Authors: Adrian Hunter
  20. * Artem Bityutskiy (Битюцкий Артём)
  21. */
  22. /*
  23. * This file implements commit-related functionality of the LEB properties
  24. * subsystem.
  25. */
  26. #include "crc16.h"
  27. #include "ubifs.h"
  28. /**
  29. * free_obsolete_cnodes - free obsolete cnodes for commit end.
  30. * @c: UBIFS file-system description object
  31. */
  32. static void free_obsolete_cnodes(struct ubifs_info *c)
  33. {
  34. struct ubifs_cnode *cnode, *cnext;
  35. cnext = c->lpt_cnext;
  36. if (!cnext)
  37. return;
  38. do {
  39. cnode = cnext;
  40. cnext = cnode->cnext;
  41. if (test_bit(OBSOLETE_CNODE, &cnode->flags))
  42. kfree(cnode);
  43. else
  44. cnode->cnext = NULL;
  45. } while (cnext != c->lpt_cnext);
  46. c->lpt_cnext = NULL;
  47. }
  48. /**
  49. * first_nnode - find the first nnode in memory.
  50. * @c: UBIFS file-system description object
  51. * @hght: height of tree where nnode found is returned here
  52. *
  53. * This function returns a pointer to the nnode found or %NULL if no nnode is
  54. * found. This function is a helper to 'ubifs_lpt_free()'.
  55. */
  56. static struct ubifs_nnode *first_nnode(struct ubifs_info *c, int *hght)
  57. {
  58. struct ubifs_nnode *nnode;
  59. int h, i, found;
  60. nnode = c->nroot;
  61. *hght = 0;
  62. if (!nnode)
  63. return NULL;
  64. for (h = 1; h < c->lpt_hght; h++) {
  65. found = 0;
  66. for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
  67. if (nnode->nbranch[i].nnode) {
  68. found = 1;
  69. nnode = nnode->nbranch[i].nnode;
  70. *hght = h;
  71. break;
  72. }
  73. }
  74. if (!found)
  75. break;
  76. }
  77. return nnode;
  78. }
  79. /**
  80. * next_nnode - find the next nnode in memory.
  81. * @c: UBIFS file-system description object
  82. * @nnode: nnode from which to start.
  83. * @hght: height of tree where nnode is, is passed and returned here
  84. *
  85. * This function returns a pointer to the nnode found or %NULL if no nnode is
  86. * found. This function is a helper to 'ubifs_lpt_free()'.
  87. */
  88. static struct ubifs_nnode *next_nnode(struct ubifs_info *c,
  89. struct ubifs_nnode *nnode, int *hght)
  90. {
  91. struct ubifs_nnode *parent;
  92. int iip, h, i, found;
  93. parent = nnode->parent;
  94. if (!parent)
  95. return NULL;
  96. if (nnode->iip == UBIFS_LPT_FANOUT - 1) {
  97. *hght -= 1;
  98. return parent;
  99. }
  100. for (iip = nnode->iip + 1; iip < UBIFS_LPT_FANOUT; iip++) {
  101. nnode = parent->nbranch[iip].nnode;
  102. if (nnode)
  103. break;
  104. }
  105. if (!nnode) {
  106. *hght -= 1;
  107. return parent;
  108. }
  109. for (h = *hght + 1; h < c->lpt_hght; h++) {
  110. found = 0;
  111. for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
  112. if (nnode->nbranch[i].nnode) {
  113. found = 1;
  114. nnode = nnode->nbranch[i].nnode;
  115. *hght = h;
  116. break;
  117. }
  118. }
  119. if (!found)
  120. break;
  121. }
  122. return nnode;
  123. }
  124. /**
  125. * ubifs_lpt_free - free resources owned by the LPT.
  126. * @c: UBIFS file-system description object
  127. * @wr_only: free only resources used for writing
  128. */
  129. void ubifs_lpt_free(struct ubifs_info *c, int wr_only)
  130. {
  131. struct ubifs_nnode *nnode;
  132. int i, hght;
  133. /* Free write-only things first */
  134. free_obsolete_cnodes(c); /* Leftover from a failed commit */
  135. vfree(c->ltab_cmt);
  136. c->ltab_cmt = NULL;
  137. vfree(c->lpt_buf);
  138. c->lpt_buf = NULL;
  139. kfree(c->lsave);
  140. c->lsave = NULL;
  141. if (wr_only)
  142. return;
  143. /* Now free the rest */
  144. nnode = first_nnode(c, &hght);
  145. while (nnode) {
  146. for (i = 0; i < UBIFS_LPT_FANOUT; i++)
  147. kfree(nnode->nbranch[i].nnode);
  148. nnode = next_nnode(c, nnode, &hght);
  149. }
  150. for (i = 0; i < LPROPS_HEAP_CNT; i++)
  151. kfree(c->lpt_heap[i].arr);
  152. kfree(c->dirty_idx.arr);
  153. kfree(c->nroot);
  154. vfree(c->ltab);
  155. kfree(c->lpt_nod_buf);
  156. }