xref: /csrg-svn/sys/ufs/lfs/lfs_vnops.c (revision 51183)
1 /*
2  * Copyright (c) 1982, 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.67 (Berkeley) 09/25/91
8  */
9 
10 #include "param.h"
11 #include "systm.h"
12 #include "namei.h"
13 #include "resourcevar.h"
14 #include "kernel.h"
15 #include "file.h"
16 #include "stat.h"
17 #include "buf.h"
18 #include "proc.h"
19 #include "conf.h"
20 #include "mount.h"
21 #include "vnode.h"
22 #include "specdev.h"
23 #include "fifo.h"
24 #include "malloc.h"
25 
26 #include "../ufs/lockf.h"
27 #include "../ufs/quota.h"
28 #include "../ufs/inode.h"
29 #include "../ufs/dir.h"
30 #include "lfs.h"
31 #include "lfs_extern.h"
32 
33 static int	chmod1 __P((struct vnode *, int, struct proc *));
34 static int	chown1 __P((struct vnode *, uid_t, gid_t, struct proc *));
35 static int	maknode __P((int, struct nameidata *, struct inode **));
36 
37 /*
38  * Create a regular file
39  */
40 lfs_create(ndp, vap, p)
41 	struct nameidata *ndp;
42 	struct vattr *vap;
43 	struct proc *p;
44 {
45 	struct inode *ip;
46 	int error;
47 
48 printf("lfs_create\n");
49 	if (error = maknode(MAKEIMODE(vap->va_type, vap->va_mode), ndp, &ip))
50 		return (error);
51 	ndp->ni_vp = ITOV(ip);
52 	return (0);
53 }
54 
55 /*
56  * Mknod vnode call
57  */
58 /* ARGSUSED */
59 lfs_mknod(ndp, vap, cred, p)
60 	struct nameidata *ndp;
61 	struct ucred *cred;
62 	struct vattr *vap;
63 	struct proc *p;
64 {
65 	register struct vnode *vp;
66 	struct inode *ip;
67 	int error;
68 
69 printf("lfs_mknod\n");
70 	if (error = maknode(MAKEIMODE(vap->va_type, vap->va_mode), ndp, &ip))
71 		return (error);
72 	ip->i_flag |= IACC|IUPD|ICHG;
73 	if (vap->va_rdev != VNOVAL) {
74 		/*
75 		 * Want to be able to use this to make badblock
76 		 * inodes, so don't truncate the dev number.
77 		 */
78 		ip->i_rdev = vap->va_rdev;
79 	}
80 	/*
81 	 * Remove inode so that it will be reloaded by iget and
82 	 * checked to see if it is an alias of an existing entry
83 	 * in the inode cache.
84 	 */
85 	vp = ITOV(ip);
86 	vput(vp);
87 	vp->v_type = VNON;
88 	vgone(vp);
89 	return (0);
90 }
91 
92 /* ARGSUSED */
93 lfs_getattr(vp, vap, cred, p)
94 	struct vnode *vp;
95 	register struct vattr *vap;
96 	struct ucred *cred;
97 	struct proc *p;
98 {
99 	register struct inode *ip = VTOI(vp);
100 
101 printf("lfs_getattr\n");
102 	ITIMES(ip, &time, &time);				/* LFS */
103 	/*
104 	 * Copy from inode table
105 	 */
106 	vap->va_fsid = ip->i_dev;
107 	vap->va_fileid = ip->i_number;
108 	vap->va_mode = ip->i_mode & ~IFMT;
109 	vap->va_nlink = ip->i_nlink;
110 	vap->va_uid = ip->i_uid;
111 	vap->va_gid = ip->i_gid;
112 	vap->va_rdev = (dev_t)ip->i_rdev;
113 #ifdef tahoe
114 	vap->va_size = ip->i_size;
115 	vap->va_size_rsv = 0;
116 #else
117 	vap->va_qsize = ip->i_din.di_qsize;
118 #endif
119 	vap->va_atime.tv_sec = ip->i_atime;
120 	vap->va_atime.tv_usec = 0;
121 	vap->va_mtime.tv_sec = ip->i_mtime;
122 	vap->va_mtime.tv_usec = 0;
123 	vap->va_ctime.tv_sec = ip->i_ctime;
124 	vap->va_ctime.tv_usec = 0;
125 	vap->va_flags = ip->i_flags;
126 	vap->va_gen = ip->i_gen;
127 	/* this doesn't belong here */
128 	if (vp->v_type == VBLK)
129 		vap->va_blocksize = BLKDEV_IOSIZE;
130 	else if (vp->v_type == VCHR)
131 		vap->va_blocksize = MAXBSIZE;
132 	else
133 		vap->va_blocksize = ip->i_lfs->lfs_bsize;	/* LFS */
134 	vap->va_bytes = dbtob(ip->i_blocks);
135 	vap->va_bytes_rsv = 0;
136 	vap->va_type = vp->v_type;
137 	return (0);
138 }
139 
140 /*
141  * Set attribute vnode op. called from several syscalls
142  */
143 lfs_setattr(vp, vap, cred, p)
144 	register struct vnode *vp;
145 	register struct vattr *vap;
146 	register struct ucred *cred;
147 	struct proc *p;
148 {
149 	register struct inode *ip = VTOI(vp);
150 	int error = 0;
151 
152 printf("lfs_setattr\n");
153 	/*
154 	 * Check for unsettable attributes.
155 	 */
156 	if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
157 	    (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
158 	    (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
159 	    ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
160 		return (EINVAL);
161 	}
162 	/*
163 	 * Go through the fields and update iff not VNOVAL.
164 	 */
165 	if (vap->va_uid != (u_short)VNOVAL || vap->va_gid != (u_short)VNOVAL)
166 		if (error = chown1(vp, vap->va_uid, vap->va_gid, p))
167 			return (error);
168 	if (vap->va_size != VNOVAL) {
169 		if (vp->v_type == VDIR)
170 			return (EISDIR);			/* LFS */
171 		if (error = lfs_itrunc(ip, vap->va_size, 0)) /* XXX IO_SYNC? */
172 			return (error);
173 	}
174 	if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
175 		if (cred->cr_uid != ip->i_uid &&
176 		    (error = suser(cred, &p->p_acflag)))
177 			return (error);
178 		if (vap->va_atime.tv_sec != VNOVAL)
179 			ip->i_flag |= IACC;
180 		if (vap->va_mtime.tv_sec != VNOVAL)
181 			ip->i_flag |= IUPD;
182 		ip->i_flag |= ICHG;				/* LFS */
183 		ITIMES(ip, &vap->va_atime, &vap->va_mtime);	/* LFS */
184 	}
185 	if (vap->va_mode != (u_short)VNOVAL)
186 		error = chmod1(vp, (int)vap->va_mode, p);
187 	if (vap->va_flags != VNOVAL) {
188 		if (cred->cr_uid != ip->i_uid &&
189 		    (error = suser(cred, &p->p_acflag)))
190 			return (error);
191 		if (cred->cr_uid == 0) {
192 			ip->i_flags = vap->va_flags;
193 		} else {
194 			ip->i_flags &= 0xffff0000;
195 			ip->i_flags |= (vap->va_flags & 0xffff);
196 		}
197 		ip->i_flag |= ICHG;
198 	}
199 	return (error);
200 }
201 
202 /*
203  * Vnode op for reading.
204  */
205 /* ARGSUSED */
206 lfs_read(vp, uio, ioflag, cred)
207 	struct vnode *vp;
208 	register struct uio *uio;
209 	int ioflag;
210 	struct ucred *cred;
211 {
212 	register struct inode *ip = VTOI(vp);
213 	register LFS *fs;					/* LFS */
214 	struct buf *bp;
215 	daddr_t lbn, bn, rablock;
216 	int size, diff, error = 0;
217 	long n, on, type;
218 
219 printf("lfs_read: ino %d\n", ip->i_number);
220 #ifdef DIAGNOSTIC
221 	if (uio->uio_rw != UIO_READ)
222 		panic("ufs_read mode");
223 	type = ip->i_mode & IFMT;
224 	if (type != IFDIR && type != IFREG && type != IFLNK)
225 		panic("ufs_read type");
226 #endif
227 	if (uio->uio_resid == 0)
228 		return (0);
229 	if (uio->uio_offset < 0)
230 		return (EINVAL);
231 	ip->i_flag |= IACC;
232 
233 	fs = ip->i_lfs;						/* LFS */
234 	do {
235 		lbn = lblkno(fs, uio->uio_offset);
236 		on = blkoff(fs, uio->uio_offset);
237 		n = MIN((unsigned)(fs->lfs_bsize - on), uio->uio_resid);
238 		diff = ip->i_size - uio->uio_offset;
239 		if (diff <= 0)
240 			return (0);
241 		if (diff < n)
242 			n = diff;
243 		size = blksize(fs);				/* LFS */
244 		rablock = lbn + 1;
245 		if (vp->v_lastr + 1 == lbn &&
246 		    lblktosize(fs, rablock) < ip->i_size)
247 			error = breada(ITOV(ip), lbn, size, rablock,
248 				blksize(fs), NOCRED, &bp);
249 		else
250 			error = bread(ITOV(ip), lbn, size, NOCRED, &bp);
251 		vp->v_lastr = lbn;
252 		n = MIN(n, size - bp->b_resid);
253 		if (error) {
254 			brelse(bp);
255 			return (error);
256 		}
257 		error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
258 		if (n + on == fs->lfs_bsize || uio->uio_offset == ip->i_size)
259 			bp->b_flags |= B_AGE;
260 		brelse(bp);
261 	} while (error == 0 && uio->uio_resid > 0 && n != 0);
262 	return (error);
263 }
264 
265 /*
266  * Vnode op for writing.
267  */
268 lfs_write(vp, uio, ioflag, cred)
269 	register struct vnode *vp;
270 	struct uio *uio;
271 	int ioflag;
272 	struct ucred *cred;
273 {
274 	struct proc *p = uio->uio_procp;
275 	register struct inode *ip = VTOI(vp);
276 	register LFS *fs;					/* LFS */
277 	struct buf *bp;
278 	daddr_t lbn, bn;
279 	u_long osize;
280 	int n, on, flags;
281 	int size, resid, error = 0;
282 
283 printf("lfs_write ino %d\n", ip->i_number);
284 #ifdef DIAGNOSTIC
285 	if (uio->uio_rw != UIO_WRITE)
286 		panic("ufs_write mode");
287 #endif
288 	switch (vp->v_type) {
289 	case VREG:
290 		if (ioflag & IO_APPEND)
291 			uio->uio_offset = ip->i_size;
292 		/* fall through */
293 	case VLNK:
294 		break;
295 
296 	case VDIR:
297 		if ((ioflag & IO_SYNC) == 0)
298 			panic("ufs_write nonsync dir write");
299 		break;
300 
301 	default:
302 		panic("ufs_write type");
303 	}
304 	if (uio->uio_offset < 0)
305 		return (EINVAL);
306 	if (uio->uio_resid == 0)
307 		return (0);
308 	/*
309 	 * Maybe this should be above the vnode op call, but so long as
310 	 * file servers have no limits, i don't think it matters
311 	 */
312 	if (vp->v_type == VREG && p &&
313 	    uio->uio_offset + uio->uio_resid >
314 	      p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
315 		psignal(p, SIGXFSZ);
316 		return (EFBIG);
317 	}
318 	resid = uio->uio_resid;
319 	osize = ip->i_size;
320 	fs = ip->i_lfs;						/* LFS */
321 	flags = 0;
322 #ifdef NOTLFS
323 	if (ioflag & IO_SYNC)
324 		flags = B_SYNC;
325 #endif
326 	do {
327 		lbn = lblkno(fs, uio->uio_offset);
328 		on = blkoff(fs, uio->uio_offset);		/* LFS */
329 		n = MIN((unsigned)(fs->lfs_bsize - on), uio->uio_resid);
330 		if (n < fs->lfs_bsize)				/* LFS */
331 			flags |= B_CLRBUF;
332 		else
333 			flags &= ~B_CLRBUF;			/* LFS */
334 		if (error = bread(vp, lbn, fs->lfs_bsize, NOCRED, &bp))
335 			break;
336 		bn = bp->b_blkno;
337 		if (uio->uio_offset + n > ip->i_size) {
338 			ip->i_size = uio->uio_offset + n;
339 			vnode_pager_setsize(vp, ip->i_size);
340 		}
341 		size = blksize(fs);
342 		(void) vnode_pager_uncache(vp);
343 		n = MIN(n, size - bp->b_resid);
344 		error = uiomove(bp->b_un.b_addr + on, n, uio);
345 #ifdef NOTLFS							/* LFS */
346 		if (ioflag & IO_SYNC)
347 			(void) bwrite(bp);
348 		else if (n + on == fs->fs_bsize) {
349 			bp->b_flags |= B_AGE;
350 			bawrite(bp);
351 		} else
352 			bdwrite(bp);
353 #else
354 		/*
355 		 * Update segment usage information; call segment
356 		 * writer if necessary.
357 		 */
358 		lfs_bwrite(bp);
359 #endif
360 		ip->i_flag |= IUPD|ICHG;
361 		if (cred->cr_uid != 0)
362 			ip->i_mode &= ~(ISUID|ISGID);
363 	} while (error == 0 && uio->uio_resid > 0 && n != 0);
364 	if (error && (ioflag & IO_UNIT)) {
365 #ifdef NOTLFS
366 	/* This just doesn't work... */
367 		(void) lfs_itrunc(ip, osize, ioflag & IO_SYNC);
368 #endif
369 		uio->uio_offset -= resid - uio->uio_resid;
370 		uio->uio_resid = resid;
371 	}
372 	if (!error && (ioflag & IO_SYNC))
373 		ITIMES(ip, &time, &time);			/* LFS */
374 	return (error);
375 }
376 
377 /*
378  * Synch an open file.
379  */
380 /* ARGSUSED */
381 lfs_fsync(vp, fflags, cred, waitfor, p)
382 	struct vnode *vp;
383 	int fflags;
384 	struct ucred *cred;
385 	int waitfor;
386 	struct proc *p;
387 {
388 	struct inode *ip = VTOI(vp);
389 
390 printf("lfs_sync: ino %d\n", ip->i_number);
391 	if (fflags & FWRITE)
392 		ip->i_flag |= ICHG;
393 	ITIMES(ip, &time, &time);				/* LFS */
394 	vflushbuf(vp, waitfor == MNT_WAIT ? B_SYNC : 0);	/* LFS */
395 	return (0);
396 }
397 
398 /*
399  * ufs remove
400  * Hard to avoid races here, especially
401  * in unlinking directories.
402  */
403 lfs_remove(ndp, p)
404 	struct nameidata *ndp;
405 	struct proc *p;
406 {
407 	register struct inode *ip, *dp;
408 	int error;
409 
410 printf("lfs_remove\n");
411 	ip = VTOI(ndp->ni_vp);
412 	dp = VTOI(ndp->ni_dvp);
413 	error = lfs_dirremove(ndp);				/* LFS */
414 	if (!error) {
415 		ip->i_nlink--;
416 		ip->i_flag |= ICHG;
417 	}
418 	if (dp == ip)
419 		vrele(ITOV(ip));
420 	else
421 		iput(ip);
422 	iput(dp);
423 	return (error);
424 }
425 /*
426  * link vnode call
427  */
428 lfs_link(vp, ndp, p)
429 	register struct vnode *vp;
430 	register struct nameidata *ndp;
431 	struct proc *p;
432 {
433 	register struct inode *ip = VTOI(vp);
434 	int error;
435 
436 printf("lfs_link\n");
437 #ifdef DIANOSTIC
438 	if ((ndp->ni_nameiop & HASBUF) == 0)
439 		panic("ufs_link: no name");
440 #endif
441 	if ((unsigned short)ip->i_nlink >= LINK_MAX) {
442 		free(ndp->ni_pnbuf, M_NAMEI);
443 		return (EMLINK);
444 	}
445 	if (ndp->ni_dvp != vp)
446 		ILOCK(ip);
447 	ip->i_nlink++;
448 	ip->i_flag |= ICHG;
449 	ITIMES(ip, &time, &time);				/* LFS */
450 	error = lfs_direnter(ip, ndp);				/* LFS */
451 	if (ndp->ni_dvp != vp)
452 		IUNLOCK(ip);
453 	FREE(ndp->ni_pnbuf, M_NAMEI);
454 	vput(ndp->ni_dvp);
455 	if (error) {
456 		ip->i_nlink--;
457 		ip->i_flag |= ICHG;
458 	}
459 	return (error);
460 }
461 
462 /*
463  * Rename system call.
464  * 	rename("foo", "bar");
465  * is essentially
466  *	unlink("bar");
467  *	link("foo", "bar");
468  *	unlink("foo");
469  * but ``atomically''.  Can't do full commit without saving state in the
470  * inode on disk which isn't feasible at this time.  Best we can do is
471  * always guarantee the target exists.
472  *
473  * Basic algorithm is:
474  *
475  * 1) Bump link count on source while we're linking it to the
476  *    target.  This also ensure the inode won't be deleted out
477  *    from underneath us while we work (it may be truncated by
478  *    a concurrent `trunc' or `open' for creation).
479  * 2) Link source to destination.  If destination already exists,
480  *    delete it first.
481  * 3) Unlink source reference to inode if still around. If a
482  *    directory was moved and the parent of the destination
483  *    is different from the source, patch the ".." entry in the
484  *    directory.
485  */
486 lfs_rename(fndp, tndp, p)
487 	register struct nameidata *fndp, *tndp;
488 	struct proc *p;
489 {
490 	register struct inode *ip, *xp, *dp;
491 	struct dirtemplate dirbuf;
492 	int doingdirectory = 0, oldparent = 0, newparent = 0;
493 	int error = 0;
494 
495 printf("lfs_rename\n");
496 #ifdef DIANOSTIC
497 	if ((tndp->ni_nameiop & HASBUF) == 0 ||
498 	    (fndp->ni_nameiop & HASBUF) == 0)
499 		panic("ufs_rename: no name");
500 #endif
501 	dp = VTOI(fndp->ni_dvp);
502 	ip = VTOI(fndp->ni_vp);
503 	/*
504 	 * Check if just deleting a link name.
505 	 */
506 	if (fndp->ni_vp == tndp->ni_vp) {
507 		VOP_ABORTOP(tndp);
508 		vput(tndp->ni_dvp);
509 		vput(tndp->ni_vp);
510 		vrele(fndp->ni_dvp);
511 		if ((ip->i_mode&IFMT) == IFDIR) {
512 			VOP_ABORTOP(fndp);
513 			vrele(fndp->ni_vp);
514 			return (EINVAL);
515 		}
516 		doingdirectory = 0;
517 		goto unlinkit;
518 	}
519 	ILOCK(ip);
520 	if ((ip->i_mode&IFMT) == IFDIR) {
521 		/*
522 		 * Avoid ".", "..", and aliases of "." for obvious reasons.
523 		 */
524 		if ((fndp->ni_namelen == 1 && fndp->ni_ptr[0] == '.') ||
525 		    dp == ip || fndp->ni_isdotdot || (ip->i_flag & IRENAME)) {
526 			VOP_ABORTOP(tndp);
527 			vput(tndp->ni_dvp);
528 			if (tndp->ni_vp)
529 				vput(tndp->ni_vp);
530 			VOP_ABORTOP(fndp);
531 			vrele(fndp->ni_dvp);
532 			vput(fndp->ni_vp);
533 			return (EINVAL);
534 		}
535 		ip->i_flag |= IRENAME;
536 		oldparent = dp->i_number;
537 		doingdirectory++;
538 	}
539 	vrele(fndp->ni_dvp);
540 
541 	/*
542 	 * 1) Bump link count while we're moving stuff
543 	 *    around.  If we crash somewhere before
544 	 *    completing our work, the link count
545 	 *    may be wrong, but correctable.
546 	 */
547 	ip->i_nlink++;
548 	ip->i_flag |= ICHG;
549 	ITIMES(ip, &time, &time);				/* LFS */
550 	IUNLOCK(ip);
551 
552 	/*
553 	 * When the target exists, both the directory
554 	 * and target vnodes are returned locked.
555 	 */
556 	dp = VTOI(tndp->ni_dvp);
557 	xp = NULL;
558 	if (tndp->ni_vp)
559 		xp = VTOI(tndp->ni_vp);
560 	/*
561 	 * If ".." must be changed (ie the directory gets a new
562 	 * parent) then the source directory must not be in the
563 	 * directory heirarchy above the target, as this would
564 	 * orphan everything below the source directory. Also
565 	 * the user must have write permission in the source so
566 	 * as to be able to change "..". We must repeat the call
567 	 * to namei, as the parent directory is unlocked by the
568 	 * call to checkpath().
569 	 */
570 	if (oldparent != dp->i_number)
571 		newparent = dp->i_number;
572 	if (doingdirectory && newparent) {
573 		VOP_LOCK(fndp->ni_vp);
574 		error = ufs_access(fndp->ni_vp, VWRITE, tndp->ni_cred, p);
575 		VOP_UNLOCK(fndp->ni_vp);
576 		if (error)
577 			goto bad;
578 		if (xp != NULL)
579 			iput(xp);				/* LFS */
580 		if (error = lfs_checkpath(ip, dp, tndp->ni_cred))
581 			goto out;
582 		if ((tndp->ni_nameiop & SAVESTART) == 0)
583 			panic("ufs_rename: lost to startdir");
584 		if (error = lookup(tndp, p))
585 			goto out;
586 		dp = VTOI(tndp->ni_dvp);
587 		xp = NULL;
588 		if (tndp->ni_vp)
589 			xp = VTOI(tndp->ni_vp);
590 	}
591 	/*
592 	 * 2) If target doesn't exist, link the target
593 	 *    to the source and unlink the source.
594 	 *    Otherwise, rewrite the target directory
595 	 *    entry to reference the source inode and
596 	 *    expunge the original entry's existence.
597 	 */
598 	if (xp == NULL) {
599 		if (dp->i_dev != ip->i_dev)
600 			panic("rename: EXDEV");
601 		/*
602 		 * Account for ".." in new directory.
603 		 * When source and destination have the same
604 		 * parent we don't fool with the link count.
605 		 */
606 		if (doingdirectory && newparent) {
607 			if ((unsigned short)dp->i_nlink >= LINK_MAX) {
608 				error = EMLINK;
609 				goto bad;
610 			}
611 			dp->i_nlink++;
612 			dp->i_flag |= ICHG;			/* LFS */
613 			ITIMES(dp, &time, &time);		/* LFS */
614 		}
615 		if (error = lfs_direnter(ip, tndp)) {
616 			if (doingdirectory && newparent) {
617 				dp->i_nlink--;
618 				dp->i_flag |= ICHG;		/* LFS */
619 				ITIMES(dp, &time, &time);	/* LFS */
620 			}
621 			goto bad;
622 		}
623 		iput(dp);
624 	} else {
625 		if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev)
626 			panic("rename: EXDEV");
627 		/*
628 		 * Short circuit rename(foo, foo).
629 		 */
630 		if (xp->i_number == ip->i_number)
631 			panic("rename: same file");
632 		/*
633 		 * If the parent directory is "sticky", then the user must
634 		 * own the parent directory, or the destination of the rename,
635 		 * otherwise the destination may not be changed (except by
636 		 * root). This implements append-only directories.
637 		 */
638 		if ((dp->i_mode & ISVTX) && tndp->ni_cred->cr_uid != 0 &&
639 		    tndp->ni_cred->cr_uid != dp->i_uid &&
640 		    xp->i_uid != tndp->ni_cred->cr_uid) {
641 			error = EPERM;
642 			goto bad;
643 		}
644 		/*
645 		 * Target must be empty if a directory and have no links
646 		 * to it. Also, ensure source and target are compatible
647 		 * (both directories, or both not directories).
648 		 */
649 		if ((xp->i_mode&IFMT) == IFDIR) {
650 			if (!dirempty(xp, dp->i_number, tndp->ni_cred) ||
651 			    xp->i_nlink > 2) {
652 				error = ENOTEMPTY;
653 				goto bad;
654 			}
655 			if (!doingdirectory) {
656 				error = ENOTDIR;
657 				goto bad;
658 			}
659 			cache_purge(ITOV(dp));
660 		} else if (doingdirectory) {
661 			error = EISDIR;
662 			goto bad;
663 		}
664 		if (error = dirrewrite(dp, ip, tndp))
665 			goto bad;
666 		/*
667 		 * If the target directory is in the same
668 		 * directory as the source directory,
669 		 * decrement the link count on the parent
670 		 * of the target directory.
671 		 */
672 		 if (doingdirectory && !newparent) {
673 			dp->i_nlink--;
674 			dp->i_flag |= ICHG;
675 		}
676 		vput(ITOV(dp));
677 		/*
678 		 * Adjust the link count of the target to
679 		 * reflect the dirrewrite above.  If this is
680 		 * a directory it is empty and there are
681 		 * no links to it, so we can squash the inode and
682 		 * any space associated with it.  We disallowed
683 		 * renaming over top of a directory with links to
684 		 * it above, as the remaining link would point to
685 		 * a directory without "." or ".." entries.
686 		 */
687 		xp->i_nlink--;
688 		if (doingdirectory) {
689 			if (--xp->i_nlink != 0)			/* LFS */
690 				panic("rename: linked directory");
691 			error = lfs_itrunc(xp, (u_long)0, IO_SYNC);
692 		}
693 		xp->i_flag |= ICHG;
694 		iput(xp);
695 		xp = NULL;
696 	}
697 
698 	/*
699 	 * 3) Unlink the source.
700 	 */
701 unlinkit:
702 	fndp->ni_nameiop &= ~MODMASK;
703 	fndp->ni_nameiop |= LOCKPARENT | LOCKLEAF;
704 	if ((fndp->ni_nameiop & SAVESTART) == 0)
705 		panic("ufs_rename: lost from startdir");
706 	(void) lookup(fndp, p);
707 	if (fndp->ni_vp != NULL) {
708 		xp = VTOI(fndp->ni_vp);
709 		dp = VTOI(fndp->ni_dvp);
710 	} else {
711 		/*
712 		 * From name has disappeared.
713 		 */
714 		if (doingdirectory)
715 			panic("rename: lost dir entry");
716 		vrele(ITOV(ip));
717 		return (0);
718 	}
719 	/*
720 	 * Ensure that the directory entry still exists and has not
721 	 * changed while the new name has been entered. If the source is
722 	 * a file then the entry may have been unlinked or renamed. In
723 	 * either case there is no further work to be done. If the source
724 	 * is a directory then it cannot have been rmdir'ed; its link
725 	 * count of three would cause a rmdir to fail with ENOTEMPTY.
726 	 * The IRENAME flag ensures that it cannot be moved by another
727 	 * rename.
728 	 */
729 	if (xp != ip) {
730 		if (doingdirectory)
731 			panic("rename: lost dir entry");
732 	} else {
733 		/*
734 		 * If the source is a directory with a
735 		 * new parent, the link count of the old
736 		 * parent directory must be decremented
737 		 * and ".." set to point to the new parent.
738 		 */
739 		if (doingdirectory && newparent) {
740 			dp->i_nlink--;
741 			dp->i_flag |= ICHG;
742 			error = vn_rdwr(UIO_READ, ITOV(xp), (caddr_t)&dirbuf,
743 				sizeof (struct dirtemplate), (off_t)0,
744 				UIO_SYSSPACE, IO_NODELOCKED,
745 				tndp->ni_cred, (int *)0, (struct proc *)0);
746 			if (error == 0) {
747 				if (dirbuf.dotdot_namlen != 2 ||
748 				    dirbuf.dotdot_name[0] != '.' ||
749 				    dirbuf.dotdot_name[1] != '.') {
750 					lfs_dirbad(xp, 12,
751 					    "rename: mangled dir");
752 				} else {
753 					dirbuf.dotdot_ino = newparent;
754 					(void) vn_rdwr(UIO_WRITE, ITOV(xp),
755 					    (caddr_t)&dirbuf,
756 					    sizeof (struct dirtemplate),
757 					    (off_t)0, UIO_SYSSPACE,
758 					    IO_NODELOCKED|IO_SYNC,
759 					    tndp->ni_cred, (int *)0,
760 					    (struct proc *)0);
761 					cache_purge(ITOV(dp));
762 				}
763 			}
764 		}
765 		error = lfs_dirremove(fndp);			/* LFS */
766 		if (!error) {
767 			xp->i_nlink--;
768 			xp->i_flag |= ICHG;
769 		}
770 		xp->i_flag &= ~IRENAME;
771 	}
772 	if (dp)
773 		vput(ITOV(dp));
774 	if (xp)
775 		vput(ITOV(xp));
776 	vrele(ITOV(ip));
777 	return (error);
778 
779 bad:
780 	if (xp)
781 		vput(ITOV(xp));
782 	vput(ITOV(dp));
783 out:
784 	ip->i_nlink--;
785 	ip->i_flag |= ICHG;
786 	vrele(ITOV(ip));
787 	return (error);
788 }
789 
790 /*
791  * A virgin directory (no blushing please).
792  */
793 static struct dirtemplate mastertemplate = {
794 	0, 12, 1, ".",
795 	0, DIRBLKSIZ - 12, 2, ".."
796 };
797 
798 /*
799  * Mkdir system call
800  */
801 lfs_mkdir(ndp, vap, p)
802 	struct nameidata *ndp;
803 	struct vattr *vap;
804 	struct proc *p;
805 {
806 	register struct inode *ip, *dp;
807 	struct inode *tip;
808 	struct vnode *dvp;
809 	struct dirtemplate dirtemplate;
810 	int error;
811 	int dmode;
812 
813 printf("lfs_mkdir\n");
814 #ifdef DIANOSTIC
815 	if ((ndp->ni_nameiop & HASBUF) == 0)
816 		panic("ufs_mkdir: no name");
817 #endif
818 	dvp = ndp->ni_dvp;
819 	dp = VTOI(dvp);
820 	if ((unsigned short)dp->i_nlink >= LINK_MAX) {
821 		free(ndp->ni_pnbuf, M_NAMEI);
822 		iput(dp);
823 		return (EMLINK);
824 	}
825 	dmode = vap->va_mode&0777;
826 	dmode |= IFDIR;
827 	/*
828 	 * Must simulate part of maknode here to acquire the inode, but
829 	 * not have it entered in the parent directory. The entry is made
830 	 * later after writing "." and ".." entries.
831 	 */
832 #ifdef NOTLFS							/* LFS */
833 	if (error = ialloc(dp, dirpref(dp->i_fs), dmode, ndp->ni_cred, &tip)) {
834 #else
835 	if (error = lfs_ialloc(dp->i_lfs, dp, &tip, ndp->ni_cred)) {
836 #endif
837 		free(ndp->ni_pnbuf, M_NAMEI);
838 		iput(dp);
839 		return (error);
840 	}
841 	ip = tip;
842 	ip->i_uid = ndp->ni_cred->cr_uid;
843 	ip->i_gid = dp->i_gid;
844 #ifdef QUOTA
845 	if ((error = getinoquota(ip)) ||
846 	    (error = chkiq(ip, 1, ndp->ni_cred, 0))) {
847 		free(ndp->ni_pnbuf, M_NAMEI);
848 #ifdef NOTLFS							/* LFS */
849 		ifree(ip, ip->i_number, dmode);
850 #else
851 		lfs_ifree(ip);
852 #endif
853 		iput(ip);
854 		iput(dp);
855 		return (error);
856 	}
857 #endif
858 	ip->i_flag |= IACC|IUPD|ICHG;
859 	ip->i_mode = dmode;
860 	ITOV(ip)->v_type = VDIR;	/* Rest init'd in iget() */
861 	ip->i_nlink = 2;
862 	ITIMES(ip, &time, &time);				/* LFS */
863 
864 	/*
865 	 * Bump link count in parent directory
866 	 * to reflect work done below.  Should
867 	 * be done before reference is created
868 	 * so reparation is possible if we crash.
869 	 */
870 	dp->i_nlink++;
871 	dp->i_flag |= ICHG;
872 	ITIMES(dp, &time, &time);				/* LFS */
873 
874 	/*
875 	 * Initialize directory with "."
876 	 * and ".." from static template.
877 	 */
878 	dirtemplate = mastertemplate;
879 	dirtemplate.dot_ino = ip->i_number;
880 	dirtemplate.dotdot_ino = dp->i_number;
881 	error = vn_rdwr(UIO_WRITE, ITOV(ip), (caddr_t)&dirtemplate,
882 	    sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE,
883 	    IO_NODELOCKED|IO_SYNC, ndp->ni_cred, (int *)0, (struct proc *)0);
884 	if (error) {
885 		dp->i_nlink--;
886 		dp->i_flag |= ICHG;
887 		goto bad;
888 	}
889 	if (DIRBLKSIZ > dp->i_lfs->lfs_fsize) {
890 		panic("mkdir: blksize");     /* XXX - should grow w/balloc() */
891 	} else {
892 		ip->i_size = DIRBLKSIZ;
893 		ip->i_flag |= ICHG;
894 	}
895 	/*
896 	 * Directory all set up, now
897 	 * install the entry for it in
898 	 * the parent directory.
899 	 */
900 	if (error = lfs_direnter(ip, ndp)) {			/* LFS */
901 		dp->i_nlink--;
902 		dp->i_flag |= ICHG;
903 	}
904 bad:
905 	/*
906 	 * No need to do an explicit lfs_itrunc here,
907 	 * vrele will do this for us because we set
908 	 * the link count to 0.
909 	 */
910 	if (error) {
911 		ip->i_nlink = 0;
912 		ip->i_flag |= ICHG;
913 		iput(ip);
914 	} else
915 		ndp->ni_vp = ITOV(ip);
916 	FREE(ndp->ni_pnbuf, M_NAMEI);
917 	iput(dp);
918 	return (error);
919 }
920 
921 /*
922  * Rmdir system call.
923  */
924 lfs_rmdir(ndp, p)
925 	register struct nameidata *ndp;
926 	struct proc *p;
927 {
928 	register struct inode *ip, *dp;
929 	int error = 0;
930 
931 printf("lfs_rmdir\n");
932 	ip = VTOI(ndp->ni_vp);
933 	dp = VTOI(ndp->ni_dvp);
934 	/*
935 	 * No rmdir "." please.
936 	 */
937 	if (dp == ip) {
938 		vrele(ITOV(dp));
939 		iput(ip);
940 		return (EINVAL);
941 	}
942 	/*
943 	 * Verify the directory is empty (and valid).
944 	 * (Rmdir ".." won't be valid since
945 	 *  ".." will contain a reference to
946 	 *  the current directory and thus be
947 	 *  non-empty.)
948 	 */
949 	if (ip->i_nlink != 2 || !dirempty(ip, dp->i_number, ndp->ni_cred)) {
950 		error = ENOTEMPTY;
951 		goto out;
952 	}
953 	/*
954 	 * Delete reference to directory before purging
955 	 * inode.  If we crash in between, the directory
956 	 * will be reattached to lost+found,
957 	 */
958 	if (error = lfs_dirremove(ndp))				/* LFS */
959 		goto out;
960 	dp->i_nlink--;
961 	dp->i_flag |= ICHG;
962 	cache_purge(ITOV(dp));
963 	iput(dp);
964 	ndp->ni_dvp = NULL;
965 	/*
966 	 * Truncate inode.  The only stuff left
967 	 * in the directory is "." and "..".  The
968 	 * "." reference is inconsequential since
969 	 * we're quashing it.  The ".." reference
970 	 * has already been adjusted above.  We've
971 	 * removed the "." reference and the reference
972 	 * in the parent directory, but there may be
973 	 * other hard links so decrement by 2 and
974 	 * worry about them later.
975 	 */
976 	ip->i_nlink -= 2;
977 	error = lfs_itrunc(ip, (u_long)0, IO_SYNC);		/* LFS */
978 	cache_purge(ITOV(ip));
979 out:
980 	if (ndp->ni_dvp)
981 		iput(dp);
982 	iput(ip);
983 	return (error);
984 }
985 
986 /*
987  * symlink -- make a symbolic link
988  */
989 lfs_symlink(ndp, vap, target, p)
990 	struct nameidata *ndp;
991 	struct vattr *vap;
992 	char *target;
993 	struct proc *p;
994 {
995 	struct inode *ip;
996 	int error;
997 
998 printf("lfs_symlink\n");
999 	error = maknode(IFLNK | vap->va_mode, ndp, &ip);
1000 	if (error)
1001 		return (error);
1002 	error = vn_rdwr(UIO_WRITE, ITOV(ip), target, strlen(target), (off_t)0,
1003 		UIO_SYSSPACE, IO_NODELOCKED, ndp->ni_cred, (int *)0,
1004 		(struct proc *)0);
1005 	iput(ip);
1006 	return (error);
1007 }
1008 
1009 /*
1010  * Vnode op for read and write
1011  */
1012 lfs_readdir(vp, uio, cred, eofflagp)
1013 	struct vnode *vp;
1014 	register struct uio *uio;
1015 	struct ucred *cred;
1016 	int *eofflagp;
1017 {
1018 	int count, lost, error;
1019 
1020 printf("lfs_readdir\n");
1021 	count = uio->uio_resid;
1022 	count &= ~(DIRBLKSIZ - 1);
1023 	lost = uio->uio_resid - count;
1024 	if (count < DIRBLKSIZ || (uio->uio_offset & (DIRBLKSIZ -1)))
1025 		return (EINVAL);
1026 	uio->uio_resid = count;
1027 	uio->uio_iov->iov_len = count;
1028 	error = lfs_read(vp, uio, 0, cred);			/* LFS */
1029 	uio->uio_resid += lost;
1030 	if ((VTOI(vp)->i_size - uio->uio_offset) <= 0)
1031 		*eofflagp = 1;
1032 	else
1033 		*eofflagp = 0;
1034 	return (error);
1035 }
1036 
1037 /*
1038  * Return target name of a symbolic link
1039  */
1040 lfs_readlink(vp, uiop, cred)
1041 	struct vnode *vp;
1042 	struct uio *uiop;
1043 	struct ucred *cred;
1044 {
1045 
1046 printf("lfs_readlink\n");
1047 	return (lfs_read(vp, uiop, 0, cred));			/* LFS */
1048 }
1049 
1050 /*
1051  * Get access to bmap
1052  */
1053 lfs_vbmap(vp, bn, vpp, bnp)
1054 	struct vnode *vp;
1055 	daddr_t bn;
1056 	struct vnode **vpp;
1057 	daddr_t *bnp;
1058 {
1059 	struct inode *ip = VTOI(vp);
1060 
1061 printf("lfs_vbmap\n");
1062 	if (vpp != NULL)
1063 		*vpp = ip->i_devvp;
1064 	if (bnp == NULL)
1065 		return (0);
1066 	return (lfs_bmap(ip, bn, bnp));				/* LFS */
1067 }
1068 
1069 /*
1070  * Calculate the logical to physical mapping if not done already,
1071  * then call the device strategy routine.
1072  */
1073 lfs_strategy(bp)
1074 	register struct buf *bp;
1075 {
1076 	register struct inode *ip = VTOI(bp->b_vp);
1077 	struct vnode *vp;
1078 	int error;
1079 
1080 printf("lfs_strategy: type: %d lblk %d pblk %d\n", bp->b_vp->v_type,
1081 	bp->b_lblkno, bp->b_blkno);
1082 	if (bp->b_vp->v_type == VBLK || bp->b_vp->v_type == VCHR)
1083 		panic("ufs_strategy: spec");
1084 	if (bp->b_blkno == bp->b_lblkno) {			/* LFS */
1085 		if (error = lfs_bmap(ip, bp->b_lblkno, &bp->b_blkno))
1086 			return (error);
1087 		if ((long)bp->b_blkno == -1)
1088 			clrbuf(bp);
1089 	}
1090 	if ((long)bp->b_blkno == -1) {
1091 		biodone(bp);
1092 		return (0);
1093 	}
1094 	vp = ip->i_devvp;
1095 	bp->b_dev = vp->v_rdev;
1096 	(*(vp->v_op->vop_strategy))(bp);
1097 	return (0);
1098 }
1099 
1100 /*
1101  * Allocate a new inode.
1102  */
1103 static int
1104 maknode(mode, ndp, ipp)
1105 	int mode;
1106 	register struct nameidata *ndp;
1107 	struct inode **ipp;
1108 {
1109 	register struct inode *ip;
1110 	struct inode *tip;
1111 	register struct inode *pdir = VTOI(ndp->ni_dvp);
1112 	ino_t ipref;
1113 	int error;
1114 
1115 printf("maknode\n");
1116 #ifdef DIANOSTIC
1117 	if ((ndp->ni_nameiop & HASBUF) == 0)
1118 		panic("maknode: no name");
1119 #endif
1120 	*ipp = 0;
1121 	if ((mode & IFMT) == 0)
1122 		mode |= IFREG;
1123 #ifdef NOTLFS							/* LFS */
1124 	if ((mode & IFMT) == IFDIR)
1125 		ipref = dirpref(pdir->i_fs);
1126 	else
1127 		ipref = pdir->i_number;
1128 	if (error = ialloc(pdir, ipref, mode, ndp->ni_cred, &tip)) {
1129 #else
1130 	if (error = lfs_ialloc(pdir->i_lfs, pdir, &tip, ndp->ni_cred)) {
1131 #endif
1132 		free(ndp->ni_pnbuf, M_NAMEI);
1133 		iput(pdir);
1134 		return (error);
1135 	}
1136 	ip = tip;
1137 	ip->i_uid = ndp->ni_cred->cr_uid;
1138 	ip->i_gid = pdir->i_gid;
1139 #ifdef QUOTA
1140 	if ((error = getinoquota(ip)) ||
1141 	    (error = chkiq(ip, 1, ndp->ni_cred, 0))) {
1142 		free(ndp->ni_pnbuf, M_NAMEI);
1143 #ifdef NOTLFS							/* LFS */
1144 		ifree(ip, ip->i_number, mode);
1145 #else
1146 		lfs_ifree(ip);
1147 #endif
1148 		iput(ip);
1149 		iput(pdir);
1150 		return (error);
1151 	}
1152 #endif
1153 	ip->i_flag |= IACC|IUPD|ICHG;
1154 	ip->i_mode = mode;
1155 	ITOV(ip)->v_type = IFTOVT(mode);	/* Rest init'd in iget() */
1156 	ip->i_nlink = 1;
1157 	if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, ndp->ni_cred) &&
1158 	    suser(ndp->ni_cred, NULL))
1159 		ip->i_mode &= ~ISGID;
1160 
1161 	ITIMES(ip, &time, &time);				/* LFS */
1162 	if (error = lfs_direnter(ip, ndp))			/* LFS */
1163 		goto bad;
1164 	if ((ndp->ni_nameiop & SAVESTART) == 0)
1165 		FREE(ndp->ni_pnbuf, M_NAMEI);
1166 	iput(pdir);
1167 	*ipp = ip;
1168 	return (0);
1169 
1170 bad:
1171 	/*
1172 	 * Write error occurred trying to update the inode
1173 	 * or the directory so must deallocate the inode.
1174 	 */
1175 	free(ndp->ni_pnbuf, M_NAMEI);
1176 	iput(pdir);
1177 	ip->i_nlink = 0;
1178 	ip->i_flag |= ICHG;
1179 	iput(ip);
1180 	return (error);
1181 }
1182 
1183 /*
1184  * Global vfs data structures for lfs
1185  */
1186 struct vnodeops lfs_vnodeops = {
1187 	lfs_lookup,		/* lookup */
1188 	lfs_create,		/* create */
1189 	lfs_mknod,		/* mknod */
1190 	ufs_open,		/* open */
1191 	ufs_close,		/* close */
1192 	ufs_access,		/* access */
1193 	lfs_getattr,		/* getattr */
1194 	lfs_setattr,		/* setattr */
1195 	lfs_read,		/* read */
1196 	lfs_write,		/* write */
1197 	ufs_ioctl,		/* ioctl */
1198 	ufs_select,		/* select */
1199 	ufs_mmap,		/* mmap */
1200 	lfs_fsync,		/* fsync */
1201 	ufs_seek,		/* seek */
1202 	lfs_remove,		/* remove */
1203 	lfs_link,		/* link */
1204 	lfs_rename,		/* rename */
1205 	lfs_mkdir,		/* mkdir */
1206 	lfs_rmdir,		/* rmdir */
1207 	lfs_symlink,		/* symlink */
1208 	lfs_readdir,		/* readdir */
1209 	lfs_readlink,		/* readlink */
1210 	ufs_abortop,		/* abortop */
1211 	lfs_inactive,		/* inactive */
1212 	ufs_reclaim,		/* reclaim */
1213 	ufs_lock,		/* lock */
1214 	ufs_unlock,		/* unlock */
1215 	lfs_vbmap,		/* bmap */
1216 	lfs_strategy,		/* strategy */
1217 	ufs_print,		/* print */
1218 	ufs_islocked,		/* islocked */
1219 	ufs_advlock,		/* advlock */
1220 };
1221