xref: /csrg-svn/sys/ufs/lfs/lfs_inode.c (revision 51595)
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.48 (Berkeley) 11/08/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_vget(mntp, ino, vpp)
41 	struct mount *mntp;
42 	ino_t ino;
43 	struct vnode **vpp;
44 {
45 	register struct lfs *fs;
46 	register struct inode *ip;
47 	struct buf *bp;
48 	struct vnode *vp;
49 	struct ufsmount *ump;
50 	dev_t dev;
51 	int error;
52 
53 	ump = VFSTOUFS(mntp);
54 	dev = ump->um_dev;
55 	if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
56 		return (0);
57 
58 	/* Allocate new vnode/inode. */
59 	if (error = lfs_vcreate(mntp, ino, &vp)) {
60 		*vpp = NULL;
61 		return (error);
62 	}
63 	/*
64 	 * Put it onto its hash chain and lock it so that other requests for
65 	 * this inode will block if they arrive while we are sleeping waiting
66 	 * for old data structures to be purged or for the contents of the
67 	 * disk portion of this inode to be read.
68 	 */
69 	ip = VTOI(vp);
70 	ufs_ihashins(ip);
71 
72 	/* Read in the disk contents for the inode, copy into the inode. */
73 	fs = ump->um_lfs;
74 	if (error = bread(ump->um_devvp, lfs_itod(fs, ino),
75 	    (int)fs->lfs_bsize, NOCRED, &bp)) {
76 		/*
77 		 * The inode does not contain anything useful, so it would
78 		 * be misleading to leave it on its hash chain.  Iput() will
79 		 * return it to the free list.
80 		 */
81 		remque(ip);
82 		ip->i_forw = ip;
83 		ip->i_back = ip;
84 
85 		/* Unlock and discard unneeded inode. */
86 		ufs_iput(ip);
87 		brelse(bp);
88 		*vpp = NULL;
89 		return (error);
90 	}
91 	ip->i_din = *lfs_ifind(fs, ino, bp->b_un.b_dino);
92 	brelse(bp);
93 
94 	/*
95 	 * Initialize the vnode from the inode, check for aliases.  In all
96 	 * cases re-init ip, the underlying vnode/inode may have changed.
97 	 */
98 	if (error = ufs_vinit(mntp, &lfs_specops, LFS_FIFOOPS, &vp)) {
99 		ufs_iput(ip);
100 		*vpp = NULL;
101 		return (error);
102 	}
103 	/*
104 	 * Finish inode initialization now that aliasing has been resolved.
105 	 */
106 	ip = VTOI(vp);
107 	ip->i_lfs = ump->um_lfs;
108 	ip->i_devvp = ump->um_devvp;
109 	VREF(ip->i_devvp);
110 	*vpp = vp;
111 	return (0);
112 }
113 
114 int
115 lfs_update(vp, ta, tm, waitfor)
116 	register struct vnode *vp;
117 	struct timeval *ta, *tm;
118         int waitfor;
119 {
120 	struct inode *ip;
121 
122 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
123 		return (0);
124 	ip = VTOI(vp);
125 	if ((ip->i_flag & (IUPD|IACC|ICHG|IMOD)) == 0)
126 		return (0);
127 	if (ip->i_flag&IACC)
128 		ip->i_atime = ta->tv_sec;
129 	if (ip->i_flag&IUPD)
130 		ip->i_mtime = tm->tv_sec;
131 	if (ip->i_flag&ICHG)
132 		ip->i_ctime = time.tv_sec;
133 	ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD);
134 
135 	/*
136 	 * XXX
137 	 * I'm not real sure what to do here; once we have fsync and partial
138 	 * segments working in the LFS context, this must be fixed to be
139 	 * correct.  The contents of the inode have to be pushed back to
140 	 * stable storage; note that the ifile contains the access time of
141 	 * the inode and must be updated as well.
142 	 */
143 	return (0);
144 }
145 
146 /*
147  * Truncate the inode ip to at most length size.
148  *
149  * NB: triple indirect blocks are untested.
150  */
151 /* ARGSUSED */
152 int
153 lfs_truncate(ovp, length, flags)
154 	struct vnode *ovp;
155 	u_long length;
156 	int flags;
157 {
158 	register struct lfs *fs;
159 	register struct inode *oip;
160 	struct buf *bp;
161 	daddr_t lbn;
162 	int error, offset, size;
163 
164 	vnode_pager_setsize(ovp, length);
165 	oip = VTOI(ovp);
166 
167 	/* If length is larger than the file, just update the times. */
168 	if (oip->i_size <= length) {
169 		oip->i_flag |= ICHG|IUPD;
170 		ITIMES(oip, &time, &time);
171 		return (0);
172 	}
173 
174 	/*
175 	 * Update the size of the file. If the file is not being truncated to
176 	 * a block boundry, the contents of the partial block following the end
177 	 * of the file must be zero'ed in case it ever become accessable again
178 	 * because of subsequent file growth.
179 	 */
180 	fs = oip->i_lfs;
181 	offset = blkoff(fs, length);
182 	if (offset == 0)
183 		oip->i_size = length;
184 	else {
185 		lbn = lblkno(fs, length);
186 #ifdef QUOTA
187 		if (error = getinoquota(oip))
188 			return (error);
189 #endif
190 		if (error = bread(ovp, lbn, fs->lfs_bsize, NOCRED, &bp))
191 			return (error);
192 		oip->i_size = length;
193 		size = blksize(fs);				/* LFS */
194 		(void) vnode_pager_uncache(ovp);
195 		bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset));
196 		allocbuf(bp, size);
197 		lfs_bwrite(bp);
198 	}
199 	/* BZERO INODE BLOCK POINTERS HERE, FOR CONSISTENCY XXX */
200 }
201