1*0a6a1f1dSLionel Sambuc /* $NetBSD: udf_rename.c,v 1.12 2014/11/10 19:44:08 riz Exp $ */
29f988b79SJean-Baptiste Boric
39f988b79SJean-Baptiste Boric /*
49f988b79SJean-Baptiste Boric * Copyright (c) 2013 Reinoud Zandijk
59f988b79SJean-Baptiste Boric * All rights reserved.
69f988b79SJean-Baptiste Boric *
79f988b79SJean-Baptiste Boric * Redistribution and use in source and binary forms, with or without
89f988b79SJean-Baptiste Boric * modification, are permitted provided that the following conditions
99f988b79SJean-Baptiste Boric * are met:
109f988b79SJean-Baptiste Boric * 1. Redistributions of source code must retain the above copyright
119f988b79SJean-Baptiste Boric * notice, this list of conditions and the following disclaimer.
129f988b79SJean-Baptiste Boric * 2. Redistributions in binary form must reproduce the above copyright
139f988b79SJean-Baptiste Boric * notice, this list of conditions and the following disclaimer in the
149f988b79SJean-Baptiste Boric * documentation and/or other materials provided with the distribution.
159f988b79SJean-Baptiste Boric *
169f988b79SJean-Baptiste Boric * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
179f988b79SJean-Baptiste Boric * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
189f988b79SJean-Baptiste Boric * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
199f988b79SJean-Baptiste Boric * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
209f988b79SJean-Baptiste Boric * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
219f988b79SJean-Baptiste Boric * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
229f988b79SJean-Baptiste Boric * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
239f988b79SJean-Baptiste Boric * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
249f988b79SJean-Baptiste Boric * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
259f988b79SJean-Baptiste Boric * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
269f988b79SJean-Baptiste Boric *
279f988b79SJean-Baptiste Boric * Comments and trivial code from the reference implementation in tmpfs.
289f988b79SJean-Baptiste Boric */
299f988b79SJean-Baptiste Boric
309f988b79SJean-Baptiste Boric #include <sys/cdefs.h>
31*0a6a1f1dSLionel Sambuc __KERNEL_RCSID(0, "$NetBSD: udf_rename.c,v 1.12 2014/11/10 19:44:08 riz Exp $");
329f988b79SJean-Baptiste Boric
339f988b79SJean-Baptiste Boric #include <sys/param.h>
349f988b79SJean-Baptiste Boric #include <sys/errno.h>
359f988b79SJean-Baptiste Boric #include <sys/kauth.h>
369f988b79SJean-Baptiste Boric #include <sys/mount.h>
379f988b79SJean-Baptiste Boric #include <sys/namei.h>
389f988b79SJean-Baptiste Boric #include <sys/stat.h>
399f988b79SJean-Baptiste Boric #include <sys/malloc.h>
409f988b79SJean-Baptiste Boric #include <sys/dirent.h>
419f988b79SJean-Baptiste Boric #include <sys/vnode.h>
429f988b79SJean-Baptiste Boric #include <sys/vnode_if.h>
439f988b79SJean-Baptiste Boric
449f988b79SJean-Baptiste Boric #include <miscfs/genfs/genfs.h>
459f988b79SJean-Baptiste Boric
469f988b79SJean-Baptiste Boric #include <fs/udf/ecma167-udf.h>
479f988b79SJean-Baptiste Boric #include <fs/udf/udf_mount.h>
489f988b79SJean-Baptiste Boric #include <sys/dirhash.h>
499f988b79SJean-Baptiste Boric
509f988b79SJean-Baptiste Boric #include "udf.h"
519f988b79SJean-Baptiste Boric #include "udf_subr.h"
529f988b79SJean-Baptiste Boric #include "udf_bswap.h"
539f988b79SJean-Baptiste Boric
549f988b79SJean-Baptiste Boric
559f988b79SJean-Baptiste Boric /* forwards */
569f988b79SJean-Baptiste Boric static int udf_sane_rename( struct vnode *, struct componentname *,
579f988b79SJean-Baptiste Boric struct vnode *, struct componentname *,
589f988b79SJean-Baptiste Boric kauth_cred_t, bool);
599f988b79SJean-Baptiste Boric static bool udf_rmdired_p(struct vnode *);
609f988b79SJean-Baptiste Boric static int udf_gro_lock_directory(struct mount *, struct vnode *);
619f988b79SJean-Baptiste Boric
629f988b79SJean-Baptiste Boric static const struct genfs_rename_ops udf_genfs_rename_ops;
639f988b79SJean-Baptiste Boric
649f988b79SJean-Baptiste Boric
659f988b79SJean-Baptiste Boric #define VTOI(vnode) ((struct udf_node *) (vnode)->v_data)
669f988b79SJean-Baptiste Boric
679f988b79SJean-Baptiste Boric
689f988b79SJean-Baptiste Boric /*
699f988b79SJean-Baptiste Boric * udf_sane_rename: The hairiest vop, with the saner API.
709f988b79SJean-Baptiste Boric *
719f988b79SJean-Baptiste Boric * Arguments:
729f988b79SJean-Baptiste Boric *
739f988b79SJean-Baptiste Boric * . fdvp (from directory vnode),
749f988b79SJean-Baptiste Boric * . fcnp (from component name),
759f988b79SJean-Baptiste Boric * . tdvp (to directory vnode),
769f988b79SJean-Baptiste Boric * . tcnp (to component name),
779f988b79SJean-Baptiste Boric * . cred (credentials structure), and
789f988b79SJean-Baptiste Boric * . posixly_correct (flag for behaviour if target & source link same file).
799f988b79SJean-Baptiste Boric *
809f988b79SJean-Baptiste Boric * fdvp and tdvp may be the same, and must be referenced and unlocked.
819f988b79SJean-Baptiste Boric */
829f988b79SJean-Baptiste Boric static int
udf_sane_rename(struct vnode * fdvp,struct componentname * fcnp,struct vnode * tdvp,struct componentname * tcnp,kauth_cred_t cred,bool posixly_correct)839f988b79SJean-Baptiste Boric udf_sane_rename( struct vnode *fdvp, struct componentname *fcnp,
849f988b79SJean-Baptiste Boric struct vnode *tdvp, struct componentname *tcnp,
859f988b79SJean-Baptiste Boric kauth_cred_t cred, bool posixly_correct)
869f988b79SJean-Baptiste Boric {
879f988b79SJean-Baptiste Boric DPRINTF(CALL, ("udf_sane_rename '%s' -> '%s'\n",
889f988b79SJean-Baptiste Boric fcnp->cn_nameptr, tcnp->cn_nameptr));
899f988b79SJean-Baptiste Boric return genfs_sane_rename(&udf_genfs_rename_ops,
909f988b79SJean-Baptiste Boric fdvp, fcnp, NULL, tdvp, tcnp, NULL,
919f988b79SJean-Baptiste Boric cred, posixly_correct);
929f988b79SJean-Baptiste Boric }
939f988b79SJean-Baptiste Boric
949f988b79SJean-Baptiste Boric
959f988b79SJean-Baptiste Boric /*
969f988b79SJean-Baptiste Boric * udf_rename: the hairiest vop, with the insanest API. Pass to
979f988b79SJean-Baptiste Boric * genfs_insane_rename immediately.
989f988b79SJean-Baptiste Boric */
999f988b79SJean-Baptiste Boric int
udf_rename(void * v)1009f988b79SJean-Baptiste Boric udf_rename(void *v)
1019f988b79SJean-Baptiste Boric {
1029f988b79SJean-Baptiste Boric struct vop_rename_args /* {
1039f988b79SJean-Baptiste Boric struct vnode *a_fdvp;
1049f988b79SJean-Baptiste Boric struct vnode *a_fvp;
1059f988b79SJean-Baptiste Boric struct componentname *a_fcnp;
1069f988b79SJean-Baptiste Boric struct vnode *a_tdvp;
1079f988b79SJean-Baptiste Boric struct vnode *a_tvp;
1089f988b79SJean-Baptiste Boric struct componentname *a_tcnp;
1099f988b79SJean-Baptiste Boric } */ *ap = v;
1109f988b79SJean-Baptiste Boric DPRINTF(CALL, ("udf_rename called\n"));
1119f988b79SJean-Baptiste Boric return genfs_insane_rename(ap, &udf_sane_rename);
1129f988b79SJean-Baptiste Boric }
1139f988b79SJean-Baptiste Boric
1149f988b79SJean-Baptiste Boric
1159f988b79SJean-Baptiste Boric /*
1169f988b79SJean-Baptiste Boric * udf_gro_directory_empty_p: return true if the directory vp is empty. dvp is
1179f988b79SJean-Baptiste Boric * its parent.
1189f988b79SJean-Baptiste Boric *
1199f988b79SJean-Baptiste Boric * vp and dvp must be locked and referenced.
1209f988b79SJean-Baptiste Boric */
1219f988b79SJean-Baptiste Boric static bool
udf_gro_directory_empty_p(struct mount * mp,kauth_cred_t cred,struct vnode * vp,struct vnode * dvp)1229f988b79SJean-Baptiste Boric udf_gro_directory_empty_p(struct mount *mp, kauth_cred_t cred,
1239f988b79SJean-Baptiste Boric struct vnode *vp, struct vnode *dvp)
1249f988b79SJean-Baptiste Boric {
1259f988b79SJean-Baptiste Boric struct udf_node *udf_node = VTOI(vp);
1269f988b79SJean-Baptiste Boric int error, isempty;
1279f988b79SJean-Baptiste Boric
1289f988b79SJean-Baptiste Boric KASSERT(mp != NULL);
1299f988b79SJean-Baptiste Boric KASSERT(vp != NULL);
1309f988b79SJean-Baptiste Boric KASSERT(dvp != NULL);
1319f988b79SJean-Baptiste Boric KASSERT(vp != dvp);
1329f988b79SJean-Baptiste Boric KASSERT(vp->v_mount == mp);
1339f988b79SJean-Baptiste Boric KASSERT(dvp->v_mount == mp);
1349f988b79SJean-Baptiste Boric KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
1359f988b79SJean-Baptiste Boric KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
1369f988b79SJean-Baptiste Boric
1379f988b79SJean-Baptiste Boric DPRINTF(CALL, ("udf_gro_directory_empty_p called\n"));
1389f988b79SJean-Baptiste Boric /* make sure our `leaf' node's hash is populated */
1399f988b79SJean-Baptiste Boric dirhash_get(&udf_node->dir_hash);
1409f988b79SJean-Baptiste Boric error = udf_dirhash_fill(udf_node);
1419f988b79SJean-Baptiste Boric if (error) {
1429f988b79SJean-Baptiste Boric dirhash_put(udf_node->dir_hash);
1439f988b79SJean-Baptiste Boric /* VERY unlikely, answer its not empty */
1449f988b79SJean-Baptiste Boric return 0;
1459f988b79SJean-Baptiste Boric }
1469f988b79SJean-Baptiste Boric
1479f988b79SJean-Baptiste Boric /* check to see if the directory is empty */
1489f988b79SJean-Baptiste Boric isempty = dirhash_dir_isempty(udf_node->dir_hash);
1499f988b79SJean-Baptiste Boric dirhash_put(udf_node->dir_hash);
1509f988b79SJean-Baptiste Boric
1519f988b79SJean-Baptiste Boric return isempty;
1529f988b79SJean-Baptiste Boric }
1539f988b79SJean-Baptiste Boric
1549f988b79SJean-Baptiste Boric
1559f988b79SJean-Baptiste Boric /*
1569f988b79SJean-Baptiste Boric * udf_gro_rename_check_possible: check whether a rename is possible
1579f988b79SJean-Baptiste Boric * independent of credentials.
1589f988b79SJean-Baptiste Boric */
1599f988b79SJean-Baptiste Boric static int
udf_gro_rename_check_possible(struct mount * mp,struct vnode * fdvp,struct vnode * fvp,struct vnode * tdvp,struct vnode * tvp)1609f988b79SJean-Baptiste Boric udf_gro_rename_check_possible(struct mount *mp,
1619f988b79SJean-Baptiste Boric struct vnode *fdvp, struct vnode *fvp,
1629f988b79SJean-Baptiste Boric struct vnode *tdvp, struct vnode *tvp)
1639f988b79SJean-Baptiste Boric {
1649f988b79SJean-Baptiste Boric (void)mp;
1659f988b79SJean-Baptiste Boric KASSERT(mp != NULL);
1669f988b79SJean-Baptiste Boric KASSERT(fdvp != NULL);
1679f988b79SJean-Baptiste Boric KASSERT(fvp != NULL);
1689f988b79SJean-Baptiste Boric KASSERT(tdvp != NULL);
1699f988b79SJean-Baptiste Boric KASSERT(fdvp != fvp);
1709f988b79SJean-Baptiste Boric KASSERT(fdvp != tvp);
1719f988b79SJean-Baptiste Boric KASSERT(tdvp != fvp);
1729f988b79SJean-Baptiste Boric KASSERT(tdvp != tvp);
1739f988b79SJean-Baptiste Boric KASSERT(fvp != tvp);
1749f988b79SJean-Baptiste Boric KASSERT(fdvp->v_type == VDIR);
1759f988b79SJean-Baptiste Boric KASSERT(tdvp->v_type == VDIR);
1769f988b79SJean-Baptiste Boric KASSERT(fdvp->v_mount == mp);
1779f988b79SJean-Baptiste Boric KASSERT(fvp->v_mount == mp);
1789f988b79SJean-Baptiste Boric KASSERT(tdvp->v_mount == mp);
1799f988b79SJean-Baptiste Boric KASSERT((tvp == NULL) || (tvp->v_mount == mp));
1809f988b79SJean-Baptiste Boric KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
1819f988b79SJean-Baptiste Boric KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
1829f988b79SJean-Baptiste Boric KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
1839f988b79SJean-Baptiste Boric KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
1849f988b79SJean-Baptiste Boric
1859f988b79SJean-Baptiste Boric DPRINTF(CALL, ("udf_gro_rename_check_possible called\n"));
1869f988b79SJean-Baptiste Boric
1879f988b79SJean-Baptiste Boric /* flags not implemented since they are not defined (yet) in UDF */
1889f988b79SJean-Baptiste Boric return 0;
1899f988b79SJean-Baptiste Boric }
1909f988b79SJean-Baptiste Boric
1919f988b79SJean-Baptiste Boric
1929f988b79SJean-Baptiste Boric /*
1939f988b79SJean-Baptiste Boric * udf_gro_rename_check_permitted: check whether a rename is permitted given
1949f988b79SJean-Baptiste Boric * our credentials.
1959f988b79SJean-Baptiste Boric */
1969f988b79SJean-Baptiste Boric static int
udf_gro_rename_check_permitted(struct mount * mp,kauth_cred_t cred,struct vnode * fdvp,struct vnode * fvp,struct vnode * tdvp,struct vnode * tvp)1979f988b79SJean-Baptiste Boric udf_gro_rename_check_permitted(struct mount *mp, kauth_cred_t cred,
1989f988b79SJean-Baptiste Boric struct vnode *fdvp, struct vnode *fvp,
1999f988b79SJean-Baptiste Boric struct vnode *tdvp, struct vnode *tvp)
2009f988b79SJean-Baptiste Boric {
2019f988b79SJean-Baptiste Boric struct udf_node *fdir_node = VTOI(fdvp);
2029f988b79SJean-Baptiste Boric struct udf_node *tdir_node = VTOI(tdvp);
2039f988b79SJean-Baptiste Boric struct udf_node *f_node = VTOI(fvp);
2049f988b79SJean-Baptiste Boric struct udf_node *t_node = (tvp? VTOI(tvp): NULL);
2059f988b79SJean-Baptiste Boric mode_t fdmode, tdmode;
2069f988b79SJean-Baptiste Boric uid_t fduid, tduid, fuid, tuid;
2079f988b79SJean-Baptiste Boric gid_t gdummy;
2089f988b79SJean-Baptiste Boric
2099f988b79SJean-Baptiste Boric (void)mp;
2109f988b79SJean-Baptiste Boric KASSERT(mp != NULL);
2119f988b79SJean-Baptiste Boric KASSERT(fdvp != NULL);
2129f988b79SJean-Baptiste Boric KASSERT(fvp != NULL);
2139f988b79SJean-Baptiste Boric KASSERT(tdvp != NULL);
2149f988b79SJean-Baptiste Boric KASSERT(fdvp != fvp);
2159f988b79SJean-Baptiste Boric KASSERT(fdvp != tvp);
2169f988b79SJean-Baptiste Boric KASSERT(tdvp != fvp);
2179f988b79SJean-Baptiste Boric KASSERT(tdvp != tvp);
2189f988b79SJean-Baptiste Boric KASSERT(fvp != tvp);
2199f988b79SJean-Baptiste Boric KASSERT(fdvp->v_type == VDIR);
2209f988b79SJean-Baptiste Boric KASSERT(tdvp->v_type == VDIR);
2219f988b79SJean-Baptiste Boric KASSERT(fdvp->v_mount == mp);
2229f988b79SJean-Baptiste Boric KASSERT(fvp->v_mount == mp);
2239f988b79SJean-Baptiste Boric KASSERT(tdvp->v_mount == mp);
2249f988b79SJean-Baptiste Boric KASSERT((tvp == NULL) || (tvp->v_mount == mp));
2259f988b79SJean-Baptiste Boric KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
2269f988b79SJean-Baptiste Boric KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
2279f988b79SJean-Baptiste Boric KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
2289f988b79SJean-Baptiste Boric KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
2299f988b79SJean-Baptiste Boric
2309f988b79SJean-Baptiste Boric DPRINTF(CALL, ("udf_gro_rename_check_permitted called\n"));
2319f988b79SJean-Baptiste Boric fdmode = udf_getaccessmode(fdir_node);
2329f988b79SJean-Baptiste Boric tdmode = udf_getaccessmode(tdir_node);
2339f988b79SJean-Baptiste Boric
2349f988b79SJean-Baptiste Boric udf_getownership(fdir_node, &fduid, &gdummy);
2359f988b79SJean-Baptiste Boric udf_getownership(tdir_node, &tduid, &gdummy);
2369f988b79SJean-Baptiste Boric udf_getownership(f_node, &fuid, &gdummy);
2379f988b79SJean-Baptiste Boric
2389f988b79SJean-Baptiste Boric tuid = 0;
2399f988b79SJean-Baptiste Boric if (t_node)
2409f988b79SJean-Baptiste Boric udf_getownership(t_node, &tuid, &gdummy);
2419f988b79SJean-Baptiste Boric
2429f988b79SJean-Baptiste Boric return genfs_ufslike_rename_check_permitted(cred,
2439f988b79SJean-Baptiste Boric fdvp, fdmode, fduid,
2449f988b79SJean-Baptiste Boric fvp, fuid,
2459f988b79SJean-Baptiste Boric tdvp, tdmode, tduid,
2469f988b79SJean-Baptiste Boric tvp, tuid);
2479f988b79SJean-Baptiste Boric }
2489f988b79SJean-Baptiste Boric
2499f988b79SJean-Baptiste Boric
2509f988b79SJean-Baptiste Boric /*
2519f988b79SJean-Baptiste Boric * udf_gro_remove_check_possible: check whether a remove is possible
2529f988b79SJean-Baptiste Boric * independent of credentials.
2539f988b79SJean-Baptiste Boric *
2549f988b79SJean-Baptiste Boric * XXX could check for special attributes?
2559f988b79SJean-Baptiste Boric */
2569f988b79SJean-Baptiste Boric static int
udf_gro_remove_check_possible(struct mount * mp,struct vnode * dvp,struct vnode * vp)2579f988b79SJean-Baptiste Boric udf_gro_remove_check_possible(struct mount *mp,
2589f988b79SJean-Baptiste Boric struct vnode *dvp, struct vnode *vp)
2599f988b79SJean-Baptiste Boric {
2609f988b79SJean-Baptiste Boric (void)mp;
2619f988b79SJean-Baptiste Boric KASSERT(mp != NULL);
2629f988b79SJean-Baptiste Boric KASSERT(dvp != NULL);
2639f988b79SJean-Baptiste Boric KASSERT(vp != NULL);
2649f988b79SJean-Baptiste Boric KASSERT(dvp != vp);
2659f988b79SJean-Baptiste Boric KASSERT(dvp->v_type == VDIR);
2669f988b79SJean-Baptiste Boric KASSERT(vp->v_type != VDIR);
2679f988b79SJean-Baptiste Boric KASSERT(dvp->v_mount == mp);
2689f988b79SJean-Baptiste Boric KASSERT(vp->v_mount == mp);
2699f988b79SJean-Baptiste Boric KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
2709f988b79SJean-Baptiste Boric KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
2719f988b79SJean-Baptiste Boric
2729f988b79SJean-Baptiste Boric DPRINTF(CALL, ("udf_gro_remove_check_possible called\n"));
2739f988b79SJean-Baptiste Boric
2749f988b79SJean-Baptiste Boric /* flags not implemented since they are not defined (yet) in UDF */
2759f988b79SJean-Baptiste Boric return 0;
2769f988b79SJean-Baptiste Boric }
2779f988b79SJean-Baptiste Boric
2789f988b79SJean-Baptiste Boric
2799f988b79SJean-Baptiste Boric /*
2809f988b79SJean-Baptiste Boric * udf_gro_remove_check_permitted: check whether a remove is permitted given
2819f988b79SJean-Baptiste Boric * our credentials.
2829f988b79SJean-Baptiste Boric */
2839f988b79SJean-Baptiste Boric static int
udf_gro_remove_check_permitted(struct mount * mp,kauth_cred_t cred,struct vnode * dvp,struct vnode * vp)2849f988b79SJean-Baptiste Boric udf_gro_remove_check_permitted(struct mount *mp, kauth_cred_t cred,
2859f988b79SJean-Baptiste Boric struct vnode *dvp, struct vnode *vp)
2869f988b79SJean-Baptiste Boric {
2879f988b79SJean-Baptiste Boric struct udf_node *dir_node = VTOI(dvp);
2889f988b79SJean-Baptiste Boric struct udf_node *udf_node = VTOI(vp);
2899f988b79SJean-Baptiste Boric mode_t dmode;
2909f988b79SJean-Baptiste Boric uid_t duid, uid;
2919f988b79SJean-Baptiste Boric gid_t gdummy;
2929f988b79SJean-Baptiste Boric
2939f988b79SJean-Baptiste Boric (void)mp;
2949f988b79SJean-Baptiste Boric KASSERT(mp != NULL);
2959f988b79SJean-Baptiste Boric KASSERT(dvp != NULL);
2969f988b79SJean-Baptiste Boric KASSERT(vp != NULL);
2979f988b79SJean-Baptiste Boric KASSERT(dvp != vp);
2989f988b79SJean-Baptiste Boric KASSERT(dvp->v_type == VDIR);
2999f988b79SJean-Baptiste Boric KASSERT(vp->v_type != VDIR);
3009f988b79SJean-Baptiste Boric KASSERT(dvp->v_mount == mp);
3019f988b79SJean-Baptiste Boric KASSERT(vp->v_mount == mp);
3029f988b79SJean-Baptiste Boric KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
3039f988b79SJean-Baptiste Boric KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
3049f988b79SJean-Baptiste Boric
3059f988b79SJean-Baptiste Boric DPRINTF(CALL, ("udf_gro_remove_check_permitted called\n"));
3069f988b79SJean-Baptiste Boric dmode = udf_getaccessmode(dir_node);
3079f988b79SJean-Baptiste Boric
3089f988b79SJean-Baptiste Boric udf_getownership(dir_node, &duid, &gdummy);
3099f988b79SJean-Baptiste Boric udf_getownership(udf_node, &uid, &gdummy);
3109f988b79SJean-Baptiste Boric
3119f988b79SJean-Baptiste Boric return genfs_ufslike_remove_check_permitted(cred,
3129f988b79SJean-Baptiste Boric dvp, dmode, duid,
3139f988b79SJean-Baptiste Boric vp, uid);
3149f988b79SJean-Baptiste Boric }
3159f988b79SJean-Baptiste Boric
3169f988b79SJean-Baptiste Boric
3179f988b79SJean-Baptiste Boric /*
3189f988b79SJean-Baptiste Boric * udf_gro_rename: actually perform the rename operation.
3199f988b79SJean-Baptiste Boric */
3209f988b79SJean-Baptiste Boric static int
udf_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)3219f988b79SJean-Baptiste Boric udf_gro_rename(struct mount *mp, kauth_cred_t cred,
3229f988b79SJean-Baptiste Boric struct vnode *fdvp, struct componentname *fcnp,
3239f988b79SJean-Baptiste Boric void *fde, struct vnode *fvp,
3249f988b79SJean-Baptiste Boric struct vnode *tdvp, struct componentname *tcnp,
3259f988b79SJean-Baptiste Boric void *tde, struct vnode *tvp)
3269f988b79SJean-Baptiste Boric {
3279f988b79SJean-Baptiste Boric struct udf_node *fnode, *fdnode, *tnode, *tdnode;
3289f988b79SJean-Baptiste Boric struct vattr fvap;
3299f988b79SJean-Baptiste Boric int error;
3309f988b79SJean-Baptiste Boric
3319f988b79SJean-Baptiste Boric (void)cred;
3329f988b79SJean-Baptiste Boric KASSERT(mp != NULL);
3339f988b79SJean-Baptiste Boric KASSERT(fdvp != NULL);
3349f988b79SJean-Baptiste Boric KASSERT(fcnp != NULL);
3359f988b79SJean-Baptiste Boric KASSERT(fvp != NULL);
3369f988b79SJean-Baptiste Boric KASSERT(tdvp != NULL);
3379f988b79SJean-Baptiste Boric KASSERT(tcnp != NULL);
3389f988b79SJean-Baptiste Boric KASSERT(fdvp != fvp);
3399f988b79SJean-Baptiste Boric KASSERT(fdvp != tvp);
3409f988b79SJean-Baptiste Boric KASSERT(tdvp != fvp);
3419f988b79SJean-Baptiste Boric KASSERT(tdvp != tvp);
3429f988b79SJean-Baptiste Boric KASSERT(fvp != tvp);
3439f988b79SJean-Baptiste Boric KASSERT(fdvp->v_mount == mp);
3449f988b79SJean-Baptiste Boric KASSERT(fvp->v_mount == mp);
3459f988b79SJean-Baptiste Boric KASSERT(tdvp->v_mount == mp);
3469f988b79SJean-Baptiste Boric KASSERT((tvp == NULL) || (tvp->v_mount == mp));
3479f988b79SJean-Baptiste Boric KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
3489f988b79SJean-Baptiste Boric KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
3499f988b79SJean-Baptiste Boric KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
3509f988b79SJean-Baptiste Boric KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
3519f988b79SJean-Baptiste Boric
3529f988b79SJean-Baptiste Boric DPRINTF(CALL, ("udf_gro_rename called\n"));
3539f988b79SJean-Baptiste Boric DPRINTF(NODE, ("udf_gro_rename called : %s -> %s\n",
3549f988b79SJean-Baptiste Boric fcnp->cn_nameptr, tcnp->cn_nameptr));
3559f988b79SJean-Baptiste Boric
3569f988b79SJean-Baptiste Boric fnode = VTOI(fvp);
3579f988b79SJean-Baptiste Boric fdnode = VTOI(fdvp);
3589f988b79SJean-Baptiste Boric tnode = (tvp == NULL) ? NULL : VTOI(tvp);
3599f988b79SJean-Baptiste Boric tdnode = VTOI(tdvp);
3609f988b79SJean-Baptiste Boric
3619f988b79SJean-Baptiste Boric /* get attribute information */
3629f988b79SJean-Baptiste Boric error = VOP_GETATTR(fvp, &fvap, NULL);
3639f988b79SJean-Baptiste Boric if (error)
3649f988b79SJean-Baptiste Boric return error;
3659f988b79SJean-Baptiste Boric
3669f988b79SJean-Baptiste Boric /* remove existing entry if present */
3679f988b79SJean-Baptiste Boric if (tvp)
3689f988b79SJean-Baptiste Boric udf_dir_detach(tdnode->ump, tdnode, tnode, tcnp);
3699f988b79SJean-Baptiste Boric
3709f988b79SJean-Baptiste Boric /* create new directory entry for the node */
3719f988b79SJean-Baptiste Boric error = udf_dir_attach(tdnode->ump, tdnode, fnode, &fvap, tcnp);
3729f988b79SJean-Baptiste Boric if (error)
3739f988b79SJean-Baptiste Boric return error;
3749f988b79SJean-Baptiste Boric
3759f988b79SJean-Baptiste Boric /* unlink old directory entry for the node, if failing, unattach new */
3769f988b79SJean-Baptiste Boric error = udf_dir_detach(tdnode->ump, fdnode, fnode, fcnp);
3779f988b79SJean-Baptiste Boric if (error)
3789f988b79SJean-Baptiste Boric goto rollback_attach;
3799f988b79SJean-Baptiste Boric
3809f988b79SJean-Baptiste Boric if ((fdnode != tdnode) && (fvp->v_type == VDIR)) {
3819f988b79SJean-Baptiste Boric /* update fnode's '..' entry */
3829f988b79SJean-Baptiste Boric error = udf_dir_update_rootentry(fnode->ump, fnode, tdnode);
3839f988b79SJean-Baptiste Boric if (error)
3849f988b79SJean-Baptiste Boric goto rollback;
3859f988b79SJean-Baptiste Boric }
3869f988b79SJean-Baptiste Boric
3879f988b79SJean-Baptiste Boric VN_KNOTE(fvp, NOTE_RENAME);
3889f988b79SJean-Baptiste Boric genfs_rename_cache_purge(fdvp, fvp, tdvp, tvp);
3899f988b79SJean-Baptiste Boric return 0;
3909f988b79SJean-Baptiste Boric
3919f988b79SJean-Baptiste Boric rollback:
3929f988b79SJean-Baptiste Boric /* 'try' to recover from this situation */
3939f988b79SJean-Baptiste Boric udf_dir_attach(tdnode->ump, fdnode, fnode, &fvap, fcnp);
3949f988b79SJean-Baptiste Boric rollback_attach:
3959f988b79SJean-Baptiste Boric udf_dir_detach(tdnode->ump, tdnode, fnode, tcnp);
3969f988b79SJean-Baptiste Boric
3979f988b79SJean-Baptiste Boric return error;
3989f988b79SJean-Baptiste Boric }
3999f988b79SJean-Baptiste Boric
4009f988b79SJean-Baptiste Boric
4019f988b79SJean-Baptiste Boric /*
4029f988b79SJean-Baptiste Boric * udf_gro_remove: rename an object over another link to itself, effectively
4039f988b79SJean-Baptiste Boric * removing just the original link.
4049f988b79SJean-Baptiste Boric */
4059f988b79SJean-Baptiste Boric static int
udf_gro_remove(struct mount * mp,kauth_cred_t cred,struct vnode * dvp,struct componentname * cnp,void * de,struct vnode * vp)4069f988b79SJean-Baptiste Boric udf_gro_remove(struct mount *mp, kauth_cred_t cred,
4079f988b79SJean-Baptiste Boric struct vnode *dvp, struct componentname *cnp, void *de, struct vnode *vp)
4089f988b79SJean-Baptiste Boric {
4099f988b79SJean-Baptiste Boric struct udf_node *dir_node, *udf_node;
4109f988b79SJean-Baptiste Boric
4119f988b79SJean-Baptiste Boric KASSERT(mp != NULL);
4129f988b79SJean-Baptiste Boric KASSERT(dvp != NULL);
4139f988b79SJean-Baptiste Boric KASSERT(cnp != NULL);
4149f988b79SJean-Baptiste Boric KASSERT(vp != NULL);
4159f988b79SJean-Baptiste Boric KASSERT(dvp != vp);
4169f988b79SJean-Baptiste Boric KASSERT(dvp->v_mount == mp);
4179f988b79SJean-Baptiste Boric KASSERT(vp->v_mount == mp);
4189f988b79SJean-Baptiste Boric KASSERT(dvp->v_type == VDIR);
4199f988b79SJean-Baptiste Boric KASSERT(vp->v_type != VDIR);
4209f988b79SJean-Baptiste Boric KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
4219f988b79SJean-Baptiste Boric KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
4229f988b79SJean-Baptiste Boric
4239f988b79SJean-Baptiste Boric DPRINTF(CALL, ("udf_gro_remove called\n"));
4249f988b79SJean-Baptiste Boric
4259f988b79SJean-Baptiste Boric dir_node = VTOI(dvp);
4269f988b79SJean-Baptiste Boric udf_node = VTOI(vp);
4279f988b79SJean-Baptiste Boric udf_dir_detach(dir_node->ump, dir_node, udf_node, cnp);
4289f988b79SJean-Baptiste Boric
4299f988b79SJean-Baptiste Boric return 0;
4309f988b79SJean-Baptiste Boric }
4319f988b79SJean-Baptiste Boric
4329f988b79SJean-Baptiste Boric
4339f988b79SJean-Baptiste Boric /*
4349f988b79SJean-Baptiste Boric * udf_gro_lookup: look up and save the lookup results.
4359f988b79SJean-Baptiste Boric */
4369f988b79SJean-Baptiste Boric static int
udf_gro_lookup(struct mount * mp,struct vnode * dvp,struct componentname * cnp,void * de_ret,struct vnode ** vp_ret)4379f988b79SJean-Baptiste Boric udf_gro_lookup(struct mount *mp, struct vnode *dvp,
4389f988b79SJean-Baptiste Boric struct componentname *cnp, void *de_ret, struct vnode **vp_ret)
4399f988b79SJean-Baptiste Boric {
4409f988b79SJean-Baptiste Boric struct udf_node *dir_node, *res_node;
4419f988b79SJean-Baptiste Boric struct long_ad icb_loc;
4429f988b79SJean-Baptiste Boric const char *name;
4439f988b79SJean-Baptiste Boric int namelen, error;
4449f988b79SJean-Baptiste Boric int found;
4459f988b79SJean-Baptiste Boric
4469f988b79SJean-Baptiste Boric (void)mp;
4479f988b79SJean-Baptiste Boric KASSERT(mp != NULL);
4489f988b79SJean-Baptiste Boric KASSERT(dvp != NULL);
4499f988b79SJean-Baptiste Boric KASSERT(cnp != NULL);
4509f988b79SJean-Baptiste Boric KASSERT(vp_ret != NULL);
4519f988b79SJean-Baptiste Boric KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
4529f988b79SJean-Baptiste Boric
4539f988b79SJean-Baptiste Boric dir_node = VTOI(dvp);
4549f988b79SJean-Baptiste Boric
4559f988b79SJean-Baptiste Boric DPRINTF(CALL, ("udf_gro_lookup called\n"));
4569f988b79SJean-Baptiste Boric
4579f988b79SJean-Baptiste Boric /* lookup filename in the directory; location icb_loc */
4589f988b79SJean-Baptiste Boric name = cnp->cn_nameptr;
4599f988b79SJean-Baptiste Boric namelen = cnp->cn_namelen;
4609f988b79SJean-Baptiste Boric error = udf_lookup_name_in_dir(dvp, name, namelen,
4619f988b79SJean-Baptiste Boric &icb_loc, &found);
4629f988b79SJean-Baptiste Boric if (error)
4639f988b79SJean-Baptiste Boric return error;
4649f988b79SJean-Baptiste Boric if (!found)
4659f988b79SJean-Baptiste Boric return ENOENT;
4669f988b79SJean-Baptiste Boric
4679f988b79SJean-Baptiste Boric DPRINTF(LOOKUP, ("udf_gro_lookup found '%s'\n", name));
4689f988b79SJean-Baptiste Boric error = udf_get_node(dir_node->ump, &icb_loc, &res_node);
4699f988b79SJean-Baptiste Boric if (error)
4709f988b79SJean-Baptiste Boric return error;
4719f988b79SJean-Baptiste Boric *vp_ret = res_node->vnode;
4729f988b79SJean-Baptiste Boric VOP_UNLOCK(res_node->vnode);
4739f988b79SJean-Baptiste Boric
4749f988b79SJean-Baptiste Boric return 0;
4759f988b79SJean-Baptiste Boric }
4769f988b79SJean-Baptiste Boric
4779f988b79SJean-Baptiste Boric
4789f988b79SJean-Baptiste Boric /*
4799f988b79SJean-Baptiste Boric * udf_rmdired_p: check whether the directory vp has been rmdired.
4809f988b79SJean-Baptiste Boric *
4819f988b79SJean-Baptiste Boric * vp must be locked and referenced.
4829f988b79SJean-Baptiste Boric */
4839f988b79SJean-Baptiste Boric static bool
udf_rmdired_p(struct vnode * vp)4849f988b79SJean-Baptiste Boric udf_rmdired_p(struct vnode *vp)
4859f988b79SJean-Baptiste Boric {
4869f988b79SJean-Baptiste Boric DPRINTF(CALL, ("udf_rmdired_p called\n"));
4879f988b79SJean-Baptiste Boric
4889f988b79SJean-Baptiste Boric KASSERT(vp != NULL);
4899f988b79SJean-Baptiste Boric KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
4909f988b79SJean-Baptiste Boric KASSERT(vp->v_type == VDIR);
4919f988b79SJean-Baptiste Boric
4929f988b79SJean-Baptiste Boric return (VTOI(vp)->i_flags & IN_DELETED);
4939f988b79SJean-Baptiste Boric }
4949f988b79SJean-Baptiste Boric
4959f988b79SJean-Baptiste Boric
4969f988b79SJean-Baptiste Boric /*
4979f988b79SJean-Baptiste Boric * udf_gro_genealogy: analyze the genealogy of the source and target
4989f988b79SJean-Baptiste Boric * directories.
4999f988b79SJean-Baptiste Boric */
5009f988b79SJean-Baptiste Boric static int
udf_gro_genealogy(struct mount * mp,kauth_cred_t cred,struct vnode * fdvp,struct vnode * tdvp,struct vnode ** intermediate_node_ret)5019f988b79SJean-Baptiste Boric udf_gro_genealogy(struct mount *mp, kauth_cred_t cred,
5029f988b79SJean-Baptiste Boric struct vnode *fdvp, struct vnode *tdvp,
5039f988b79SJean-Baptiste Boric struct vnode **intermediate_node_ret)
5049f988b79SJean-Baptiste Boric {
5059f988b79SJean-Baptiste Boric struct udf_mount *ump;
5069f988b79SJean-Baptiste Boric struct udf_node *parent_node;
5079f988b79SJean-Baptiste Boric struct vnode *vp, *dvp;
5089f988b79SJean-Baptiste Boric struct long_ad parent_loc;
5099f988b79SJean-Baptiste Boric const char *name;
5109f988b79SJean-Baptiste Boric int namelen;
5119f988b79SJean-Baptiste Boric int error, found;
5129f988b79SJean-Baptiste Boric
5139f988b79SJean-Baptiste Boric (void)cred;
5149f988b79SJean-Baptiste Boric KASSERT(mp != NULL);
5159f988b79SJean-Baptiste Boric KASSERT(fdvp != NULL);
5169f988b79SJean-Baptiste Boric KASSERT(tdvp != NULL);
5179f988b79SJean-Baptiste Boric KASSERT(fdvp != tdvp);
5189f988b79SJean-Baptiste Boric KASSERT(intermediate_node_ret != NULL);
5199f988b79SJean-Baptiste Boric KASSERT(fdvp->v_mount == mp);
5209f988b79SJean-Baptiste Boric KASSERT(tdvp->v_mount == mp);
5219f988b79SJean-Baptiste Boric KASSERT(fdvp->v_type == VDIR);
5229f988b79SJean-Baptiste Boric KASSERT(tdvp->v_type == VDIR);
5239f988b79SJean-Baptiste Boric
5249f988b79SJean-Baptiste Boric DPRINTF(CALL, ("udf_gro_genealogy called\n"));
5259f988b79SJean-Baptiste Boric
5269f988b79SJean-Baptiste Boric /*
5279f988b79SJean-Baptiste Boric * We need to provisionally lock tdvp to keep rmdir from deleting it
5289f988b79SJean-Baptiste Boric * -- or any ancestor -- at an inopportune moment.
5299f988b79SJean-Baptiste Boric *
5309f988b79SJean-Baptiste Boric * XXX WHY is this not in genfs's rename? XXX
5319f988b79SJean-Baptiste Boric */
5329f988b79SJean-Baptiste Boric error = udf_gro_lock_directory(mp, tdvp);
5339f988b79SJean-Baptiste Boric if (error)
5349f988b79SJean-Baptiste Boric return error;
5359f988b79SJean-Baptiste Boric
5369f988b79SJean-Baptiste Boric name = "..";
5379f988b79SJean-Baptiste Boric namelen = 2;
5389f988b79SJean-Baptiste Boric error = 0;
5399f988b79SJean-Baptiste Boric
5409f988b79SJean-Baptiste Boric ump = VTOI(tdvp)->ump;
5419f988b79SJean-Baptiste Boric
5429f988b79SJean-Baptiste Boric /* if nodes are equal, it is no use looking */
5439f988b79SJean-Baptiste Boric KASSERT(udf_compare_icb(&VTOI(fdvp)->loc, &VTOI(tdvp)->loc) != 0);
5449f988b79SJean-Baptiste Boric
5459f988b79SJean-Baptiste Boric /* start at destination vnode and walk up the tree */
5469f988b79SJean-Baptiste Boric vp = tdvp;
5479f988b79SJean-Baptiste Boric vref(vp);
5489f988b79SJean-Baptiste Boric
5499f988b79SJean-Baptiste Boric for (;;) {
5509f988b79SJean-Baptiste Boric KASSERT(vp != NULL);
5519f988b79SJean-Baptiste Boric KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
5529f988b79SJean-Baptiste Boric KASSERT(vp->v_mount == mp);
5539f988b79SJean-Baptiste Boric KASSERT(vp->v_type == VDIR);
5549f988b79SJean-Baptiste Boric KASSERT(!udf_rmdired_p(vp));
5559f988b79SJean-Baptiste Boric
5569f988b79SJean-Baptiste Boric DPRINTF(NODE, ("udf_gro_genealogy : "
5579f988b79SJean-Baptiste Boric "fdvp %p, looking at vp %p\n",
5589f988b79SJean-Baptiste Boric fdvp, vp));
5599f988b79SJean-Baptiste Boric
5609f988b79SJean-Baptiste Boric /* sanity check */
5619f988b79SJean-Baptiste Boric if (vp->v_type != VDIR) {
5629f988b79SJean-Baptiste Boric vput(vp);
5639f988b79SJean-Baptiste Boric return ENOTDIR;
5649f988b79SJean-Baptiste Boric }
5659f988b79SJean-Baptiste Boric
5669f988b79SJean-Baptiste Boric /* go down one level */
5679f988b79SJean-Baptiste Boric error = udf_lookup_name_in_dir(vp, name, namelen,
5689f988b79SJean-Baptiste Boric &parent_loc, &found);
5699f988b79SJean-Baptiste Boric DPRINTF(NODE, ("\tlookup of parent '..' resulted in error %d, "
5709f988b79SJean-Baptiste Boric "found %d\n", error, found));
5719f988b79SJean-Baptiste Boric if (!found)
5729f988b79SJean-Baptiste Boric error = ENOENT;
5739f988b79SJean-Baptiste Boric if (error) {
5749f988b79SJean-Baptiste Boric vput(vp);
5759f988b79SJean-Baptiste Boric return error;
5769f988b79SJean-Baptiste Boric }
5779f988b79SJean-Baptiste Boric
5789f988b79SJean-Baptiste Boric /* did we encounter the root node? i.e. loop back */
5799f988b79SJean-Baptiste Boric if (udf_compare_icb(&parent_loc, &VTOI(vp)->loc) == 0) {
5809f988b79SJean-Baptiste Boric DPRINTF(NODE, ("ROOT found!\n"));
5819f988b79SJean-Baptiste Boric vput(vp);
5829f988b79SJean-Baptiste Boric *intermediate_node_ret = NULL;
5839f988b79SJean-Baptiste Boric return 0;
5849f988b79SJean-Baptiste Boric }
5859f988b79SJean-Baptiste Boric
5869f988b79SJean-Baptiste Boric /* Did we find that fdvp is an ancestor of tdvp? */
5879f988b79SJean-Baptiste Boric if (udf_compare_icb(&parent_loc, &VTOI(fdvp)->loc) == 0) {
5889f988b79SJean-Baptiste Boric DPRINTF(NODE, ("fdvp is ancestor of tdvp\n"));
5899f988b79SJean-Baptiste Boric *intermediate_node_ret = vp;
5909f988b79SJean-Baptiste Boric VOP_UNLOCK(vp);
5919f988b79SJean-Baptiste Boric return 0;
5929f988b79SJean-Baptiste Boric }
5939f988b79SJean-Baptiste Boric
5949f988b79SJean-Baptiste Boric /*
5959f988b79SJean-Baptiste Boric * Unlock vp so that we can lock the parent, but keep child vp
5969f988b79SJean-Baptiste Boric * referenced until after we have found the parent, so that
5979f988b79SJean-Baptiste Boric * parent_node will not be recycled.
5989f988b79SJean-Baptiste Boric */
5999f988b79SJean-Baptiste Boric DPRINTF(NODE, ("\tgetting the parent node\n"));
6009f988b79SJean-Baptiste Boric VOP_UNLOCK(vp);
6019f988b79SJean-Baptiste Boric error = udf_get_node(ump, &parent_loc, &parent_node);
6029f988b79SJean-Baptiste Boric vrele(vp);
6039f988b79SJean-Baptiste Boric if (error)
6049f988b79SJean-Baptiste Boric return error;
6059f988b79SJean-Baptiste Boric
6069f988b79SJean-Baptiste Boric dvp = parent_node->vnode;
6079f988b79SJean-Baptiste Boric
6089f988b79SJean-Baptiste Boric /* switch */
6099f988b79SJean-Baptiste Boric KASSERT(dvp != NULL);
6109f988b79SJean-Baptiste Boric KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
6119f988b79SJean-Baptiste Boric vp = dvp;
6129f988b79SJean-Baptiste Boric
6139f988b79SJean-Baptiste Boric /* sanity check */
6149f988b79SJean-Baptiste Boric if (vp->v_type != VDIR) {
6159f988b79SJean-Baptiste Boric /*
6169f988b79SJean-Baptiste Boric * Odd, but can happen if we loose the race and the
6179f988b79SJean-Baptiste Boric * '..' node has been recycled.
6189f988b79SJean-Baptiste Boric */
6199f988b79SJean-Baptiste Boric vput(vp);
6209f988b79SJean-Baptiste Boric return ENOTDIR;
6219f988b79SJean-Baptiste Boric }
6229f988b79SJean-Baptiste Boric
6239f988b79SJean-Baptiste Boric if (udf_rmdired_p(vp)) {
6249f988b79SJean-Baptiste Boric vput(vp);
6259f988b79SJean-Baptiste Boric return ENOENT;
6269f988b79SJean-Baptiste Boric }
6279f988b79SJean-Baptiste Boric }
6289f988b79SJean-Baptiste Boric }
6299f988b79SJean-Baptiste Boric
6309f988b79SJean-Baptiste Boric
6319f988b79SJean-Baptiste Boric /*
6329f988b79SJean-Baptiste Boric * udf_gro_lock_directory: lock the directory vp, but fail if it has been
6339f988b79SJean-Baptiste Boric * rmdir'd.
6349f988b79SJean-Baptiste Boric */
6359f988b79SJean-Baptiste Boric static int
udf_gro_lock_directory(struct mount * mp,struct vnode * vp)6369f988b79SJean-Baptiste Boric udf_gro_lock_directory(struct mount *mp, struct vnode *vp)
6379f988b79SJean-Baptiste Boric {
6389f988b79SJean-Baptiste Boric
6399f988b79SJean-Baptiste Boric (void)mp;
6409f988b79SJean-Baptiste Boric KASSERT(mp != NULL);
6419f988b79SJean-Baptiste Boric KASSERT(vp != NULL);
6429f988b79SJean-Baptiste Boric KASSERT(vp->v_mount == mp);
6439f988b79SJean-Baptiste Boric
6449f988b79SJean-Baptiste Boric DPRINTF(CALL, ("udf_gro_lock_directory called\n"));
6459f988b79SJean-Baptiste Boric DPRINTF(LOCKING, ("udf_gro_lock_directory called\n"));
6469f988b79SJean-Baptiste Boric
6479f988b79SJean-Baptiste Boric vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
6489f988b79SJean-Baptiste Boric
6499f988b79SJean-Baptiste Boric if (udf_rmdired_p(vp)) {
6509f988b79SJean-Baptiste Boric VOP_UNLOCK(vp);
6519f988b79SJean-Baptiste Boric return ENOENT;
6529f988b79SJean-Baptiste Boric }
6539f988b79SJean-Baptiste Boric
6549f988b79SJean-Baptiste Boric return 0;
6559f988b79SJean-Baptiste Boric }
6569f988b79SJean-Baptiste Boric
6579f988b79SJean-Baptiste Boric
6589f988b79SJean-Baptiste Boric static const struct genfs_rename_ops udf_genfs_rename_ops = {
6599f988b79SJean-Baptiste Boric .gro_directory_empty_p = udf_gro_directory_empty_p,
6609f988b79SJean-Baptiste Boric .gro_rename_check_possible = udf_gro_rename_check_possible,
6619f988b79SJean-Baptiste Boric .gro_rename_check_permitted = udf_gro_rename_check_permitted,
6629f988b79SJean-Baptiste Boric .gro_remove_check_possible = udf_gro_remove_check_possible,
6639f988b79SJean-Baptiste Boric .gro_remove_check_permitted = udf_gro_remove_check_permitted,
6649f988b79SJean-Baptiste Boric .gro_rename = udf_gro_rename,
6659f988b79SJean-Baptiste Boric .gro_remove = udf_gro_remove,
6669f988b79SJean-Baptiste Boric .gro_lookup = udf_gro_lookup,
6679f988b79SJean-Baptiste Boric .gro_genealogy = udf_gro_genealogy,
6689f988b79SJean-Baptiste Boric .gro_lock_directory = udf_gro_lock_directory,
6699f988b79SJean-Baptiste Boric };
670