|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26: /*
27: * Copyright (c) 1982, 1986, 1989, 1993
28: * The Regents of the University of California. All rights reserved.
29: *
30: * Redistribution and use in source and binary forms, with or without
31: * modification, are permitted provided that the following conditions
32: * are met:
33: * 1. Redistributions of source code must retain the above copyright
34: * notice, this list of conditions and the following disclaimer.
35: * 2. Redistributions in binary form must reproduce the above copyright
36: * notice, this list of conditions and the following disclaimer in the
37: * documentation and/or other materials provided with the distribution.
38: * 3. All advertising materials mentioning features or use of this software
39: * must display the following acknowledgement:
40: * This product includes software developed by the University of
41: * California, Berkeley and its contributors.
42: * 4. Neither the name of the University nor the names of its contributors
43: * may be used to endorse or promote products derived from this software
44: * without specific prior written permission.
45: *
46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56: * SUCH DAMAGE.
57: *
58: * @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95
59: */
60:
61: #include <rev_endian_fs.h>
62: #include <mach_nbc.h>
63: #include <sys/param.h>
64: #include <sys/systm.h>
65: #include <sys/buf.h>
66: #include <sys/proc.h>
67: #include <sys/file.h>
68: #include <sys/vnode.h>
69: #if REV_ENDIAN_FS
70: #include <sys/mount.h>
71: #endif /* REV_ENDIAN_FS */
72:
73: #include <sys/vm.h>
74:
75: #include <ufs/ufs/quota.h>
76: #include <ufs/ufs/inode.h>
77: #include <ufs/ufs/ufs_extern.h>
78:
79: #include <ufs/ffs/fs.h>
80: #include <ufs/ffs/ffs_extern.h>
81:
82: #if REV_ENDIAN_FS
83: #include <ufs/ufs/ufs_byte_order.h>
84: #include <architecture/byte_order.h>
85: #endif /* REV_ENDIAN_FS */
86:
87: #if MACH_NBC
88: #include <kern/mapfs.h>
89: #endif /* MACH_NBC */
90: /*
91: * Balloc defines the structure of file system storage
92: * by allocating the physical blocks on a device given
93: * the inode and the logical block number in a file.
94: */
95: ffs_balloc(ip, lbn, size, cred, bpp, flags)
96: register struct inode *ip;
97: register ufs_daddr_t lbn;
98: int size;
99: struct ucred *cred;
100: struct buf **bpp;
101: int flags;
102: {
103: register struct fs *fs;
104: register ufs_daddr_t nb;
105: struct buf *bp, *nbp;
106: struct vnode *vp = ITOV(ip);
107: struct indir indirs[NIADDR + 2];
108: ufs_daddr_t newb, *bap, pref;
109: int deallocated, osize, nsize, num, i, error;
110: ufs_daddr_t *allocib, *blkp, *allocblk, allociblk[NIADDR + 1];
111: #ifdef NeXT
112: int devBlockSize=0;
113: #endif /* NeXT */
114: #if REV_ENDIAN_FS
115: struct mount *mp=vp->v_mount;
116: int rev_endian=(mp->mnt_flag & MNT_REVEND);
117: #endif /* REV_ENDIAN_FS */
118:
119: *bpp = NULL;
120: if (lbn < 0)
121: return (EFBIG);
122: fs = ip->i_fs;
123:
124: /*
125: * If the next write will extend the file into a new block,
126: * and the file is currently composed of a fragment
127: * this fragment has to be extended to be a full block.
128: */
129: nb = lblkno(fs, ip->i_size);
130: if (nb < NDADDR && nb < lbn) {
131: osize = blksize(fs, ip, nb);
132: if (osize < fs->fs_bsize && osize > 0) {
133: error = ffs_realloccg(ip, nb,
134: ffs_blkpref(ip, nb, (int)nb, &ip->i_db[0]),
135: osize, (int)fs->fs_bsize, cred, &bp);
136: if (error)
137: return (error);
138: ip->i_size = (nb + 1) * fs->fs_bsize;
139: #if MACH_NBC
140: if ((vp->v_type == VREG) && (vp->v_vm_info && !(vp->v_vm_info->mapped))) {
141: #endif /* MACH_NBC */
142: vnode_pager_setsize(vp, (u_long)ip->i_size);
143: #if MACH_NBC
144: }
145: #endif /* MACH_NBC */
146: ip->i_db[nb] = dbtofsb(fs, bp->b_blkno);
147: ip->i_flag |= IN_CHANGE | IN_UPDATE;
148: if (flags & B_SYNC)
149: bwrite(bp);
150: else
151: bawrite(bp);
152: }
153: }
154: /*
155: * The first NDADDR blocks are direct blocks
156: */
157: if (lbn < NDADDR) {
158: nb = ip->i_db[lbn];
159: if (nb != 0 && ip->i_size >= (lbn + 1) * fs->fs_bsize) {
160: error = bread(vp, lbn, fs->fs_bsize, NOCRED, &bp);
161: if (error) {
162: brelse(bp);
163: return (error);
164: }
165: *bpp = bp;
166: return (0);
167: }
168: if (nb != 0) {
169: /*
170: * Consider need to reallocate a fragment.
171: */
172: osize = fragroundup(fs, blkoff(fs, ip->i_size));
173: nsize = fragroundup(fs, size);
174: if (nsize <= osize) {
175: error = bread(vp, lbn, osize, NOCRED, &bp);
176: if (error) {
177: brelse(bp);
178: return (error);
179: }
180: } else {
181: error = ffs_realloccg(ip, lbn,
182: ffs_blkpref(ip, lbn, (int)lbn,
183: &ip->i_db[0]), osize, nsize, cred, &bp);
184: if (error)
185: return (error);
186: }
187: } else {
188: if (ip->i_size < (lbn + 1) * fs->fs_bsize)
189: nsize = fragroundup(fs, size);
190: else
191: nsize = fs->fs_bsize;
192: error = ffs_alloc(ip, lbn,
193: ffs_blkpref(ip, lbn, (int)lbn, &ip->i_db[0]),
194: nsize, cred, &newb);
195: if (error)
196: return (error);
197: bp = getblk(vp, lbn, nsize, 0, 0);
198: bp->b_blkno = fsbtodb(fs, newb);
199: if (flags & B_CLRBUF)
200: clrbuf(bp);
201: }
202: ip->i_db[lbn] = dbtofsb(fs, bp->b_blkno);
203: ip->i_flag |= IN_CHANGE | IN_UPDATE;
204: *bpp = bp;
205: return (0);
206: }
207: /*
208: * Determine the number of levels of indirection.
209: */
210: pref = 0;
211: if (error = ufs_getlbns(vp, lbn, indirs, &num))
212: return(error);
213: #if DIAGNOSTIC
214: if (num < 1)
215: panic ("ffs_balloc: ufs_bmaparray returned indirect block\n");
216: #endif
217: /*
218: * Fetch the first indirect block allocating if necessary.
219: */
220: --num;
221: nb = ip->i_ib[indirs[0].in_off];
222: allocib = NULL;
223: allocblk = allociblk;
224: if (nb == 0) {
225: pref = ffs_blkpref(ip, lbn, 0, (ufs_daddr_t *)0);
226: if (error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize,
227: cred, &newb))
228: return (error);
229: nb = newb;
230: *allocblk++ = nb;
231: bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0);
232: bp->b_blkno = fsbtodb(fs, nb);
233: clrbuf(bp);
234: /*
235: * Write synchronously so that indirect blocks
236: * never point at garbage.
237: */
238: if (error = bwrite(bp))
239: goto fail;
240: allocib = &ip->i_ib[indirs[0].in_off];
241: *allocib = nb;
242: ip->i_flag |= IN_CHANGE | IN_UPDATE;
243: }
244: /*
245: * Fetch through the indirect blocks, allocating as necessary.
246: */
247: for (i = 1;;) {
248: error = bread(vp,
249: indirs[i].in_lbn, (int)fs->fs_bsize, NOCRED, &bp);
250: if (error) {
251: brelse(bp);
252: goto fail;
253: }
254: bap = (ufs_daddr_t *)bp->b_data;
255: #if REV_ENDIAN_FS
256: if (rev_endian)
257: nb = NXSwapLong(bap[indirs[i].in_off]);
258: else {
259: #endif /* REV_ENDIAN_FS */
260: nb = bap[indirs[i].in_off];
261: #if REV_ENDIAN_FS
262: }
263: #endif /* REV_ENDIAN_FS */
264: if (i == num)
265: break;
266: i += 1;
267: if (nb != 0) {
268: brelse(bp);
269: continue;
270: }
271: if (pref == 0)
272: pref = ffs_blkpref(ip, lbn, 0, (ufs_daddr_t *)0);
273: if (error =
274: ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb)) {
275: brelse(bp);
276: goto fail;
277: }
278: nb = newb;
279: *allocblk++ = nb;
280: nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0);
281: nbp->b_blkno = fsbtodb(fs, nb);
282: clrbuf(nbp);
283: /*
284: * Write synchronously so that indirect blocks
285: * never point at garbage.
286: */
287: if (error = bwrite(nbp)) {
288: brelse(bp);
289: goto fail;
290: }
291: #if REV_ENDIAN_FS
292: if (rev_endian)
293: bap[indirs[i - 1].in_off] = NXSwapLong(nb);
294: else {
295: #endif /* REV_ENDIAN_FS */
296: bap[indirs[i - 1].in_off] = nb;
297: #if REV_ENDIAN_FS
298: }
299: #endif /* REV_ENDIAN_FS */
300: /*
301: * If required, write synchronously, otherwise use
302: * delayed write.
303: */
304: if (flags & B_SYNC) {
305: bwrite(bp);
306: } else {
307: bdwrite(bp);
308: }
309: }
310: /*
311: * Get the data block, allocating if necessary.
312: */
313: if (nb == 0) {
314: pref = ffs_blkpref(ip, lbn, indirs[i].in_off, &bap[0]);
315: if (error = ffs_alloc(ip,
316: lbn, pref, (int)fs->fs_bsize, cred, &newb)) {
317: brelse(bp);
318: goto fail;
319: }
320: nb = newb;
321: *allocblk++ = nb;
322: nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
323: nbp->b_blkno = fsbtodb(fs, nb);
324: if (flags & B_CLRBUF)
325: clrbuf(nbp);
326: #if REV_ENDIAN_FS
327: if (rev_endian)
328: bap[indirs[i].in_off] = NXSwapLong(nb);
329: else {
330: #endif /* REV_ENDIAN_FS */
331: bap[indirs[i].in_off] = nb;
332: #if REV_ENDIAN_FS
333: }
334: #endif /* REV_ENDIAN_FS */
335: /*
336: * If required, write synchronously, otherwise use
337: * delayed write.
338: */
339: if (flags & B_SYNC) {
340: bwrite(bp);
341: } else {
342: bdwrite(bp);
343: }
344: *bpp = nbp;
345: return (0);
346: }
347: brelse(bp);
348: if (flags & B_CLRBUF) {
349: error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp);
350: if (error) {
351: brelse(nbp);
352: goto fail;
353: }
354: } else {
355: nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
356: nbp->b_blkno = fsbtodb(fs, nb);
357: }
358: *bpp = nbp;
359: return (0);
360: fail:
361: /*
362: * If we have failed part way through block allocation, we
363: * have to deallocate any indirect blocks that we have allocated.
364: */
365: for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) {
366: ffs_blkfree(ip, *blkp, fs->fs_bsize);
367: deallocated += fs->fs_bsize;
368: }
369: if (allocib != NULL)
370: *allocib = 0;
371: if (deallocated) {
372: #ifdef NeXT
373: VOP_DEVBLOCKSIZE(ip->i_devvp,&devBlockSize);
374: #endif /* NeXT */
375:
376: #if QUOTA
377: /*
378: * Restore user's disk quota because allocation failed.
379: */
380: #ifdef NeXT
381: (void) chkdq(ip, (long)-btodb(deallocated, devBlockSize), cred, FORCE);
382: #else
383: (void) chkdq(ip, (long)-btodb(deallocated), cred, FORCE);
384: #endif /* NeXT */
385: #endif /* QUOTA */
386: #ifdef NeXT
387: ip->i_blocks -= btodb(deallocated, devBlockSize);
388: #else
389: ip->i_blocks -= btodb(deallocated);
390: #endif /* NeXT */
391: ip->i_flag |= IN_CHANGE | IN_UPDATE;
392: }
393: return (error);
394: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.