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