|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution is only permitted until one year after the first shipment
6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
7: * binary forms are permitted provided that: (1) source distributions retain
8: * this entire copyright notice and comment, and (2) distributions including
9: * binaries display the following acknowledgement: This product includes
10: * software developed by the University of California, Berkeley and its
11: * contributors'' in the documentation or other materials provided with the
12: * distribution and in all advertising materials mentioning features or use
13: * of this software. Neither the name of the University nor the names of
14: * its contributors may be used to endorse or promote products derived from
15: * this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: * @(#)ufs_inode.c 7.34 (Berkeley) 7/3/90
21: */
22:
23: #include "param.h"
24: #include "systm.h"
25: #include "mount.h"
26: #include "user.h"
27: #include "proc.h"
28: #include "file.h"
29: #include "buf.h"
30: #include "cmap.h"
31: #include "vnode.h"
32: #include "../ufs/quota.h"
33: #include "../ufs/inode.h"
34: #include "../ufs/fs.h"
35: #include "../ufs/ufsmount.h"
36: #include "kernel.h"
37: #include "malloc.h"
38:
39: #define INOHSZ 512
40: #if ((INOHSZ&(INOHSZ-1)) == 0)
41: #define INOHASH(dev,ino) (((dev)+(ino))&(INOHSZ-1))
42: #else
43: #define INOHASH(dev,ino) (((unsigned)((dev)+(ino)))%INOHSZ)
44: #endif
45:
46: union ihead {
47: union ihead *ih_head[2];
48: struct inode *ih_chain[2];
49: } ihead[INOHSZ];
50:
51: int prtactive; /* 1 => print out reclaim of active vnodes */
52:
53: /*
54: * Initialize hash links for inodes.
55: */
56: ufs_init()
57: {
58: register int i;
59: register union ihead *ih = ihead;
60:
61: #ifndef lint
62: if (VN_MAXPRIVATE < sizeof(struct inode))
63: panic("ihinit: too small");
64: #endif /* not lint */
65: for (i = INOHSZ; --i >= 0; ih++) {
66: ih->ih_head[0] = ih;
67: ih->ih_head[1] = ih;
68: }
69: #ifdef QUOTA
70: dqinit();
71: #endif /* QUOTA */
72: }
73:
74: /*
75: * Look up an vnode/inode by device,inumber.
76: * If it is in core (in the inode structure),
77: * honor the locking protocol.
78: * If it is not in core, read it in from the
79: * specified device.
80: * Callers must check for mount points!!
81: * In all cases, a pointer to a locked
82: * inode structure is returned.
83: */
84: iget(xp, ino, ipp)
85: struct inode *xp;
86: ino_t ino;
87: struct inode **ipp;
88: {
89: dev_t dev = xp->i_dev;
90: struct mount *mntp = ITOV(xp)->v_mount;
91: register struct fs *fs = VFSTOUFS(mntp)->um_fs;
92: extern struct vnodeops ufs_vnodeops, spec_inodeops;
93: register struct inode *ip, *iq;
94: register struct vnode *vp;
95: struct vnode *nvp;
96: struct buf *bp;
97: struct dinode *dp;
98: union ihead *ih;
99: int i, error;
100:
101: ih = &ihead[INOHASH(dev, ino)];
102: loop:
103: for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw) {
104: if (ino != ip->i_number || dev != ip->i_dev)
105: continue;
106: if ((ip->i_flag&ILOCKED) != 0) {
107: ip->i_flag |= IWANT;
108: sleep((caddr_t)ip, PINOD);
109: goto loop;
110: }
111: if (vget(ITOV(ip)))
112: goto loop;
113: *ipp = ip;
114: return(0);
115: }
116: /*
117: * Allocate a new inode.
118: */
119: if (error = getnewvnode(VT_UFS, mntp, &ufs_vnodeops, &nvp)) {
120: *ipp = 0;
121: return (error);
122: }
123: ip = VTOI(nvp);
124: ip->i_vnode = nvp;
125: ip->i_flag = 0;
126: ip->i_devvp = 0;
127: ip->i_mode = 0;
128: ip->i_diroff = 0;
129: #ifdef QUOTA
130: for (i = 0; i < MAXQUOTAS; i++)
131: ip->i_dquot[i] = NODQUOT;
132: #endif
133: /*
134: * Put it onto its hash chain and lock it so that other requests for
135: * this inode will block if they arrive while we are sleeping waiting
136: * for old data structures to be purged or for the contents of the
137: * disk portion of this inode to be read.
138: */
139: ip->i_dev = dev;
140: ip->i_number = ino;
141: insque(ip, ih);
142: ILOCK(ip);
143: /*
144: * Read in the disk contents for the inode.
145: */
146: if (error = bread(VFSTOUFS(mntp)->um_devvp, fsbtodb(fs, itod(fs, ino)),
147: (int)fs->fs_bsize, NOCRED, &bp)) {
148: /*
149: * The inode does not contain anything useful, so it would
150: * be misleading to leave it on its hash chain.
151: * Iput() will take care of putting it back on the free list.
152: */
153: remque(ip);
154: ip->i_forw = ip;
155: ip->i_back = ip;
156: /*
157: * Unlock and discard unneeded inode.
158: */
159: iput(ip);
160: brelse(bp);
161: *ipp = 0;
162: return (error);
163: }
164: dp = bp->b_un.b_dino;
165: dp += itoo(fs, ino);
166: ip->i_din = *dp;
167: brelse(bp);
168: /*
169: * Initialize the associated vnode
170: */
171: vp = ITOV(ip);
172: vp->v_type = IFTOVT(ip->i_mode);
173: if (vp->v_type == VFIFO) {
174: #ifdef FIFO
175: extern struct vnodeops fifo_inodeops;
176: vp->v_op = &fifo_inodeops;
177: #else
178: iput(ip);
179: *ipp = 0;
180: return (EOPNOTSUPP);
181: #endif /* FIFO */
182: }
183: if (vp->v_type == VCHR || vp->v_type == VBLK) {
184: vp->v_op = &spec_inodeops;
185: if (nvp = checkalias(vp, ip->i_rdev, mntp)) {
186: /*
187: * Reinitialize aliased inode.
188: */
189: vp = nvp;
190: iq = VTOI(vp);
191: iq->i_vnode = vp;
192: iq->i_flag = 0;
193: ILOCK(iq);
194: iq->i_din = ip->i_din;
195: iq->i_dev = dev;
196: iq->i_number = ino;
197: insque(iq, ih);
198: /*
199: * Discard unneeded vnode
200: */
201: ip->i_mode = 0;
202: iput(ip);
203: ip = iq;
204: }
205: }
206: if (ino == ROOTINO)
207: vp->v_flag |= VROOT;
208: /*
209: * Finish inode initialization.
210: */
211: ip->i_fs = fs;
212: ip->i_devvp = VFSTOUFS(mntp)->um_devvp;
213: VREF(ip->i_devvp);
214: /*
215: * Set up a generation number for this inode if it does not
216: * already have one. This should only happen on old filesystems.
217: */
218: if (ip->i_gen == 0) {
219: if (++nextgennumber < (u_long)time.tv_sec)
220: nextgennumber = time.tv_sec;
221: ip->i_gen = nextgennumber;
222: if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
223: ip->i_flag |= IMOD;
224: }
225: *ipp = ip;
226: return (0);
227: }
228:
229: /*
230: * Unlock and decrement the reference count of an inode structure.
231: */
232: iput(ip)
233: register struct inode *ip;
234: {
235:
236: if ((ip->i_flag & ILOCKED) == 0)
237: panic("iput");
238: IUNLOCK(ip);
239: vrele(ITOV(ip));
240: }
241:
242: /*
243: * Last reference to an inode, write the inode out and if necessary,
244: * truncate and deallocate the file.
245: */
246: ufs_inactive(vp)
247: struct vnode *vp;
248: {
249: register struct inode *ip = VTOI(vp);
250: int mode, error = 0;
251:
252: if (prtactive && vp->v_usecount != 0)
253: vprint("ufs_inactive: pushing active", vp);
254: /*
255: * Get rid of inodes related to stale file handles.
256: */
257: if (ip->i_mode == 0) {
258: if ((vp->v_flag & VXLOCK) == 0)
259: vgone(vp);
260: return (0);
261: }
262: ILOCK(ip);
263: if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
264: #ifdef QUOTA
265: if (!getinoquota(ip))
266: (void) chkiq(ip, -1, NOCRED, 0);
267: #endif
268: error = itrunc(ip, (u_long)0, 0);
269: mode = ip->i_mode;
270: ip->i_mode = 0;
271: ip->i_rdev = 0;
272: ip->i_flag |= IUPD|ICHG;
273: ifree(ip, ip->i_number, mode);
274: }
275: IUPDAT(ip, &time, &time, 0);
276: IUNLOCK(ip);
277: ip->i_flag = 0;
278: /*
279: * If we are done with the inode, reclaim it
280: * so that it can be reused immediately.
281: */
282: if (vp->v_usecount == 0 && ip->i_mode == 0)
283: vgone(vp);
284: return (error);
285: }
286:
287: /*
288: * Reclaim an inode so that it can be used for other purposes.
289: */
290: ufs_reclaim(vp)
291: register struct vnode *vp;
292: {
293: register struct inode *ip = VTOI(vp);
294: int i;
295:
296: if (prtactive && vp->v_usecount != 0)
297: vprint("ufs_reclaim: pushing active", vp);
298: /*
299: * Remove the inode from its hash chain.
300: */
301: remque(ip);
302: ip->i_forw = ip;
303: ip->i_back = ip;
304: /*
305: * Purge old data structures associated with the inode.
306: */
307: cache_purge(vp);
308: if (ip->i_devvp) {
309: vrele(ip->i_devvp);
310: ip->i_devvp = 0;
311: }
312: #ifdef QUOTA
313: for (i = 0; i < MAXQUOTAS; i++) {
314: if (ip->i_dquot[i] != NODQUOT) {
315: dqrele(vp, ip->i_dquot[i]);
316: ip->i_dquot[i] = NODQUOT;
317: }
318: }
319: #endif
320: ip->i_flag = 0;
321: return (0);
322: }
323:
324: /*
325: * Check accessed and update flags on an inode structure.
326: * If any is on, update the inode with the current time.
327: * If waitfor is given, then must ensure I/O order,
328: * so wait for write to complete.
329: */
330: iupdat(ip, ta, tm, waitfor)
331: register struct inode *ip;
332: struct timeval *ta, *tm;
333: int waitfor;
334: {
335: struct buf *bp;
336: struct vnode *vp = ITOV(ip);
337: struct dinode *dp;
338: register struct fs *fs;
339: int error;
340:
341: fs = ip->i_fs;
342: if ((ip->i_flag & (IUPD|IACC|ICHG|IMOD)) == 0)
343: return (0);
344: if (vp->v_mount->mnt_flag & MNT_RDONLY)
345: return (0);
346: error = bread(ip->i_devvp, fsbtodb(fs, itod(fs, ip->i_number)),
347: (int)fs->fs_bsize, NOCRED, &bp);
348: if (error) {
349: brelse(bp);
350: return (error);
351: }
352: if (ip->i_flag&IACC)
353: ip->i_atime = ta->tv_sec;
354: if (ip->i_flag&IUPD)
355: ip->i_mtime = tm->tv_sec;
356: if (ip->i_flag&ICHG)
357: ip->i_ctime = time.tv_sec;
358: ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD);
359: dp = bp->b_un.b_dino + itoo(fs, ip->i_number);
360: *dp = ip->i_din;
361: if (waitfor) {
362: return (bwrite(bp));
363: } else {
364: bdwrite(bp);
365: return (0);
366: }
367: }
368:
369: #define SINGLE 0 /* index of single indirect block */
370: #define DOUBLE 1 /* index of double indirect block */
371: #define TRIPLE 2 /* index of triple indirect block */
372: /*
373: * Truncate the inode ip to at most length size. Free affected disk
374: * blocks -- the blocks of the file are removed in reverse order.
375: *
376: * NB: triple indirect blocks are untested.
377: */
378: itrunc(oip, length, flags)
379: register struct inode *oip;
380: u_long length;
381: int flags;
382: {
383: register daddr_t lastblock;
384: daddr_t bn, lbn, lastiblock[NIADDR];
385: register struct fs *fs;
386: register struct inode *ip;
387: struct buf *bp;
388: int offset, osize, size, level;
389: long count, nblocks, blocksreleased = 0;
390: register int i;
391: int aflags, error, allerror;
392: struct inode tip;
393:
394: if (oip->i_size <= length) {
395: oip->i_flag |= ICHG|IUPD;
396: error = iupdat(oip, &time, &time, 1);
397: return (error);
398: }
399: /*
400: * Calculate index into inode's block list of
401: * last direct and indirect blocks (if any)
402: * which we want to keep. Lastblock is -1 when
403: * the file is truncated to 0.
404: */
405: fs = oip->i_fs;
406: lastblock = lblkno(fs, length + fs->fs_bsize - 1) - 1;
407: lastiblock[SINGLE] = lastblock - NDADDR;
408: lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs);
409: lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs);
410: nblocks = btodb(fs->fs_bsize);
411: /*
412: * Update the size of the file. If the file is not being
413: * truncated to a block boundry, the contents of the
414: * partial block following the end of the file must be
415: * zero'ed in case it ever become accessable again because
416: * of subsequent file growth.
417: */
418: osize = oip->i_size;
419: offset = blkoff(fs, length);
420: if (offset == 0) {
421: oip->i_size = length;
422: } else {
423: lbn = lblkno(fs, length);
424: aflags = B_CLRBUF;
425: if (flags & IO_SYNC)
426: aflags |= B_SYNC;
427: #ifdef QUOTA
428: if (error = getinoquota(oip))
429: return (error);
430: #endif
431: if (error = balloc(oip, lbn, offset, &bp, aflags))
432: return (error);
433: oip->i_size = length;
434: size = blksize(fs, oip, lbn);
435: bn = bp->b_blkno;
436: count = howmany(size, CLBYTES);
437: for (i = 0; i < count; i++)
438: munhash(oip->i_devvp, bn + i * CLBYTES / DEV_BSIZE);
439: bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset));
440: brealloc(bp, size);
441: if (flags & IO_SYNC)
442: bwrite(bp);
443: else
444: bdwrite(bp);
445: }
446: /*
447: * Update file and block pointers
448: * on disk before we start freeing blocks.
449: * If we crash before free'ing blocks below,
450: * the blocks will be returned to the free list.
451: * lastiblock values are also normalized to -1
452: * for calls to indirtrunc below.
453: */
454: tip = *oip;
455: tip.i_size = osize;
456: for (level = TRIPLE; level >= SINGLE; level--)
457: if (lastiblock[level] < 0) {
458: oip->i_ib[level] = 0;
459: lastiblock[level] = -1;
460: }
461: for (i = NDADDR - 1; i > lastblock; i--)
462: oip->i_db[i] = 0;
463: oip->i_flag |= ICHG|IUPD;
464: vinvalbuf(ITOV(oip), (length > 0));
465: allerror = iupdat(oip, &time, &time, MNT_WAIT);
466:
467: /*
468: * Indirect blocks first.
469: */
470: ip = &tip;
471: for (level = TRIPLE; level >= SINGLE; level--) {
472: bn = ip->i_ib[level];
473: if (bn != 0) {
474: error = indirtrunc(ip, bn, lastiblock[level], level,
475: &count);
476: if (error)
477: allerror = error;
478: blocksreleased += count;
479: if (lastiblock[level] < 0) {
480: ip->i_ib[level] = 0;
481: blkfree(ip, bn, (off_t)fs->fs_bsize);
482: blocksreleased += nblocks;
483: }
484: }
485: if (lastiblock[level] >= 0)
486: goto done;
487: }
488:
489: /*
490: * All whole direct blocks or frags.
491: */
492: for (i = NDADDR - 1; i > lastblock; i--) {
493: register off_t bsize;
494:
495: bn = ip->i_db[i];
496: if (bn == 0)
497: continue;
498: ip->i_db[i] = 0;
499: bsize = (off_t)blksize(fs, ip, i);
500: blkfree(ip, bn, bsize);
501: blocksreleased += btodb(bsize);
502: }
503: if (lastblock < 0)
504: goto done;
505:
506: /*
507: * Finally, look for a change in size of the
508: * last direct block; release any frags.
509: */
510: bn = ip->i_db[lastblock];
511: if (bn != 0) {
512: off_t oldspace, newspace;
513:
514: /*
515: * Calculate amount of space we're giving
516: * back as old block size minus new block size.
517: */
518: oldspace = blksize(fs, ip, lastblock);
519: ip->i_size = length;
520: newspace = blksize(fs, ip, lastblock);
521: if (newspace == 0)
522: panic("itrunc: newspace");
523: if (oldspace - newspace > 0) {
524: /*
525: * Block number of space to be free'd is
526: * the old block # plus the number of frags
527: * required for the storage we're keeping.
528: */
529: bn += numfrags(fs, newspace);
530: blkfree(ip, bn, oldspace - newspace);
531: blocksreleased += btodb(oldspace - newspace);
532: }
533: }
534: done:
535: /* BEGIN PARANOIA */
536: for (level = SINGLE; level <= TRIPLE; level++)
537: if (ip->i_ib[level] != oip->i_ib[level])
538: panic("itrunc1");
539: for (i = 0; i < NDADDR; i++)
540: if (ip->i_db[i] != oip->i_db[i])
541: panic("itrunc2");
542: /* END PARANOIA */
543: oip->i_blocks -= blocksreleased;
544: if (oip->i_blocks < 0) /* sanity */
545: oip->i_blocks = 0;
546: oip->i_flag |= ICHG;
547: #ifdef QUOTA
548: if (!getinoquota(oip))
549: (void) chkdq(oip, -blocksreleased, NOCRED, 0);
550: #endif
551: return (allerror);
552: }
553:
554: /*
555: * Release blocks associated with the inode ip and
556: * stored in the indirect block bn. Blocks are free'd
557: * in LIFO order up to (but not including) lastbn. If
558: * level is greater than SINGLE, the block is an indirect
559: * block and recursive calls to indirtrunc must be used to
560: * cleanse other indirect blocks.
561: *
562: * NB: triple indirect blocks are untested.
563: */
564: indirtrunc(ip, bn, lastbn, level, countp)
565: register struct inode *ip;
566: daddr_t bn, lastbn;
567: int level;
568: long *countp;
569: {
570: register int i;
571: struct buf *bp;
572: register struct fs *fs = ip->i_fs;
573: register daddr_t *bap;
574: daddr_t *copy, nb, last;
575: long blkcount, factor;
576: int nblocks, blocksreleased = 0;
577: int error, allerror = 0;
578:
579: /*
580: * Calculate index in current block of last
581: * block to be kept. -1 indicates the entire
582: * block so we need not calculate the index.
583: */
584: factor = 1;
585: for (i = SINGLE; i < level; i++)
586: factor *= NINDIR(fs);
587: last = lastbn;
588: if (lastbn > 0)
589: last /= factor;
590: nblocks = btodb(fs->fs_bsize);
591: /*
592: * Get buffer of block pointers, zero those
593: * entries corresponding to blocks to be free'd,
594: * and update on disk copy first.
595: */
596: error = bread(ip->i_devvp, fsbtodb(fs, bn), (int)fs->fs_bsize,
597: NOCRED, &bp);
598: if (error) {
599: brelse(bp);
600: *countp = 0;
601: return (error);
602: }
603: bap = bp->b_un.b_daddr;
604: MALLOC(copy, daddr_t *, fs->fs_bsize, M_TEMP, M_WAITOK);
605: bcopy((caddr_t)bap, (caddr_t)copy, (u_int)fs->fs_bsize);
606: bzero((caddr_t)&bap[last + 1],
607: (u_int)(NINDIR(fs) - (last + 1)) * sizeof (daddr_t));
608: if (last == -1)
609: bp->b_flags |= B_INVAL;
610: error = bwrite(bp);
611: if (error)
612: allerror = error;
613: bap = copy;
614:
615: /*
616: * Recursively free totally unused blocks.
617: */
618: for (i = NINDIR(fs) - 1; i > last; i--) {
619: nb = bap[i];
620: if (nb == 0)
621: continue;
622: if (level > SINGLE) {
623: error = indirtrunc(ip, nb, (daddr_t)-1, level - 1,
624: &blkcount);
625: if (error)
626: allerror = error;
627: blocksreleased += blkcount;
628: }
629: blkfree(ip, nb, (off_t)fs->fs_bsize);
630: blocksreleased += nblocks;
631: }
632:
633: /*
634: * Recursively free last partial block.
635: */
636: if (level > SINGLE && lastbn >= 0) {
637: last = lastbn % factor;
638: nb = bap[i];
639: if (nb != 0) {
640: error = indirtrunc(ip, nb, last, level - 1, &blkcount);
641: if (error)
642: allerror = error;
643: blocksreleased += blkcount;
644: }
645: }
646: FREE(copy, M_TEMP);
647: *countp = blocksreleased;
648: return (allerror);
649: }
650:
651: /*
652: * Lock an inode. If its already locked, set the WANT bit and sleep.
653: */
654: ilock(ip)
655: register struct inode *ip;
656: {
657:
658: while (ip->i_flag & ILOCKED) {
659: ip->i_flag |= IWANT;
660: if (ip->i_spare0 == u.u_procp->p_pid)
661: panic("locking against myself");
662: ip->i_spare1 = u.u_procp->p_pid;
663: (void) sleep((caddr_t)ip, PINOD);
664: }
665: ip->i_spare1 = 0;
666: ip->i_spare0 = u.u_procp->p_pid;
667: u.u_spare[0]++;
668: ip->i_flag |= ILOCKED;
669: }
670:
671: /*
672: * Unlock an inode. If WANT bit is on, wakeup.
673: */
674: iunlock(ip)
675: register struct inode *ip;
676: {
677:
678: if ((ip->i_flag & ILOCKED) == 0)
679: vprint("iunlock: unlocked inode", ITOV(ip));
680: ip->i_spare0 = 0;
681: u.u_spare[0]--;
682: ip->i_flag &= ~ILOCKED;
683: if (ip->i_flag&IWANT) {
684: ip->i_flag &= ~IWANT;
685: wakeup((caddr_t)ip);
686: }
687: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.