change iput() to irele() when releasing unlocked inodes
[unix-history] / usr / src / sys / ufs / lfs / lfs_inode.c
CommitLineData
8eee8525 1/* lfs_inode.c 4.12 82/06/10 */
5d5124a1
BJ
2
3#include "../h/param.h"
4#include "../h/systm.h"
5#include "../h/mount.h"
6#include "../h/dir.h"
7#include "../h/user.h"
8#include "../h/inode.h"
6459ebe0 9#include "../h/fs.h"
5d5124a1
BJ
10#include "../h/conf.h"
11#include "../h/buf.h"
12#include "../h/inline.h"
13
14#define INOHSZ 63
15#define INOHASH(dev,ino) (((dev)+(ino))%INOHSZ)
16short inohash[INOHSZ];
17short ifreel;
18
19/*
20 * Initialize hash links for inodes
21 * and build inode free list.
22 */
23ihinit()
24{
25 register int i;
75105cf0 26 register struct inode *ip = inode;
5d5124a1
BJ
27
28 ifreel = 0;
75105cf0
BJ
29 for (i = 0; i < ninode-1; i++, ip++)
30 ip->i_hlink = i+1;
31 ip->i_hlink = -1;
5d5124a1
BJ
32 for (i = 0; i < INOHSZ; i++)
33 inohash[i] = -1;
34}
35
5d5124a1
BJ
36/*
37 * Look up an inode by device,inumber.
38 * If it is in core (in the inode structure),
39 * honor the locking protocol.
40 * If it is not in core, read it in from the
41 * specified device.
42 * If the inode is mounted on, perform
43 * the indicated indirection.
44 * In all cases, a pointer to a locked
45 * inode structure is returned.
46 *
5d5124a1
BJ
47 * panic: no imt -- if the mounted file
48 * system is not in the mount table.
49 * "cannot happen"
50 */
51struct inode *
6459ebe0 52iget(dev, fs, ino)
7494ef16 53 dev_t dev;
6459ebe0 54 register struct fs *fs;
7494ef16 55 ino_t ino;
5d5124a1
BJ
56{
57 register struct inode *ip;
58 register struct mount *mp;
59 register struct buf *bp;
60 register struct dinode *dp;
61 register int slot;
62
63loop:
6459ebe0
KM
64 if (getfs(dev) != fs)
65 panic("iget: bad fs");
5d5124a1
BJ
66 slot = INOHASH(dev, ino);
67 ip = &inode[inohash[slot]];
68 while (ip != &inode[-1]) {
7494ef16
BJ
69 if (ino == ip->i_number && dev == ip->i_dev) {
70 if ((ip->i_flag&ILOCK) != 0) {
5d5124a1
BJ
71 ip->i_flag |= IWANT;
72 sleep((caddr_t)ip, PINOD);
73 goto loop;
74 }
7494ef16 75 if ((ip->i_flag&IMOUNT) != 0) {
6459ebe0 76 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
7494ef16 77 if (mp->m_inodp == ip) {
5d5124a1 78 dev = mp->m_dev;
6459ebe0 79 fs = mp->m_bufp->b_un.b_fs;
5d5124a1
BJ
80 ino = ROOTINO;
81 goto loop;
82 }
83 panic("no imt");
84 }
85 ip->i_count++;
86 ip->i_flag |= ILOCK;
87 return(ip);
88 }
89 ip = &inode[ip->i_hlink];
90 }
7494ef16 91 if (ifreel < 0) {
945fbb1b 92 tablefull("inode");
5d5124a1
BJ
93 u.u_error = ENFILE;
94 return(NULL);
95 }
96 ip = &inode[ifreel];
97 ifreel = ip->i_hlink;
98 ip->i_hlink = inohash[slot];
99 inohash[slot] = ip - inode;
100 ip->i_dev = dev;
6459ebe0 101 ip->i_fs = fs;
5d5124a1
BJ
102 ip->i_number = ino;
103 ip->i_flag = ILOCK;
104 ip->i_count++;
6459ebe0
KM
105 ip->i_lastr = 0;
106 bp = bread(dev, fsbtodb(fs, itod(fs, ino)), fs->fs_bsize);
5d5124a1
BJ
107 /*
108 * Check I/O errors
109 */
7494ef16 110 if ((bp->b_flags&B_ERROR) != 0) {
5d5124a1
BJ
111 brelse(bp);
112 iput(ip);
113 return(NULL);
114 }
115 dp = bp->b_un.b_dino;
6459ebe0
KM
116 dp += itoo(fs, ino);
117 ip->i_ic = dp->di_ic;
5d5124a1 118 brelse(bp);
6459ebe0 119 return (ip);
5d5124a1
BJ
120}
121
122/*
123 * Decrement reference count of
124 * an inode structure.
125 * On the last reference,
126 * write the inode out and if necessary,
127 * truncate and deallocate the file.
128 */
129iput(ip)
7494ef16 130 register struct inode *ip;
5d5124a1 131{
ff56f48a
KM
132
133 if ((ip->i_flag & ILOCK) == 0)
134 panic("iput");
135 iunlock(ip);
136 irele(ip);
137}
138
139irele(ip)
140 register struct inode *ip;
141{
5d5124a1
BJ
142 register int i, x;
143 register struct inode *jp;
6459ebe0 144 int mode;
5d5124a1 145
7494ef16 146 if (ip->i_count == 1) {
5d5124a1 147 ip->i_flag |= ILOCK;
7494ef16 148 if (ip->i_nlink <= 0) {
5d5124a1 149 itrunc(ip);
6459ebe0 150 mode = ip->i_mode;
5d5124a1
BJ
151 ip->i_mode = 0;
152 ip->i_flag |= IUPD|ICHG;
6459ebe0 153 ifree(ip, ip->i_number, mode);
5d5124a1 154 }
c0bb1685 155 IUPDAT(ip, &time, &time, 0);
ff56f48a 156 iunlock(ip);
5d5124a1
BJ
157 i = INOHASH(ip->i_dev, ip->i_number);
158 x = ip - inode;
159 if (inohash[i] == x) {
160 inohash[i] = ip->i_hlink;
161 } else {
162 for (jp = &inode[inohash[i]]; jp != &inode[-1];
163 jp = &inode[jp->i_hlink])
164 if (jp->i_hlink == x) {
165 jp->i_hlink = ip->i_hlink;
166 goto done;
167 }
168 panic("iput");
169 }
170done:
171 ip->i_hlink = ifreel;
172 ifreel = x;
173 ip->i_flag = 0;
174 ip->i_number = 0;
ff56f48a 175 }
5d5124a1
BJ
176 ip->i_count--;
177}
178
179/*
180 * Check accessed and update flags on
181 * an inode structure.
182 * If any is on, update the inode
183 * with the current time.
c0bb1685
BJ
184 * If waitfor is given, then must insure
185 * i/o order so wait for write to complete.
5d5124a1 186 */
c0bb1685 187iupdat(ip, ta, tm, waitfor)
7494ef16
BJ
188 register struct inode *ip;
189 time_t *ta, *tm;
190 int waitfor;
5d5124a1
BJ
191{
192 register struct buf *bp;
193 struct dinode *dp;
6459ebe0 194 register struct fs *fp;
5d5124a1 195
6459ebe0
KM
196 fp = ip->i_fs;
197 if ((ip->i_flag & (IUPD|IACC|ICHG)) != 0) {
198 if (fp->fs_ronly)
5d5124a1 199 return;
6459ebe0
KM
200 bp = bread(ip->i_dev, fsbtodb(fp, itod(fp, ip->i_number)),
201 fp->fs_bsize);
5d5124a1
BJ
202 if (bp->b_flags & B_ERROR) {
203 brelse(bp);
204 return;
205 }
7494ef16 206 if (ip->i_flag&IACC)
6459ebe0 207 ip->i_atime = *ta;
7494ef16 208 if (ip->i_flag&IUPD)
6459ebe0 209 ip->i_mtime = *tm;
7494ef16 210 if (ip->i_flag&ICHG)
6459ebe0 211 ip->i_ctime = time;
5d5124a1 212 ip->i_flag &= ~(IUPD|IACC|ICHG);
6459ebe0
KM
213 dp = bp->b_un.b_dino + itoo(fp, ip->i_number);
214 dp->di_ic = ip->i_ic;
c0bb1685
BJ
215 if (waitfor)
216 bwrite(bp);
217 else
218 bdwrite(bp);
5d5124a1
BJ
219 }
220}
221
222/*
223 * Free all the disk blocks associated
224 * with the specified inode structure.
225 * The blocks of the file are removed
226 * in reverse order. This FILO
227 * algorithm will tend to maintain
228 * a contiguous free list much longer
229 * than FIFO.
230 */
231itrunc(ip)
7494ef16 232 register struct inode *ip;
5d5124a1
BJ
233{
234 register i;
235 dev_t dev;
236 daddr_t bn;
c0bb1685 237 struct inode itmp;
6459ebe0 238 register struct fs *fs;
5d5124a1 239
5d5124a1 240 i = ip->i_mode & IFMT;
6459ebe0 241 if (i != IFREG && i != IFDIR && i != IFLNK)
5d5124a1 242 return;
c0bb1685
BJ
243 /*
244 * Clean inode on disk before freeing blocks
245 * to insure no duplicates if system crashes.
246 */
247 itmp = *ip;
248 itmp.i_size = 0;
6459ebe0
KM
249 for (i = 0; i < NDADDR; i++)
250 itmp.i_db[i] = 0;
251 for (i = 0; i < NIADDR; i++)
252 itmp.i_ib[i] = 0;
c0bb1685
BJ
253 itmp.i_flag |= ICHG|IUPD;
254 iupdat(&itmp, &time, &time, 1);
255 ip->i_flag &= ~(IUPD|IACC|ICHG);
256
257 /*
258 * Now return blocks to free list... if machine
259 * crashes, they will be harmless MISSING blocks.
260 */
5d5124a1 261 dev = ip->i_dev;
6459ebe0
KM
262 fs = ip->i_fs;
263 /*
264 * release double indirect block first
265 */
266 bn = ip->i_ib[NIADDR-1];
267 if (bn != (daddr_t)0) {
268 ip->i_ib[NIADDR - 1] = (daddr_t)0;
269 tloop(ip, bn, 1);
270 }
271 /*
272 * release single indirect blocks second
273 */
274 for (i = NIADDR - 2; i >= 0; i--) {
275 bn = ip->i_ib[i];
276 if (bn != (daddr_t)0) {
277 ip->i_ib[i] = (daddr_t)0;
278 tloop(ip, bn, 0);
279 }
280 }
281 /*
282 * finally release direct blocks
283 */
284 for (i = NDADDR - 1; i>=0; i--) {
285 bn = ip->i_db[i];
7494ef16 286 if (bn == (daddr_t)0)
5d5124a1 287 continue;
6459ebe0
KM
288 ip->i_db[i] = (daddr_t)0;
289 fre(ip, bn, (off_t)blksize(fs, ip, i));
5d5124a1
BJ
290 }
291 ip->i_size = 0;
c0bb1685
BJ
292 /*
293 * Inode was written and flags updated above.
294 * No need to modify flags here.
295 */
5d5124a1
BJ
296}
297
6459ebe0
KM
298tloop(ip, bn, indflg)
299 register struct inode *ip;
300 daddr_t bn;
301 int indflg;
5d5124a1
BJ
302{
303 register i;
304 register struct buf *bp;
305 register daddr_t *bap;
6459ebe0 306 register struct fs *fs;
5d5124a1
BJ
307 daddr_t nb;
308
309 bp = NULL;
6459ebe0
KM
310 fs = ip->i_fs;
311 for (i = NINDIR(fs) - 1; i >= 0; i--) {
7494ef16 312 if (bp == NULL) {
6459ebe0 313 bp = bread(ip->i_dev, fsbtodb(fs, bn), fs->fs_bsize);
5d5124a1
BJ
314 if (bp->b_flags & B_ERROR) {
315 brelse(bp);
316 return;
317 }
318 bap = bp->b_un.b_daddr;
319 }
320 nb = bap[i];
7494ef16 321 if (nb == (daddr_t)0)
5d5124a1 322 continue;
6459ebe0
KM
323 if (indflg)
324 tloop(ip, nb, 0);
325 else
326 fre(ip, nb, fs->fs_bsize);
5d5124a1 327 }
7494ef16 328 if (bp != NULL)
5d5124a1 329 brelse(bp);
6459ebe0 330 fre(ip, bn, fs->fs_bsize);
5d5124a1
BJ
331}
332
333/*
334 * Make a new file.
335 */
336struct inode *
337maknode(mode)
6459ebe0 338 int mode;
5d5124a1
BJ
339{
340 register struct inode *ip;
6459ebe0 341 ino_t ipref;
5d5124a1 342
6459ebe0
KM
343 if ((mode & IFMT) == IFDIR)
344 ipref = dirpref(u.u_pdir->i_fs);
345 else
346 ipref = u.u_pdir->i_number;
347 ip = ialloc(u.u_pdir, ipref, mode);
7494ef16 348 if (ip == NULL) {
5d5124a1
BJ
349 iput(u.u_pdir);
350 return(NULL);
351 }
352 ip->i_flag |= IACC|IUPD|ICHG;
6459ebe0 353 if ((mode & IFMT) == 0)
5d5124a1
BJ
354 mode |= IFREG;
355 ip->i_mode = mode & ~u.u_cmask;
356 ip->i_nlink = 1;
357 ip->i_uid = u.u_uid;
4f4caf05 358 ip->i_gid = u.u_pdir->i_gid;
c0bb1685
BJ
359
360 /*
361 * Make sure inode goes to disk before directory entry.
362 */
363 iupdat(ip, &time, &time, 1);
5d5124a1 364 wdir(ip);
6459ebe0
KM
365 if (u.u_error) {
366 /*
367 * write error occurred trying to update directory
368 * so must deallocate the inode
369 */
370 ip->i_nlink = 0;
371 ip->i_flag |= ICHG;
372 iput(ip);
373 return(NULL);
374 }
5d5124a1
BJ
375 return(ip);
376}
377
378/*
379 * Write a directory entry with
380 * parameters left as side effects
381 * to a call to namei.
382 */
383wdir(ip)
7494ef16 384 struct inode *ip;
5d5124a1 385{
6459ebe0
KM
386 register struct direct *dp, *ndp;
387 struct fs *fs;
388 struct buf *bp;
389 int lbn, bn, base;
390 int loc, dsize, spccnt, newsize;
391 char *dirbuf;
5d5124a1
BJ
392
393 u.u_dent.d_ino = ip->i_number;
5d5124a1 394 u.u_segflg = 1;
6459ebe0
KM
395 newsize = DIRSIZ(&u.u_dent);
396 /*
397 * if u.u_count == 0, a new directory block must be allocated.
398 */
399 if (u.u_count == 0) {
400 u.u_dent.d_reclen = DIRBLKSIZ;
401 u.u_count = newsize;
402 u.u_base = (caddr_t)&u.u_dent;
403 writei(u.u_pdir);
404 iput(u.u_pdir);
405 return;
406 }
407 /*
408 * must read in an existing directory block
409 * to prepare to place the new entry into it.
410 */
411 fs = u.u_pdir->i_fs;
412 lbn = lblkno(fs, u.u_offset);
413 base = blkoff(fs, u.u_offset);
414 bn = fsbtodb(fs, bmap(u.u_pdir, lbn, B_WRITE, base + u.u_count));
415 if (u.u_offset + u.u_count > u.u_pdir->i_size)
416 u.u_pdir->i_size = u.u_offset + u.u_count;
417 bp = bread(u.u_pdir->i_dev, bn, blksize(fs, u.u_pdir, lbn));
418 if (bp->b_flags & B_ERROR) {
419 brelse(bp);
420 return;
421 }
422 dirbuf = bp->b_un.b_addr + base;
423 dp = (struct direct *)dirbuf;
424 dsize = DIRSIZ(dp);
425 spccnt = dp->d_reclen - dsize;
426 /*
427 * if there is insufficient room to make an entry at this point
428 * namei insures that compacting from u.u_offset for u.u_count
429 * bytes will provide the necessary space.
430 */
431 for (loc = dp->d_reclen; loc < u.u_count; ) {
432 ndp = (struct direct *)(dirbuf + loc);
433 if (dp->d_ino == 0) {
434 spccnt += dsize;
435 } else {
436 dp->d_reclen = dsize;
437 dp = (struct direct *)((char *)dp + dsize);
438 }
439 dsize = DIRSIZ(ndp);
440 spccnt += ndp->d_reclen - dsize;
441 loc += ndp->d_reclen;
442 bcopy(ndp, dp, dsize);
443 }
444 /*
445 * Update the pointer fields in the previous entry (if any),
446 * copy in the new entry, and write out the block.
447 */
448 if (dp->d_ino == 0) {
449 if (spccnt + dsize < newsize)
450 panic("wdir: compact failed");
451 u.u_dent.d_reclen = spccnt + dsize;
452 } else {
453 if (spccnt < newsize)
454 panic("wdir: compact failed");
455 u.u_dent.d_reclen = spccnt;
456 dp->d_reclen = dsize;
457 dp = (struct direct *)((char *)dp + dsize);
458 }
459 bcopy(&u.u_dent, dp, newsize);
460 bwrite(bp);
461 u.u_pdir->i_flag |= IUPD|ICHG;
5d5124a1
BJ
462 iput(u.u_pdir);
463}
d6a210b8 464
7494ef16
BJ
465#ifdef ilock
466#undef ilock
d6a210b8 467#endif
ff56f48a
KM
468#ifdef iunlock
469#undef iunlock
d6a210b8
BJ
470#endif
471/*
7494ef16 472 * Lock an inode. If its already locked, set the WANT bit and sleep.
d6a210b8 473 */
7494ef16
BJ
474ilock(ip)
475 register struct inode *ip;
d6a210b8
BJ
476{
477
7494ef16 478 while (ip->i_flag&ILOCK) {
d6a210b8
BJ
479 ip->i_flag |= IWANT;
480 sleep((caddr_t)ip, PINOD);
481 }
482 ip->i_flag |= ILOCK;
483}
484
485/*
7494ef16 486 * Unlock an inode. If WANT bit is on, wakeup.
d6a210b8 487 */
ff56f48a 488iunlock(ip)
7494ef16 489 register struct inode *ip;
d6a210b8
BJ
490{
491
492 ip->i_flag &= ~ILOCK;
7494ef16 493 if (ip->i_flag&IWANT) {
d6a210b8
BJ
494 ip->i_flag &= ~IWANT;
495 wakeup((caddr_t)ip);
496 }
497}