| GENFS_RENAME(9) | Kernel Developer's Manual | GENFS_RENAME(9) | 
genfs_rename,
  genfs_insane_rename,
  genfs_sane_rename —
genfs_insane_rename(struct
  vop_rename_args *v, int (*sane_rename)(struct vnode
  *fdvp, struct componentname *fcnp, struct vnode *tdvp, struct componentname
  *tcnp, kauth_cred_t, bool));
int
  
  genfs_sane_rename(const struct
    genfs_rename_ops *gro, struct vnode *fdvp,
    struct componentname *fcnp, void
    *fde, struct vnode *tdvp, struct
    componentname *tcnp, void *tde,
    kauth_cred_t cred, bool
    posixly_correct);
int
  
  genfs_rename_knote(struct vnode
    *fdvp, struct vnode *fvp, struct
    vnode *tdvp, struct vnode *tvp);
void
  
  genfs_rename_cache_purge(struct vnode
    *fdvp, struct vnode *fvp, struct
    vnode *tdvp, struct vnode *tvp);
int
  
  genfs_ufslike_rename_check_possible(unsigned
    long fdflags, unsigned long fflags,
    unsigned long tdflags, unsigned long
    tflags, bool clobber, unsigned
    long immutable, unsigned long append);
int
  
  genfs_ufslike_rename_check_permitted(kauth_cred_t
    cred, struct vnode *fdvp, mode_t
    fdmode, uid_t fduid, struct
    vnode *fvp, uid_t fuid, struct
    vnode *tdvp, mode_t tdmode,
    uid_t tduid, struct vnode *tvp,
    uid_t tuid);
int
  
  genfs_ufslike_remove_check_possible(unsigned
    long dflags, unsigned long flags,
    unsigned long immutable, unsigned long
    append);
int
  
  genfs_ufslike_remove_check_permitted(kauth_cred_t
    cred, struct vnode *dvp, mode_t
    dmode, uid_t duid, struct vnode
    *vp, uid_t uid);
genfs_rename functions provide a
  file-system-independent framework for implementing
  VOP_RENAME(9) with correct
  locking and error-checking.
Implementing rename is nontrivial. If you are doing it for a new
    file system, you should consider starting from
    tmpfs_rename() as implemented in
    sys/fs/tmpfs/tmpfs_rename.c and adapting it to your
    file system's physical operations.
Because there are so many moving parts to a rename operation,
    genfs_rename uses the following naming
  conventions:
NULL if there was no entry beforeA file system mumblefs should implement various
    file-system-dependent parts of the rename operation in a
    struct genfs_rename_ops, and use
    genfs_rename to implement
    mumblefs_rename() for
    VOP_RENAME(9) as
  follows:
static const struct genfs_rename_ops mumblefs_genfs_rename_ops;
static int
mumblefs_sane_rename(
    struct vnode *fdvp, struct componentname *fcnp,
    struct vnode *tdvp, struct componentname *tcnp,
    kauth_cred_t cred, bool posixly_correct)
{
	struct mumblefs_lookup_results fulr, tulr;
	return genfs_sane_rename(&mumblefs_genfs_rename_ops,
	    fdvp, fcnp, &fulr, tdvp, tcnp, &tulr,
	    cred, posixly_correct);
}
int
mumblefs_rename(void *v)
{
	return genfs_insane_rename(v, &mumblefs_sane_rename);
}
The split between mumblefs_rename() and
    mumblefs_sane_rename() is designed to enable us to
    easily change the
    VOP_RENAME(9) interface,
    which is currently designed for a broken (hence ‘insane’)
    locking scheme, to a more sensible locking scheme once all the file systems
    have their rename operations split up thus.
The struct mumblefs_lookup_results structure is storage for information about directory entries which needs to pass from the lookups of the children (see the gro_lookup member of struct genfs_rename_ops) to the physical on-disk rename or remove operations (see the gro_rename and gro_remove members of struct genfs_rename_ops).
Callers must implement the following operations as members in a
    struct genfs_rename_ops structure passed to
    genfs_rename:
(*gro_genealogy)(struct mount
    *mp, kauth_cred_t cred, struct
    vnode *fdvp, struct vnode *tdvp,
    struct vnode **intermediate_node_ret)NULL
      in *intermediate_node_ret. Return zero on success or
      error on failure. (Failure means file-system-specific failures, not
      hitting or missing fdvp.)
    fdvp and tdvp are guaranteed to be distinct, nonnull, referenced, and unlocked. Since no locks are held on entry except for the file-system-wide rename lock, gro_genealogy may take any locks it pleases.
(*gro_lock_directory)(struct mount
    *mp, struct vnode *vp)(*gro_lookup)(struct mount
    *mp, struct vnode *dvp, struct
    componentname *cnp, void *de,
    struct vnode **vpp)genfs_sane_rename, to store information about the
      directory entry as needed by the file system's
      gro_rename operation, and return zero. If there is
      no such entry, return error.
    dvp is guaranteed to be locked, and the vnode returned in *vpp must be unlocked. However, gro_lookup may temporarily lock the vnode without causing deadlock.
(*gro_directory_empty_p)(struct
    mount *mp, kauth_cred_t cred,
    struct vnode *vp, struct vnode
    *dvp)dvp and vp are guaranteed to be distinct, nonnull, referenced, and locked.
