xref: /csrg-svn/sys/ufs/lfs/lfs_inode.c (revision 52221)
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.52 (Berkeley) 01/18/92
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 #ifdef VERBOSE
32 	printf("lfs_init\n");
33 #endif
34 	return (ufs_init());
35 }
36 
37 static daddr_t
38 lfs_itod(fs, ino)
39 	struct lfs *fs;
40 	ino_t ino;
41 {
42 	BUF *bp;
43 	IFILE *ifp;
44 	daddr_t iaddr;
45 
46 	/* Translate an inode number to a disk address. */
47 	if (ino == LFS_IFILE_INUM)
48 		return (fs->lfs_idaddr);
49 
50 	LFS_IENTRY(ifp, fs, ino, bp);
51 	iaddr = ifp->if_daddr;
52 	brelse(bp);
53 	return (iaddr);
54 }
55 
56 /*
57  * Look up an LFS dinode number to find its incore vnode.  If not already
58  * in core, read it in from the specified device.  Return the inode locked.
59  * Detection and handling of mount points must be done by the calling routine.
60  */
61 int
62 lfs_vget(mntp, ino, vpp)
63 	struct mount *mntp;
64 	ino_t ino;
65 	struct vnode **vpp;
66 {
67 	register struct lfs *fs;
68 	register struct inode *ip;
69 	struct buf *bp;
70 	struct vnode *vp;
71 	struct ufsmount *ump;
72 	dev_t dev;
73 	int error;
74 
75 #ifdef VERBOSE
76 	printf("lfs_vget\n");
77 #endif
78 	ump = VFSTOUFS(mntp);
79 	dev = ump->um_dev;
80 	if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
81 		return (0);
82 
83 	/* Allocate new vnode/inode. */
84 	if (error = lfs_vcreate(mntp, ino, &vp)) {
85 		*vpp = NULL;
86 		return (error);
87 	}
88 	/*
89 	 * Put it onto its hash chain and lock it so that other requests for
90 	 * this inode will block if they arrive while we are sleeping waiting
91 	 * for old data structures to be purged or for the contents of the
92 	 * disk portion of this inode to be read.
93 	 */
94 	ip = VTOI(vp);
95 	ufs_ihashins(ip);
96 
97 	/* Read in the disk contents for the inode, copy into the inode. */
98 	ip->i_lfs = fs = ump->um_lfs;
99 	if (error = bread(ump->um_devvp, lfs_itod(fs, ino),
100 	    (int)fs->lfs_bsize, NOCRED, &bp)) {
101 		/*
102 		 * The inode does not contain anything useful, so it
103 		 * would be misleading to leave it on its hash chain.
104 		 * Iput() will return it to the free list.
105 		 */
106 		remque(ip);
107 		ip->i_forw = ip;
108 		ip->i_back = ip;
109 
110 		/* Unlock and discard unneeded inode. */
111 		ufs_iput(ip);
112 		brelse(bp);
113 		*vpp = NULL;
114 		return (error);
115 	}
116 	ip->i_din = *lfs_ifind(fs, ino, bp->b_un.b_dino);
117 	brelse(bp);
118 
119 	/*
120 	 * Initialize the vnode from the inode, check for aliases.  In all
121 	 * cases re-init ip, the underlying vnode/inode may have changed.
122 	 */
123 	if (error = ufs_vinit(mntp, &lfs_specops, LFS_FIFOOPS, &vp)) {
124 		ufs_iput(ip);
125 		*vpp = NULL;
126 		return (error);
127 	}
128 	/*
129 	 * Finish inode initialization now that aliasing has been resolved.
130 	 */
131 	ip->i_devvp = ump->um_devvp;
132 	VREF(ip->i_devvp);
133 	*vpp = vp;
134 	return (0);
135 }
136 
137 int
138 lfs_update(vp, ta, tm, waitfor)
139 	register struct vnode *vp;
140 	struct timeval *ta, *tm;
141         int waitfor;
142 {
143 	struct inode *ip;
144 
145 #ifdef VERBOSE
146 	printf("lfs_update\n");
147 #endif
148 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
149 		return (0);
150 	ip = VTOI(vp);
151 	if ((ip->i_flag & (IUPD|IACC|ICHG|IMOD)) == 0)
152 		return (0);
153 	if (ip->i_flag&IACC)
154 		ip->i_atime = ta->tv_sec;
155 	if (ip->i_flag&IUPD) {
156 		ip->i_mtime = tm->tv_sec;
157 		INCRQUAD((ip)->i_modrev);
158 	}
159 	if (ip->i_flag&ICHG)
160 		ip->i_ctime = time.tv_sec;
161 	ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD);
162 
163 	/*
164 	 * XXX
165 	 * I'm not real sure what to do here; once we have fsync and partial
166 	 * segments working in the LFS context, this must be fixed to be
167 	 * correct.  The contents of the inode have to be pushed back to
168 	 * stable storage.
169 	 */
170 	return (0);
171 }
172 
173 /*
174  * Truncate the inode ip to at most length size.
175  *
176  * NB: triple indirect blocks are untested.
177  */
178 /* ARGSUSED */
179 int
180 lfs_truncate(ovp, length, flags)
181 	struct vnode *ovp;
182 	u_long length;
183 	int flags;
184 {
185 	register struct lfs *fs;
186 	register struct inode *oip;
187 	struct buf *bp;
188 	daddr_t lbn;
189 	int error, offset, size;
190 
191 #ifdef VERBOSE
192 	printf("lfs_truncate\n");
193 #endif
194 	vnode_pager_setsize(ovp, length);
195 	oip = VTOI(ovp);
196 
197 	/* If length is larger than the file, just update the times. */
198 	if (oip->i_size <= length) {
199 		oip->i_flag |= ICHG|IUPD;
200 		ITIMES(oip, &time, &time);
201 		return (0);
202 	}
203 
204 	/*
205 	 * Update the size of the file. If the file is not being truncated to
206 	 * a block boundry, the contents of the partial block following the end
207 	 * of the file must be zero'ed in case it ever become accessable again
208 	 * because of subsequent file growth.
209 	 */
210 	fs = oip->i_lfs;
211 	offset = blkoff(fs, length);
212 	if (offset == 0)
213 		oip->i_size = length;
214 	else {
215 		lbn = lblkno(fs, length);
216 #ifdef QUOTA
217 		if (error = getinoquota(oip))
218 			return (error);
219 #endif
220 		if (error = bread(ovp, lbn, fs->lfs_bsize, NOCRED, &bp))
221 			return (error);
222 		oip->i_size = length;
223 		size = blksize(fs);
224 		(void)vnode_pager_uncache(ovp);
225 		bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset));
226 		allocbuf(bp, size);
227 		LFS_UBWRITE(bp);
228 	}
229 	/*
230 	 * XXX
231 	 * Bzero inode block pointers here, for consistency with ffs.
232 	 * Segment usage information has to be updated when the blocks
233 	 * are free.
234 	 * Block count in the inode has to be fixed when blocks are
235 	 * free.
236 	 */
237 	(void)vinvalbuf(ovp, length > 0);
238 	return (0);
239 }
240