ext2fs_balloc.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. /* $OpenBSD: ext2fs_balloc.c,v 1.25 2015/03/14 03:38:52 jsg Exp $ */
  2. /* $NetBSD: ext2fs_balloc.c,v 1.10 2001/07/04 21:16:01 chs Exp $ */
  3. /*
  4. * Copyright (c) 1997 Manuel Bouyer.
  5. * Copyright (c) 1982, 1986, 1989, 1993
  6. * The Regents of the University of California. All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. Neither the name of the University nor the names of its contributors
  17. * may be used to endorse or promote products derived from this software
  18. * without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  21. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  24. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * @(#)ffs_balloc.c 8.4 (Berkeley) 9/23/93
  33. * Modified for ext2fs by Manuel Bouyer.
  34. */
  35. #include <sys/param.h>
  36. #include <sys/systm.h>
  37. #include <sys/buf.h>
  38. #include <sys/vnode.h>
  39. #include <ufs/ufs/quota.h>
  40. #include <ufs/ufs/inode.h>
  41. #include <ufs/ufs/ufs_extern.h>
  42. #include <ufs/ext2fs/ext2fs.h>
  43. #include <ufs/ext2fs/ext2fs_extern.h>
  44. /*
  45. * Balloc defines the structure of file system storage
  46. * by allocating the physical blocks on a device given
  47. * the inode and the logical block number in a file.
  48. */
  49. int
  50. ext2fs_buf_alloc(struct inode *ip, u_int32_t bn, int size, struct ucred *cred,
  51. struct buf **bpp, int flags)
  52. {
  53. struct m_ext2fs *fs;
  54. struct buf *bp, *nbp;
  55. struct vnode *vp = ITOV(ip);
  56. struct indir indirs[NIADDR + 2];
  57. u_int32_t nb, newb, *bap;
  58. int num, i, error;
  59. u_int deallocated;
  60. u_int32_t *allocib, *blkp, *allocblk, allociblk[NIADDR + 1];
  61. int unwindidx = -1;
  62. daddr_t lbn, pref;
  63. *bpp = NULL;
  64. if (bn < 0)
  65. return (EFBIG);
  66. fs = ip->i_e2fs;
  67. lbn = bn;
  68. /*
  69. * The first NDADDR blocks are direct blocks
  70. */
  71. if (bn < NDADDR) {
  72. nb = letoh32(ip->i_e2fs_blocks[bn]);
  73. if (nb != 0) {
  74. error = bread(vp, bn, fs->e2fs_bsize, &bp);
  75. if (error) {
  76. brelse(bp);
  77. return (error);
  78. }
  79. *bpp = bp;
  80. return (0);
  81. }
  82. /*
  83. * allocate a new direct block.
  84. */
  85. error = ext2fs_alloc(ip, bn,
  86. ext2fs_blkpref(ip, bn, (int)bn, &ip->i_e2fs_blocks[0]),
  87. cred, &newb);
  88. if (error)
  89. return (error);
  90. ip->i_e2fs_last_lblk = lbn;
  91. ip->i_e2fs_last_blk = newb;
  92. ip->i_e2fs_blocks[bn] = htole32(newb);
  93. ip->i_flag |= IN_CHANGE | IN_UPDATE;
  94. bp = getblk(vp, bn, fs->e2fs_bsize, 0, 0);
  95. bp->b_blkno = fsbtodb(fs, newb);
  96. if (flags & B_CLRBUF)
  97. clrbuf(bp);
  98. *bpp = bp;
  99. return (0);
  100. }
  101. /*
  102. * Determine the number of levels of indirection.
  103. */
  104. pref = 0;
  105. if ((error = ufs_getlbns(vp, bn, indirs, &num)) != 0)
  106. return(error);
  107. #ifdef DIAGNOSTIC
  108. if (num < 1)
  109. panic ("ext2fs_balloc: ufs_getlbns returned indirect block");
  110. #endif
  111. /*
  112. * Fetch the first indirect block allocating if necessary.
  113. */
  114. --num;
  115. nb = letoh32(ip->i_e2fs_blocks[NDADDR + indirs[0].in_off]);
  116. allocib = NULL;
  117. allocblk = allociblk;
  118. if (nb == 0) {
  119. pref = ext2fs_blkpref(ip, lbn, 0, NULL);
  120. error = ext2fs_alloc(ip, lbn, pref, cred, &newb);
  121. if (error)
  122. return (error);
  123. nb = newb;
  124. *allocblk++ = nb;
  125. ip->i_e2fs_last_blk = newb;
  126. bp = getblk(vp, indirs[1].in_lbn, fs->e2fs_bsize, 0, 0);
  127. bp->b_blkno = fsbtodb(fs, newb);
  128. clrbuf(bp);
  129. /*
  130. * Write synchronously so that indirect blocks
  131. * never point at garbage.
  132. */
  133. if ((error = bwrite(bp)) != 0)
  134. goto fail;
  135. unwindidx = 0;
  136. allocib = &ip->i_e2fs_blocks[NDADDR + indirs[0].in_off];
  137. *allocib = htole32(newb);
  138. ip->i_flag |= IN_CHANGE | IN_UPDATE;
  139. }
  140. /*
  141. * Fetch through the indirect blocks, allocating as necessary.
  142. */
  143. for (i = 1;;) {
  144. error = bread(vp, indirs[i].in_lbn, (int)fs->e2fs_bsize, &bp);
  145. if (error) {
  146. brelse(bp);
  147. goto fail;
  148. }
  149. bap = (u_int32_t *)bp->b_data;
  150. nb = letoh32(bap[indirs[i].in_off]);
  151. if (i == num)
  152. break;
  153. i++;
  154. if (nb != 0) {
  155. brelse(bp);
  156. continue;
  157. }
  158. pref = ext2fs_blkpref(ip, lbn, 0, NULL);
  159. error = ext2fs_alloc(ip, lbn, pref, cred, &newb);
  160. if (error) {
  161. brelse(bp);
  162. goto fail;
  163. }
  164. nb = newb;
  165. *allocblk++ = nb;
  166. ip->i_e2fs_last_blk = newb;
  167. nbp = getblk(vp, indirs[i].in_lbn, fs->e2fs_bsize, 0, 0);
  168. nbp->b_blkno = fsbtodb(fs, nb);
  169. clrbuf(nbp);
  170. /*
  171. * Write synchronously so that indirect blocks
  172. * never point at garbage.
  173. */
  174. if ((error = bwrite(nbp)) != 0) {
  175. brelse(bp);
  176. goto fail;
  177. }
  178. if (unwindidx < 0)
  179. unwindidx = i - 1;
  180. bap[indirs[i - 1].in_off] = htole32(nb);
  181. /*
  182. * If required, write synchronously, otherwise use
  183. * delayed write.
  184. */
  185. if (flags & B_SYNC) {
  186. bwrite(bp);
  187. } else {
  188. bdwrite(bp);
  189. }
  190. }
  191. /*
  192. * Get the data block, allocating if necessary.
  193. */
  194. if (nb == 0) {
  195. pref = ext2fs_blkpref(ip, lbn, indirs[num].in_off, bap);
  196. error = ext2fs_alloc(ip, lbn, pref, cred, &newb);
  197. if (error) {
  198. brelse(bp);
  199. goto fail;
  200. }
  201. nb = newb;
  202. *allocblk++ = nb;
  203. ip->i_e2fs_last_lblk = lbn;
  204. ip->i_e2fs_last_blk = newb;
  205. bap[indirs[num].in_off] = htole32(nb);
  206. /*
  207. * If required, write synchronously, otherwise use
  208. * delayed write.
  209. */
  210. if (flags & B_SYNC) {
  211. bwrite(bp);
  212. } else {
  213. bdwrite(bp);
  214. }
  215. nbp = getblk(vp, lbn, fs->e2fs_bsize, 0, 0);
  216. nbp->b_blkno = fsbtodb(fs, nb);
  217. if (flags & B_CLRBUF)
  218. clrbuf(nbp);
  219. *bpp = nbp;
  220. return (0);
  221. }
  222. brelse(bp);
  223. if (flags & B_CLRBUF) {
  224. error = bread(vp, lbn, (int)fs->e2fs_bsize, &nbp);
  225. if (error) {
  226. brelse(nbp);
  227. goto fail;
  228. }
  229. } else {
  230. nbp = getblk(vp, lbn, fs->e2fs_bsize, 0, 0);
  231. nbp->b_blkno = fsbtodb(fs, nb);
  232. }
  233. *bpp = nbp;
  234. return (0);
  235. fail:
  236. /*
  237. * If we have failed part way through block allocation, we
  238. * have to deallocate any indirect blocks that we have allocated.
  239. */
  240. for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) {
  241. ext2fs_blkfree(ip, *blkp);
  242. deallocated += fs->e2fs_bsize;
  243. }
  244. if (unwindidx >= 0) {
  245. if (unwindidx == 0) {
  246. *allocib = 0;
  247. } else {
  248. int r;
  249. r = bread(vp, indirs[unwindidx].in_lbn,
  250. (int)fs->e2fs_bsize, &bp);
  251. if (r) {
  252. panic("Could not unwind indirect block, error %d", r);
  253. } else {
  254. bap = (u_int32_t *)bp->b_data;
  255. bap[indirs[unwindidx].in_off] = 0;
  256. if (flags & B_SYNC)
  257. bwrite(bp);
  258. else
  259. bdwrite(bp);
  260. }
  261. }
  262. for (i = unwindidx + 1; i <= num; i++) {
  263. bp = getblk(vp, indirs[i].in_lbn, (int)fs->e2fs_bsize,
  264. 0, 0);
  265. bp->b_flags |= B_INVAL;
  266. brelse(bp);
  267. }
  268. }
  269. if (deallocated) {
  270. ip->i_e2fs_nblock -= btodb(deallocated);
  271. ip->i_e2fs_flags |= IN_CHANGE | IN_UPDATE;
  272. }
  273. return error;
  274. }