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