xref: /csrg-svn/sys/ufs/lfs/lfs_vnops.c (revision 51155)
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.66 (Berkeley) 09/20/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);
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 		if (error = lfs_iupdat(ip, &vap->va_atime, &vap->va_mtime, 1))
184 			return (error);
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 struct fs *fs;
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 #ifdef NOTLFS							/* LFS */
322 	fs = ip->i_fs;
323 	flags = 0;
324 	if (ioflag & IO_SYNC)
325 		flags = B_SYNC;
326 	do {
327 		lbn = lblkno(fs, uio->uio_offset);
328 		on = blkoff(fs, uio->uio_offset);
329 		n = MIN((unsigned)(fs->fs_bsize - on), uio->uio_resid);
330 		if (n < fs->fs_bsize)
331 			flags |= B_CLRBUF;
332 		else
333 			flags &= ~B_CLRBUF;
334 		if (error = balloc(ip, lbn, (int)(on + n), &bp, flags))
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, ip, lbn);
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 		if (ioflag & IO_SYNC)
346 			(void) bwrite(bp);
347 		else if (n + on == fs->fs_bsize) {
348 			bp->b_flags |= B_AGE;
349 			bawrite(bp);
350 		} else
351 			bdwrite(bp);
352 		ip->i_flag |= IUPD|ICHG;
353 		if (cred->cr_uid != 0)
354 			ip->i_mode &= ~(ISUID|ISGID);
355 	} while (error == 0 && uio->uio_resid > 0 && n != 0);
356 #else
357 	/* LFS IMPLEMENT -- write call */
358 	panic("lfs_write not implemented");
359 #endif
360 	if (error && (ioflag & IO_UNIT)) {
361 		(void) lfs_itrunc(ip, osize, ioflag & IO_SYNC);
362 		uio->uio_offset -= resid - uio->uio_resid;
363 		uio->uio_resid = resid;
364 	}
365 	if (!error && (ioflag & IO_SYNC))
366 		error = lfs_iupdat(ip, &time, &time, 1);
367 	return (error);
368 }
369 
370 /*
371  * Synch an open file.
372  */
373 /* ARGSUSED */
374 lfs_fsync(vp, fflags, cred, waitfor, p)
375 	struct vnode *vp;
376 	int fflags;
377 	struct ucred *cred;
378 	int waitfor;
379 	struct proc *p;
380 {
381 	struct inode *ip = VTOI(vp);
382 
383 printf("lfs_sync: ino %d\n", ip->i_number);
384 	if (fflags & FWRITE)
385 		ip->i_flag |= ICHG;
386 	vflushbuf(vp, waitfor == MNT_WAIT ? B_SYNC : 0);	/* LFS */
387 	return (lfs_iupdat(ip, &time, &time, waitfor == MNT_WAIT));
388 }
389 
390 /*
391  * ufs remove
392  * Hard to avoid races here, especially
393  * in unlinking directories.
394  */
395 lfs_remove(ndp, p)
396 	struct nameidata *ndp;
397 	struct proc *p;
398 {
399 	register struct inode *ip, *dp;
400 	int error;
401 
402 printf("lfs_remove\n");
403 	ip = VTOI(ndp->ni_vp);
404 	dp = VTOI(ndp->ni_dvp);
405 	error = lfs_dirremove(ndp);				/* LFS */
406 	if (!error) {
407 		ip->i_nlink--;
408 		ip->i_flag |= ICHG;
409 	}
410 	if (dp == ip)
411 		vrele(ITOV(ip));
412 	else
413 		iput(ip);
414 	iput(dp);
415 	return (error);
416 }
417 /*
418  * link vnode call
419  */
420 lfs_link(vp, ndp, p)
421 	register struct vnode *vp;
422 	register struct nameidata *ndp;
423 	struct proc *p;
424 {
425 	register struct inode *ip = VTOI(vp);
426 	int error;
427 
428 printf("lfs_link\n");
429 #ifdef DIANOSTIC
430 	if ((ndp->ni_nameiop & HASBUF) == 0)
431 		panic("ufs_link: no name");
432 #endif
433 	if ((unsigned short)ip->i_nlink >= LINK_MAX) {
434 		free(ndp->ni_pnbuf, M_NAMEI);
435 		return (EMLINK);
436 	}
437 	if (ndp->ni_dvp != vp)
438 		ILOCK(ip);
439 	ip->i_nlink++;
440 	ip->i_flag |= ICHG;
441 	error = lfs_iupdat(ip, &time, &time, 1);		/* LFS */
442 	if (!error)
443 		error = lfs_direnter(ip, ndp);			/* LFS */
444 	if (ndp->ni_dvp != vp)
445 		IUNLOCK(ip);
446 	FREE(ndp->ni_pnbuf, M_NAMEI);
447 	vput(ndp->ni_dvp);
448 	if (error) {
449 		ip->i_nlink--;
450 		ip->i_flag |= ICHG;
451 	}
452 	return (error);
453 }
454 
455 /*
456  * Rename system call.
457  * 	rename("foo", "bar");
458  * is essentially
459  *	unlink("bar");
460  *	link("foo", "bar");
461  *	unlink("foo");
462  * but ``atomically''.  Can't do full commit without saving state in the
463  * inode on disk which isn't feasible at this time.  Best we can do is
464  * always guarantee the target exists.
465  *
466  * Basic algorithm is:
467  *
468  * 1) Bump link count on source while we're linking it to the
469  *    target.  This also ensure the inode won't be deleted out
470  *    from underneath us while we work (it may be truncated by
471  *    a concurrent `trunc' or `open' for creation).
472  * 2) Link source to destination.  If destination already exists,
473  *    delete it first.
474  * 3) Unlink source reference to inode if still around. If a
475  *    directory was moved and the parent of the destination
476  *    is different from the source, patch the ".." entry in the
477  *    directory.
478  */
479 lfs_rename(fndp, tndp, p)
480 	register struct nameidata *fndp, *tndp;
481 	struct proc *p;
482 {
483 	register struct inode *ip, *xp, *dp;
484 	struct dirtemplate dirbuf;
485 	int doingdirectory = 0, oldparent = 0, newparent = 0;
486 	int error = 0;
487 
488 printf("lfs_rename\n");
489 #ifdef DIANOSTIC
490 	if ((tndp->ni_nameiop & HASBUF) == 0 ||
491 	    (fndp->ni_nameiop & HASBUF) == 0)
492 		panic("ufs_rename: no name");
493 #endif
494 	dp = VTOI(fndp->ni_dvp);
495 	ip = VTOI(fndp->ni_vp);
496 	/*
497 	 * Check if just deleting a link name.
498 	 */
499 	if (fndp->ni_vp == tndp->ni_vp) {
500 		VOP_ABORTOP(tndp);
501 		vput(tndp->ni_dvp);
502 		vput(tndp->ni_vp);
503 		vrele(fndp->ni_dvp);
504 		if ((ip->i_mode&IFMT) == IFDIR) {
505 			VOP_ABORTOP(fndp);
506 			vrele(fndp->ni_vp);
507 			return (EINVAL);
508 		}
509 		doingdirectory = 0;
510 		goto unlinkit;
511 	}
512 	ILOCK(ip);
513 	if ((ip->i_mode&IFMT) == IFDIR) {
514 		/*
515 		 * Avoid ".", "..", and aliases of "." for obvious reasons.
516 		 */
517 		if ((fndp->ni_namelen == 1 && fndp->ni_ptr[0] == '.') ||
518 		    dp == ip || fndp->ni_isdotdot || (ip->i_flag & IRENAME)) {
519 			VOP_ABORTOP(tndp);
520 			vput(tndp->ni_dvp);
521 			if (tndp->ni_vp)
522 				vput(tndp->ni_vp);
523 			VOP_ABORTOP(fndp);
524 			vrele(fndp->ni_dvp);
525 			vput(fndp->ni_vp);
526 			return (EINVAL);
527 		}
528 		ip->i_flag |= IRENAME;
529 		oldparent = dp->i_number;
530 		doingdirectory++;
531 	}
532 	vrele(fndp->ni_dvp);
533 
534 	/*
535 	 * 1) Bump link count while we're moving stuff
536 	 *    around.  If we crash somewhere before
537 	 *    completing our work, the link count
538 	 *    may be wrong, but correctable.
539 	 */
540 	ip->i_nlink++;
541 	ip->i_flag |= ICHG;
542 	error = lfs_iupdat(ip, &time, &time, 1);		/* LFS */
543 	IUNLOCK(ip);
544 
545 	/*
546 	 * When the target exists, both the directory
547 	 * and target vnodes are returned locked.
548 	 */
549 	dp = VTOI(tndp->ni_dvp);
550 	xp = NULL;
551 	if (tndp->ni_vp)
552 		xp = VTOI(tndp->ni_vp);
553 	/*
554 	 * If ".." must be changed (ie the directory gets a new
555 	 * parent) then the source directory must not be in the
556 	 * directory heirarchy above the target, as this would
557 	 * orphan everything below the source directory. Also
558 	 * the user must have write permission in the source so
559 	 * as to be able to change "..". We must repeat the call
560 	 * to namei, as the parent directory is unlocked by the
561 	 * call to checkpath().
562 	 */
563 	if (oldparent != dp->i_number)
564 		newparent = dp->i_number;
565 	if (doingdirectory && newparent) {
566 		VOP_LOCK(fndp->ni_vp);
567 		error = ufs_access(fndp->ni_vp, VWRITE, tndp->ni_cred, p);
568 		VOP_UNLOCK(fndp->ni_vp);
569 		if (error)
570 			goto bad;
571 		if (xp != NULL)
572 			iput(xp);				/* LFS */
573 		if (error = lfs_checkpath(ip, dp, tndp->ni_cred))
574 			goto out;
575 		if ((tndp->ni_nameiop & SAVESTART) == 0)
576 			panic("ufs_rename: lost to startdir");
577 		if (error = lookup(tndp, p))
578 			goto out;
579 		dp = VTOI(tndp->ni_dvp);
580 		xp = NULL;
581 		if (tndp->ni_vp)
582 			xp = VTOI(tndp->ni_vp);
583 	}
584 	/*
585 	 * 2) If target doesn't exist, link the target
586 	 *    to the source and unlink the source.
587 	 *    Otherwise, rewrite the target directory
588 	 *    entry to reference the source inode and
589 	 *    expunge the original entry's existence.
590 	 */
591 	if (xp == NULL) {
592 		if (dp->i_dev != ip->i_dev)
593 			panic("rename: EXDEV");
594 		/*
595 		 * Account for ".." in new directory.
596 		 * When source and destination have the same
597 		 * parent we don't fool with the link count.
598 		 */
599 		if (doingdirectory && newparent) {
600 			if ((unsigned short)dp->i_nlink >= LINK_MAX) {
601 				error = EMLINK;
602 				goto bad;
603 			}
604 			dp->i_nlink++;
605 			dp->i_flag |= ICHG;			/* LFS */
606 			if (error = lfs_iupdat(dp, &time, &time, 1))
607 				goto bad;
608 		}
609 		if (error = lfs_direnter(ip, tndp)) {
610 			if (doingdirectory && newparent) {
611 				dp->i_nlink--;
612 				dp->i_flag |= ICHG;		/* LFS */
613 				(void) lfs_iupdat(dp, &time, &time, 1);
614 			}
615 			goto bad;
616 		}
617 		iput(dp);
618 	} else {
619 		if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev)
620 			panic("rename: EXDEV");
621 		/*
622 		 * Short circuit rename(foo, foo).
623 		 */
624 		if (xp->i_number == ip->i_number)
625 			panic("rename: same file");
626 		/*
627 		 * If the parent directory is "sticky", then the user must
628 		 * own the parent directory, or the destination of the rename,
629 		 * otherwise the destination may not be changed (except by
630 		 * root). This implements append-only directories.
631 		 */
632 		if ((dp->i_mode & ISVTX) && tndp->ni_cred->cr_uid != 0 &&
633 		    tndp->ni_cred->cr_uid != dp->i_uid &&
634 		    xp->i_uid != tndp->ni_cred->cr_uid) {
635 			error = EPERM;
636 			goto bad;
637 		}
638 		/*
639 		 * Target must be empty if a directory and have no links
640 		 * to it. Also, ensure source and target are compatible
641 		 * (both directories, or both not directories).
642 		 */
643 		if ((xp->i_mode&IFMT) == IFDIR) {
644 			if (!dirempty(xp, dp->i_number, tndp->ni_cred) ||
645 			    xp->i_nlink > 2) {
646 				error = ENOTEMPTY;
647 				goto bad;
648 			}
649 			if (!doingdirectory) {
650 				error = ENOTDIR;
651 				goto bad;
652 			}
653 			cache_purge(ITOV(dp));
654 		} else if (doingdirectory) {
655 			error = EISDIR;
656 			goto bad;
657 		}
658 		if (error = dirrewrite(dp, ip, tndp))
659 			goto bad;
660 		/*
661 		 * If the target directory is in the same
662 		 * directory as the source directory,
663 		 * decrement the link count on the parent
664 		 * of the target directory.
665 		 */
666 		 if (doingdirectory && !newparent) {
667 			dp->i_nlink--;
668 			dp->i_flag |= ICHG;
669 		}
670 		vput(ITOV(dp));
671 		/*
672 		 * Adjust the link count of the target to
673 		 * reflect the dirrewrite above.  If this is
674 		 * a directory it is empty and there are
675 		 * no links to it, so we can squash the inode and
676 		 * any space associated with it.  We disallowed
677 		 * renaming over top of a directory with links to
678 		 * it above, as the remaining link would point to
679 		 * a directory without "." or ".." entries.
680 		 */
681 		xp->i_nlink--;
682 		if (doingdirectory) {
683 			if (--xp->i_nlink != 0)			/* LFS */
684 				panic("rename: linked directory");
685 			error = lfs_itrunc(xp, (u_long)0, IO_SYNC);
686 		}
687 		xp->i_flag |= ICHG;
688 		iput(xp);
689 		xp = NULL;
690 	}
691 
692 	/*
693 	 * 3) Unlink the source.
694 	 */
695 unlinkit:
696 	fndp->ni_nameiop &= ~MODMASK;
697 	fndp->ni_nameiop |= LOCKPARENT | LOCKLEAF;
698 	if ((fndp->ni_nameiop & SAVESTART) == 0)
699 		panic("ufs_rename: lost from startdir");
700 	(void) lookup(fndp, p);
701 	if (fndp->ni_vp != NULL) {
702 		xp = VTOI(fndp->ni_vp);
703 		dp = VTOI(fndp->ni_dvp);
704 	} else {
705 		/*
706 		 * From name has disappeared.
707 		 */
708 		if (doingdirectory)
709 			panic("rename: lost dir entry");
710 		vrele(ITOV(ip));
711 		return (0);
712 	}
713 	/*
714 	 * Ensure that the directory entry still exists and has not
715 	 * changed while the new name has been entered. If the source is
716 	 * a file then the entry may have been unlinked or renamed. In
717 	 * either case there is no further work to be done. If the source
718 	 * is a directory then it cannot have been rmdir'ed; its link
719 	 * count of three would cause a rmdir to fail with ENOTEMPTY.
720 	 * The IRENAME flag ensures that it cannot be moved by another
721 	 * rename.
722 	 */
723 	if (xp != ip) {
724 		if (doingdirectory)
725 			panic("rename: lost dir entry");
726 	} else {
727 		/*
728 		 * If the source is a directory with a
729 		 * new parent, the link count of the old
730 		 * parent directory must be decremented
731 		 * and ".." set to point to the new parent.
732 		 */
733 		if (doingdirectory && newparent) {
734 			dp->i_nlink--;
735 			dp->i_flag |= ICHG;
736 			error = vn_rdwr(UIO_READ, ITOV(xp), (caddr_t)&dirbuf,
737 				sizeof (struct dirtemplate), (off_t)0,
738 				UIO_SYSSPACE, IO_NODELOCKED,
739 				tndp->ni_cred, (int *)0, (struct proc *)0);
740 			if (error == 0) {
741 				if (dirbuf.dotdot_namlen != 2 ||
742 				    dirbuf.dotdot_name[0] != '.' ||
743 				    dirbuf.dotdot_name[1] != '.') {
744 					lfs_dirbad(xp, 12,
745 					    "rename: mangled dir");
746 				} else {
747 					dirbuf.dotdot_ino = newparent;
748 					(void) vn_rdwr(UIO_WRITE, ITOV(xp),
749 					    (caddr_t)&dirbuf,
750 					    sizeof (struct dirtemplate),
751 					    (off_t)0, UIO_SYSSPACE,
752 					    IO_NODELOCKED|IO_SYNC,
753 					    tndp->ni_cred, (int *)0,
754 					    (struct proc *)0);
755 					cache_purge(ITOV(dp));
756 				}
757 			}
758 		}
759 		error = lfs_dirremove(fndp);			/* LFS */
760 		if (!error) {
761 			xp->i_nlink--;
762 			xp->i_flag |= ICHG;
763 		}
764 		xp->i_flag &= ~IRENAME;
765 	}
766 	if (dp)
767 		vput(ITOV(dp));
768 	if (xp)
769 		vput(ITOV(xp));
770 	vrele(ITOV(ip));
771 	return (error);
772 
773 bad:
774 	if (xp)
775 		vput(ITOV(xp));
776 	vput(ITOV(dp));
777 out:
778 	ip->i_nlink--;
779 	ip->i_flag |= ICHG;
780 	vrele(ITOV(ip));
781 	return (error);
782 }
783 
784 /*
785  * A virgin directory (no blushing please).
786  */
787 static struct dirtemplate mastertemplate = {
788 	0, 12, 1, ".",
789 	0, DIRBLKSIZ - 12, 2, ".."
790 };
791 
792 /*
793  * Mkdir system call
794  */
795 lfs_mkdir(ndp, vap, p)
796 	struct nameidata *ndp;
797 	struct vattr *vap;
798 	struct proc *p;
799 {
800 	register struct inode *ip, *dp;
801 	struct inode *tip;
802 	struct vnode *dvp;
803 	struct dirtemplate dirtemplate;
804 	int error;
805 	int dmode;
806 
807 printf("lfs_mkdir\n");
808 #ifdef DIANOSTIC
809 	if ((ndp->ni_nameiop & HASBUF) == 0)
810 		panic("ufs_mkdir: no name");
811 #endif
812 	dvp = ndp->ni_dvp;
813 	dp = VTOI(dvp);
814 	if ((unsigned short)dp->i_nlink >= LINK_MAX) {
815 		free(ndp->ni_pnbuf, M_NAMEI);
816 		iput(dp);
817 		return (EMLINK);
818 	}
819 	dmode = vap->va_mode&0777;
820 	dmode |= IFDIR;
821 	/*
822 	 * Must simulate part of maknode here to acquire the inode, but
823 	 * not have it entered in the parent directory. The entry is made
824 	 * later after writing "." and ".." entries.
825 	 */
826 #ifdef NOTLFS							/* LFS */
827 	if (error = ialloc(dp, dirpref(dp->i_fs), dmode, ndp->ni_cred, &tip)) {
828 #else
829 	if (error = lfs_ialloc(dp->i_lfs, dp, &tip, ndp->ni_cred)) {
830 #endif
831 		free(ndp->ni_pnbuf, M_NAMEI);
832 		iput(dp);
833 		return (error);
834 	}
835 	ip = tip;
836 	ip->i_uid = ndp->ni_cred->cr_uid;
837 	ip->i_gid = dp->i_gid;
838 #ifdef QUOTA
839 	if ((error = getinoquota(ip)) ||
840 	    (error = chkiq(ip, 1, ndp->ni_cred, 0))) {
841 		free(ndp->ni_pnbuf, M_NAMEI);
842 #ifdef NOTLFS							/* LFS */
843 		ifree(ip, ip->i_number, dmode);
844 #else
845 		lfs_ifree(ip);
846 #endif
847 		iput(ip);
848 		iput(dp);
849 		return (error);
850 	}
851 #endif
852 	ip->i_flag |= IACC|IUPD|ICHG;
853 	ip->i_mode = dmode;
854 	ITOV(ip)->v_type = VDIR;	/* Rest init'd in iget() */
855 	ip->i_nlink = 2;
856 	error = lfs_iupdat(ip, &time, &time, 1);		/* LFS */
857 
858 	/*
859 	 * Bump link count in parent directory
860 	 * to reflect work done below.  Should
861 	 * be done before reference is created
862 	 * so reparation is possible if we crash.
863 	 */
864 	dp->i_nlink++;
865 	dp->i_flag |= ICHG;
866 	if (error = lfs_iupdat(dp, &time, &time, 1))		/* LFS */
867 		goto bad;
868 
869 	/*
870 	 * Initialize directory with "."
871 	 * and ".." from static template.
872 	 */
873 	dirtemplate = mastertemplate;
874 	dirtemplate.dot_ino = ip->i_number;
875 	dirtemplate.dotdot_ino = dp->i_number;
876 	error = vn_rdwr(UIO_WRITE, ITOV(ip), (caddr_t)&dirtemplate,
877 	    sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE,
878 	    IO_NODELOCKED|IO_SYNC, ndp->ni_cred, (int *)0, (struct proc *)0);
879 	if (error) {
880 		dp->i_nlink--;
881 		dp->i_flag |= ICHG;
882 		goto bad;
883 	}
884 	if (DIRBLKSIZ > dp->i_lfs->lfs_fsize) {
885 		panic("mkdir: blksize");     /* XXX - should grow w/balloc() */
886 	} else {
887 		ip->i_size = DIRBLKSIZ;
888 		ip->i_flag |= ICHG;
889 	}
890 	/*
891 	 * Directory all set up, now
892 	 * install the entry for it in
893 	 * the parent directory.
894 	 */
895 	if (error = lfs_direnter(ip, ndp)) {			/* LFS */
896 		dp->i_nlink--;
897 		dp->i_flag |= ICHG;
898 	}
899 bad:
900 	/*
901 	 * No need to do an explicit lfs_itrunc here,
902 	 * vrele will do this for us because we set
903 	 * the link count to 0.
904 	 */
905 	if (error) {
906 		ip->i_nlink = 0;
907 		ip->i_flag |= ICHG;
908 		iput(ip);
909 	} else
910 		ndp->ni_vp = ITOV(ip);
911 	FREE(ndp->ni_pnbuf, M_NAMEI);
912 	iput(dp);
913 	return (error);
914 }
915 
916 /*
917  * Rmdir system call.
918  */
919 lfs_rmdir(ndp, p)
920 	register struct nameidata *ndp;
921 	struct proc *p;
922 {
923 	register struct inode *ip, *dp;
924 	int error = 0;
925 
926 printf("lfs_rmdir\n");
927 	ip = VTOI(ndp->ni_vp);
928 	dp = VTOI(ndp->ni_dvp);
929 	/*
930 	 * No rmdir "." please.
931 	 */
932 	if (dp == ip) {
933 		vrele(ITOV(dp));
934 		iput(ip);
935 		return (EINVAL);
936 	}
937 	/*
938 	 * Verify the directory is empty (and valid).
939 	 * (Rmdir ".." won't be valid since
940 	 *  ".." will contain a reference to
941 	 *  the current directory and thus be
942 	 *  non-empty.)
943 	 */
944 	if (ip->i_nlink != 2 || !dirempty(ip, dp->i_number, ndp->ni_cred)) {
945 		error = ENOTEMPTY;
946 		goto out;
947 	}
948 	/*
949 	 * Delete reference to directory before purging
950 	 * inode.  If we crash in between, the directory
951 	 * will be reattached to lost+found,
952 	 */
953 	if (error = lfs_dirremove(ndp))				/* LFS */
954 		goto out;
955 	dp->i_nlink--;
956 	dp->i_flag |= ICHG;
957 	cache_purge(ITOV(dp));
958 	iput(dp);
959 	ndp->ni_dvp = NULL;
960 	/*
961 	 * Truncate inode.  The only stuff left
962 	 * in the directory is "." and "..".  The
963 	 * "." reference is inconsequential since
964 	 * we're quashing it.  The ".." reference
965 	 * has already been adjusted above.  We've
966 	 * removed the "." reference and the reference
967 	 * in the parent directory, but there may be
968 	 * other hard links so decrement by 2 and
969 	 * worry about them later.
970 	 */
971 	ip->i_nlink -= 2;
972 	error = lfs_itrunc(ip, (u_long)0, IO_SYNC);		/* LFS */
973 	cache_purge(ITOV(ip));
974 out:
975 	if (ndp->ni_dvp)
976 		iput(dp);
977 	iput(ip);
978 	return (error);
979 }
980 
981 /*
982  * symlink -- make a symbolic link
983  */
984 lfs_symlink(ndp, vap, target, p)
985 	struct nameidata *ndp;
986 	struct vattr *vap;
987 	char *target;
988 	struct proc *p;
989 {
990 	struct inode *ip;
991 	int error;
992 
993 printf("lfs_symlink\n");
994 	error = maknode(IFLNK | vap->va_mode, ndp, &ip);
995 	if (error)
996 		return (error);
997 	error = vn_rdwr(UIO_WRITE, ITOV(ip), target, strlen(target), (off_t)0,
998 		UIO_SYSSPACE, IO_NODELOCKED, ndp->ni_cred, (int *)0,
999 		(struct proc *)0);
1000 	iput(ip);
1001 	return (error);
1002 }
1003 
1004 /*
1005  * Vnode op for read and write
1006  */
1007 lfs_readdir(vp, uio, cred, eofflagp)
1008 	struct vnode *vp;
1009 	register struct uio *uio;
1010 	struct ucred *cred;
1011 	int *eofflagp;
1012 {
1013 	int count, lost, error;
1014 
1015 printf("lfs_readdir\n");
1016 	count = uio->uio_resid;
1017 	count &= ~(DIRBLKSIZ - 1);
1018 	lost = uio->uio_resid - count;
1019 	if (count < DIRBLKSIZ || (uio->uio_offset & (DIRBLKSIZ -1)))
1020 		return (EINVAL);
1021 	uio->uio_resid = count;
1022 	uio->uio_iov->iov_len = count;
1023 	error = lfs_read(vp, uio, 0, cred);			/* LFS */
1024 	uio->uio_resid += lost;
1025 	if ((VTOI(vp)->i_size - uio->uio_offset) <= 0)
1026 		*eofflagp = 1;
1027 	else
1028 		*eofflagp = 0;
1029 	return (error);
1030 }
1031 
1032 /*
1033  * Return target name of a symbolic link
1034  */
1035 lfs_readlink(vp, uiop, cred)
1036 	struct vnode *vp;
1037 	struct uio *uiop;
1038 	struct ucred *cred;
1039 {
1040 
1041 printf("lfs_readlink\n");
1042 	return (lfs_read(vp, uiop, 0, cred));			/* LFS */
1043 }
1044 
1045 /*
1046  * Get access to bmap
1047  */
1048 lfs_vbmap(vp, bn, vpp, bnp)
1049 	struct vnode *vp;
1050 	daddr_t bn;
1051 	struct vnode **vpp;
1052 	daddr_t *bnp;
1053 {
1054 	struct inode *ip = VTOI(vp);
1055 
1056 printf("lfs_vbmap\n");
1057 	if (vpp != NULL)
1058 		*vpp = ip->i_devvp;
1059 	if (bnp == NULL)
1060 		return (0);
1061 	return (lfs_bmap(ip, bn, bnp));				/* LFS */
1062 }
1063 
1064 /*
1065  * Calculate the logical to physical mapping if not done already,
1066  * then call the device strategy routine.
1067  */
1068 lfs_strategy(bp)
1069 	register struct buf *bp;
1070 {
1071 	register struct inode *ip = VTOI(bp->b_vp);
1072 	struct vnode *vp;
1073 	int error;
1074 
1075 printf("lfs_strategy: type: %d lblk %d pblk %d\n", bp->b_vp->v_type,
1076 	bp->b_lblkno, bp->b_blkno);
1077 	if (bp->b_vp->v_type == VBLK || bp->b_vp->v_type == VCHR)
1078 		panic("ufs_strategy: spec");
1079 	if (bp->b_blkno == bp->b_lblkno) {			/* LFS */
1080 		if (error = lfs_bmap(ip, bp->b_lblkno, &bp->b_blkno))
1081 			return (error);
1082 		if ((long)bp->b_blkno == -1)
1083 			clrbuf(bp);
1084 	}
1085 	if ((long)bp->b_blkno == -1) {
1086 		biodone(bp);
1087 		return (0);
1088 	}
1089 	vp = ip->i_devvp;
1090 	bp->b_dev = vp->v_rdev;
1091 	(*(vp->v_op->vop_strategy))(bp);
1092 	return (0);
1093 }
1094 
1095 /*
1096  * Allocate a new inode.
1097  */
1098 static int
1099 maknode(mode, ndp, ipp)
1100 	int mode;
1101 	register struct nameidata *ndp;
1102 	struct inode **ipp;
1103 {
1104 	register struct inode *ip;
1105 	struct inode *tip;
1106 	register struct inode *pdir = VTOI(ndp->ni_dvp);
1107 	ino_t ipref;
1108 	int error;
1109 
1110 printf("maknode\n");
1111 #ifdef DIANOSTIC
1112 	if ((ndp->ni_nameiop & HASBUF) == 0)
1113 		panic("maknode: no name");
1114 #endif
1115 	*ipp = 0;
1116 	if ((mode & IFMT) == 0)
1117 		mode |= IFREG;
1118 #ifdef NOTLFS							/* LFS */
1119 	if ((mode & IFMT) == IFDIR)
1120 		ipref = dirpref(pdir->i_fs);
1121 	else
1122 		ipref = pdir->i_number;
1123 	if (error = ialloc(pdir, ipref, mode, ndp->ni_cred, &tip)) {
1124 #else
1125 	if (error = lfs_ialloc(pdir->i_lfs, pdir, &tip, ndp->ni_cred)) {
1126 #endif
1127 		free(ndp->ni_pnbuf, M_NAMEI);
1128 		iput(pdir);
1129 		return (error);
1130 	}
1131 	ip = tip;
1132 	ip->i_uid = ndp->ni_cred->cr_uid;
1133 	ip->i_gid = pdir->i_gid;
1134 #ifdef QUOTA
1135 	if ((error = getinoquota(ip)) ||
1136 	    (error = chkiq(ip, 1, ndp->ni_cred, 0))) {
1137 		free(ndp->ni_pnbuf, M_NAMEI);
1138 #ifdef NOTLFS							/* LFS */
1139 		ifree(ip, ip->i_number, mode);
1140 #else
1141 		lfs_ifree(ip);
1142 #endif
1143 		iput(ip);
1144 		iput(pdir);
1145 		return (error);
1146 	}
1147 #endif
1148 	ip->i_flag |= IACC|IUPD|ICHG;
1149 	ip->i_mode = mode;
1150 	ITOV(ip)->v_type = IFTOVT(mode);	/* Rest init'd in iget() */
1151 	ip->i_nlink = 1;
1152 	if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, ndp->ni_cred) &&
1153 	    suser(ndp->ni_cred, NULL))
1154 		ip->i_mode &= ~ISGID;
1155 
1156 	/*
1157 	 * Make sure inode goes to disk before directory entry.
1158 	 *
1159 	 * XXX Wrong...
1160 	 */
1161 	if (error = lfs_iupdat(ip, &time, &time, 1))		/* LFS */
1162 		goto bad;
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