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