(*gro_rename_check_possible)(struct
    mount *mp, struct vnode *fdvp,
    struct vnode *fvp, struct vnode
    *tdvp, struct vnode *tvp)genfs_ufslike_rename_check_possible() for file
      systems similar to UFS/FFS.
    fdvp and tdvp may
        be the same; every other pair of vnodes is guaranteed to be distinct.
        tvp may be NULL; every
        other vnode is guaranteed to be nonnull. All three or four vnodes are
        guaranteed to be referenced and locked.
(*gro_rename_check_permitted)(struct
    mount *mp, kauth_cred_t cred,
    struct vnode *fdvp, struct vnode
    *fvp, struct vnode *tdvp, struct
    vnode *tvp)genfs_ufslike_rename_check_permitted()
      for file systems similar to UFS/FFS.
    fdvp and tdvp may
        be the same; every other pair of vnodes is guaranteed to be distinct.
        tvp may be NULL; every
        other vnode is guaranteed to be nonnull. All three or four vnodes are
        guaranteed to be referenced and locked.
(*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)File systems using
        fstrans(9) should use
        fstrans_start(9)
        and fstrans_done(9)
        here. fde and tde are the
        pointers that were supplied to
        genfs_sane_rename() and got passed to the
        gro_lookup operation to find information about
        directory entries.
This may use genfs_rename_knote() to
        report any knotes, if the various file-system-dependent routines it uses
        to edit links don't do that already. This should use
        genfs_rename_cache_purge() to purge the
        namecache.
fdvp and tdvp may be the same; every other pair of vnodes is guaranteed to be distinct. tvp may be null; every other vnode is guaranteed to be nonnull. All three or four vnodes are guaranteed to be referenced and locked.
(*gro_remove_check_possible)(struct
    mount *mp, struct vnode *dvp,
    struct vnode *vp)genfs_ufslike_remove_check_possible() for file
      systems similar to UFS/FFS.
    dvp and vp are guaranteed to be distinct, nonnull, referenced, and locked.
This, and gro_remove_check_permitted
        below, are for renames that reduce to a remove; that is, renaming one
        entry to another when both entries refer to the same file. For reasons
        of locking insanity, genfs_rename cannot simply
        call VOP_REMOVE(9)
        instead.
(*gro_remove_check_permitted)(struct
    mount *mp, kauth_cred_t cred,
    struct vnode *dvp, struct vnode
    *vp)genfs_ufslike_remove_check_permitted() for file
      systems similar to UFS/FFS.
    dvp and vp are guaranteed to be distinct, nonnull, referenced, and locked.
(*gro_remove)(struct mount
    *mp, kauth_cred_t cred, struct
    vnode *dvp, struct componentname *cnp,
    void *de, struct vnode *vp)File systems using
        fstrans(9) should use
        fstrans_start(9)
        and fstrans_done(9)
        here. de is one of the pointers that were supplied
        to genfs_sane_rename() and got passed to the
        gro_lookup operation to find information about
        directory entries.
This should signal a NOTE_WRITE knote
        for dvp, and either a
        NOTE_DELETE or a
        NOTE_LINK knote for vp,
        depending on whether this removed the last link to it or not.
dvp and vp are guaranteed to be distinct, nonnull, referenced, and locked.
The following utilities are provided for implementing the struct genfs_rename_ops operations:
genfs_rename_knote(fdvp,
    fvp, tdvp,
    tvp)genfs_rename_cache_purge(fdvp,
    fvp, tdvp,
    tvp)genfs_ufslike_rename_check_possible(fdflags,
    fflags, tdflags,
    tflags, clobber,
    immutable, append)IMMUTABLEAPPENDgenfs_ufslike_rename_check_permitted(cred,
    fdvp, fdmode,
    fduid, fvp,
    fuid, tdvp,
    tdmode, tduid,
    tvp, tuid)NULL if
        notgenfs_ufslike_remove_check_possible(dflags,
    flags, immutable,
    append)IMMUTABLEAPPENDgenfs_ufslike_remove_check_permitted(cred,
    dvp, dmode,
    duid, vp,
    uid)| fdvp
      = fvp | rename("a/.",
      "b") | 
| fdvp
      = tdvp | rename("a/b",
      "a/c") | 
| fdvp
      = tvp | rename("a/b",
      "a") | 
| fvp
      = tdvp | rename("a",
      "a/b") | 
| fvp
      = tvp | rename("a",
      "a") | 
| tdvp
      = tvp | rename("a",
      "b/.") | 
Handling all these cases correctly, and getting the locking
    correct and deadlock-free, is very tricky, which is why
    genfs_rename exists. The interface to
    genfs_rename is very complicated because it must fit
    the insane VOP_RENAME(9)
    and VOP_LOOKUP(9)
    protocols until we can fix them, and because it must accommodate a variety
    of crufty file systems.
genfs_rename was designed and implemented by
  Taylor R. Campbell
  <riastradh@NetBSD.org>
  after many discussions with David Holland
  <dholland@NetBSD.org>,
  and first appeared in NetBSD 6.0.
| May 1, 2013 | NetBSD 9.3 |