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