1: /*
2: * Copyright (c) 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)ufs_alloc.c 1.3 (2.11BSD GTE) 1996/9/19
7: */
8:
9: #include "param.h"
10: #include "../machine/seg.h"
11:
12: #include "fs.h"
13: #include "dir.h"
14: #include "inode.h"
15: #include "buf.h"
16: #include "user.h"
17: #include "kernel.h"
18: #include "mount.h"
19: #ifdef QUOTA
20: #include "quota.h"
21: #endif
22:
23: typedef struct fblk *FBLKP;
24:
25: /*
26: * Allocate a block in the file system.
27: *
28: * alloc will obtain the next available free disk block from the
29: * free list of the specified device. The super block has up to
30: * NICFREE remembered free blocks; the last of these is read to
31: * obtain NICFREE more...
32: */
33: struct buf *
34: balloc(ip, flags)
35: struct inode *ip;
36: int flags;
37: {
38: register struct fs *fs;
39: register struct buf *bp;
40: int async;
41: daddr_t bno;
42:
43: fs = ip->i_fs;
44: async = fs->fs_flags & MNT_ASYNC;
45:
46: while (fs->fs_flock)
47: sleep((caddr_t)&fs->fs_flock, PINOD);
48: do {
49: if (fs->fs_nfree <= 0)
50: goto nospace;
51: if (fs->fs_nfree > NICFREE) {
52: fserr(fs, "bad free count");
53: goto nospace;
54: }
55: bno = fs->fs_free[--fs->fs_nfree];
56: if (bno == 0)
57: goto nospace;
58: } while (badblock(fs, bno));
59: if (fs->fs_nfree <= 0) {
60: fs->fs_flock++;
61: bp = bread(ip->i_dev, bno);
62: if (((bp->b_flags&B_ERROR) == 0) && (bp->b_resid==0)) {
63: register struct fblk *fbp;
64:
65: fbp = (FBLKP) mapin(bp);
66: *((FBLKP)&fs->fs_nfree) = *fbp;
67: mapout(bp);
68: }
69: brelse(bp);
70: /*
71: * Write the superblock back, synchronously if requested,
72: * so that the free list pointer won't point at garbage.
73: * We can still end up with dups in free if we then
74: * use some of the blocks in this freeblock, then crash
75: * without a sync.
76: */
77: bp = getblk(ip->i_dev, SUPERB);
78: fs->fs_fmod = 0;
79: fs->fs_time = time.tv_sec;
80: {
81: register struct fs *fps;
82:
83: fps = (struct fs *)mapin(bp);
84: *fps = *fs;
85: }
86: mapout(bp);
87: if (!async)
88: bwrite(bp);
89: else
90: bdwrite(bp);
91: fs->fs_flock = 0;
92: wakeup((caddr_t)&fs->fs_flock);
93: if (fs->fs_nfree <=0)
94: goto nospace;
95: }
96: bp = getblk(ip->i_dev, bno);
97: bp->b_resid = 0;
98: if (flags & B_CLRBUF)
99: clrbuf(bp);
100: fs->fs_fmod = 1;
101: fs->fs_tfree--;
102: return(bp);
103:
104: nospace:
105: fs->fs_nfree = 0;
106: fs->fs_tfree = 0;
107: fserr(fs, "file system full");
108: /*
109: * THIS IS A KLUDGE...
110: * SHOULD RATHER SEND A SIGNAL AND SUSPEND THE PROCESS IN A
111: * STATE FROM WHICH THE SYSTEM CALL WILL RESTART
112: */
113: uprintf("\n%s: write failed, file system full\n", fs->fs_fsmnt);
114: {
115: register int i;
116:
117: for (i = 0; i < 5; i++)
118: sleep((caddr_t)&lbolt, PRIBIO);
119: }
120: u.u_error = ENOSPC;
121: return(NULL);
122: }
123:
124: /*
125: * Allocate an inode in the file system.
126: *
127: * Allocate an unused I node on the specified device. Used with file
128: * creation. The algorithm keeps up to NICINOD spare I nodes in the
129: * super block. When this runs out, a linear search through the I list
130: * is instituted to pick up NICINOD more.
131: */
132: struct inode *
133: ialloc(pip)
134: struct inode *pip;
135: {
136: register struct fs *fs;
137: register struct buf *bp;
138: register struct inode *ip;
139: int i;
140: struct dinode *dp;
141: ino_t ino;
142: daddr_t adr;
143: ino_t inobas;
144: int first;
145: struct inode *ifind();
146: char *emsg = "no inodes free";
147:
148: fs = pip->i_fs;
149: while (fs->fs_ilock)
150: sleep((caddr_t)&fs->fs_ilock, PINOD);
151: #ifdef QUOTA
152: QUOTAMAP();
153: u.u_error = chkiq(pip->i_dev, NULL, u.u_uid, 0);
154: QUOTAUNMAP();
155: if (u.u_error)
156: return(NULL);
157: #endif
158: loop:
159: if (fs->fs_ninode > 0) {
160: ino = fs->fs_inode[--fs->fs_ninode];
161: if (ino <= ROOTINO)
162: goto loop;
163: ip = iget(pip->i_dev, fs, ino);
164: if (ip == NULL)
165: return(NULL);
166: if (ip->i_mode == 0) {
167: bzero((caddr_t)ip->i_addr,sizeof(ip->i_addr));
168: ip->i_flags = 0;
169: fs->fs_fmod = 1;
170: fs->fs_tinode--;
171: return(ip);
172: }
173: /*
174: * Inode was allocated after all.
175: * Look some more.
176: */
177: iput(ip);
178: goto loop;
179: }
180: fs->fs_ilock++;
181: if (fs->fs_nbehind < 4 * NICINOD) {
182: first = 1;
183: ino = fs->fs_lasti;
184: #ifdef DIAGNOSTIC
185: if (itoo(ino))
186: panic("ialloc");
187: #endif DIAGNOSTIC
188: adr = itod(ino);
189: } else {
190: fromtop:
191: first = 0;
192: ino = 1;
193: adr = SUPERB+1;
194: fs->fs_nbehind = 0;
195: }
196: for (;adr < fs->fs_isize;adr++) {
197: inobas = ino;
198: bp = bread(pip->i_dev, adr);
199: if ((bp->b_flags & B_ERROR) || bp->b_resid) {
200: brelse(bp);
201: ino += INOPB;
202: continue;
203: }
204: dp = (struct dinode *)mapin(bp);
205: for (i = 0;i < INOPB;i++) {
206: if (dp->di_mode != 0)
207: goto cont;
208: if (ifind(pip->i_dev, ino))
209: goto cont;
210: fs->fs_inode[fs->fs_ninode++] = ino;
211: if (fs->fs_ninode >= NICINOD)
212: break;
213: cont:
214: ino++;
215: dp++;
216: }
217: mapout(bp);
218: brelse(bp);
219: if (fs->fs_ninode >= NICINOD)
220: break;
221: }
222: if (fs->fs_ninode < NICINOD && first)
223: goto fromtop;
224: fs->fs_lasti = inobas;
225: fs->fs_ilock = 0;
226: wakeup((caddr_t)&fs->fs_ilock);
227: if (fs->fs_ninode > 0)
228: goto loop;
229: fserr(fs, emsg);
230: uprintf("\n%s: %s\n", fs->fs_fsmnt, emsg);
231: u.u_error = ENOSPC;
232: return(NULL);
233: }
234:
235: /*
236: * Free a block or fragment.
237: *
238: * Place the specified disk block back on the free list of the
239: * specified device.
240: */
241: free(ip, bno)
242: struct inode *ip;
243: daddr_t bno;
244: {
245: register struct fs *fs;
246: register struct buf *bp;
247: struct fblk *fbp;
248:
249: fs = ip->i_fs;
250: if (badblock(fs, bno)) {
251: printf("bad block %D, ino %d\n", bno, ip->i_number);
252: return;
253: }
254: while (fs->fs_flock)
255: sleep((caddr_t)&fs->fs_flock, PINOD);
256: if (fs->fs_nfree <= 0) {
257: fs->fs_nfree = 1;
258: fs->fs_free[0] = 0;
259: }
260: if (fs->fs_nfree >= NICFREE) {
261: fs->fs_flock++;
262: bp = getblk(ip->i_dev, bno);
263: fbp = (FBLKP)mapin(bp);
264: *fbp = *((FBLKP)&fs->fs_nfree);
265: mapout(bp);
266: fs->fs_nfree = 0;
267: if (fs->fs_flags & MNT_ASYNC)
268: bdwrite(bp);
269: else
270: bwrite(bp);
271: fs->fs_flock = 0;
272: wakeup((caddr_t)&fs->fs_flock);
273: }
274: fs->fs_free[fs->fs_nfree++] = bno;
275: fs->fs_tfree++;
276: fs->fs_fmod = 1;
277: }
278:
279: /*
280: * Free an inode.
281: *
282: * Free the specified I node on the specified device. The algorithm
283: * stores up to NICINOD I nodes in the super block and throws away any more.
284: */
285: ifree(ip, ino)
286: struct inode *ip;
287: ino_t ino;
288: {
289: register struct fs *fs;
290:
291: fs = ip->i_fs;
292: fs->fs_tinode++;
293: if (fs->fs_ilock)
294: return;
295: if (fs->fs_ninode >= NICINOD) {
296: if (fs->fs_lasti > ino)
297: fs->fs_nbehind++;
298: return;
299: }
300: fs->fs_inode[fs->fs_ninode++] = ino;
301: fs->fs_fmod = 1;
302: }
303:
304: /*
305: * Fserr prints the name of a file system with an error diagnostic.
306: *
307: * The form of the error message is:
308: * fs: error message
309: */
310: fserr(fp, cp)
311: struct fs *fp;
312: char *cp;
313: {
314: printf("%s: %s\n", fp->fs_fsmnt, cp);
315: }
Defined functions
free
defined in line
241; used 4 times
Defined typedef's
FBLKP
defined in line
23; used 4 times