1/* $NetBSD: lfs_rename.c,v 1.25 2021/10/20 03:08:19 thorpej Exp $ */ 2/* from NetBSD: ufs_rename.c,v 1.12 2015/03/27 17:27:56 riastradh Exp */ 3 4/*- 5 * Copyright (c) 2012 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Taylor R Campbell. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32/*- 33 * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc. 34 * All rights reserved. 35 * 36 * This code is derived from software contributed to The NetBSD Foundation 37 * by Konrad E. Schroder <perseant@hhhh.org>. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 49 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 50 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 51 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 52 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 53 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 54 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 55 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 56 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 57 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 58 * POSSIBILITY OF SUCH DAMAGE. 59 */ 60/* 61 * Copyright (c) 1986, 1989, 1991, 1993, 1995 62 * The Regents of the University of California. All rights reserved. 63 * 64 * Redistribution and use in source and binary forms, with or without 65 * modification, are permitted provided that the following conditions 66 * are met: 67 * 1. Redistributions of source code must retain the above copyright 68 * notice, this list of conditions and the following disclaimer. 69 * 2. Redistributions in binary form must reproduce the above copyright 70 * notice, this list of conditions and the following disclaimer in the 71 * documentation and/or other materials provided with the distribution. 72 * 3. Neither the name of the University nor the names of its contributors 73 * may be used to endorse or promote products derived from this software 74 * without specific prior written permission. 75 * 76 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 77 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 78 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 79 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 80 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 81 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 82 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 83 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 84 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 85 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 86 * SUCH DAMAGE. 87 * 88 * @(#)lfs_vnops.c 8.13 (Berkeley) 6/10/95 89 */ 90 91#include <sys/cdefs.h> 92__KERNEL_RCSID(0, "$NetBSD: lfs_rename.c,v 1.25 2021/10/20 03:08:19 thorpej Exp $"); 93 94#include <sys/param.h> 95#include <sys/systm.h> 96#include <sys/errno.h> 97#include <sys/namei.h> 98#include <sys/resourcevar.h> 99#include <sys/kernel.h> 100#include <sys/file.h> 101#include <sys/stat.h> 102#include <sys/buf.h> 103#include <sys/proc.h> 104#include <sys/mount.h> 105#include <sys/vnode.h> 106#include <sys/vnode_if.h> 107#include <sys/pool.h> 108#include <sys/signalvar.h> 109#include <sys/kauth.h> 110#include <sys/syslog.h> 111 112#include <miscfs/fifofs/fifo.h> 113#include <miscfs/genfs/genfs.h> 114#include <miscfs/specfs/specdev.h> 115 116#include <ufs/lfs/ulfs_inode.h> 117#include <ufs/lfs/ulfsmount.h> 118#include <ufs/lfs/ulfs_bswap.h> 119#include <ufs/lfs/ulfs_extern.h> 120 121#include <ufs/lfs/lfs.h> 122#include <ufs/lfs/lfs_accessors.h> 123#include <ufs/lfs/lfs_extern.h> 124 125/* 126 * ulfs_gro_directory_empty_p: Return true if the directory vp is 127 * empty. dvp is its parent. 128 * 129 * vp and dvp must be locked and referenced. 130 */ 131static bool 132ulfs_gro_directory_empty_p(struct mount *mp, kauth_cred_t cred, 133 struct vnode *vp, struct vnode *dvp) 134{ 135 136 (void)mp; 137 KASSERT(mp != NULL); 138 KASSERT(vp != NULL); 139 KASSERT(dvp != NULL); 140 KASSERT(vp != dvp); 141 KASSERT(vp->v_mount == mp); 142 KASSERT(dvp->v_mount == mp); 143 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 144 KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); 145 146 return ulfs_dirempty(VTOI(vp), VTOI(dvp)->i_number, cred); 147} 148 149/* 150 * ulfs_gro_rename_check_possible: Check whether a rename is possible 151 * independent of credentials. 152 */ 153static int 154ulfs_gro_rename_check_possible(struct mount *mp, 155 struct vnode *fdvp, struct vnode *fvp, 156 struct vnode *tdvp, struct vnode *tvp) 157{ 158 159 (void)mp; 160 KASSERT(mp != NULL); 161 KASSERT(fdvp != NULL); 162 KASSERT(fvp != NULL); 163 KASSERT(tdvp != NULL); 164 KASSERT(fdvp != fvp); 165 KASSERT(fdvp != tvp); 166 KASSERT(tdvp != fvp); 167 KASSERT(tdvp != tvp); 168 KASSERT(fvp != tvp); 169 KASSERT(fdvp->v_type == VDIR); 170 KASSERT(tdvp->v_type == VDIR); 171 KASSERT(fdvp->v_mount == mp); 172 KASSERT(fvp->v_mount == mp); 173 KASSERT(tdvp->v_mount == mp); 174 KASSERT((tvp == NULL) || (tvp->v_mount == mp)); 175 KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE); 176 KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE); 177 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE); 178 KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE)); 179 180 return genfs_ufslike_rename_check_possible( 181 VTOI(fdvp)->i_flags, VTOI(fvp)->i_flags, 182 VTOI(tdvp)->i_flags, (tvp? VTOI(tvp)->i_flags : 0), 183 (tvp != NULL), 184 IMMUTABLE, APPEND); 185} 186 187/* 188 * ulfs_gro_rename_check_permitted: Check whether a rename is permitted 189 * given our credentials. 190 */ 191static int 192ulfs_gro_rename_check_permitted(struct mount *mp, kauth_cred_t cred, 193 struct vnode *fdvp, struct vnode *fvp, 194 struct vnode *tdvp, struct vnode *tvp) 195{ 196 197 (void)mp; 198 KASSERT(mp != NULL); 199 KASSERT(fdvp != NULL); 200 KASSERT(fvp != NULL); 201 KASSERT(tdvp != NULL); 202 KASSERT(fdvp != fvp); 203 KASSERT(fdvp != tvp); 204 KASSERT(tdvp != fvp); 205 KASSERT(tdvp != tvp); 206 KASSERT(fvp != tvp); 207 KASSERT(fdvp->v_type == VDIR); 208 KASSERT(tdvp->v_type == VDIR); 209 KASSERT(fdvp->v_mount == mp); 210 KASSERT(fvp->v_mount == mp); 211 KASSERT(tdvp->v_mount == mp); 212 KASSERT((tvp == NULL) || (tvp->v_mount == mp)); 213 KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE); 214 KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE); 215 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE); 216 KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE)); 217 218 return genfs_ufslike_rename_check_permitted(cred, 219 fdvp, VTOI(fdvp)->i_mode, VTOI(fdvp)->i_uid, 220 fvp, VTOI(fvp)->i_uid, 221 tdvp, VTOI(tdvp)->i_mode, VTOI(tdvp)->i_uid, 222 tvp, (tvp? VTOI(tvp)->i_uid : 0)); 223} 224 225/* 226 * ulfs_gro_remove_check_possible: Check whether a remove is possible 227 * independent of credentials. 228 */ 229static int 230ulfs_gro_remove_check_possible(struct mount *mp, 231 struct vnode *dvp, struct vnode *vp) 232{ 233 234 (void)mp; 235 KASSERT(mp != NULL); 236 KASSERT(dvp != NULL); 237 KASSERT(vp != NULL); 238 KASSERT(dvp != vp); 239 KASSERT(dvp->v_type == VDIR); 240 KASSERT(vp->v_type != VDIR); 241 KASSERT(dvp->v_mount == mp); 242 KASSERT(vp->v_mount == mp); 243 KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); 244 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 245 246 return genfs_ufslike_remove_check_possible( 247 VTOI(dvp)->i_flags, VTOI(vp)->i_flags, 248 IMMUTABLE, APPEND); 249} 250 251/* 252 * ulfs_gro_remove_check_permitted: Check whether a remove is permitted 253 * given our credentials. 254 */ 255static int 256ulfs_gro_remove_check_permitted(struct mount *mp, kauth_cred_t cred, 257 struct vnode *dvp, struct vnode *vp) 258{ 259 260 (void)mp; 261 KASSERT(mp != NULL); 262 KASSERT(dvp != NULL); 263 KASSERT(vp != NULL); 264 KASSERT(dvp != vp); 265 KASSERT(dvp->v_type == VDIR); 266 KASSERT(vp->v_type != VDIR); 267 KASSERT(dvp->v_mount == mp); 268 KASSERT(vp->v_mount == mp); 269 KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); 270 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 271 272 return genfs_ufslike_remove_check_permitted(cred, 273 dvp, VTOI(dvp)->i_mode, VTOI(dvp)->i_uid, vp, VTOI(vp)->i_uid); 274} 275 276/* 277 * ulfs_rename_ulr_overlap_p: True iff tulr overlaps with fulr so that 278 * entering a directory entry at tulr may move fulr. 279 */ 280static bool 281ulfs_rename_ulr_overlap_p(const struct ulfs_lookup_results *fulr, 282 const struct ulfs_lookup_results *tulr) 283{ 284 doff_t from_prev_start, from_prev_end, to_start, to_end; 285 286 KASSERT(fulr != NULL); 287 KASSERT(tulr != NULL); 288 KASSERT(fulr != tulr); 289 290 /* 291 * fulr is from a DELETE lookup, so fulr->ulr_count is the size 292 * of the preceding entry (d_reclen). 293 */ 294 from_prev_end = fulr->ulr_offset; 295 KASSERT(fulr->ulr_count <= from_prev_end); 296 from_prev_start = (from_prev_end - fulr->ulr_count); 297 298 /* 299 * tulr is from a RENAME lookup, so tulr->ulr_count is the size 300 * of the free space for an entry that we are about to fill. 301 */ 302 to_start = tulr->ulr_offset; 303 KASSERT(tulr->ulr_count < (LFS_MAXDIRSIZE - to_start)); 304 to_end = (to_start + tulr->ulr_count); 305 306 return 307 (((to_start <= from_prev_start) && (from_prev_start < to_end)) || 308 ((to_start <= from_prev_end) && (from_prev_end < to_end))); 309} 310 311/* 312 * ulfs_direct_namlen: Return the namlen of the directory entry ep from 313 * the directory vp. 314 */ 315static int /* XXX int? uint8_t? */ 316ulfs_direct_namlen(const LFS_DIRHEADER *ep, const struct vnode *vp) 317{ 318 struct lfs *fs; 319 320 KASSERT(ep != NULL); 321 KASSERT(vp != NULL); 322 KASSERT(VTOI(vp) != NULL); 323 KASSERT(VTOI(vp)->i_ump != NULL); 324 KASSERT(VTOI(vp)->i_lfs != NULL); 325 fs = VTOI(vp)->i_lfs; 326 327 return lfs_dir_getnamlen(fs, ep); 328} 329 330/* 331 * ulfs_rename_recalculate_fulr: If we have just entered a directory into 332 * dvp at tulr, and we were about to remove one at fulr for an entry 333 * named fcnp, fulr may be invalid. So, if necessary, recalculate it. 334 */ 335static int 336ulfs_rename_recalculate_fulr(struct vnode *dvp, 337 struct ulfs_lookup_results *fulr, const struct ulfs_lookup_results *tulr, 338 const struct componentname *fcnp) 339{ 340 struct mount *mp; 341 struct lfs *fs; 342 struct ulfsmount *ump; 343 /* XXX int is a silly type for this; blame ulfsmount::um_dirblksiz. */ 344 int dirblksiz; 345 doff_t search_start, search_end; 346 doff_t offset; /* Offset of entry we're examining. */ 347 struct buf *bp; /* I/O block we're examining. */ 348 char *dirbuf; /* Pointer into directory at search_start. */ 349 LFS_DIRHEADER *ep; /* Pointer to the entry we're examining. */ 350 /* XXX direct::d_reclen is 16-bit; 351 * ulfs_lookup_results::ulr_reclen is 32-bit. Blah. */ 352 uint32_t reclen; /* Length of the entry we're examining. */ 353 uint32_t prev_reclen; /* Length of the preceding entry. */ 354 int error; 355 356 KASSERT(dvp != NULL); 357 KASSERT(dvp->v_mount != NULL); 358 KASSERT(VTOI(dvp) != NULL); 359 KASSERT(fulr != NULL); 360 KASSERT(tulr != NULL); 361 KASSERT(fulr != tulr); 362 KASSERT(ulfs_rename_ulr_overlap_p(fulr, tulr)); 363 364 mp = dvp->v_mount; 365 ump = VFSTOULFS(mp); 366 fs = ump->um_lfs; 367 KASSERT(ump != NULL); 368 KASSERT(ump == VTOI(dvp)->i_ump); 369 KASSERT(fs == VTOI(dvp)->i_lfs); 370 371 dirblksiz = fs->um_dirblksiz; 372 KASSERT(0 < dirblksiz); 373 KASSERT((dirblksiz & (dirblksiz - 1)) == 0); 374 375 /* A directory block may not span across multiple I/O blocks. */ 376 KASSERT(dirblksiz <= mp->mnt_stat.f_iosize); 377 378 /* Find the bounds of the search. */ 379 search_start = tulr->ulr_offset; 380 KASSERT(fulr->ulr_reclen < (LFS_MAXDIRSIZE - fulr->ulr_offset)); 381 search_end = (fulr->ulr_offset + fulr->ulr_reclen); 382 383 /* Compaction must happen only within a directory block. (*) */ 384 KASSERT(search_start <= search_end); 385 KASSERT((search_end - (search_start &~ (dirblksiz - 1))) <= dirblksiz); 386 387 dirbuf = NULL; 388 bp = NULL; 389 error = ulfs_blkatoff(dvp, (off_t)search_start, &dirbuf, &bp, false); 390 if (error) 391 return error; 392 KASSERT(dirbuf != NULL); 393 KASSERT(bp != NULL); 394 395 /* 396 * Guarantee we sha'n't go past the end of the buffer we got. 397 * dirbuf is bp->b_data + (search_start & (iosize - 1)), and 398 * the valid range is [bp->b_data, bp->b_data + bp->b_bcount). 399 */ 400 KASSERT((search_end - search_start) <= 401 (bp->b_bcount - (search_start & (mp->mnt_stat.f_iosize - 1)))); 402 403 prev_reclen = fulr->ulr_count; 404 offset = search_start; 405 406 /* 407 * Search from search_start to search_end for the entry matching 408 * fcnp, which must be there because we found it before and it 409 * should only at most have moved earlier. 410 */ 411 for (;;) { 412 KASSERT(search_start <= offset); 413 KASSERT(offset < search_end); 414 415 /* 416 * Examine the directory entry at offset. 417 */ 418 ep = (LFS_DIRHEADER *)(dirbuf + (offset - search_start)); 419 reclen = lfs_dir_getreclen(fs, ep); 420 421 if (lfs_dir_getino(fs, ep) == 0) 422 goto next; /* Entry is unused. */ 423 424 if (lfs_dir_getino(fs, ep) == ULFS_WINO) 425 goto next; /* Entry is whiteout. */ 426 427 if (fcnp->cn_namelen != ulfs_direct_namlen(ep, dvp)) 428 goto next; /* Wrong name length. */ 429 430 if (memcmp(lfs_dir_nameptr(fs, ep), fcnp->cn_nameptr, fcnp->cn_namelen)) 431 goto next; /* Wrong name. */ 432 433 /* Got it! */ 434 break; 435 436next: 437 if (! ((reclen < search_end) && 438 (offset < (search_end - reclen)))) { 439 brelse(bp, 0); 440 return EIO; /* XXX Panic? What? */ 441 } 442 443 /* We may not move past the search end. */ 444 KASSERT(reclen < search_end); 445 KASSERT(offset < (search_end - reclen)); 446 447 /* 448 * We may not move across a directory block boundary; 449 * see (*) above. 450 */ 451 KASSERT((offset &~ (dirblksiz - 1)) == 452 ((offset + reclen) &~ (dirblksiz - 1))); 453 454 prev_reclen = reclen; 455 offset += reclen; 456 } 457 458 /* 459 * Found the entry. Record where. 460 */ 461 fulr->ulr_offset = offset; 462 fulr->ulr_reclen = reclen; 463 464 /* 465 * Record the preceding record length, but not if we're at the 466 * start of a directory block. 467 */ 468 fulr->ulr_count = ((offset & (dirblksiz - 1))? prev_reclen : 0); 469 470 brelse(bp, 0); 471 return 0; 472} 473 474/* 475 * ulfs_gro_remove: Rename an object over another link to itself, 476 * effectively removing just the original link. 477 */ 478static int 479ulfs_gro_remove(struct mount *mp, kauth_cred_t cred, 480 struct vnode *dvp, struct componentname *cnp, void *de, struct vnode *vp, 481 nlink_t *tvp_nlinkp) 482{ 483 struct ulfs_lookup_results *ulr = de; 484 int error; 485 486 KASSERT(mp != NULL); 487 KASSERT(dvp != NULL); 488 KASSERT(cnp != NULL); 489 KASSERT(ulr != NULL); 490 KASSERT(vp != NULL); 491 KASSERT(dvp != vp); 492 KASSERT(dvp->v_mount == mp); 493 KASSERT(vp->v_mount == mp); 494 KASSERT(dvp->v_type == VDIR); 495 KASSERT(vp->v_type != VDIR); 496 KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); 497 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 498 KASSERT(cnp->cn_nameiop == DELETE); 499 500 /* XXX ulfs_dirremove decrements vp's link count for us. */ 501 error = ulfs_dirremove(dvp, ulr, VTOI(vp), cnp->cn_flags, 0); 502 503 *tvp_nlinkp = VTOI(vp)->i_nlink; 504 505 return error; 506} 507 508/* 509 * ulfs_gro_lookup: Look up and save the lookup results. 510 */ 511static int 512ulfs_gro_lookup(struct mount *mp, struct vnode *dvp, 513 struct componentname *cnp, void *de_ret, struct vnode **vp_ret) 514{ 515 struct ulfs_lookup_results *ulr_ret = de_ret; 516 struct vnode *vp = NULL; 517 int error; 518 519 (void)mp; 520 KASSERT(mp != NULL); 521 KASSERT(dvp != NULL); 522 KASSERT(cnp != NULL); 523 KASSERT(ulr_ret != NULL); 524 KASSERT(vp_ret != NULL); 525 KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); 526 527 /* Kludge cargo-culted from dholland's ulfs_rename. */ 528 cnp->cn_flags &=~ MODMASK; 529 cnp->cn_flags |= (LOCKPARENT | LOCKLEAF); 530 531 error = relookup(dvp, &vp, cnp, 0 /* dummy */); 532 if ((error == 0) && (vp == NULL)) { 533 error = ENOENT; 534 goto out; 535 } else if (error) { 536 return error; 537 } 538 539 /* 540 * Thanks to VFS insanity, relookup locks vp, which screws us 541 * in various ways. 542 */ 543 KASSERT(vp != NULL); 544 VOP_UNLOCK(vp); 545 546out: *ulr_ret = VTOI(dvp)->i_crap; 547 *vp_ret = vp; 548 return error; 549} 550 551/* 552 * ulfs_rmdired_p: Check whether the directory vp has been rmdired. 553 * 554 * vp must be locked and referenced. 555 */ 556static bool 557ulfs_rmdired_p(struct vnode *vp) 558{ 559 560 KASSERT(vp != NULL); 561 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 562 KASSERT(vp->v_type == VDIR); 563 564 /* XXX Is this correct? */ 565 return (VTOI(vp)->i_size == 0); 566} 567 568/* 569 * ulfs_read_dotdot: Store in *ino_ret the inode number of the parent 570 * of the directory vp. 571 */ 572static int 573ulfs_read_dotdot(struct vnode *vp, kauth_cred_t cred, ino_t *ino_ret) 574{ 575 struct lfs *fs; 576 union lfs_dirtemplate dirbuf; 577 LFS_DIRHEADER *dotdot; 578 const char *name; 579 int error; 580 581 KASSERT(vp != NULL); 582 KASSERT(ino_ret != NULL); 583 KASSERT(vp->v_type == VDIR); 584 585 KASSERT(VTOI(vp) != NULL); 586 KASSERT(VTOI(vp)->i_lfs != NULL); 587 fs = VTOI(vp)->i_lfs; 588 589 error = ulfs_bufio(UIO_READ, vp, &dirbuf, sizeof dirbuf, (off_t)0, 590 IO_NODELOCKED, cred, NULL, NULL); 591 if (error) 592 return error; 593 594 dotdot = lfs_dirtemplate_dotdot(fs, &dirbuf); 595 name = lfs_dirtemplate_dotdotname(fs, &dirbuf); 596 if (lfs_dir_getnamlen(fs, dotdot) != 2 || 597 name[0] != '.' || 598 name[1] != '.') 599 /* XXX Panic? Print warning? */ 600 return ENOTDIR; 601 602 *ino_ret = lfs_dir_getino(fs, dotdot); 603 return 0; 604} 605 606/* 607 * ulfs_gro_lock_directory: Lock the directory vp, but fail if it has 608 * been rmdir'd. 609 */ 610static int 611ulfs_gro_lock_directory(struct mount *mp, struct vnode *vp) 612{ 613 614 (void)mp; 615 KASSERT(mp != NULL); 616 KASSERT(vp != NULL); 617 KASSERT(vp->v_mount == mp); 618 619 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 620 621 if (ulfs_rmdired_p(vp)) { 622 VOP_UNLOCK(vp); 623 return ENOENT; 624 } 625 626 return 0; 627} 628 629/* 630 * ulfs_gro_genealogy: Analyze the genealogy of the source and target 631 * directories. 632 */ 633static int 634ulfs_gro_genealogy(struct mount *mp, kauth_cred_t cred, 635 struct vnode *fdvp, struct vnode *tdvp, 636 struct vnode **intermediate_node_ret) 637{ 638 struct vnode *vp, *dvp; 639 ino_t dotdot_ino = -1; /* XXX gcc 4.8: maybe-uninitialized */ 640 int error; 641 642 KASSERT(mp != NULL); 643 KASSERT(fdvp != NULL); 644 KASSERT(tdvp != NULL); 645 KASSERT(fdvp != tdvp); 646 KASSERT(intermediate_node_ret != NULL); 647 KASSERT(fdvp->v_mount == mp); 648 KASSERT(tdvp->v_mount == mp); 649 KASSERT(fdvp->v_type == VDIR); 650 KASSERT(tdvp->v_type == VDIR); 651 652 /* 653 * We need to provisionally lock tdvp to keep rmdir from 654 * deleting it -- or any ancestor -- at an inopportune moment. 655 */ 656 error = ulfs_gro_lock_directory(mp, tdvp); 657 if (error) 658 return error; 659 660 vp = tdvp; 661 vref(vp); 662 663 for (;;) { 664 KASSERT(vp != NULL); 665 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 666 KASSERT(vp->v_mount == mp); 667 KASSERT(vp->v_type == VDIR); 668 KASSERT(!ulfs_rmdired_p(vp)); 669 670 /* Did we hit the root without finding fdvp? */ 671 if (VTOI(vp)->i_number == ULFS_ROOTINO) { 672 vput(vp); 673 *intermediate_node_ret = NULL; 674 return 0; 675 } 676 677 error = ulfs_read_dotdot(vp, cred, &dotdot_ino); 678 if (error) { 679 vput(vp); 680 return error; 681 } 682 683 /* Did we find that fdvp is an ancestor of tdvp? */ 684 if (VTOI(fdvp)->i_number == dotdot_ino) { 685 /* Unlock vp, but keep it referenced. */ 686 VOP_UNLOCK(vp); 687 *intermediate_node_ret = vp; 688 return 0; 689 } 690 691 /* Neither -- keep ascending the family tree. */ 692 error = vcache_get(mp, &dotdot_ino, sizeof(dotdot_ino), &dvp); 693 vput(vp); 694 if (error) 695 return error; 696 error = vn_lock(dvp, LK_EXCLUSIVE); 697 if (error) { 698 vrele(dvp); 699 return error; 700 } 701 702 KASSERT(dvp != NULL); 703 KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); 704 vp = dvp; 705 706 if (vp->v_type != VDIR) { 707 /* 708 * XXX Panic? Print a warning? Can this 709 * happen if we lose the race I suspect to 710 * exist above, and the `..' inode number has 711 * been recycled? 712 */ 713 vput(vp); 714 return ENOTDIR; 715 } 716 717 if (ulfs_rmdired_p(vp)) { 718 vput(vp); 719 return ENOENT; 720 } 721 } 722} 723 724/* 725 * ulfs_gro_rename: Actually perform the rename operation. 726 */ 727static int 728ulfs_gro_rename(struct mount *mp, kauth_cred_t cred, 729 struct vnode *fdvp, struct componentname *fcnp, 730 void *fde, struct vnode *fvp, 731 struct vnode *tdvp, struct componentname *tcnp, 732 void *tde, struct vnode *tvp, nlink_t *tvp_nlinkp) 733{ 734 struct lfs *fs; 735 struct ulfs_lookup_results *fulr = fde; 736 struct ulfs_lookup_results *tulr = tde; 737 bool directory_p, reparent_p; 738 int error; 739 740 KASSERT(mp != NULL); 741 KASSERT(fdvp != NULL); 742 KASSERT(fcnp != NULL); 743 KASSERT(fulr != NULL); 744 KASSERT(fvp != NULL); 745 KASSERT(tdvp != NULL); 746 KASSERT(tcnp != NULL); 747 KASSERT(tulr != NULL); 748 KASSERT(fulr != tulr); 749 KASSERT(fdvp != fvp); 750 KASSERT(fdvp != tvp); 751 KASSERT(tdvp != fvp); 752 KASSERT(tdvp != tvp); 753 KASSERT(fvp != tvp); 754 KASSERT(fdvp->v_mount == mp); 755 KASSERT(fvp->v_mount == mp); 756 KASSERT(tdvp->v_mount == mp); 757 KASSERT((tvp == NULL) || (tvp->v_mount == mp)); 758 KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE); 759 KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE); 760 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE); 761 KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE)); 762 763 fs = VTOI(fdvp)->i_lfs; 764 KASSERT(fs == VTOI(tdvp)->i_lfs); 765 766 /* 767 * We shall need to temporarily bump the link count, so make 768 * sure there is room to do so. 769 */ 770 if ((nlink_t)VTOI(fvp)->i_nlink >= LINK_MAX) 771 return EMLINK; 772 773 directory_p = (fvp->v_type == VDIR); 774 KASSERT(directory_p == ((VTOI(fvp)->i_mode & LFS_IFMT) == LFS_IFDIR)); 775 KASSERT((tvp == NULL) || (directory_p == (tvp->v_type == VDIR))); 776 KASSERT((tvp == NULL) || (directory_p == 777 ((VTOI(tvp)->i_mode & LFS_IFMT) == LFS_IFDIR))); 778 779 reparent_p = (fdvp != tdvp); 780 KASSERT(reparent_p == (VTOI(fdvp)->i_number != VTOI(tdvp)->i_number)); 781 782 /* 783 * Commence hacking of the data on disk. 784 */ 785 786 error = 0; 787 788 /* 789 * 1) Bump link count while we're moving stuff 790 * around. If we crash somewhere before 791 * completing our work, the link count 792 * may be wrong, but correctable. 793 */ 794 795 KASSERT((nlink_t)VTOI(fvp)->i_nlink < LINK_MAX); 796 VTOI(fvp)->i_nlink++; 797 DIP_ASSIGN(VTOI(fvp), nlink, VTOI(fvp)->i_nlink); 798 VTOI(fvp)->i_state |= IN_CHANGE; 799 error = lfs_update(fvp, NULL, NULL, UPDATE_DIROP); 800 if (error) 801 goto whymustithurtsomuch; 802 803 /* 804 * 2) If target doesn't exist, link the target 805 * to the source and unlink the source. 806 * Otherwise, rewrite the target directory 807 * entry to reference the source inode and 808 * expunge the original entry's existence. 809 */ 810 811 if (tvp == NULL) { 812 /* 813 * Account for ".." in new directory. 814 * When source and destination have the same 815 * parent we don't fool with the link count. 816 */ 817 if (directory_p && reparent_p) { 818 if ((nlink_t)VTOI(tdvp)->i_nlink >= LINK_MAX) { 819 error = EMLINK; 820 goto whymustithurtsomuch; 821 } 822 KASSERT((nlink_t)VTOI(tdvp)->i_nlink < LINK_MAX); 823 VTOI(tdvp)->i_nlink++; 824 DIP_ASSIGN(VTOI(tdvp), nlink, VTOI(tdvp)->i_nlink); 825 VTOI(tdvp)->i_state |= IN_CHANGE; 826 error = lfs_update(tdvp, NULL, NULL, UPDATE_DIROP); 827 if (error) { 828 /* 829 * Link count update didn't take -- 830 * back out the in-memory link count. 831 */ 832 KASSERT(0 < VTOI(tdvp)->i_nlink); 833 VTOI(tdvp)->i_nlink--; 834 DIP_ASSIGN(VTOI(tdvp), nlink, 835 VTOI(tdvp)->i_nlink); 836 VTOI(tdvp)->i_state |= IN_CHANGE; 837 goto whymustithurtsomuch; 838 } 839 } 840 841 error = ulfs_direnter(tdvp, tulr, 842 NULL, tcnp, VTOI(fvp)->i_number, LFS_IFTODT(VTOI(fvp)->i_mode), 843 NULL); 844 if (error) { 845 if (directory_p && reparent_p) { 846 /* 847 * Directory update didn't take, but 848 * the link count update did -- back 849 * out the in-memory link count and the 850 * on-disk link count. 851 */ 852 KASSERT(0 < VTOI(tdvp)->i_nlink); 853 VTOI(tdvp)->i_nlink--; 854 DIP_ASSIGN(VTOI(tdvp), nlink, 855 VTOI(tdvp)->i_nlink); 856 VTOI(tdvp)->i_state |= IN_CHANGE; 857 (void)lfs_update(tdvp, NULL, NULL, 858 UPDATE_WAIT | UPDATE_DIROP); 859 } 860 goto whymustithurtsomuch; 861 } 862 } else { 863 if (directory_p) 864 /* XXX WTF? Why purge here? Why not purge others? */ 865 cache_purge(tdvp); 866 867 /* 868 * Make the target directory's entry for tcnp point at 869 * the source node. 870 * 871 * XXX ulfs_dirrewrite decrements tvp's link count, but 872 * doesn't touch the link count of the new inode. Go 873 * figure. 874 */ 875 error = ulfs_dirrewrite(VTOI(tdvp), tulr->ulr_offset, 876 VTOI(tvp), VTOI(fvp)->i_number, LFS_IFTODT(VTOI(fvp)->i_mode), 877 ((directory_p && reparent_p) ? reparent_p : directory_p), 878 IN_CHANGE | IN_UPDATE); 879 if (error) 880 goto whymustithurtsomuch; 881 882 /* 883 * If the source and target are directories, and the 884 * target is in the same directory as the source, 885 * decrement the link count of the common parent 886 * directory, since we are removing the target from 887 * that directory. 888 */ 889 if (directory_p && !reparent_p) { 890 KASSERT(fdvp == tdvp); 891 /* XXX check, don't kassert */ 892 KASSERT(0 < VTOI(tdvp)->i_nlink); 893 VTOI(tdvp)->i_nlink--; 894 DIP_ASSIGN(VTOI(tdvp), nlink, VTOI(tdvp)->i_nlink); 895 VTOI(tdvp)->i_state |= IN_CHANGE; 896 } 897 898 if (directory_p) { 899 /* 900 * XXX I don't understand the following comment 901 * from ulfs_rename -- in particular, the part 902 * about `there may be other hard links'. 903 * 904 * Truncate inode. The only stuff left in the directory 905 * is "." and "..". The "." reference is inconsequential 906 * since we are quashing it. We have removed the "." 907 * reference and the reference in the parent directory, 908 * but there may be other hard links. 909 * 910 * XXX The ulfs_dirempty call earlier does 911 * not guarantee anything about nlink. 912 */ 913 if (VTOI(tvp)->i_nlink != 1) 914 ulfs_dirbad(VTOI(tvp), (doff_t)0, 915 "hard-linked directory"); 916 VTOI(tvp)->i_nlink = 0; 917 DIP_ASSIGN(VTOI(tvp), nlink, 0); 918 error = lfs_truncate(tvp, (off_t)0, IO_SYNC, cred); 919 if (error) 920 goto whymustithurtsomuch; 921 } 922 } 923 924 /* 925 * If the source is a directory with a new parent, the link 926 * count of the old parent directory must be decremented and 927 * ".." set to point to the new parent. 928 * 929 * XXX ulfs_dirrewrite updates the link count of fdvp, but not 930 * the link count of fvp or the link count of tdvp. Go figure. 931 */ 932 if (directory_p && reparent_p) { 933 off_t position; 934 935 /* 936 * The .. entry goes immediately after the . entry, so 937 * the position is the record length of the . entry, 938 * namely LFS_DIRECTSIZ(1). 939 */ 940 position = LFS_DIRECTSIZ(fs, 1); 941 error = ulfs_dirrewrite(VTOI(fvp), position, 942 VTOI(fdvp), VTOI(tdvp)->i_number, LFS_DT_DIR, 0, IN_CHANGE); 943#if 0 /* XXX This branch was not in ulfs_rename! */ 944 if (error) 945 goto whymustithurtsomuch; 946#endif 947 948 /* XXX WTF? Why purge here? Why not purge others? */ 949 cache_purge(fdvp); 950 } 951 952 /* 953 * 3) Unlink the source. 954 */ 955 956 /* 957 * ulfs_direnter may compact the directory in the process of 958 * inserting a new entry. That may invalidate fulr, which we 959 * need in order to remove the old entry. In that case, we 960 * need to recalculate what fulr should be. 961 */ 962 if (!reparent_p && (tvp == NULL) && 963 ulfs_rename_ulr_overlap_p(fulr, tulr)) { 964 error = ulfs_rename_recalculate_fulr(fdvp, fulr, tulr, fcnp); 965#if 0 /* XXX */ 966 if (error) /* XXX Try to back out changes? */ 967 goto whymustithurtsomuch; 968#endif 969 } 970 971 /* 972 * XXX 0 means !isrmdir. But can't this be an rmdir? 973 * XXX Well, turns out that argument to ulfs_dirremove is ignored... 974 * XXX And it turns out ulfs_dirremove updates the link count of fvp. 975 * XXX But it doesn't update the link count of fdvp. Go figure. 976 * XXX fdvp's link count is updated in ulfs_dirrewrite instead. 977 * XXX Actually, sometimes it doesn't update fvp's link count. 978 * XXX I hate the world. 979 */ 980 error = ulfs_dirremove(fdvp, fulr, VTOI(fvp), fcnp->cn_flags, 0); 981 if (error) 982#if 0 /* XXX */ 983 goto whymustithurtsomuch; 984#endif 985 goto arghmybrainhurts; 986 987 if (tvp != NULL) { 988 *tvp_nlinkp = VTOI(tvp)->i_nlink; 989 } 990#if 0 /* XXX */ 991 genfs_rename_cache_purge(fdvp, fvp, tdvp, tvp); 992#endif 993 goto arghmybrainhurts; 994 995whymustithurtsomuch: 996 KASSERT(0 < VTOI(fvp)->i_nlink); 997 VTOI(fvp)->i_nlink--; 998 DIP_ASSIGN(VTOI(fvp), nlink, VTOI(fvp)->i_nlink); 999 VTOI(fvp)->i_state |= IN_CHANGE; 1000 1001arghmybrainhurts: 1002/*ihateyou:*/ 1003 return error; 1004} 1005 1006/* 1007 * lfs_gro_rename: Actually perform the rename operation. Do a little 1008 * LFS bookkeeping and then defer to ulfs_gro_rename. 1009 */ 1010static int 1011lfs_gro_rename(struct mount *mp, kauth_cred_t cred, 1012 struct vnode *fdvp, struct componentname *fcnp, 1013 void *fde, struct vnode *fvp, 1014 struct vnode *tdvp, struct componentname *tcnp, 1015 void *tde, struct vnode *tvp, nlink_t *tvp_nlinkp) 1016{ 1017 int error; 1018 1019 KASSERT(mp != NULL); 1020 KASSERT(fdvp != NULL); 1021 KASSERT(fcnp != NULL); 1022 KASSERT(fde != NULL); 1023 KASSERT(fvp != NULL); 1024 KASSERT(tdvp != NULL); 1025 KASSERT(tcnp != NULL); 1026 KASSERT(tde != NULL); 1027 KASSERT(fdvp != fvp); 1028 KASSERT(fdvp != tvp); 1029 KASSERT(tdvp != fvp); 1030 KASSERT(tdvp != tvp); 1031 KASSERT(fvp != tvp); 1032 KASSERT(fdvp->v_mount == mp); 1033 KASSERT(fvp->v_mount == mp); 1034 KASSERT(tdvp->v_mount == mp); 1035 KASSERT((tvp == NULL) || (tvp->v_mount == mp)); 1036 KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE); 1037 KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE); 1038 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE); 1039 KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE)); 1040 1041 error = lfs_set_dirop(tdvp, tvp); 1042 if (error != 0) 1043 return error; 1044 1045 MARK_VNODE(fdvp); 1046 MARK_VNODE(fvp); 1047 1048 error = ulfs_gro_rename(mp, cred, 1049 fdvp, fcnp, fde, fvp, 1050 tdvp, tcnp, tde, tvp, 1051 tvp_nlinkp); 1052 1053 if (tvp && VTOI(tvp)->i_nlink == 0) 1054 lfs_orphan(VTOI(tvp)->i_lfs, VTOI(tvp)->i_number); 1055 1056 UNMARK_VNODE(fdvp); 1057 UNMARK_VNODE(fvp); 1058 UNMARK_VNODE(tdvp); 1059 if (tvp) { 1060 UNMARK_VNODE(tvp); 1061 } 1062 lfs_unset_dirop(VFSTOULFS(mp)->um_lfs, tdvp, "rename"); 1063 vrele(tdvp); 1064 if (tvp) { 1065 vrele(tvp); 1066 } 1067 1068 return error; 1069} 1070 1071static const struct genfs_rename_ops lfs_genfs_rename_ops = { 1072 .gro_directory_empty_p = ulfs_gro_directory_empty_p, 1073 .gro_rename_check_possible = ulfs_gro_rename_check_possible, 1074 .gro_rename_check_permitted = ulfs_gro_rename_check_permitted, 1075 .gro_remove_check_possible = ulfs_gro_remove_check_possible, 1076 .gro_remove_check_permitted = ulfs_gro_remove_check_permitted, 1077 .gro_rename = lfs_gro_rename, 1078 .gro_remove = ulfs_gro_remove, 1079 .gro_lookup = ulfs_gro_lookup, 1080 .gro_genealogy = ulfs_gro_genealogy, 1081 .gro_lock_directory = ulfs_gro_lock_directory, 1082}; 1083 1084/* 1085 * lfs_sane_rename: The hairiest vop, with the saner API. 1086 * 1087 * Arguments: 1088 * 1089 * . fdvp (from directory vnode), 1090 * . fcnp (from component name), 1091 * . tdvp (to directory vnode), 1092 * . tcnp (to component name), 1093 * . cred (credentials structure), and 1094 * . posixly_correct (flag for behaviour if target & source link same file). 1095 * 1096 * fdvp and tdvp may be the same, and must be referenced and unlocked. 1097 */ 1098static int 1099lfs_sane_rename( 1100 struct vnode *fdvp, struct componentname *fcnp, 1101 struct vnode *tdvp, struct componentname *tcnp, 1102 kauth_cred_t cred, bool posixly_correct) 1103{ 1104 struct ulfs_lookup_results fulr, tulr; 1105 1106 /* 1107 * XXX Provisional kludge -- ulfs_lookup does not reject rename 1108 * of . or .. (from or to), so we hack it here. This is not 1109 * the right place: it should be caller's responsibility to 1110 * reject this case. 1111 */ 1112 KASSERT(fcnp != NULL); 1113 KASSERT(tcnp != NULL); 1114 KASSERT(fcnp != tcnp); 1115 KASSERT(fcnp->cn_nameptr != NULL); 1116 KASSERT(tcnp->cn_nameptr != NULL); 1117 1118 if ((fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT) 1119 return EINVAL; /* XXX EISDIR? */ 1120 if ((fcnp->cn_namelen == 1) && (fcnp->cn_nameptr[0] == '.')) 1121 return EINVAL; 1122 if ((tcnp->cn_namelen == 1) && (tcnp->cn_nameptr[0] == '.')) 1123 return EINVAL; 1124 1125 return genfs_sane_rename(&lfs_genfs_rename_ops, 1126 fdvp, fcnp, &fulr, tdvp, tcnp, &tulr, 1127 cred, posixly_correct); 1128} 1129 1130/* 1131 * lfs_rename: The hairiest vop, with the insanest API. Defer to 1132 * genfs_insane_rename immediately. 1133 */ 1134int 1135lfs_rename(void *v) 1136{ 1137 1138 return genfs_insane_rename(v, &lfs_sane_rename); 1139} 1140