xref: /original-bsd/sys/ufs/ffs/ffs_vnops.c (revision 1b11f3a3)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)ffs_vnops.c	7.66 (Berkeley) 11/05/91
8  */
9 
10 #include <sys/param.h>
11 #include <sys/systm.h>
12 #include <sys/namei.h>
13 #include <sys/resourcevar.h>
14 #include <sys/kernel.h>
15 #include <sys/file.h>
16 #include <sys/stat.h>
17 #include <sys/buf.h>
18 #include <sys/proc.h>
19 #include <sys/conf.h>
20 #include <sys/mount.h>
21 #include <sys/vnode.h>
22 #include <sys/specdev.h>
23 #include <sys/fifo.h>
24 #include <sys/malloc.h>
25 
26 #include <ufs/ufs/lockf.h>
27 #include <ufs/ufs/quota.h>
28 #include <ufs/ufs/inode.h>
29 #include <ufs/ufs/dir.h>
30 #include <ufs/ufs/ufs_extern.h>
31 
32 #include <ufs/ffs/fs.h>
33 #include <ufs/ffs/ffs_extern.h>
34 
35 /* Global vfs data structures for ufs. */
36 struct vnodeops ffs_vnodeops = {
37 	ufs_lookup,		/* lookup */
38 	ufs_create,		/* create */
39 	ufs_mknod,		/* mknod */
40 	ufs_open,		/* open */
41 	ufs_close,		/* close */
42 	ufs_access,		/* access */
43 	ufs_getattr,		/* getattr */
44 	ufs_setattr,		/* setattr */
45 	ffs_read,		/* read */
46 	ffs_write,		/* write */
47 	ufs_ioctl,		/* ioctl */
48 	ufs_select,		/* select */
49 	ufs_mmap,		/* mmap */
50 	ffs_fsync,		/* fsync */
51 	ufs_seek,		/* seek */
52 	ufs_remove,		/* remove */
53 	ufs_link,		/* link */
54 	ufs_rename,		/* rename */
55 	ufs_mkdir,		/* mkdir */
56 	ufs_rmdir,		/* rmdir */
57 	ufs_symlink,		/* symlink */
58 	ufs_readdir,		/* readdir */
59 	ufs_readlink,		/* readlink */
60 	ufs_abortop,		/* abortop */
61 	ffs_inactive,		/* inactive */
62 	ufs_reclaim,		/* reclaim */
63 	ufs_lock,		/* lock */
64 	ufs_unlock,		/* unlock */
65 	ffs_bmap,		/* bmap */
66 	ufs_strategy,		/* strategy */
67 	ufs_print,		/* print */
68 	ufs_islocked,		/* islocked */
69 	ufs_advlock,		/* advlock */
70 	ffs_blkatoff,		/* blkatoff */
71 	ffs_vget,		/* vget */
72 	ffs_valloc,		/* valloc */
73 	ffs_vfree,		/* vfree */
74 	ffs_truncate,		/* truncate */
75 	ffs_update,		/* update */
76 	bwrite,			/* bwrite */
77 };
78 
79 struct vnodeops ffs_specops = {
80 	spec_lookup,		/* lookup */
81 	spec_create,		/* create */
82 	spec_mknod,		/* mknod */
83 	spec_open,		/* open */
84 	ufsspec_close,		/* close */
85 	ufs_access,		/* access */
86 	ufs_getattr,		/* getattr */
87 	ufs_setattr,		/* setattr */
88 	ufsspec_read,		/* read */
89 	ufsspec_write,		/* write */
90 	spec_ioctl,		/* ioctl */
91 	spec_select,		/* select */
92 	spec_mmap,		/* mmap */
93 	spec_fsync,		/* fsync */
94 	spec_seek,		/* seek */
95 	spec_remove,		/* remove */
96 	spec_link,		/* link */
97 	spec_rename,		/* rename */
98 	spec_mkdir,		/* mkdir */
99 	spec_rmdir,		/* rmdir */
100 	spec_symlink,		/* symlink */
101 	spec_readdir,		/* readdir */
102 	spec_readlink,		/* readlink */
103 	spec_abortop,		/* abortop */
104 	ffs_inactive,		/* inactive */
105 	ufs_reclaim,		/* reclaim */
106 	ufs_lock,		/* lock */
107 	ufs_unlock,		/* unlock */
108 	spec_bmap,		/* bmap */
109 	spec_strategy,		/* strategy */
110 	ufs_print,		/* print */
111 	ufs_islocked,		/* islocked */
112 	spec_advlock,		/* advlock */
113 	spec_blkatoff,		/* blkatoff */
114 	spec_vget,		/* vget */
115 	spec_valloc,		/* valloc */
116 	spec_vfree,		/* vfree */
117 	spec_truncate,		/* truncate */
118 	ffs_update,		/* update */
119 	bwrite,			/* bwrite */
120 };
121 
122 #ifdef FIFO
123 struct vnodeops ffs_fifoops = {
124 	fifo_lookup,		/* lookup */
125 	fifo_create,		/* create */
126 	fifo_mknod,		/* mknod */
127 	fifo_open,		/* open */
128 	ufsfifo_close,		/* close */
129 	ufs_access,		/* access */
130 	ufs_getattr,		/* getattr */
131 	ufs_setattr,		/* setattr */
132 	ufsfifo_read,		/* read */
133 	ufsfifo_write,		/* write */
134 	fifo_ioctl,		/* ioctl */
135 	fifo_select,		/* select */
136 	fifo_mmap,		/* mmap */
137 	fifo_fsync,		/* fsync */
138 	fifo_seek,		/* seek */
139 	fifo_remove,		/* remove */
140 	fifo_link,		/* link */
141 	fifo_rename,		/* rename */
142 	fifo_mkdir,		/* mkdir */
143 	fifo_rmdir,		/* rmdir */
144 	fifo_symlink,		/* symlink */
145 	fifo_readdir,		/* readdir */
146 	fifo_readlink,		/* readlink */
147 	fifo_abortop,		/* abortop */
148 	ffs_inactive,		/* inactive */
149 	ufs_reclaim,		/* reclaim */
150 	ufs_lock,		/* lock */
151 	ufs_unlock,		/* unlock */
152 	fifo_bmap,		/* bmap */
153 	fifo_strategy,		/* strategy */
154 	ufs_print,		/* print */
155 	ufs_islocked,		/* islocked */
156 	fifo_advlock,		/* advlock */
157 	fifo_blkatoff,		/* blkatoff */
158 	fifo_vget,		/* vget */
159 	fifo_valloc,		/* valloc */
160 	fifo_vfree,		/* vfree */
161 	fifo_truncate,		/* truncate */
162 	ffs_update,		/* update */
163 	bwrite,			/* bwrite */
164 };
165 #endif /* FIFO */
166 
167 int	maknode __P((int, struct nameidata *, struct inode **));
168 
169 /*
170  * Vnode op for reading.
171  */
172 /* ARGSUSED */
173 ffs_read(vp, uio, ioflag, cred)
174 	struct vnode *vp;
175 	register struct uio *uio;
176 	int ioflag;
177 	struct ucred *cred;
178 {
179 	register struct inode *ip = VTOI(vp);
180 	register struct fs *fs;
181 	struct buf *bp;
182 	daddr_t lbn, bn, rablock;
183 	int size, diff, error = 0;
184 	long n, on, type;
185 
186 #ifdef DIAGNOSTIC
187 	if (uio->uio_rw != UIO_READ)
188 		panic("ffs_read mode");
189 	type = ip->i_mode & IFMT;
190 	if (type != IFDIR && type != IFREG && type != IFLNK)
191 		panic("ffs_read type");
192 #endif
193 	if (uio->uio_resid == 0)
194 		return (0);
195 	if (uio->uio_offset < 0)
196 		return (EINVAL);
197 	ip->i_flag |= IACC;
198 	fs = ip->i_fs;
199 	do {
200 		lbn = lblkno(fs, uio->uio_offset);
201 		on = blkoff(fs, uio->uio_offset);
202 		n = MIN((unsigned)(fs->fs_bsize - on), uio->uio_resid);
203 		diff = ip->i_size - uio->uio_offset;
204 		if (diff <= 0)
205 			return (0);
206 		if (diff < n)
207 			n = diff;
208 		size = blksize(fs, ip, lbn);
209 		rablock = lbn + 1;
210 		if (vp->v_lastr + 1 == lbn &&
211 		    lblktosize(fs, rablock) < ip->i_size)
212 			error = breada(ITOV(ip), lbn, size, rablock,
213 				blksize(fs, ip, rablock), NOCRED, &bp);
214 		else
215 			error = bread(ITOV(ip), lbn, size, NOCRED, &bp);
216 		vp->v_lastr = lbn;
217 		n = MIN(n, size - bp->b_resid);
218 		if (error) {
219 			brelse(bp);
220 			return (error);
221 		}
222 		error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
223 		if (n + on == fs->fs_bsize || uio->uio_offset == ip->i_size)
224 			bp->b_flags |= B_AGE;
225 		brelse(bp);
226 	} while (error == 0 && uio->uio_resid > 0 && n != 0);
227 	return (error);
228 }
229 
230 /*
231  * Vnode op for writing.
232  */
233 ffs_write(vp, uio, ioflag, cred)
234 	register struct vnode *vp;
235 	struct uio *uio;
236 	int ioflag;
237 	struct ucred *cred;
238 {
239 	struct proc *p = uio->uio_procp;
240 	register struct inode *ip = VTOI(vp);
241 	register struct fs *fs;
242 	struct buf *bp;
243 	daddr_t lbn, bn;
244 	u_long osize;
245 	int n, on, flags;
246 	int size, resid, error = 0;
247 
248 #ifdef DIAGNOSTIC
249 	if (uio->uio_rw != UIO_WRITE)
250 		panic("ffs_write mode");
251 #endif
252 	switch (vp->v_type) {
253 	case VREG:
254 		if (ioflag & IO_APPEND)
255 			uio->uio_offset = ip->i_size;
256 		/* fall through */
257 	case VLNK:
258 		break;
259 
260 	case VDIR:
261 		if ((ioflag & IO_SYNC) == 0)
262 			panic("ffs_write nonsync dir write");
263 		break;
264 
265 	default:
266 		panic("ffs_write type");
267 	}
268 	if (uio->uio_offset < 0)
269 		return (EINVAL);
270 	if (uio->uio_resid == 0)
271 		return (0);
272 	/*
273 	 * Maybe this should be above the vnode op call, but so long as
274 	 * file servers have no limits, i don't think it matters
275 	 */
276 	if (vp->v_type == VREG && p &&
277 	    uio->uio_offset + uio->uio_resid >
278 	      p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
279 		psignal(p, SIGXFSZ);
280 		return (EFBIG);
281 	}
282 	resid = uio->uio_resid;
283 	osize = ip->i_size;
284 	fs = ip->i_fs;
285 	flags = 0;
286 	if (ioflag & IO_SYNC)
287 		flags = B_SYNC;
288 	do {
289 		lbn = lblkno(fs, uio->uio_offset);
290 		on = blkoff(fs, uio->uio_offset);
291 		n = MIN((unsigned)(fs->fs_bsize - on), uio->uio_resid);
292 		if (n < fs->fs_bsize)
293 			flags |= B_CLRBUF;
294 		else
295 			flags &= ~B_CLRBUF;
296 		if (error = ffs_balloc(ip, lbn, (int)(on + n), &bp, flags))
297 			break;
298 		bn = bp->b_blkno;
299 		if (uio->uio_offset + n > ip->i_size) {
300 			ip->i_size = uio->uio_offset + n;
301 			vnode_pager_setsize(vp, ip->i_size);
302 		}
303 		size = blksize(fs, ip, lbn);
304 		(void) vnode_pager_uncache(vp);
305 		n = MIN(n, size - bp->b_resid);
306 		error = uiomove(bp->b_un.b_addr + on, n, uio);
307 		if (ioflag & IO_SYNC)
308 			(void) bwrite(bp);
309 		else if (n + on == fs->fs_bsize) {
310 			bp->b_flags |= B_AGE;
311 			bawrite(bp);
312 		} else
313 			bdwrite(bp);
314 		ip->i_flag |= IUPD|ICHG;
315 		if (cred->cr_uid != 0)
316 			ip->i_mode &= ~(ISUID|ISGID);
317 	} while (error == 0 && uio->uio_resid > 0 && n != 0);
318 	if (error && (ioflag & IO_UNIT)) {
319 		(void)ffs_truncate(vp, osize, ioflag & IO_SYNC);
320 		uio->uio_offset -= resid - uio->uio_resid;
321 		uio->uio_resid = resid;
322 	}
323 	if (!error && (ioflag & IO_SYNC))
324 		error = ffs_update(vp, &time, &time, 1);
325 	return (error);
326 }
327 
328 /*
329  * Synch an open file.
330  */
331 /* ARGSUSED */
332 int
333 ffs_fsync(vp, fflags, cred, waitfor, p)
334 	struct vnode *vp;
335 	int fflags;
336 	struct ucred *cred;
337 	int waitfor;
338 	struct proc *p;
339 {
340 	struct inode *ip = VTOI(vp);
341 
342 	if (fflags & FWRITE)
343 		ip->i_flag |= ICHG;
344 	vflushbuf(vp, waitfor == MNT_WAIT ? B_SYNC : 0);
345 	return (ffs_update(vp, &time, &time, waitfor == MNT_WAIT));
346 }
347 
348 /*
349  * Last reference to an inode, write the inode out and if necessary,
350  * truncate and deallocate the file.
351  */
352 int
353 ffs_inactive(vp, p)
354 	struct vnode *vp;
355 	struct proc *p;
356 {
357 	register struct inode *ip;
358 	int mode, error;
359 	extern int prtactive;
360 
361 	if (prtactive && vp->v_usecount != 0)
362 		vprint("ffs_inactive: pushing active", vp);
363 
364 	/* Get rid of inodes related to stale file handles. */
365 	ip = VTOI(vp);
366 	if (ip->i_mode == 0) {
367 		if ((vp->v_flag & VXLOCK) == 0)
368 			vgone(vp);
369 		return (0);
370 	}
371 
372 	error = 0;
373 	ILOCK(ip);
374 	if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
375 #ifdef QUOTA
376 		if (!getinoquota(ip))
377 			(void)chkiq(ip, -1, NOCRED, 0);
378 #endif
379 		error = ffs_truncate(vp, (u_long)0, 0);
380 		mode = ip->i_mode;
381 		ip->i_mode = 0;
382 		ip->i_rdev = 0;
383 		ip->i_flag |= IUPD|ICHG;
384 		ffs_vfree(vp, ip->i_number, mode);
385 	}
386 	if (ip->i_flag&(IUPD|IACC|ICHG|IMOD))
387 		ffs_update(vp, &time, &time, 0);
388 	IUNLOCK(ip);
389 	ip->i_flag = 0;
390 	/*
391 	 * If we are done with the inode, reclaim it
392 	 * so that it can be reused immediately.
393 	 */
394 	if (vp->v_usecount == 0 && ip->i_mode == 0)
395 		vgone(vp);
396 	return (error);
397 }
398