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