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