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