1.\" $NetBSD: genfs_rename.9,v 1.5 2022/01/17 22:27:10 wiz Exp $ 2.\" 3.\" Copyright (c) 2013 The NetBSD Foundation, Inc. 4.\" All rights reserved. 5.\" 6.\" This documentation is derived from text contributed to The NetBSD 7.\" Foundation by Taylor R. Campbell. 8.\" 9.\" Redistribution and use in source and binary forms, with or without 10.\" modification, are permitted provided that the following conditions 11.\" are met: 12.\" 1. Redistributions of source code must retain the above copyright 13.\" notice, this list of conditions and the following disclaimer. 14.\" 2. Redistributions in binary form must reproduce the above copyright 15.\" notice, this list of conditions and the following disclaimer in the 16.\" documentation and/or other materials provided with the distribution. 17.\" 18.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28.\" POSSIBILITY OF SUCH DAMAGE. 29.\" 30.Dd May 1, 2013 31.Dt GENFS_RENAME 9 32.Os 33.Sh NAME 34.Nm genfs_rename , 35.Nm genfs_insane_rename , 36.Nm genfs_sane_rename 37.Nd generic framework for implementing 38.Xr VOP_RENAME 9 39.Sh SYNOPSIS 40.Ft int 41.Fo genfs_insane_rename 42.Fa "struct vop_rename_args *v" 43.Fa "int (*sane_rename)(struct vnode *fdvp, struct componentname *fcnp, struct vnode *tdvp, struct componentname *tcnp, kauth_cred_t, bool)" 44.Fc 45.Ft int 46.Fo genfs_sane_rename 47.Fa "const struct genfs_rename_ops *gro" 48.Fa "struct vnode *fdvp" 49.Fa "struct componentname *fcnp" 50.Fa "void *fde" 51.Fa "struct vnode *tdvp" 52.Fa "struct componentname *tcnp" 53.Fa "void *tde" 54.Fa "kauth_cred_t cred" 55.Fa "bool posixly_correct" 56.Fc 57.Ft int 58.Fo genfs_rename_knote 59.Fa "struct vnode *fdvp" 60.Fa "struct vnode *fvp" 61.Fa "struct vnode *tdvp" 62.Fa "struct vnode *tvp" 63.Fc 64.Ft void 65.Fo genfs_rename_cache_purge 66.Fa "struct vnode *fdvp" 67.Fa "struct vnode *fvp" 68.Fa "struct vnode *tdvp" 69.Fa "struct vnode *tvp" 70.Fc 71.Ft int 72.Fo genfs_ufslike_rename_check_possible 73.Fa "unsigned long fdflags" 74.Fa "unsigned long fflags" 75.Fa "unsigned long tdflags" 76.Fa "unsigned long tflags" 77.Fa "bool clobber" 78.Fa "unsigned long immutable" 79.Fa "unsigned long append" 80.Fc 81.Ft int 82.Fo genfs_ufslike_rename_check_permitted 83.Fa "kauth_cred_t cred" 84.Fa "struct vnode *fdvp" 85.Fa "mode_t fdmode" 86.Fa "uid_t fduid" 87.Fa "struct vnode *fvp" 88.Fa "uid_t fuid" 89.Fa "struct vnode *tdvp" 90.Fa "mode_t tdmode" 91.Fa "uid_t tduid" 92.Fa "struct vnode *tvp" 93.Fa "uid_t tuid" 94.Fc 95.Ft int 96.Fo genfs_ufslike_remove_check_possible 97.Fa "unsigned long dflags" 98.Fa "unsigned long flags" 99.Fa "unsigned long immutable" 100.Fa "unsigned long append" 101.Fc 102.Ft int 103.Fo genfs_ufslike_remove_check_permitted 104.Fa "kauth_cred_t cred" 105.Fa "struct vnode *dvp" 106.Fa "mode_t dmode" 107.Fa "uid_t duid" 108.Fa "struct vnode *vp" 109.Fa "uid_t uid" 110.Fc 111.Sh DESCRIPTION 112The 113.Nm 114functions provide a file-system-independent framework for implementing 115.Xr VOP_RENAME 9 116with correct locking and error-checking. 117.Pp 118Implementing rename is nontrivial. 119If you are doing it for a new file system, you should consider starting 120from 121.Fn tmpfs_rename 122as implemented in 123.Pa sys/fs/tmpfs/tmpfs_rename.c 124and adapting it to your file system's physical operations. 125.Pp 126Because there are so many moving parts to a rename operation, 127.Nm 128uses the following naming conventions: 129.Bl -tag -width indent 130.It Fa mp Pq "mount point" 131mount point of the file system in question 132.It Fa fdvp Pq "from directory vnode pointer" 133directory from which we are removing an entry 134.It Fa fcnp Pq "from componentname pointer" 135name of entry to remove from 136.Fa fdvp 137.It Fa fde Pq "from directory entry" 138fs-specific data about the entry in 139.Fa fdvp 140.It Fa fvp Pq "from vnode pointer" 141file at the entry named 142.Fa fcnp 143in 144.Fa fdvp 145.It Fa tdvp Pq "to directory vnode pointer" 146directory to which we are adding an entry 147.It Fa tcnp Pq "to componentname pointer" 148name of entry to add to 149.Fa tdvp 150.It Fa tde Pq "to directory entry" 151fs-specific data about the entry in 152.Fa tdvp 153.It Fa tvp Pq "to vnode pointer" 154file previously at the entry named 155.Fa tcnp 156in 157.Fa tdvp , 158to be replaced, if any, or 159.Dv NULL 160if there was no entry before 161.It Fa vp Pq "vnode pointer" 162any file 163.It Fa dvp Pq "directory vnode pointer" 164any directory with an entry for 165.Fa vp 166.El 167.Pp 168A file system mumblefs should implement various file-system-dependent 169parts of the rename operation in a 170.Vt struct genfs_rename_ops , 171and use 172.Nm 173to implement 174.Fn mumblefs_rename 175for 176.Xr VOP_RENAME 9 177as follows: 178.Bd -literal -offset indent 179static const struct genfs_rename_ops mumblefs_genfs_rename_ops; 180 181static int 182mumblefs_sane_rename( 183 struct vnode *fdvp, struct componentname *fcnp, 184 struct vnode *tdvp, struct componentname *tcnp, 185 kauth_cred_t cred, bool posixly_correct) 186{ 187 struct mumblefs_lookup_results fulr, tulr; 188 189 return genfs_sane_rename(&mumblefs_genfs_rename_ops, 190 fdvp, fcnp, &fulr, tdvp, tcnp, &tulr, 191 cred, posixly_correct); 192} 193 194int 195mumblefs_rename(void *v) 196{ 197 198 return genfs_insane_rename(v, &mumblefs_sane_rename); 199} 200.Ed 201.Pp 202The split between 203.Fn mumblefs_rename 204and 205.Fn mumblefs_sane_rename 206is designed to enable us to easily change the 207.Xr VOP_RENAME 9 208interface, which is currently designed for a broken (hence 209.Sq insane ) 210locking scheme, to a more sensible locking scheme once all the file 211systems have their rename operations split up thus. 212.Pp 213The 214.Vt struct mumblefs_lookup_results 215structure is storage for information about directory entries which 216needs to pass from the lookups of the children (see the 217.Fa gro_lookup 218member of 219.Vt "struct genfs_rename_ops" ) 220to the physical on-disk rename or remove operations (see the 221.Fa gro_rename 222and 223.Fa gro_remove 224members of 225.Vt "struct genfs_rename_ops" ) . 226.Pp 227Callers must implement the following operations as members in a 228.Vt struct genfs_rename_ops 229structure passed to 230.Nm : 231.Bl -tag -width indent 232.It Ft int Fn "(*gro_genealogy)" "struct mount *mp" "kauth_cred_t cred" "struct vnode *fdvp" "struct vnode *tdvp" "struct vnode **intermediate_node_ret" 233Walk up the directory tree from the directory vnode 234.Fa tdvp 235until hitting either 236.Fa fdvp 237or the root. 238If 239.Fa fdvp 240is hit, store the child of 241.Fa fdvp 242through which the path from 243.Fa tdvp 244passed in 245.Fa *intermediate_node_ret , 246referenced but unlocked. 247If 248.Fa fdvp 249is not hit, store 250.Dv NULL 251in 252.Fa *intermediate_node_ret . 253Return zero on success or error on failure. 254(Failure means file-system-specific failures, not hitting or missing 255.Fa fdvp . ) 256.Pp 257.Fa fdvp 258and 259.Fa tdvp 260are guaranteed to be distinct, non-null, referenced, and unlocked. 261Since no locks are held on entry except for the file-system-wide rename 262lock, 263.Fa gro_genealogy 264may take any locks it pleases. 265.It Ft int Fn "(*gro_lock_directory)" "struct mount *mp" "struct vnode *vp" 266Lock the directory vnode 267.Fa vp , 268but fail if it has been rmdired already. 269Return zero on success or error on failure. 270.It Ft int Fn "(*gro_lookup)" "struct mount *mp" "struct vnode *dvp" "struct componentname *cnp" "void *de" "struct vnode **vpp" 271Look up the entry in 272.Fa dvp 273for 274.Fa cnp , 275storing the vnode in 276.Fa "*vpp" 277and using 278.Fa de , 279one of the pointers passed to 280.Nm genfs_sane_rename , 281to store information about the directory entry as needed by the file 282system's 283.Fa gro_rename 284operation, and return zero. 285If there is no such entry, return error. 286.Pp 287.Fa dvp 288is guaranteed to be locked, and the vnode returned in 289.Fa "*vpp" 290must be unlocked. 291However, 292.Fa gro_lookup 293may temporarily lock the vnode without causing deadlock. 294.It Ft bool Fn "(*gro_directory_empty_p)" "struct mount *mp" "kauth_cred_t cred" "struct vnode *vp" "struct vnode *dvp" 295Return true if the directory vnode 296.Fa vp 297is empty. 298The argument 299.Fa dvp 300is the parent of 301.Fa vp , 302as required for this check by some file systems. 303.Pp 304.Fa dvp 305and 306.Fa vp 307are guaranteed to be distinct, non-null, referenced, and locked. 308.It Ft int Fn "(*gro_rename_check_possible)" "struct mount *mp" "struct vnode *fdvp" "struct vnode *fvp" "struct vnode *tdvp" "struct vnode *tvp" 309Return zero if the file system might allow the rename independent of 310credentials, or error if not. 311This should check, for example, any immutability flags in the vnodes in 312question, and should use 313.Fn genfs_ufslike_rename_check_possible 314for file systems similar to UFS/FFS. 315.Pp 316.Fa fdvp 317and 318.Fa tdvp 319may be the same; every other pair of vnodes is guaranteed to be 320distinct. 321.Fa tvp 322may be 323.Dv NULL ; 324every other vnode is guaranteed to be non-null. 325All three or four vnodes are guaranteed to be referenced and locked. 326.It Ft int Fn "(*gro_rename_check_permitted)" "struct mount *mp" "kauth_cred_t cred" "struct vnode *fdvp" "struct vnode *fvp" "struct vnode *tdvp" "struct vnode *tvp" 327Return zero if the file system allows the rename given the credentials 328.Fa cred , 329or error if not. 330This should check, for example, the ownership and permissions bits of 331the vnodes in question, and should use 332.Fn genfs_ufslike_rename_check_permitted 333for file systems similar to UFS/FFS. 334.Pp 335.Fa fdvp 336and 337.Fa tdvp 338may be the same; every other pair of vnodes is guaranteed to be 339distinct. 340.Fa tvp 341may be 342.Dv NULL ; 343every other vnode is guaranteed to be non-null. 344All three or four vnodes are guaranteed to be referenced and locked. 345.It Ft int Fn "(*gro_rename)" "struct mount *mp" "kauth_cred_t cred" "struct vnode *fdvp" "struct componentname *fcnp" "void *fde" "struct vnode *fvp" "struct vnode *tdvp" "struct componentname *tcnp" "void *tde" "struct vnode *tvp" 346Perform the physical file system rename operation, report any knotes, 347and purge the namecache entries. 348Return zero on success or error on failure. 349All file-system-independent error cases have been handled already. 350.Pp 351File systems using 352.Xr fstrans 9 353should use 354.Xr fstrans_start 9 355and 356.Xr fstrans_done 9 357here. 358.Fa fde 359and 360.Fa tde 361are the pointers that were supplied to 362.Fn genfs_sane_rename 363and got passed to the 364.Fa gro_lookup 365operation to find information about directory entries. 366.Pp 367This may use 368.Fn genfs_rename_knote 369to report any knotes, if the various file-system-dependent routines it 370uses to edit links don't do that already. 371This should use 372.Fn genfs_rename_cache_purge 373to purge the namecache. 374.Pp 375.Fa fdvp 376and 377.Fa tdvp 378may be the same; every other pair of vnodes is guaranteed to be 379distinct. 380.Fa tvp 381may be null; every other vnode is guaranteed to be non-null. 382All three or four vnodes are guaranteed to be referenced and locked. 383.It Ft int Fn "(*gro_remove_check_possible)" "struct mount *mp" "struct vnode *dvp" "struct vnode *vp" 384Return zero if the file system might allow removing an entry in 385.Fa dvp 386for 387.Fa vp 388independent of credentials, or error if not. 389This should use 390.Fn genfs_ufslike_remove_check_possible 391for file systems similar to UFS/FFS. 392.Pp 393.Fa dvp 394and 395.Fa vp 396are guaranteed to be distinct, non-null, referenced, and locked. 397.Pp 398This, and 399.Fa gro_remove_check_permitted 400below, are for renames that reduce to a remove; that is, renaming one 401entry to another when both entries refer to the same file. 402For reasons of locking insanity, 403.Nm 404cannot simply call 405.Xr VOP_REMOVE 9 406instead. 407.It Ft int Fn "(*gro_remove_check_permitted)" "struct mount *mp" "kauth_cred_t cred" "struct vnode *dvp" "struct vnode *vp" 408Return zero if the file system allows removing an entry in 409.Fa dvp 410for 411.Fa vp 412given the credentials 413.Fa cred , 414or error if not. 415This should use 416.Fn genfs_ufslike_remove_check_permitted 417for file systems similar to UFS/FFS. 418.Pp 419.Fa dvp 420and 421.Fa vp 422are guaranteed to be distinct, non-null, referenced, and locked. 423.It Ft int Fn "(*gro_remove)" "struct mount *mp" "kauth_cred_t cred" "struct vnode *dvp" "struct componentname *cnp" "void *de" "struct vnode *vp" 424For a rename that is effectively a remove, perform the physical file 425system remove operation, report any knotes, and purge the namecache 426entries. 427Return zero on success or error on failure. 428All file-system-independent error cases have been handled already. 429.Pp 430File systems using 431.Xr fstrans 9 432should use 433.Xr fstrans_start 9 434and 435.Xr fstrans_done 9 436here. 437.Fa de 438is one of the pointers that were supplied to 439.Fn genfs_sane_rename 440and got passed to the 441.Fa gro_lookup 442operation to find information about directory entries. 443.Pp 444This should signal a 445.Dv NOTE_WRITE 446knote for 447.Fa dvp , 448and either a 449.Dv NOTE_DELETE 450or a 451.Dv NOTE_LINK 452knote for 453.Fa vp , 454depending on whether this removed the last link to it or not. 455.Pp 456.Fa dvp 457and 458.Fa vp 459are guaranteed to be distinct, non-null, referenced, and locked. 460.El 461.Pp 462The following utilities are provided for implementing the 463.Vt struct genfs_rename_ops 464operations: 465.Bl -tag -width indent 466.It Fn genfs_rename_knote fdvp fvp tdvp tvp 467Signal all the knotes relevant for the rename operation. 468.It Fn genfs_rename_cache_purge fdvp fvp tdvp tvp 469Purge any namecache entries that the rename operation invalidates. 470.It Fn genfs_ufslike_rename_check_possible fdflags fflags tdflags tflags clobber immutable append 471Check whether the UFS/FFS-like flags of the files involved a rename 472allow it. 473Return zero if allowed or error if not. 474.Pp 475.Bl -tag -width immutable -compact 476.It Fa fdflags 477flags of source directory 478.It Fa fflags 479flags of source file 480.It Fa tdflags 481flags of target directory 482.It Fa tflags 483flags of target file, if there is one and 484.Fa clobber 485is true, or ignored otherwise 486.It Fa clobber 487true if there is a target file whose entry will be clobbered or false 488if not 489.It Fa immutable 490bit mask for the file system's immutable bit, like the UFS/FFS 491.Dv IMMUTABLE 492.It Fa append 493bit mask for the file system's append-only bit, like the UFS/FFS 494.Dv APPEND 495.El 496.It Fn genfs_ufslike_rename_check_permitted cred fdvp fdmode fduid fvp fuid tdvp tdmode tduid tvp tuid 497Check whether the credentials 498.Fa cred 499are permitted by the file ownership and permissions bits to perform a 500rename. 501Return zero if permitted or error if not. 502.Pp 503.Bl -tag -width fdmode -compact 504.It Fa cred 505caller's credentials 506.It Fa fdvp 507source directory 508.It Fa fdmode 509file permissions bits of 510.Fa fdvp 511.It Fa fduid 512uid of the owner of 513.Fa fdvp 514.It Fa fvp 515source file 516.It Fa fuid 517uid of owner of 518.Fa fvp 519.It Fa tdvp 520target directory 521.It Fa tdmode 522file permissions bits of 523.Fa tdvp 524.It Fa tduid 525uid of owner of 526.Fa tdvp 527.It Fa tvp 528target file, if there is one, or 529.Dv NULL 530if not 531.It Fa tuid 532uid of owner of 533.Fa tvp , 534if there is a target file, or ignored otherwise 535.El 536.It Fn genfs_ufslike_remove_check_possible dflags flags immutable append 537Check whether the UFS/FFS-like flags of the files involved a remove 538allow it. 539Return zero if allowed or error if not. 540.Pp 541.Bl -tag -width immutable -compact 542.It Fa dflags 543flags of the directory 544.It Fa flags 545flags of the file in the directory 546.It Fa immutable 547bit mask for the file system's immutable bit, like the UFS/FFS 548.Dv IMMUTABLE 549.It Fa append 550bit mask for the file system's append-only bit, like the UFS/FFS 551.Dv APPEND 552.El 553.It Fn genfs_ufslike_remove_check_permitted cred dvp dmode duid vp uid 554Check whether the credentials 555.Fa cred 556are permitted by the file ownership and permissions bits to perform a 557remove. 558Return zero if permitted or error if not. 559.Pp 560.Bl -tag -width fdmode -compact 561.It Fa cred 562caller's credentials 563.It Fa dvp 564directory 565.It Fa dmode 566file permissions bits of 567.Fa dvp 568.It Fa duid 569uid of owner of 570.Fa dvp 571.It Fa vp 572file in 573.Fa dvp 574.It Fa uid 575uid of owner of 576.Fa vp 577.El 578.El 579.Sh NOTES 580Because there are so many cases of rename, it cannot be assumed a 581priori that any pairs of 582.Fa fdvp , 583.Fa fvp , 584.Fa tdvp , 585or 586.Fa fvp 587are distinct: 588.Bl -column -offset indent \ 589"fdvp = tdvp" "rename(\*qa/b\*q, \*qa/c\*q)" 590.It Li "fdvp = fvp" Ta Li "rename(\*qa/.\*q, \*qb\*q)" 591.It Li "fdvp = tdvp" Ta Li "rename(\*qa/b\*q, \*qa/c\*q)" 592.It Li "fdvp = tvp" Ta Li "rename(\*qa/b\*q, \*qa\*q)" 593.It Li "fvp = tdvp" Ta Li "rename(\*qa\*q, \*qa/b\*q)" 594.It Li "fvp = tvp" Ta Li "rename(\*qa\*q, \*qa\*q)" 595.It Li "tdvp = tvp" Ta Li "rename(\*qa\*q, \*qb/.\*q)" 596.El 597.Pp 598Handling all these cases correctly, and getting the locking correct and 599deadlock-free, is very tricky, which is why 600.Nm 601exists. 602The interface to 603.Nm 604is very complicated because it must fit the insane 605.Xr VOP_RENAME 9 606and 607.Xr VOP_LOOKUP 9 608protocols until we can fix them, and because it must accommodate a 609variety of crufty file systems. 610.Sh SEE ALSO 611.Xr genfs 9 , 612.Xr vfs 9 , 613.Xr vnodeops 9 614.Sh HISTORY 615.Nm 616was designed and implemented by 617.An Taylor R. Campbell Aq Mt riastradh@NetBSD.org 618after many discussions with 619.An David Holland Aq Mt dholland@NetBSD.org , 620and first appeared in 621.Nx 6.0 . 622