1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 #include <sys/t_lock.h> 31 #include <sys/param.h> 32 #include <sys/time.h> 33 #include <sys/systm.h> 34 #include <sys/sysmacros.h> 35 #include <sys/resource.h> 36 #include <sys/signal.h> 37 #include <sys/cred.h> 38 #include <sys/user.h> 39 #include <sys/buf.h> 40 #include <sys/vfs.h> 41 #include <sys/stat.h> 42 #include <sys/vnode.h> 43 #include <sys/mode.h> 44 #include <sys/proc.h> 45 #include <sys/disp.h> 46 #include <sys/file.h> 47 #include <sys/fcntl.h> 48 #include <sys/flock.h> 49 #include <sys/kmem.h> 50 #include <sys/uio.h> 51 #include <sys/dnlc.h> 52 #include <sys/conf.h> 53 #include <sys/errno.h> 54 #include <sys/mman.h> 55 #include <sys/fbuf.h> 56 #include <sys/pathname.h> 57 #include <sys/debug.h> 58 #include <sys/vmsystm.h> 59 #include <sys/cmn_err.h> 60 #include <sys/dirent.h> 61 #include <sys/errno.h> 62 #include <sys/modctl.h> 63 #include <sys/statvfs.h> 64 #include <sys/mount.h> 65 #include <sys/sunddi.h> 66 #include <sys/bootconf.h> 67 #include <sys/policy.h> 68 69 #include <vm/hat.h> 70 #include <vm/page.h> 71 #include <vm/pvn.h> 72 #include <vm/as.h> 73 #include <vm/seg.h> 74 #include <vm/seg_map.h> 75 #include <vm/seg_kmem.h> 76 #include <vm/seg_vn.h> 77 #include <vm/rm.h> 78 #include <vm/page.h> 79 #include <sys/swap.h> 80 81 82 #include <fs/fs_subr.h> 83 84 85 #include <sys/fs/udf_volume.h> 86 #include <sys/fs/udf_inode.h> 87 88 89 struct slot { 90 enum {NONE, COMPACT, FOUND, EXIST} status; 91 off_t offset; /* offset of area with free space */ 92 int size; /* size of area at slotoffset */ 93 struct fbuf *fbp; /* dir buf where slot is */ 94 struct file_id *ep; /* pointer to slot */ 95 off_t endoff; /* last useful location found in search */ 96 }; 97 98 99 int32_t ud_dircheckforname(struct ud_inode *, char *, int, 100 struct slot *, struct ud_inode **, uint8_t *, struct cred *); 101 int32_t ud_dirempty(struct ud_inode *, uint64_t, struct cred *); 102 int32_t str2cmp(char *, int32_t, char *, int32_t, char *, int32_t); 103 int32_t ud_dircheckpath(int32_t, struct ud_inode *, struct cred *); 104 int32_t ud_dirmakeinode(struct ud_inode *, struct ud_inode **, 105 struct vattr *, enum de_op, struct cred *); 106 int32_t ud_diraddentry(struct ud_inode *, char *, 107 enum de_op, int, struct slot *, struct ud_inode *, 108 struct ud_inode *, struct cred *); 109 int32_t ud_dirmakedirect(struct ud_inode *, struct ud_inode *, struct cred *); 110 int32_t ud_dirrename(struct ud_inode *, struct ud_inode *, 111 struct ud_inode *, struct ud_inode *, char *, uint8_t *, 112 struct slot *, struct cred *); 113 int32_t ud_dirprepareentry(struct ud_inode *, 114 struct slot *, uint8_t *, struct cred *); 115 int32_t ud_dirfixdotdot(struct ud_inode *, struct ud_inode *, 116 struct ud_inode *); 117 int32_t ud_write_fid(struct ud_inode *, struct slot *, uint8_t *); 118 119 int 120 ud_dirlook(struct ud_inode *dip, 121 char *namep, struct ud_inode **ipp, struct cred *cr, int32_t skipdnlc) 122 { 123 struct udf_vfs *udf_vfsp; 124 int32_t error = 0, namelen, adhoc_search; 125 u_offset_t offset, adhoc_offset, dirsize, end; 126 struct vnode *dvp, *vp; 127 struct fbuf *fbp; 128 struct file_id *fid; 129 uint8_t *fname, dummy[3]; 130 int32_t id_len, doingchk; 131 uint32_t old_loc; 132 uint16_t old_prn; 133 134 uint8_t *dname; 135 uint8_t *buf = NULL; 136 137 ud_printf("ud_dirlook\n"); 138 139 udf_vfsp = dip->i_udf; 140 141 restart: 142 doingchk = 0; 143 old_prn = 0xFFFF; 144 old_loc = 0; 145 dvp = ITOV(dip); 146 /* 147 * Check accessibility of directory. 148 */ 149 if (dip->i_type != VDIR) { 150 return (ENOTDIR); 151 } 152 if (error = ud_iaccess(dip, IEXEC, cr)) { 153 return (error); 154 } 155 156 /* 157 * Null component name is synonym for directory being searched. 158 */ 159 if (*namep == '\0') { 160 VN_HOLD(dvp); 161 *ipp = dip; 162 return (0); 163 } 164 namelen = strlen(namep); 165 if ((namelen == 1) && 166 (namep[0] == '.') && (namep[1] == '\0')) { 167 /* Current directory */ 168 VN_HOLD(dvp); 169 *ipp = dip; 170 dnlc_enter(dvp, namep, ITOV(*ipp)); 171 return (0); 172 } 173 174 if ((!skipdnlc) && (vp = dnlc_lookup(dvp, namep))) { 175 /* vp is already held from dnlc_lookup */ 176 177 *ipp = VTOI(vp); 178 return (0); 179 } 180 181 dname = kmem_zalloc(1024, KM_SLEEP); 182 buf = kmem_zalloc(udf_vfsp->udf_lbsize, KM_SLEEP); 183 184 /* 185 * Read lock the inode we are searching. You will notice that we 186 * didn't hold the read lock while searching the dnlc. This means 187 * that the entry could now be in the dnlc. This doesn't cause any 188 * problems because dnlc_enter won't add an entry if it is already 189 * there. 190 */ 191 rw_enter(&dip->i_rwlock, RW_READER); 192 193 /* 194 * Take care to look at dip->i_diroff only once, as it 195 * may be changing due to other threads/cpus. 196 */ 197 198 recheck: 199 offset = dip->i_diroff; 200 end = dirsize = dip->i_size; 201 202 if (offset > dirsize) { 203 offset = 0; 204 } 205 adhoc_offset = offset; 206 adhoc_search = (offset == 0) ? 1 : 2; 207 208 fbp = NULL; 209 210 while (adhoc_search--) { 211 while (offset < end) { 212 error = ud_get_next_fid(dip, &fbp, 213 offset, &fid, &fname, buf); 214 if (error != 0) { 215 break; 216 } 217 if ((fid->fid_flags & FID_DELETED) == 0) { 218 if (fid->fid_flags & FID_PARENT) { 219 id_len = 2; 220 fname = dummy; 221 dummy[0] = '.'; 222 dummy[1] = '.'; 223 dummy[2] = '\0'; 224 } else { 225 if ((error = ud_uncompress( 226 fid->fid_idlen, &id_len, 227 fname, dname)) != 0) { 228 break; 229 } 230 fname = (uint8_t *)dname; 231 fname[id_len] = '\0'; 232 } 233 if ((namelen == id_len) && 234 (strncmp(namep, (caddr_t)fname, 235 namelen) == 0)) { 236 uint32_t loc; 237 uint16_t prn; 238 239 240 loc = SWAP_32(fid->fid_icb.lad_ext_loc); 241 prn = SWAP_16(fid->fid_icb.lad_ext_prn); 242 dip->i_diroff = offset + 243 FID_LEN(fid); 244 245 if (doingchk) { 246 if ((loc == old_loc) && 247 (prn == old_prn)) { 248 goto checkok; 249 } else { 250 if (fbp != NULL) { 251 fbrelse(fbp, 252 S_READ); 253 fbp = NULL; 254 } 255 VN_RELE(ITOV(*ipp)); 256 rw_exit(&dip->i_rwlock); 257 goto restart; 258 } 259 /* NOTREACHED */ 260 } 261 262 if (namelen == 2 && 263 fname[0] == '.' && 264 fname[1] == '.') { 265 266 struct timespec32 omtime; 267 268 omtime = dip->i_mtime; 269 rw_exit(&dip->i_rwlock); 270 271 error = ud_iget(dip->i_vfs, prn, 272 loc, ipp, NULL, cr); 273 274 rw_enter(&dip->i_rwlock, 275 RW_READER); 276 277 if (error) { 278 goto done; 279 } 280 281 if ((omtime.tv_sec != 282 dip->i_mtime.tv_sec) || 283 (omtime.tv_nsec != 284 dip->i_mtime.tv_nsec)) { 285 286 doingchk = 1; 287 old_prn = prn; 288 old_loc = loc; 289 dip->i_diroff = 0; 290 if (fbp != NULL) { 291 fbrelse(fbp, 292 S_READ); 293 fbp = NULL; 294 } 295 goto recheck; 296 } 297 } else { 298 299 error = ud_iget(dip->i_vfs, prn, 300 loc, ipp, NULL, cr); 301 } 302 checkok: 303 if (error == 0) { 304 dnlc_enter(dvp, namep, 305 ITOV(*ipp)); 306 } 307 goto done; 308 } 309 } 310 offset += FID_LEN(fid); 311 } 312 if (fbp != NULL) { 313 fbrelse(fbp, S_READ); 314 fbp = NULL; 315 } 316 end = adhoc_offset; 317 offset = 0; 318 } 319 error = ENOENT; 320 done: 321 kmem_free(buf, udf_vfsp->udf_lbsize); 322 kmem_free(dname, 1024); 323 if (fbp != NULL) { 324 fbrelse(fbp, S_READ); 325 } 326 rw_exit(&dip->i_rwlock); 327 return (error); 328 } 329 330 int 331 ud_direnter(struct ud_inode *tdp, 332 char *namep, enum de_op op, struct ud_inode *sdp, struct ud_inode *sip, 333 struct vattr *vap, struct ud_inode **ipp, struct cred *cr) 334 { 335 struct udf_vfs *udf_vfsp; 336 struct ud_inode *tip; 337 struct slot slot; 338 int32_t namlen, err; 339 char *s; 340 341 uint8_t *buf = NULL; 342 343 ud_printf("ud_direnter\n"); 344 345 udf_vfsp = tdp->i_udf; 346 /* don't allow '/' characters in pathname component */ 347 for (s = namep, namlen = 0; *s; s++, namlen++) { 348 if (*s == '/') { 349 return (EACCES); 350 } 351 } 352 353 if (namlen == 0) { 354 cmn_err(CE_WARN, "name length == 0 in ud_direnter"); 355 return (EINVAL); 356 } 357 358 ASSERT(RW_WRITE_HELD(&tdp->i_rwlock)); 359 /* 360 * If name is "." or ".." then if this is a create look it up 361 * and return EEXIST. Rename or link TO "." or ".." is forbidden. 362 */ 363 if (namep[0] == '.' && 364 (namlen == 1 || (namlen == 2 && namep[1] == '.'))) { 365 if (op == DE_RENAME) { 366 return (EINVAL); /* *SIGH* should be ENOTEMPTY */ 367 } 368 if (ipp) { 369 /* 370 * ud_dirlook will acquire the i_rwlock 371 */ 372 rw_exit(&tdp->i_rwlock); 373 if (err = ud_dirlook(tdp, namep, ipp, cr, 0)) { 374 rw_enter(&tdp->i_rwlock, RW_WRITER); 375 return (err); 376 } 377 rw_enter(&tdp->i_rwlock, RW_WRITER); 378 } 379 return (EEXIST); 380 } 381 382 tip = NULL; 383 slot.status = NONE; 384 slot.offset = 0; 385 slot.size = 0; 386 slot.fbp = NULL; 387 slot.ep = NULL; 388 slot.endoff = 0; 389 390 /* 391 * For link and rename lock the source entry and check the link count 392 * to see if it has been removed while it was unlocked. If not, we 393 * increment the link count and force the inode to disk to make sure 394 * that it is there before any directory entry that points to it. 395 */ 396 if (op == DE_LINK || op == DE_RENAME) { 397 rw_enter(&sip->i_contents, RW_WRITER); 398 if (sip->i_nlink == 0) { 399 rw_exit(&sip->i_contents); 400 return (ENOENT); 401 } 402 if (sip->i_nlink == MAXLINK) { 403 rw_exit(&sip->i_contents); 404 return (EMLINK); 405 } 406 407 sip->i_nlink++; 408 mutex_enter(&sip->i_tlock); 409 sip->i_flag |= ICHG; 410 mutex_exit(&sip->i_tlock); 411 ud_iupdat(sip, 1); 412 rw_exit(&sip->i_contents); 413 } 414 /* 415 * If target directory has not been removed, then we can consider 416 * allowing file to be created. 417 */ 418 if (tdp->i_nlink == 0) { 419 err = ENOENT; 420 goto out2; 421 } 422 /* 423 * Check accessibility of directory. 424 */ 425 if (tdp->i_type != VDIR) { 426 err = ENOTDIR; 427 goto out2; 428 } 429 /* 430 * Execute access is required to search the directory. 431 */ 432 if (err = ud_iaccess(tdp, IEXEC, cr)) { 433 goto out2; 434 } 435 /* 436 * If this is a rename of a directory and the parent is 437 * different (".." must be changed), then the source 438 * directory must not be in the directory hierarchy 439 * above the target, as this would orphan everything 440 * below the source directory. Also the user must have 441 * write permission in the source so as to be able to 442 * change "..". 443 */ 444 if (op == DE_RENAME) { 445 if (sip == tdp) { 446 err = EINVAL; 447 goto out2; 448 } 449 rw_enter(&sip->i_contents, RW_READER); 450 if ((sip->i_type == VDIR) && (sdp != tdp)) { 451 uint32_t blkno; 452 453 if ((err = ud_iaccess(sip, IWRITE, cr))) { 454 rw_exit(&sip->i_contents); 455 goto out2; 456 } 457 blkno = sip->i_icb_lbano; 458 rw_exit(&sip->i_contents); 459 if ((err = ud_dircheckpath(blkno, tdp, cr))) { 460 goto out2; 461 } 462 } else { 463 rw_exit(&sip->i_contents); 464 } 465 } 466 467 /* 468 * Search for the entry. Return VN_HELD tip if found. 469 */ 470 buf = kmem_zalloc(udf_vfsp->udf_lbsize, KM_SLEEP); 471 rw_enter(&tdp->i_contents, RW_WRITER); 472 if (err = ud_dircheckforname(tdp, 473 namep, namlen, &slot, &tip, buf, cr)) { 474 goto out; 475 } 476 if (tip) { 477 switch (op) { 478 case DE_CREATE : 479 case DE_MKDIR : 480 if (ipp) { 481 *ipp = tip; 482 err = EEXIST; 483 } else { 484 VN_RELE(ITOV(tip)); 485 } 486 break; 487 case DE_RENAME : 488 err = ud_dirrename(sdp, sip, tdp, tip, 489 namep, buf, &slot, cr); 490 /* 491 * We used to VN_RELE() here, but this 492 * was moved down so that we could send 493 * a vnevent after the locks were dropped. 494 */ 495 break; 496 case DE_LINK : 497 /* 498 * Can't link to an existing file. 499 */ 500 VN_RELE(ITOV(tip)); 501 err = EEXIST; 502 break; 503 } 504 } else { 505 /* 506 * The entry does not exist. Check write permission in 507 * directory to see if entry can be created. 508 */ 509 if (err = ud_iaccess(tdp, IWRITE, cr)) { 510 goto out; 511 } 512 if ((op == DE_CREATE) || (op == DE_MKDIR)) { 513 /* 514 * Make new inode and directory entry as required. 515 */ 516 if (err = ud_dirmakeinode(tdp, &sip, vap, op, cr)) 517 goto out; 518 } 519 if (err = ud_diraddentry(tdp, namep, op, 520 namlen, &slot, sip, sdp, cr)) { 521 if ((op == DE_CREATE) || (op == DE_MKDIR)) { 522 /* 523 * Unmake the inode we just made. 524 */ 525 rw_enter(&sip->i_contents, RW_WRITER); 526 if (sip->i_type == VDIR) { 527 tdp->i_nlink--; 528 } 529 sip->i_nlink = 0; 530 mutex_enter(&sip->i_tlock); 531 sip->i_flag |= ICHG; 532 mutex_exit(&sip->i_tlock); 533 rw_exit(&sip->i_contents); 534 VN_RELE(ITOV(sip)); 535 sip = NULL; 536 } 537 } else if (ipp) { 538 *ipp = sip; 539 } else if ((op == DE_CREATE) || (op == DE_MKDIR)) { 540 VN_RELE(ITOV(sip)); 541 } 542 } 543 out: 544 if (buf != NULL) { 545 kmem_free(buf, udf_vfsp->udf_lbsize); 546 } 547 if (slot.fbp) { 548 fbrelse(slot.fbp, S_OTHER); 549 } 550 rw_exit(&tdp->i_contents); 551 552 if (op == DE_RENAME) { 553 /* 554 * If it's all good, send events after locks are dropped 555 * but before vnodes are released. 556 */ 557 if (err == 0) { 558 if (tip) { 559 vnevent_rename_dest(ITOV(tip)); 560 } 561 vnevent_rename_src(ITOV(sip)); 562 } 563 564 /* 565 * The following VN_RELE() was moved from the 566 * DE_RENAME case above 567 */ 568 if (tip) { 569 VN_RELE(ITOV(tip)); 570 } 571 } 572 573 out2: 574 if (err && ((op == DE_LINK) || (op == DE_RENAME))) { 575 /* 576 * Undo bumped link count. 577 */ 578 rw_enter(&sip->i_contents, RW_WRITER); 579 sip->i_nlink--; 580 rw_exit(&sip->i_contents); 581 582 mutex_enter(&sip->i_tlock); 583 sip->i_flag |= ICHG; 584 mutex_exit(&sip->i_tlock); 585 } 586 return (err); 587 } 588 589 /* 590 * Locking i_contents in this 591 * function seems to be really weird 592 */ 593 int 594 ud_dirremove(struct ud_inode *dp, 595 char *namep, struct ud_inode *oip, struct vnode *cdir, 596 enum dr_op op, struct cred *cr) 597 { 598 struct udf_vfs *udf_vfsp; 599 int32_t namelen, err = 0; 600 struct slot slot; 601 struct ud_inode *ip; 602 mode_t mode; 603 struct file_id *fid; 604 uint8_t *buf = NULL; 605 uint32_t tbno; 606 607 ud_printf("ud_dirremove\n"); 608 609 ASSERT(RW_WRITE_HELD(&dp->i_rwlock)); 610 611 udf_vfsp = dp->i_udf; 612 namelen = (int)strlen(namep); 613 if (namelen == 0) { 614 cmn_err(CE_WARN, "name length == 0 in ud_dirremove"); 615 return (EINVAL); 616 } 617 618 /* 619 * return err when removing . and .. 620 */ 621 if (namep[0] == '.') { 622 if (namelen == 1) { 623 return (EINVAL); 624 } else if (namelen == 2 && namep[1] == '.') { 625 return (EEXIST); /* SIGH should be ENOTEMPTY */ 626 } 627 } 628 629 ASSERT(RW_WRITE_HELD(&dp->i_rwlock)); 630 631 /* 632 * Check accessibility of directory. 633 */ 634 if (dp->i_type != VDIR) { 635 return (ENOTDIR); 636 } 637 638 ip = NULL; 639 slot.status = FOUND; /* don't need to look for empty slot */ 640 slot.offset = 0; 641 slot.size = 0; 642 slot.fbp = NULL; 643 slot.ep = NULL; 644 slot.endoff = 0; 645 /* 646 * Execute access is required to search the directory. 647 * Access for write is interpreted as allowing 648 * deletion of files in the directory. 649 */ 650 if (err = ud_iaccess(dp, IEXEC|IWRITE, cr)) { 651 return (err); 652 } 653 654 buf = (uint8_t *)kmem_zalloc(udf_vfsp->udf_lbsize, KM_SLEEP); 655 656 rw_enter(&dp->i_contents, RW_WRITER); 657 658 if (err = ud_dircheckforname(dp, 659 namep, namelen, &slot, &ip, buf, cr)) { 660 goto out_novfs; 661 } 662 if (ip == NULL) { 663 err = ENOENT; 664 goto out_novfs; 665 } 666 if (oip && oip != ip) { 667 err = ENOENT; 668 goto out_novfs; 669 } 670 671 if ((mode = ip->i_type) == VDIR) { 672 /* 673 * vn_vfswlock() prevents races between mount and rmdir. 674 */ 675 if (vn_vfswlock(ITOV(ip))) { 676 err = EBUSY; 677 goto out_novfs; 678 } 679 if (vn_mountedvfs(ITOV(ip)) != NULL && op != DR_RENAME) { 680 err = EBUSY; 681 goto out; 682 } 683 /* 684 * If we are removing a directory, get a lock on it. 685 * If the directory is empty, it will stay empty until 686 * we can remove it. 687 */ 688 rw_enter(&ip->i_rwlock, RW_READER); 689 } 690 /* We must be holding i_contents */ 691 rw_enter(&ip->i_contents, RW_READER); 692 693 if (err = ud_sticky_remove_access(dp, ip, cr)) { 694 rw_exit(&ip->i_contents); 695 if (mode == VDIR) { 696 rw_exit(&ip->i_rwlock); 697 } 698 goto out; 699 } 700 if (op == DR_RMDIR) { 701 /* 702 * For rmdir(2), some special checks are required. 703 * (a) Don't remove any alias of the parent (e.g. "."). 704 * (b) Don't remove the current directory. 705 * (c) Make sure the entry is (still) a directory. 706 * (d) Make sure the directory is empty. 707 */ 708 709 if (dp == ip || ITOV(ip) == cdir) { 710 err = EINVAL; 711 } else if (ip->i_type != VDIR) { 712 err = ENOTDIR; 713 } else if ((ip->i_nlink != 1) || 714 (!ud_dirempty(ip, dp->i_uniqid, cr))) { 715 /* 716 * Directories do not have an 717 * entry for "." so only one link 718 * will be there 719 */ 720 err = EEXIST; /* SIGH should be ENOTEMPTY */ 721 } 722 if (err) { 723 rw_exit(&ip->i_contents); 724 if (mode == VDIR) { 725 rw_exit(&ip->i_rwlock); 726 } 727 goto out; 728 } 729 } else if (op == DR_REMOVE) { 730 /* 731 * unlink(2) requires a different check: allow only 732 * privileged processes to unlink a directory. 733 */ 734 struct vnode *vp = ITOV(ip); 735 736 if (vp->v_type == VDIR && 737 secpolicy_fs_linkdir(cr, vp->v_vfsp)) { 738 err = EPERM; 739 rw_exit(&ip->i_contents); 740 rw_exit(&ip->i_rwlock); 741 goto out; 742 } 743 } 744 rw_exit(&ip->i_contents); 745 746 /* 747 * Remove the cache'd entry, if any. 748 */ 749 dnlc_remove(ITOV(dp), namep); 750 751 /* 752 * We can collapse all the directory 753 * entries that are deleted into one big entry 754 * but the better way is to 755 * defer it till next directory entry 756 * creation. where we can do this 757 * in a more efficient way 758 */ 759 fid = slot.ep; 760 761 /* 762 * If this is the last entry 763 * just truncate the file instead 764 * of marking it deleted 765 */ 766 if ((slot.offset + FID_LEN(fid)) == dp->i_size) { 767 fbrelse(slot.fbp, S_OTHER); 768 if ((err = ud_itrunc(dp, slot.offset, 0, cr)) != 0) { 769 goto out; 770 } 771 } else { 772 fid->fid_flags |= FID_DELETED; 773 774 if ((err = ud_ip_off2bno(dp, slot.offset, &tbno)) != 0) { 775 goto out; 776 } 777 778 ud_make_tag(dp->i_udf, &fid->fid_tag, 779 UD_FILE_ID_DESC, tbno, FID_LEN(fid)); 780 781 err = ud_write_fid(dp, &slot, buf); 782 } 783 784 slot.fbp = NULL; 785 786 /* 787 * If we were removing a directory, it is 'gone' now so we can 788 * unlock it. 789 */ 790 if (mode == VDIR) { 791 rw_exit(&ip->i_rwlock); 792 } 793 794 mutex_enter(&dp->i_tlock); 795 dp->i_flag |= IUPD|ICHG; 796 mutex_exit(&dp->i_tlock); 797 mutex_enter(&ip->i_tlock); 798 ip->i_flag |= ICHG; 799 mutex_exit(&ip->i_tlock); 800 801 if (err != 0) { 802 goto out; 803 } 804 805 rw_enter(&ip->i_contents, RW_WRITER); 806 807 /* 808 * Now dispose of the inode. 809 */ 810 if (ip->i_nlink > 0) { 811 if ((op == DR_RMDIR) && (ip->i_type == VDIR)) { 812 /* 813 * Decrement by 1 because there is no "." 814 * Clear the inode, but there may be other hard 815 * links so don't free the inode. 816 * Decrement the dp linkcount because we're 817 * trashing the ".." entry. 818 */ 819 ip->i_nlink --; 820 dp->i_nlink--; 821 dnlc_remove(ITOV(ip), "."); 822 dnlc_remove(ITOV(ip), ".."); 823 /* 824 * (void) ud_itrunc(ip, 0, 0, cr); 825 */ 826 } else { 827 ip->i_nlink--; 828 } 829 } 830 ITIMES_NOLOCK(dp); 831 ITIMES_NOLOCK(ip); 832 rw_exit(&ip->i_contents); 833 out: 834 if (mode == VDIR) { 835 vn_vfsunlock(ITOV(ip)); 836 } 837 out_novfs: 838 ASSERT(RW_WRITE_HELD(&dp->i_contents)); 839 840 if (slot.fbp != NULL) { 841 fbrelse(slot.fbp, S_OTHER); 842 } 843 rw_exit(&dp->i_contents); 844 845 if (ip) { 846 /* 847 * If no errors, send any events after locks are dropped, 848 * but before the VN_RELE(). 849 */ 850 if (err == 0) { 851 if (op == DR_REMOVE) { 852 vnevent_remove(ITOV(ip)); 853 } else if (op == DR_RMDIR) { 854 vnevent_rmdir(ITOV(ip)); 855 } 856 } 857 VN_RELE(ITOV(ip)); 858 } 859 860 kmem_free(buf, udf_vfsp->udf_lbsize); 861 return (err); 862 } 863 864 int 865 ud_dircheckforname(struct ud_inode *tdp, 866 char *namep, int32_t namelen, struct slot *slotp, 867 struct ud_inode **ipp, uint8_t *buf, struct cred *cr) 868 { 869 struct udf_vfs *udf_vfsp; 870 uint32_t dirsize, offset; 871 struct fbuf *fbp; 872 struct file_id *fid; 873 int32_t sz, error = 0, sz_req, matched = 0; 874 uint8_t *nm; 875 876 uint8_t *dname; 877 int32_t id_len; 878 879 ud_printf("ud_dircheckforname\n"); 880 881 ASSERT(RW_WRITE_HELD(&tdp->i_rwlock)); 882 fbp = NULL; 883 884 dname = (uint8_t *)kmem_zalloc(1024, KM_SLEEP); 885 886 udf_vfsp = tdp->i_udf; 887 888 offset = 0; 889 dirsize = tdp->i_size; 890 891 if (slotp->status != FOUND) { 892 int32_t temp; 893 894 temp = 1024; /* set to size of dname allocated above */ 895 if ((error = ud_compress(namelen, &temp, 896 (uint8_t *)namep, dname)) != 0) { 897 goto end; 898 } 899 sz_req = F_LEN + temp; 900 sz_req = (sz_req + 3) & ~3; 901 } 902 903 while (offset < dirsize) { 904 if ((error = ud_get_next_fid(tdp, &fbp, 905 offset, &fid, &nm, buf)) != 0) { 906 break; 907 } 908 if ((error = ud_uncompress(fid->fid_idlen, 909 &id_len, nm, dname)) != 0) { 910 break; 911 } 912 if ((fid->fid_flags & FID_DELETED) == 0) { 913 /* Check for name match */ 914 if (((namelen == id_len) && 915 (strncmp(namep, (caddr_t)dname, namelen) == 916 0)) || 917 ((fid->fid_flags & FID_PARENT) && 918 (namep[0] == '.' && 919 (namelen == 1 || 920 (namelen == 2 && namep[1] == '.'))))) { 921 922 tdp->i_diroff = offset; 923 if ((fid->fid_flags & FID_PARENT) && 924 (namelen == 1) && (namep[0] == '.')) { 925 struct vnode *vp = ITOV(tdp); 926 927 *ipp = tdp; 928 VN_HOLD(vp); 929 } else { 930 uint16_t prn; 931 uint32_t loc; 932 933 prn = SWAP_16(fid->fid_icb.lad_ext_prn); 934 loc = SWAP_32(fid->fid_icb.lad_ext_loc); 935 if ((error = ud_iget(tdp->i_vfs, prn, 936 loc, ipp, NULL, cr)) != 0) { 937 938 fbrelse(fbp, S_OTHER); 939 goto end; 940 } 941 } 942 slotp->status = EXIST; 943 slotp->offset = offset; 944 slotp->size = FID_LEN(fid); 945 slotp->fbp = fbp; 946 slotp->ep = fid; 947 slotp->endoff = 0; 948 goto end; 949 } 950 } else { 951 /* 952 * see if we need to find an 953 * empty slot and the current slot 954 * matches 955 */ 956 if ((slotp->status != FOUND) || 957 (matched == 0)) { 958 sz = FID_LEN(fid); 959 if (sz == sz_req) { 960 slotp->status = FOUND; 961 slotp->offset = offset; 962 slotp->size = sz; 963 } 964 if (matched == 0) { 965 if ((namelen == id_len) && 966 (strncmp(namep, (caddr_t)dname, 967 namelen) == 0)) { 968 matched = 1; 969 slotp->status = FOUND; 970 slotp->offset = offset; 971 slotp->size = sz; 972 } 973 } 974 } 975 } 976 offset += FID_LEN(fid); 977 } 978 if (fbp) { 979 fbrelse(fbp, S_OTHER); 980 } 981 if (slotp->status == NONE) { 982 /* 983 * We didn't find a slot; the new directory entry should be put 984 * at the end of the directory. Return an indication of where 985 * this is, and set "endoff" to zero; since we're going to have 986 * to extend the directory, we're certainly not going to 987 * trucate it. 988 */ 989 slotp->offset = dirsize; 990 if (tdp->i_desc_type == ICB_FLAG_ONE_AD) { 991 slotp->size = tdp->i_max_emb - tdp->i_size; 992 } else { 993 slotp->size = udf_vfsp->udf_lbsize - 994 slotp->offset & udf_vfsp->udf_lbmask; 995 } 996 slotp->endoff = 0; 997 } 998 999 *ipp = NULL; 1000 end: 1001 kmem_free((caddr_t)dname, 1024); 1002 return (error); 1003 } 1004 1005 /* 1006 * Return 1 if the dir has all files 1007 * deleted except the parent 1008 * else return 0 1009 */ 1010 /* ARGSUSED */ 1011 int 1012 ud_dirempty(struct ud_inode *ip, uint64_t ino, struct cred *cr) 1013 { 1014 offset_t off; 1015 int32_t empty = 1, error, count, entry_len, rcount; 1016 struct file_id *fid; 1017 caddr_t addr; 1018 uint32_t tbno; 1019 int32_t desc_len; 1020 1021 ud_printf("ud_dirempty\n"); 1022 1023 ASSERT(RW_LOCK_HELD(&ip->i_contents)); 1024 1025 if (ip->i_size == 0) { 1026 return (empty); 1027 } 1028 1029 desc_len = 1024; 1030 addr = kmem_zalloc(desc_len, KM_SLEEP); 1031 fid = (struct file_id *)addr; 1032 1033 for (off = 0; off < ip->i_size; off += entry_len) { 1034 1035 /* 1036 * First read fid 1037 * and verify checksum 1038 */ 1039 1040 rcount = sizeof (struct file_id); 1041 error = ud_rdwri(UIO_READ, FREAD, 1042 ip, addr, rcount, off, 1043 UIO_SYSSPACE, &count, cr); 1044 if ((error != 0) || (count != 0)) { 1045 empty = 0; 1046 break; 1047 } 1048 1049 if ((error = ud_ip_off2bno(ip, off, &tbno)) != 0) { 1050 empty = 0; 1051 break; 1052 } 1053 1054 /* 1055 * We verify the tag id and also the FID_LEN. 1056 * FID_LEN should be <= desc_len. 1057 */ 1058 if (ud_verify_tag_and_desc(&fid->fid_tag, 1059 UD_FILE_ID_DESC, 1060 tbno, 0, desc_len) != 0) { 1061 /* Corrupted directory */ 1062 empty = 0; 1063 break; 1064 } 1065 1066 /* 1067 * Read the fid + iulen + len 1068 * Now verify both checksum andCRC 1069 */ 1070 1071 rcount = FID_LEN(fid); 1072 error = ud_rdwri(UIO_READ, FREAD, 1073 ip, addr, rcount, off, 1074 UIO_SYSSPACE, &count, cr); 1075 if ((error != 0) || (count != 0)) { 1076 empty = 0; 1077 break; 1078 } 1079 /* 1080 * Now that the entire decsriptor is read we verify the 1081 * crc. 1082 */ 1083 if (ud_verify_tag_and_desc(&fid->fid_tag, 1084 UD_FILE_ID_DESC, 1085 tbno, 1086 1, rcount) != 0) { 1087 /* Corrupted directory */ 1088 empty = 0; 1089 break; 1090 } 1091 1092 /* 1093 * Is the file deleted 1094 */ 1095 1096 if ((fid->fid_flags & FID_DELETED) == 0) { 1097 if ((fid->fid_flags & FID_PARENT) == 0) { 1098 empty = 0; 1099 break; 1100 } 1101 } 1102 entry_len = FID_LEN(fid); 1103 } 1104 1105 kmem_free(addr, 1024); 1106 1107 return (empty); 1108 } 1109 1110 1111 int 1112 ud_dircheckpath(int32_t blkno, 1113 struct ud_inode *target, struct cred *cr) 1114 { 1115 int32_t err = 0; 1116 struct vfs *vfsp; 1117 struct udf_vfs *udf_vfsp; 1118 struct fbuf *fbp; 1119 struct file_id *fid; 1120 struct ud_inode *ip, *tip; 1121 uint16_t prn; 1122 uint32_t lbno, dummy, tbno; 1123 daddr_t parent_icb_loc; 1124 1125 ud_printf("ud_dircheckpath\n"); 1126 1127 udf_vfsp = target->i_udf; 1128 ip = target; 1129 1130 ASSERT(udf_vfsp != NULL); 1131 ASSERT(MUTEX_HELD(&target->i_udf->udf_rename_lck)); 1132 ASSERT(RW_WRITE_HELD(&ip->i_rwlock)); 1133 1134 if (ip->i_icb_lbano == blkno) { 1135 err = EINVAL; 1136 goto out; 1137 } 1138 if (ip->i_icb_lbano == udf_vfsp->udf_root_blkno) { 1139 goto out; 1140 } 1141 1142 /* 1143 * Search back through the directory tree, using the PARENT entries 1144 * Fail any attempt to move a directory into an ancestor directory. 1145 */ 1146 for (;;) { 1147 if ((err = fbread(ITOV(ip), 0, 1148 udf_vfsp->udf_lbsize, S_READ, &fbp)) != 0) { 1149 break; 1150 } 1151 1152 if ((err = ud_ip_off2bno(ip, 0, &tbno)) != 0) { 1153 break; 1154 } 1155 fid = (struct file_id *)fbp->fb_addr; 1156 /* IS this a valid file_identifier */ 1157 if (ud_verify_tag_and_desc(&fid->fid_tag, 1158 UD_FILE_ID_DESC, 1159 tbno, 1160 1, udf_vfsp->udf_lbsize) != 0) { 1161 break; 1162 } 1163 if ((fid->fid_flags & FID_DELETED) != 0) { 1164 break; 1165 } 1166 if ((fid->fid_flags & FID_PARENT) == 0) { 1167 /* 1168 * This cannot happen unless 1169 * something is grossly wrong 1170 * First entry has to be parent 1171 */ 1172 break; 1173 } 1174 prn = SWAP_16(fid->fid_icb.lad_ext_prn); 1175 lbno = SWAP_32(fid->fid_icb.lad_ext_loc); 1176 parent_icb_loc = ud_xlate_to_daddr(udf_vfsp, 1177 prn, lbno, 1, &dummy); 1178 ASSERT(dummy == 1); 1179 if (parent_icb_loc == blkno) { 1180 err = EINVAL; 1181 break; 1182 } 1183 vfsp = ip->i_vfs; 1184 udf_vfsp = ip->i_udf; 1185 if (parent_icb_loc == udf_vfsp->udf_root_blkno) { 1186 break; 1187 } 1188 if (fbp != NULL) { 1189 fbrelse(fbp, S_OTHER); 1190 fbp = NULL; 1191 } 1192 if (ip != target) { 1193 rw_exit(&ip->i_rwlock); 1194 VN_RELE(ITOV(ip)); 1195 } 1196 1197 /* 1198 * Race to get the inode. 1199 */ 1200 if (err = ud_iget(vfsp, prn, lbno, &tip, NULL, cr)) { 1201 ip = NULL; 1202 break; 1203 } 1204 ip = tip; 1205 rw_enter(&ip->i_rwlock, RW_READER); 1206 } 1207 if (fbp) { 1208 fbrelse(fbp, S_OTHER); 1209 } 1210 out: 1211 if (ip) { 1212 if (ip != target) { 1213 rw_exit(&ip->i_rwlock); 1214 VN_RELE(ITOV(ip)); 1215 } 1216 } 1217 return (err); 1218 } 1219 1220 int 1221 ud_dirmakeinode(struct ud_inode *tdp, struct ud_inode **ipp, 1222 struct vattr *vap, enum de_op op, struct cred *cr) 1223 { 1224 struct ud_inode *ip; 1225 int32_t error; 1226 1227 ASSERT(vap != NULL); 1228 ASSERT(op == DE_CREATE || op == DE_MKDIR); 1229 ASSERT((vap->va_mask & (AT_TYPE|AT_MODE)) == (AT_TYPE|AT_MODE)); 1230 ASSERT(RW_WRITE_HELD(&tdp->i_rwlock)); 1231 1232 /* 1233 * Allocate a new inode. 1234 */ 1235 if ((error = ud_ialloc(tdp, &ip, vap, cr)) != 0) { 1236 return (error); 1237 } 1238 1239 ASSERT(ip != NULL); 1240 1241 rw_enter(&ip->i_contents, RW_WRITER); 1242 1243 if (op == DE_MKDIR) { 1244 error = ud_dirmakedirect(ip, tdp, cr); 1245 } 1246 1247 ip->i_flag |= IACC|IUPD|ICHG; 1248 /* 1249 * Clear IACC and/or IUPD if the caller specified the atime and/or 1250 * mtime fields. They were set from the passed in attributes in 1251 * ud_ialloc(). 1252 */ 1253 if (vap->va_mask & AT_ATIME) 1254 ip->i_flag &= ~IACC; 1255 if (vap->va_mask & AT_MTIME) 1256 ip->i_flag &= ~IUPD; 1257 /* 1258 * push inode before it's name appears in a directory 1259 */ 1260 ud_iupdat(ip, 1); 1261 *ipp = ip; 1262 rw_exit(&ip->i_contents); 1263 return (error); 1264 } 1265 1266 /* 1267 * Enter the file sip in the directory tdp with name namep. 1268 */ 1269 int 1270 ud_diraddentry(struct ud_inode *tdp, char *namep, 1271 enum de_op op, int32_t namelen, struct slot *slotp, 1272 struct ud_inode *sip, struct ud_inode *sdp, struct cred *cr) 1273 { 1274 struct udf_vfs *udf_vfsp; 1275 int32_t error, temp; 1276 struct file_id *fid; 1277 uint8_t *buf = NULL; 1278 1279 ASSERT(RW_WRITE_HELD(&tdp->i_rwlock)); 1280 1281 ud_printf("ud_diraddentry\n"); 1282 1283 udf_vfsp = sip->i_udf; 1284 1285 /* 1286 * Check inode to be linked to see if it is in the 1287 * same filesystem. 1288 */ 1289 if (ITOV(tdp)->v_vfsp != ITOV(sip)->v_vfsp) { 1290 error = EXDEV; 1291 goto bad; 1292 } 1293 1294 if ((op == DE_RENAME) && (sip->i_type == VDIR)) { 1295 if ((error = ud_dirfixdotdot(sip, sdp, tdp)) != 0) { 1296 goto bad; 1297 } 1298 } 1299 1300 buf = (uint8_t *)kmem_zalloc(udf_vfsp->udf_lbsize, KM_SLEEP); 1301 1302 /* 1303 * Fill in entry data. 1304 */ 1305 fid = (struct file_id *)buf; 1306 fid->fid_ver = SWAP_16(1); 1307 if (sip->i_type == VDIR) { 1308 fid->fid_flags = FID_DIR; 1309 } else { 1310 fid->fid_flags = 0; 1311 } 1312 fid->fid_iulen = 0; 1313 1314 fid->fid_icb.lad_ext_len = SWAP_32(sip->i_udf->udf_lbsize); 1315 fid->fid_icb.lad_ext_loc = SWAP_32(sip->i_icb_block); 1316 fid->fid_icb.lad_ext_prn = SWAP_16(sip->i_icb_prn); 1317 fid->fid_iulen = 0; 1318 1319 temp = udf_vfsp->udf_lbsize - F_LEN; 1320 if ((error = ud_compress(namelen, &temp, 1321 (uint8_t *)namep, fid->fid_spec)) == 0) { 1322 fid->fid_idlen = (uint8_t)temp; 1323 error = ud_dirprepareentry(tdp, slotp, buf, cr); 1324 } 1325 1326 kmem_free(buf, udf_vfsp->udf_lbsize); 1327 1328 bad: 1329 return (error); 1330 } 1331 1332 /* 1333 * Write a prototype directory into the empty inode ip, whose parent is dp. 1334 */ 1335 /* ARGSUSED2 */ 1336 int 1337 ud_dirmakedirect(struct ud_inode *ip, 1338 struct ud_inode *dp, struct cred *cr) 1339 { 1340 int32_t err; 1341 uint32_t blkno, size, parent_len, tbno; 1342 struct fbuf *fbp; 1343 struct file_id *fid; 1344 struct icb_ext *iext; 1345 1346 ud_printf("ud_dirmakedirect\n"); 1347 1348 ASSERT(RW_WRITE_HELD(&ip->i_contents)); 1349 ASSERT(RW_WRITE_HELD(&dp->i_rwlock)); 1350 1351 parent_len = sizeof (struct file_id); 1352 1353 if ((ip->i_desc_type != ICB_FLAG_ONE_AD) || 1354 (parent_len > ip->i_max_emb)) { 1355 ASSERT(ip->i_ext); 1356 /* 1357 * Allocate space for the directory we're creating. 1358 */ 1359 if ((err = ud_alloc_space(ip->i_vfs, ip->i_icb_prn, 1360 0, 1, &blkno, &size, 0, 0)) != 0) { 1361 return (err); 1362 } 1363 /* 1364 * init with the size of 1365 * directory with just the 1366 * parent 1367 */ 1368 ip->i_size = sizeof (struct file_id); 1369 ip->i_flag |= IUPD|ICHG|IATTCHG; 1370 iext = ip->i_ext; 1371 iext->ib_prn = ip->i_icb_prn; 1372 iext->ib_block = blkno; 1373 iext->ib_count = ip->i_size; 1374 iext->ib_offset = 0; 1375 ip->i_ext_used = 1; 1376 } else { 1377 ip->i_size = sizeof (struct file_id); 1378 ip->i_flag |= IUPD|ICHG|IATTCHG; 1379 } 1380 1381 ITIMES_NOLOCK(ip); 1382 1383 /* 1384 * Update the dp link count and write out the change. 1385 * This reflects the ".." entry we'll soon write. 1386 */ 1387 if (dp->i_nlink == MAXLINK) { 1388 return (EMLINK); 1389 } 1390 dp->i_nlink++; 1391 dp->i_flag |= ICHG; 1392 ud_iupdat(dp, 1); 1393 1394 /* 1395 * Initialize directory with ".." 1396 * Since the parent directory is locked, we don't have to 1397 * worry about anything changing when we drop the write 1398 * lock on (ip). 1399 */ 1400 rw_exit(&ip->i_contents); 1401 if ((err = fbread(ITOV(ip), (offset_t)0, 1402 ip->i_udf->udf_lbsize, S_WRITE, &fbp)) != 0) { 1403 rw_enter(&ip->i_contents, RW_WRITER); 1404 return (err); 1405 } 1406 1407 bzero(fbp->fb_addr, ip->i_udf->udf_lbsize); 1408 1409 fid = (struct file_id *)fbp->fb_addr; 1410 fid->fid_ver = SWAP_16(1); 1411 fid->fid_flags = FID_DIR | FID_PARENT; 1412 fid->fid_icb.lad_ext_len = SWAP_32(dp->i_udf->udf_lbsize); 1413 fid->fid_icb.lad_ext_loc = SWAP_32(dp->i_icb_block); 1414 fid->fid_icb.lad_ext_prn = SWAP_16(dp->i_icb_prn); 1415 1416 /* 1417 * fid_idlen, fid_iulen and fid_spec are zero 1418 * due to bzero above 1419 */ 1420 1421 if ((err = ud_ip_off2bno(ip, 0, &tbno)) == 0) { 1422 ud_make_tag(ip->i_udf, &fid->fid_tag, 1423 UD_FILE_ID_DESC, tbno, FID_LEN(fid)); 1424 } 1425 1426 err = ud_fbwrite(fbp, ip); 1427 rw_enter(&ip->i_contents, RW_WRITER); 1428 1429 return (err); 1430 } 1431 1432 int 1433 ud_dirrename(struct ud_inode *sdp, struct ud_inode *sip, 1434 struct ud_inode *tdp, struct ud_inode *tip, char *namep, 1435 uint8_t *buf, struct slot *slotp, struct cred *cr) 1436 { 1437 int32_t error = 0, doingdirectory; 1438 struct file_id *fid; 1439 1440 ud_printf("ud_dirrename\n"); 1441 ASSERT(sdp->i_udf != NULL); 1442 ASSERT(MUTEX_HELD(&sdp->i_udf->udf_rename_lck)); 1443 ASSERT(RW_WRITE_HELD(&tdp->i_rwlock)); 1444 ASSERT(buf); 1445 ASSERT(slotp->ep); 1446 1447 fid = slotp->ep; 1448 1449 /* 1450 * Short circuit rename of something to itself. 1451 */ 1452 if (sip->i_icb_lbano == tip->i_icb_lbano) { 1453 return (ESAME); /* special KLUDGE error code */ 1454 } 1455 /* 1456 * Everything is protected under the vfs_rename_lock so the ordering 1457 * of i_contents locks doesn't matter here. 1458 */ 1459 rw_enter(&sip->i_contents, RW_READER); 1460 rw_enter(&tip->i_contents, RW_READER); 1461 1462 /* 1463 * Check that everything is on the same filesystem. 1464 */ 1465 if ((ITOV(tip)->v_vfsp != ITOV(tdp)->v_vfsp) || 1466 (ITOV(tip)->v_vfsp != ITOV(sip)->v_vfsp)) { 1467 error = EXDEV; /* XXX archaic */ 1468 goto out; 1469 } 1470 1471 /* 1472 * Must have write permission to rewrite target entry. 1473 */ 1474 if ((error = ud_iaccess(tdp, IWRITE, cr)) != 0 || 1475 (error = ud_sticky_remove_access(tdp, tip, cr)) != 0) 1476 goto out; 1477 1478 /* 1479 * Ensure source and target are compatible (both directories 1480 * or both not directories). If target is a directory it must 1481 * be empty and have no links to it; in addition it must not 1482 * be a mount point, and both the source and target must be 1483 * writable. 1484 */ 1485 doingdirectory = (sip->i_type == VDIR); 1486 if (tip->i_type == VDIR) { 1487 if (!doingdirectory) { 1488 error = EISDIR; 1489 goto out; 1490 } 1491 /* 1492 * vn_vfswlock will prevent mounts from using the directory 1493 * until we are done. 1494 */ 1495 if (vn_vfswlock(ITOV(tip))) { 1496 error = EBUSY; 1497 goto out; 1498 } 1499 if (vn_mountedvfs(ITOV(tip)) != NULL) { 1500 vn_vfsunlock(ITOV(tip)); 1501 error = EBUSY; 1502 goto out; 1503 } 1504 if (!ud_dirempty(tip, tdp->i_uniqid, cr) || tip->i_nlink > 2) { 1505 vn_vfsunlock(ITOV(tip)); 1506 error = EEXIST; /* SIGH should be ENOTEMPTY */ 1507 goto out; 1508 } 1509 } else if (doingdirectory) { 1510 error = ENOTDIR; 1511 goto out; 1512 } 1513 1514 /* 1515 * Rewrite the inode pointer for target name entry 1516 * from the target inode (ip) to the source inode (sip). 1517 * This prevents the target entry from disappearing 1518 * during a crash. Mark the directory inode to reflect the changes. 1519 */ 1520 dnlc_remove(ITOV(tdp), namep); 1521 fid->fid_icb.lad_ext_prn = SWAP_16(sip->i_icb_prn); 1522 fid->fid_icb.lad_ext_loc = SWAP_32(sip->i_icb_block); 1523 dnlc_enter(ITOV(tdp), namep, ITOV(sip)); 1524 1525 ud_make_tag(tdp->i_udf, &fid->fid_tag, UD_FILE_ID_DESC, 1526 SWAP_32(fid->fid_tag.tag_loc), FID_LEN(fid)); 1527 1528 error = ud_write_fid(tdp, slotp, buf); 1529 1530 if (error) { 1531 if (doingdirectory) { 1532 vn_vfsunlock(ITOV(tip)); 1533 } 1534 goto out; 1535 } 1536 1537 /* 1538 * Upgrade to write lock on tip 1539 */ 1540 rw_exit(&tip->i_contents); 1541 rw_enter(&tip->i_contents, RW_WRITER); 1542 1543 mutex_enter(&tdp->i_tlock); 1544 tdp->i_flag |= IUPD|ICHG; 1545 mutex_exit(&tdp->i_tlock); 1546 /* 1547 * Decrement the link count of the target inode. 1548 * Fix the ".." entry in sip to point to dp. 1549 * This is done after the new entry is on the disk. 1550 */ 1551 tip->i_nlink--; 1552 mutex_enter(&tip->i_tlock); 1553 tip->i_flag |= ICHG; 1554 mutex_exit(&tip->i_tlock); 1555 1556 if (doingdirectory) { 1557 /* 1558 * The entry for tip no longer exists so I can unlock the 1559 * vfslock. 1560 */ 1561 vn_vfsunlock(ITOV(tip)); 1562 /* 1563 * Decrement target link count once more if it was a directory. 1564 */ 1565 if (tip->i_nlink != 0) { 1566 cmn_err(CE_WARN, 1567 "ud_direnter: target directory link count != 0"); 1568 rw_exit(&tip->i_contents); 1569 rw_exit(&sip->i_contents); 1570 return (EINVAL); 1571 } 1572 /* 1573 * Renaming a directory with the parent different 1574 * requires that ".." be rewritten. The window is 1575 * still there for ".." to be inconsistent, but this 1576 * is unavoidable, and a lot shorter than when it was 1577 * done in a user process. We decrement the link 1578 * count in the new parent as appropriate to reflect 1579 * the just-removed target. If the parent is the 1580 * same, this is appropriate since the original 1581 * directory is going away. If the new parent is 1582 * different, dirfixdotdot() will bump the link count 1583 * back. 1584 */ 1585 tdp->i_nlink--; 1586 mutex_enter(&tdp->i_tlock); 1587 tdp->i_flag |= ICHG; 1588 mutex_exit(&tdp->i_tlock); 1589 ITIMES_NOLOCK(tdp); 1590 if (sdp != tdp) { 1591 rw_exit(&tip->i_contents); 1592 rw_exit(&sip->i_contents); 1593 error = ud_dirfixdotdot(sip, sdp, tdp); 1594 return (error); 1595 } 1596 } 1597 1598 out: 1599 rw_exit(&tip->i_contents); 1600 rw_exit(&sip->i_contents); 1601 return (error); 1602 } 1603 1604 1605 /* 1606 * 1. When we find a slot that belonged to a file which was deleted 1607 * and is in the middle of the directory 1608 * 2. There is not empty slot available. The new entry 1609 * will be at the end of the directory and fits in the same block. 1610 * 3. There is no empty slot available. The new 1611 * entry will not fit the left over directory 1612 * so we need to allocate a new block. If 1613 * we cannot allocate a proximity block we need 1614 * to allocate a new icb, and data block. 1615 */ 1616 int 1617 ud_dirprepareentry(struct ud_inode *dp, 1618 struct slot *slotp, uint8_t *buf, struct cred *cr) 1619 { 1620 struct fbuf *fbp; 1621 uint16_t old_dtype; 1622 int32_t error = 0; 1623 uint32_t entrysize, count, offset, tbno, old_size, off; 1624 struct file_id *fid; 1625 int32_t lbsize, lbmask, mask; 1626 1627 ASSERT(RW_WRITE_HELD(&dp->i_rwlock)); 1628 1629 ASSERT((slotp->status == NONE) || 1630 (slotp->status == FOUND)); 1631 1632 ud_printf("ud_dirprepareentry\n"); 1633 lbsize = dp->i_udf->udf_lbsize; 1634 lbmask = dp->i_udf->udf_lbmask; 1635 mask = ~lbmask; 1636 1637 fid = (struct file_id *)buf; 1638 entrysize = FID_LEN(fid); 1639 1640 /* 1641 * If we didn't find a slot, then indicate that the 1642 * new slot belongs at the end of the directory. 1643 * If we found a slot, then the new entry can be 1644 * put at slotp->offset. 1645 */ 1646 if (slotp->status == NONE) { 1647 /* 1648 * We did not find a slot, the next 1649 * entry will be in the end of the directory 1650 * see if we can fit the new entry inside 1651 * the old block. If not allocate a new block. 1652 */ 1653 if (entrysize > slotp->size) { 1654 /* 1655 * extend the directory 1656 * size by one new block 1657 */ 1658 old_dtype = dp->i_desc_type; 1659 old_size = (uint32_t)dp->i_size; 1660 error = ud_bmap_write(dp, slotp->offset, 1661 blkoff(dp->i_udf, slotp->offset) + entrysize, 1662 0, cr); 1663 if (error != 0) { 1664 return (error); 1665 } 1666 if (old_dtype != dp->i_desc_type) { 1667 /* 1668 * oops we changed the astrat 1669 * of the file, we have to 1670 * recaliculate tags 1671 * fortunately we donot have more 1672 * than one lbsize to handle here 1673 */ 1674 if ((error = ud_ip_off2bno(dp, 1675 0, &tbno)) != 0) { 1676 return (error); 1677 } 1678 if ((error = fbread(ITOV(dp), 0, 1679 dp->i_udf->udf_lbsize, 1680 S_WRITE, &fbp)) != 0) { 1681 return (error); 1682 } 1683 off = 0; 1684 while (off < old_size) { 1685 struct file_id *tfid; 1686 1687 tfid = (struct file_id *) 1688 (fbp->fb_addr + off); 1689 1690 ud_make_tag(dp->i_udf, &tfid->fid_tag, 1691 UD_FILE_ID_DESC, tbno, FID_LEN(tfid)); 1692 1693 off += FID_LEN(tfid); 1694 } 1695 if (error = ud_fbwrite(fbp, dp)) { 1696 return (error); 1697 } 1698 } 1699 } else { 1700 /* Extend the directory size */ 1701 if (dp->i_desc_type != ICB_FLAG_ONE_AD) { 1702 ASSERT(dp->i_ext); 1703 dp->i_ext[dp->i_ext_used - 1].ib_count += 1704 entrysize; 1705 } 1706 } 1707 dp->i_size += entrysize; 1708 dp->i_flag |= IUPD|ICHG|IATTCHG; 1709 ITIMES_NOLOCK(dp); 1710 } else if (slotp->status != FOUND) { 1711 cmn_err(CE_WARN, "status is not NONE/FOUND"); 1712 return (EINVAL); 1713 } 1714 1715 if ((error = ud_ip_off2bno(dp, slotp->offset, &tbno)) != 0) { 1716 return (error); 1717 } 1718 ud_make_tag(dp->i_udf, &fid->fid_tag, 1719 UD_FILE_ID_DESC, tbno, FID_LEN(fid)); 1720 1721 /* 1722 * fbread cannot cross a 1723 * MAXBSIZE boundary so handle it here 1724 */ 1725 offset = slotp->offset; 1726 if ((error = fbread(ITOV(dp), offset & mask, lbsize, 1727 S_WRITE, &fbp)) != 0) { 1728 return (error); 1729 } 1730 if ((offset & mask) != ((offset + entrysize) & mask)) { 1731 count = entrysize - ((offset + entrysize) & lbmask); 1732 } else { 1733 count = entrysize; 1734 } 1735 bcopy((caddr_t)buf, fbp->fb_addr + (offset & lbmask), count); 1736 1737 if (error = ud_fbwrite(fbp, dp)) { 1738 return (error); 1739 } 1740 1741 if (entrysize > count) { 1742 if ((error = fbread(ITOV(dp), (offset + entrysize) & mask, 1743 lbsize, S_WRITE, &fbp)) != 0) { 1744 return (error); 1745 } 1746 bcopy((caddr_t)(buf + count), fbp->fb_addr, entrysize - count); 1747 if (error = ud_fbwrite(fbp, dp)) { 1748 return (error); 1749 } 1750 } 1751 1752 dp->i_flag |= IUPD|ICHG|IATTCHG; 1753 ITIMES_NOLOCK(dp); 1754 return (error); 1755 } 1756 1757 1758 /* 1759 * Fix the FID_PARENT entry of the child directory so that it points 1760 * to the new parent directory instead of the old one. Routine 1761 * assumes that dp is a directory and that all the inodes are on 1762 * the same file system. 1763 */ 1764 int 1765 ud_dirfixdotdot(struct ud_inode *dp, 1766 struct ud_inode *opdp, struct ud_inode *npdp) 1767 { 1768 int32_t err = 0; 1769 struct fbuf *fbp; 1770 struct file_id *fid; 1771 uint32_t loc, dummy, tbno; 1772 1773 ud_printf("ud_dirfixdotdot\n"); 1774 1775 ASSERT(opdp->i_type == VDIR); 1776 ASSERT(npdp->i_type == VDIR); 1777 1778 ASSERT(RW_WRITE_HELD(&npdp->i_rwlock)); 1779 1780 err = fbread(ITOV(dp), (offset_t)0, 1781 dp->i_udf->udf_lbsize, S_WRITE, &fbp); 1782 1783 if (err || dp->i_nlink == 0 || 1784 dp->i_size < sizeof (struct file_id)) { 1785 goto bad; 1786 } 1787 1788 if ((err = ud_ip_off2bno(dp, 0, &tbno)) != 0) { 1789 goto bad; 1790 } 1791 1792 fid = (struct file_id *)fbp->fb_addr; 1793 if ((ud_verify_tag_and_desc(&fid->fid_tag, UD_FILE_ID_DESC, 1794 tbno, 1795 1, dp->i_udf->udf_lbsize) != 0) || 1796 ((fid->fid_flags & (FID_DIR | FID_PARENT)) != 1797 (FID_DIR | FID_PARENT))) { 1798 err = ENOTDIR; 1799 goto bad; 1800 } 1801 1802 loc = ud_xlate_to_daddr(dp->i_udf, 1803 SWAP_16(fid->fid_icb.lad_ext_prn), 1804 SWAP_32(fid->fid_icb.lad_ext_loc), 1, &dummy); 1805 ASSERT(dummy == 1); 1806 if (loc == npdp->i_icb_lbano) { 1807 goto bad; 1808 } 1809 1810 /* 1811 * Increment the link count in the new parent inode and force it out. 1812 */ 1813 if (npdp->i_nlink == MAXLINK) { 1814 err = EMLINK; 1815 goto bad; 1816 } 1817 1818 npdp->i_nlink++; 1819 mutex_enter(&npdp->i_tlock); 1820 npdp->i_flag |= ICHG; 1821 mutex_exit(&npdp->i_tlock); 1822 ud_iupdat(npdp, 1); 1823 1824 /* 1825 * Rewrite the child FID_PARENT entry and force it out. 1826 */ 1827 dnlc_remove(ITOV(dp), ".."); 1828 fid->fid_icb.lad_ext_loc = SWAP_32(npdp->i_icb_block); 1829 fid->fid_icb.lad_ext_prn = SWAP_16(npdp->i_icb_prn); 1830 ud_make_tag(npdp->i_udf, &fid->fid_tag, 1831 UD_FILE_ID_DESC, tbno, FID_LEN(fid)); 1832 dnlc_enter(ITOV(dp), "..", ITOV(npdp)); 1833 1834 err = ud_fbwrite(fbp, dp); 1835 fbp = NULL; 1836 if (err != 0) { 1837 goto bad; 1838 } 1839 1840 /* 1841 * Decrement the link count of the old parent inode and force 1842 * it out. If opdp is NULL, then this is a new directory link; 1843 * it has no parent, so we need not do anything. 1844 */ 1845 if (opdp != NULL) { 1846 rw_enter(&opdp->i_contents, RW_WRITER); 1847 if (opdp->i_nlink != 0) { 1848 opdp->i_nlink--; 1849 mutex_enter(&opdp->i_tlock); 1850 opdp->i_flag |= ICHG; 1851 mutex_exit(&opdp->i_tlock); 1852 ud_iupdat(opdp, 1); 1853 } 1854 rw_exit(&opdp->i_contents); 1855 } 1856 return (0); 1857 1858 bad: 1859 if (fbp) { 1860 fbrelse(fbp, S_OTHER); 1861 } 1862 return (err); 1863 } 1864 1865 int32_t 1866 ud_write_fid(struct ud_inode *dp, struct slot *slot, uint8_t *buf) 1867 { 1868 struct udf_vfs *udf_vfsp; 1869 struct fbuf *lfbp; 1870 struct file_id *fid; 1871 int32_t error = 0; 1872 uint32_t lbsize, lbmask, count, old_count; 1873 1874 1875 ASSERT(slot->fbp); 1876 ASSERT(slot->ep); 1877 1878 udf_vfsp = dp->i_udf; 1879 fid = slot->ep; 1880 lbsize = dp->i_udf->udf_lbsize; 1881 lbmask = dp->i_udf->udf_lbmask; 1882 1883 if (((uint8_t *)fid >= buf) && 1884 ((uint8_t *)fid < &buf[udf_vfsp->udf_lbsize])) { 1885 1886 1887 if ((error = fbread(ITOV(dp), 1888 (offset_t)(slot->offset & ~lbmask), 1889 lbsize, S_WRITE, &lfbp)) != 0) { 1890 goto out; 1891 } 1892 1893 1894 /* 1895 * We do not need to write the 1896 * file name. So check if the entry 1897 * does not cross a block boundary 1898 * and write only required portions 1899 */ 1900 if (((slot->offset & lbmask) + 1901 sizeof (struct file_id)) > lbsize) { 1902 1903 if ((slot->offset & lbmask) != 0) { 1904 old_count = lbsize - 1905 (slot->offset & lbmask); 1906 count = (slot->offset + 1907 sizeof (struct file_id)) & 1908 lbmask; 1909 } else { 1910 old_count = 0; 1911 count = sizeof (struct file_id); 1912 } 1913 1914 bcopy(buf, lfbp->fb_addr + 1915 (slot->offset & lbmask), old_count); 1916 bcopy(buf + old_count, 1917 slot->fbp->fb_addr, count); 1918 1919 error = ud_fbwrite(lfbp, dp); 1920 1921 error = ud_fbwrite(slot->fbp, dp); 1922 } else { 1923 bcopy(buf, lfbp->fb_addr + 1924 (slot->offset & lbmask), 1925 sizeof (struct file_id)); 1926 1927 error = ud_fbwrite(lfbp, dp); 1928 1929 fbrelse(slot->fbp, S_OTHER); 1930 } 1931 } else { 1932 if ((error = ud_fbwrite(slot->fbp, dp)) != 0) { 1933 fid->fid_flags &= ~FID_DELETED; 1934 ud_make_tag(dp->i_udf, &fid->fid_tag, UD_FILE_ID_DESC, 1935 SWAP_32(fid->fid_tag.tag_loc), FID_LEN(fid)); 1936 } 1937 } 1938 slot->fbp = NULL; 1939 1940 out: 1941 return (error); 1942 } 1943