xref: /csrg-svn/sys/ufs/lfs/lfs_inode.c (revision 51498)
1 /*
2  * Copyright (c) 1986, 1989, 1991 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)lfs_inode.c	7.46 (Berkeley) 11/01/91
8  */
9 
10 #include <sys/param.h>
11 #include <sys/systm.h>
12 #include <sys/mount.h>
13 #include <sys/proc.h>
14 #include <sys/file.h>
15 #include <sys/buf.h>
16 #include <sys/vnode.h>
17 #include <sys/kernel.h>
18 #include <sys/malloc.h>
19 
20 #include <ufs/ufs/quota.h>
21 #include <ufs/ufs/inode.h>
22 #include <ufs/ufs/ufsmount.h>
23 #include <ufs/ufs/ufs_extern.h>
24 
25 #include <ufs/lfs/lfs.h>
26 #include <ufs/lfs/lfs_extern.h>
27 
28 int
29 lfs_init()
30 {
31 	return (ufs_init());
32 }
33 
34 /*
35  * Look up an LFS dinode number to find its incore vnode.  If not already
36  * in core, read it in from the specified device.  Return the inode locked.
37  * Detection and handling of mount points must be done by the calling routine.
38  */
39 int
40 lfs_iget(pip, ino, ipp)
41 	struct inode *pip;
42 	ino_t ino;
43 	struct inode **ipp;
44 {
45 	register struct lfs *fs;
46 	register struct inode *ip;
47 	struct buf *bp;
48 	struct mount *mntp;
49 	struct vnode *vp;
50 	dev_t dev;
51 	int error;
52 
53 	mntp = ITOV(pip)->v_mount;
54 	fs = VFSTOUFS(mntp)->um_lfs;
55 	if (ino < ROOTINO)
56 		return (EINVAL);
57 
58 	dev = pip->i_dev;
59 	if ((*ipp = ufs_ihashget(dev, ino)) != NULL)
60 		return (0);
61 
62 	/* Allocate new vnode/inode. */
63 	if (error = lfs_vcreate(mntp, ino, &vp)) {
64 		*ipp = NULL;
65 		return (error);
66 	}
67 	ip = VTOI(vp);
68 
69 	/*
70 	 * Put it onto its hash chain and lock it so that other requests for
71 	 * this inode will block if they arrive while we are sleeping waiting
72 	 * for old data structures to be purged or for the contents of the
73 	 * disk portion of this inode to be read.
74 	 */
75 	ufs_ihashins(ip);
76 
77 	/* Read in the disk contents for the inode, copy into the inode. */
78 	if (error = bread(VFSTOUFS(mntp)->um_devvp, lfs_itod(fs, ino),
79 	    (int)fs->lfs_bsize, NOCRED, &bp)) {
80 		/*
81 		 * The inode does not contain anything useful, so it would
82 		 * be misleading to leave it on its hash chain.  Iput() will
83 		 * return it to the free list.
84 		 */
85 		remque(ip);
86 		ip->i_forw = ip;
87 		ip->i_back = ip;
88 
89 		/* Unlock and discard unneeded inode. */
90 		ufs_iput(ip);
91 		brelse(bp);
92 		*ipp = NULL;
93 		return (error);
94 	}
95 	ip->i_din = *lfs_ifind(fs, ino, bp->b_un.b_dino);
96 	brelse(bp);
97 
98 	/*
99 	 * Initialize the vnode from the inode, check for aliases.  In all
100 	 * cases re-init ip, the underlying vnode/inode may have changed.
101 	 */
102 	if (error = ufs_vinit(mntp, &vp)) {
103 		ufs_iput(ip);
104 		*ipp = NULL;
105 		return (error);
106 	}
107 	*ipp = VTOI(vp);
108 	return (0);
109 }
110 
111 int
112 lfs_iupdat(ip, ta, tm, waitfor)
113 	register struct inode *ip;
114 	struct timeval *ta, *tm;
115         int waitfor;
116 {
117 	/*
118 	 * XXX
119 	 * This isn't right, but ufs_iupdat() isn't either.
120 	 */
121 	ITIMES(ip, ta, tm);
122 	return (0);
123 }
124 
125 /*
126  * Truncate the inode ip to at most length size.
127  *
128  * NB: triple indirect blocks are untested.
129  */
130 /* ARGSUSED */
131 int
132 lfs_itrunc(oip, length, flags)
133 	register struct inode *oip;
134 	u_long length;
135 	int flags;
136 {
137 	register struct lfs *fs;
138 	struct buf *bp;
139 	daddr_t lbn;
140 	int error, offset, size;
141 
142 	vnode_pager_setsize(ITOV(oip), length);
143 
144 	/* If length is larger than the file, just update the times. */
145 	if (oip->i_size <= length) {
146 		oip->i_flag |= ICHG|IUPD;
147 		ITIMES(oip, &time, &time);
148 		return (0);
149 	}
150 
151 	/*
152 	 * Update the size of the file. If the file is not being truncated to
153 	 * a block boundry, the contents of the partial block following the end
154 	 * of the file must be zero'ed in case it ever become accessable again
155 	 * because of subsequent file growth.
156 	 */
157 	fs = oip->i_lfs;
158 	offset = blkoff(fs, length);
159 	if (offset == 0)
160 		oip->i_size = length;
161 	else {
162 		lbn = lblkno(fs, length);
163 #ifdef QUOTA
164 		if (error = getinoquota(oip))
165 			return (error);
166 #endif
167 		if (error = bread(ITOV(oip), lbn, fs->lfs_bsize, NOCRED, &bp))
168 			return (error);
169 		oip->i_size = length;
170 		size = blksize(fs);				/* LFS */
171 		(void) vnode_pager_uncache(ITOV(oip));
172 		bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset));
173 		allocbuf(bp, size);
174 		lfs_bwrite(bp);
175 	}
176 	/* BZERO INODE BLOCK POINTERS HERE, FOR CONSISTENCY XXX */
177 }
178