Thu Jun 25 17:16:33 2009 UTC ()
Rewrite of udf_on_rootpath(), and vop_rename() code that calls it, after the
UFS way. The tree walking is now done the same and the code hasn't locked up
on examples that made it lockup before.


(reinoud)
diff -r1.95 -r1.96 src/sys/fs/udf/udf_subr.c
diff -r1.15 -r1.16 src/sys/fs/udf/udf_subr.h
diff -r1.46 -r1.47 src/sys/fs/udf/udf_vnops.c

cvs diff -r1.95 -r1.96 src/sys/fs/udf/udf_subr.c (expand / switch to unified diff)

--- src/sys/fs/udf/udf_subr.c 2009/06/24 17:09:13 1.95
+++ src/sys/fs/udf/udf_subr.c 2009/06/25 17:16:33 1.96
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: udf_subr.c,v 1.95 2009/06/24 17:09:13 reinoud Exp $ */ 1/* $NetBSD: udf_subr.c,v 1.96 2009/06/25 17:16:33 reinoud Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006, 2008 Reinoud Zandijk 4 * Copyright (c) 2006, 2008 Reinoud Zandijk
5 * All rights reserved. 5 * All rights reserved.
6 *  6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -19,27 +19,27 @@ @@ -19,27 +19,27 @@
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *  26 *
27 */ 27 */
28 28
29 29
30#include <sys/cdefs.h> 30#include <sys/cdefs.h>
31#ifndef lint 31#ifndef lint
32__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.95 2009/06/24 17:09:13 reinoud Exp $"); 32__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.96 2009/06/25 17:16:33 reinoud Exp $");
33#endif /* not lint */ 33#endif /* not lint */
34 34
35 35
36#if defined(_KERNEL_OPT) 36#if defined(_KERNEL_OPT)
37#include "opt_compat_netbsd.h" 37#include "opt_compat_netbsd.h"
38#endif 38#endif
39 39
40#include <sys/param.h> 40#include <sys/param.h>
41#include <sys/systm.h> 41#include <sys/systm.h>
42#include <sys/sysctl.h> 42#include <sys/sysctl.h>
43#include <sys/namei.h> 43#include <sys/namei.h>
44#include <sys/proc.h> 44#include <sys/proc.h>
45#include <sys/kernel.h> 45#include <sys/kernel.h>
@@ -3363,41 +3363,48 @@ udf_read_rootdirs(struct udf_mount *ump) @@ -3363,41 +3363,48 @@ udf_read_rootdirs(struct udf_mount *ump)
3363 3363
3364/* --------------------------------------------------------------------- */ 3364/* --------------------------------------------------------------------- */
3365 3365
3366/* To make absolutely sure we are NOT returning zero, add one :) */ 3366/* To make absolutely sure we are NOT returning zero, add one :) */
3367 3367
3368long 3368long
3369udf_calchash(struct long_ad *icbptr) 3369udf_calchash(struct long_ad *icbptr)
3370{ 3370{
3371 /* ought to be enough since each mountpoint has its own chain */ 3371 /* ought to be enough since each mountpoint has its own chain */
3372 return udf_rw32(icbptr->loc.lb_num) + 1; 3372 return udf_rw32(icbptr->loc.lb_num) + 1;
3373} 3373}
3374 3374
3375 3375
 3376int
 3377udf_check_icb_equal(struct long_ad *a, struct long_ad *b)
 3378{
 3379 return (a->loc.lb_num == b->loc.lb_num &&
 3380 a->loc.part_num == b->loc.part_num);
 3381}
 3382
 3383
3376static struct udf_node * 3384static struct udf_node *
3377udf_hash_lookup(struct udf_mount *ump, struct long_ad *icbptr) 3385udf_hash_lookup(struct udf_mount *ump, struct long_ad *icbptr)
3378{ 3386{
3379 struct udf_node *node; 3387 struct udf_node *node;
3380 struct vnode *vp; 3388 struct vnode *vp;
3381 uint32_t hashline; 3389 uint32_t hashline;
3382 3390
3383loop: 3391loop:
3384 mutex_enter(&ump->ihash_lock); 3392 mutex_enter(&ump->ihash_lock);
3385 3393
3386 hashline = udf_calchash(icbptr) & UDF_INODE_HASHMASK; 3394 hashline = udf_calchash(icbptr) & UDF_INODE_HASHMASK;
3387 LIST_FOREACH(node, &ump->udf_nodes[hashline], hashchain) { 3395 LIST_FOREACH(node, &ump->udf_nodes[hashline], hashchain) {
3388 assert(node); 3396 assert(node);
3389 if (node->loc.loc.lb_num == icbptr->loc.lb_num && 3397 if (udf_check_icb_equal(&node->loc, icbptr)) {
3390 node->loc.loc.part_num == icbptr->loc.part_num) { 
3391 vp = node->vnode; 3398 vp = node->vnode;
3392 assert(vp); 3399 assert(vp);
3393 mutex_enter(&vp->v_interlock); 3400 mutex_enter(&vp->v_interlock);
3394 mutex_exit(&ump->ihash_lock); 3401 mutex_exit(&ump->ihash_lock);
3395 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) 3402 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK))
3396 goto loop; 3403 goto loop;
3397 return node; 3404 return node;
3398 } 3405 }
3399 } 3406 }
3400 mutex_exit(&ump->ihash_lock); 3407 mutex_exit(&ump->ihash_lock);
3401 3408
3402 return NULL; 3409 return NULL;
3403} 3410}

cvs diff -r1.15 -r1.16 src/sys/fs/udf/udf_subr.h (expand / switch to unified diff)

--- src/sys/fs/udf/udf_subr.h 2009/06/24 17:09:13 1.15
+++ src/sys/fs/udf/udf_subr.h 2009/06/25 17:16:33 1.16
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: udf_subr.h,v 1.15 2009/06/24 17:09:13 reinoud Exp $ */ 1/* $NetBSD: udf_subr.h,v 1.16 2009/06/25 17:16:33 reinoud Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006, 2008 Reinoud Zandijk 4 * Copyright (c) 2006, 2008 Reinoud Zandijk
5 * All rights reserved. 5 * All rights reserved.
6 *  6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -173,26 +173,27 @@ int udf_dir_detach(struct udf_mount *ump @@ -173,26 +173,27 @@ int udf_dir_detach(struct udf_mount *ump
173int udf_dir_attach(struct udf_mount *ump, struct udf_node *dir_node, struct udf_node *udf_node, struct vattr *vap, struct componentname *cnp); 173int udf_dir_attach(struct udf_mount *ump, struct udf_node *dir_node, struct udf_node *udf_node, struct vattr *vap, struct componentname *cnp);
174int udf_dir_update_rootentry(struct udf_mount *ump, struct udf_node *dir_node, struct udf_node *new_parent_node); 174int udf_dir_update_rootentry(struct udf_mount *ump, struct udf_node *dir_node, struct udf_node *new_parent_node);
175 175
176/* update and times */ 176/* update and times */
177void udf_add_to_dirtylist(struct udf_node *udf_node); 177void udf_add_to_dirtylist(struct udf_node *udf_node);
178void udf_remove_from_dirtylist(struct udf_node *udf_node); 178void udf_remove_from_dirtylist(struct udf_node *udf_node);
179void udf_itimes(struct udf_node *udf_node, struct timespec *acc, 179void udf_itimes(struct udf_node *udf_node, struct timespec *acc,
180 struct timespec *mod, struct timespec *birth); 180 struct timespec *mod, struct timespec *birth);
181int udf_update(struct vnode *node, struct timespec *acc, 181int udf_update(struct vnode *node, struct timespec *acc,
182 struct timespec *mod, struct timespec *birth, int updflags); 182 struct timespec *mod, struct timespec *birth, int updflags);
183 183
184/* helpers and converters */ 184/* helpers and converters */
185long udf_calchash(struct long_ad *icbptr); /* for `inode' numbering */ 185long udf_calchash(struct long_ad *icbptr); /* for `inode' numbering */
 186int udf_check_icb_equal(struct long_ad *a, struct long_ad *b);
186uint32_t udf_getaccessmode(struct udf_node *node); 187uint32_t udf_getaccessmode(struct udf_node *node);
187void udf_setaccessmode(struct udf_node *udf_node, mode_t mode); 188void udf_setaccessmode(struct udf_node *udf_node, mode_t mode);
188void udf_getownership(struct udf_node *udf_node, uid_t *uidp, gid_t *gidp); 189void udf_getownership(struct udf_node *udf_node, uid_t *uidp, gid_t *gidp);
189void udf_setownership(struct udf_node *udf_node, uid_t uid, gid_t gid); 190void udf_setownership(struct udf_node *udf_node, uid_t uid, gid_t gid);
190 191
191void udf_to_unix_name(char *result, int result_len, char *id, int len, struct charspec *chsp); 192void udf_to_unix_name(char *result, int result_len, char *id, int len, struct charspec *chsp);
192void unix_to_udf_name(char *result, uint8_t *result_len, char const *name, int name_len, struct charspec *chsp); 193void unix_to_udf_name(char *result, uint8_t *result_len, char const *name, int name_len, struct charspec *chsp);
193 194
194void udf_timestamp_to_timespec(struct udf_mount *ump, struct timestamp *timestamp, struct timespec *timespec); 195void udf_timestamp_to_timespec(struct udf_mount *ump, struct timestamp *timestamp, struct timespec *timespec);
195void udf_timespec_to_timestamp(struct timespec *timespec, struct timestamp *timestamp); 196void udf_timespec_to_timestamp(struct timespec *timespec, struct timestamp *timestamp);
196 197
197/* vnode operations */ 198/* vnode operations */
198int udf_inactive(void *v); 199int udf_inactive(void *v);

cvs diff -r1.46 -r1.47 src/sys/fs/udf/udf_vnops.c (expand / switch to unified diff)

--- src/sys/fs/udf/udf_vnops.c 2009/06/24 17:09:13 1.46
+++ src/sys/fs/udf/udf_vnops.c 2009/06/25 17:16:33 1.47
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: udf_vnops.c,v 1.46 2009/06/24 17:09:13 reinoud Exp $ */ 1/* $NetBSD: udf_vnops.c,v 1.47 2009/06/25 17:16:33 reinoud Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006, 2008 Reinoud Zandijk 4 * Copyright (c) 2006, 2008 Reinoud Zandijk
5 * All rights reserved. 5 * All rights reserved.
6 *  6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -22,27 +22,27 @@ @@ -22,27 +22,27 @@
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *  26 *
27 * Generic parts are derived from software contributed to The NetBSD Foundation 27 * Generic parts are derived from software contributed to The NetBSD Foundation
28 * by Julio M. Merino Vidal, developed as part of Google's Summer of Code 28 * by Julio M. Merino Vidal, developed as part of Google's Summer of Code
29 * 2005 program. 29 * 2005 program.
30 * 30 *
31 */ 31 */
32 32
33#include <sys/cdefs.h> 33#include <sys/cdefs.h>
34#ifndef lint 34#ifndef lint
35__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.46 2009/06/24 17:09:13 reinoud Exp $"); 35__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.47 2009/06/25 17:16:33 reinoud Exp $");
36#endif /* not lint */ 36#endif /* not lint */
37 37
38 38
39#include <sys/param.h> 39#include <sys/param.h>
40#include <sys/systm.h> 40#include <sys/systm.h>
41#include <sys/namei.h> 41#include <sys/namei.h>
42#include <sys/resourcevar.h> /* defines plimit structure in proc struct */ 42#include <sys/resourcevar.h> /* defines plimit structure in proc struct */
43#include <sys/kernel.h> 43#include <sys/kernel.h>
44#include <sys/file.h> /* define FWRITE ... */ 44#include <sys/file.h> /* define FWRITE ... */
45#include <sys/stat.h> 45#include <sys/stat.h>
46#include <sys/buf.h> 46#include <sys/buf.h>
47#include <sys/proc.h> 47#include <sys/proc.h>
48#include <sys/mount.h> 48#include <sys/mount.h>
@@ -1815,75 +1815,118 @@ udf_readlink(void *v) @@ -1815,75 +1815,118 @@ udf_readlink(void *v)
1815 /* uiomove() to destination */ 1815 /* uiomove() to destination */
1816 if (!error) 1816 if (!error)
1817 uiomove(targetbuf, PATH_MAX - targetlen, uio); 1817 uiomove(targetbuf, PATH_MAX - targetlen, uio);
1818 1818
1819 free(pathbuf, M_UDFTEMP); 1819 free(pathbuf, M_UDFTEMP);
1820 free(targetbuf, M_UDFTEMP); 1820 free(targetbuf, M_UDFTEMP);
1821 free(tmpname, M_UDFTEMP); 1821 free(tmpname, M_UDFTEMP);
1822 1822
1823 return error; 1823 return error;
1824} 1824}
1825 1825
1826/* --------------------------------------------------------------------- */ 1826/* --------------------------------------------------------------------- */
1827 1827
 1828/*
 1829 * Check if source directory is in the path of the target directory. Target
 1830 * is supplied locked, source is unlocked. The target is always vput before
 1831 * returning. Modeled after UFS.
 1832 *
 1833 * If source is on the path from target to the root, return error.
 1834 */
 1835
1828static int 1836static int
1829udf_on_rootpath(struct udf_node *fnode, struct udf_node *tdnode) 1837udf_on_rootpath(struct udf_node *source, struct udf_node *target)
1830{ 1838{
1831 struct udf_mount *ump = tdnode->ump; 1839 struct udf_mount *ump = target->ump;
1832 struct udf_node *res_node; 1840 struct udf_node *res_node;
1833 struct long_ad icb_loc; 1841 struct long_ad icb_loc, *root_icb;
1834 const char *name; 1842 const char *name;
1835 int namelen; 1843 int namelen;
1836 int error, found; 1844 int error, found;
1837 1845
1838 /* if fnode is on the path from tdnode to the root, return error */ 1846 name = "..";
1839 name = ".."; 1847 namelen = 2;
1840 namelen = 2; 1848 error = 0;
1841 while (fnode != tdnode) { 1849 res_node = target;
1842 DPRINTF(NODE, ("udf_on_rootpath : fnode %p, tdnode %p\n", 1850
1843 fnode, tdnode)); 1851 root_icb = &ump->fileset_desc->rootdir_icb;
1844 if (tdnode->vnode->v_vflag & VV_ROOT) { 1852
1845 /* found root, accept */ 1853 /* if nodes are equal, it is no use looking */
1846 /* DPRINTF(NODE, ("\tCOUGHT, pre-vput\n")); */ 1854 if (udf_check_icb_equal(&source->loc, &target->loc)) {
1847 vput(tdnode->vnode); 1855 error = EEXIST;
1848 DPRINTF(NODE, ("\tCOUGHT: valid\n")); 1856 goto out;
1849 return 0; 1857 }
 1858
 1859 /* nothing can exist before the root */
 1860 if (udf_check_icb_equal(root_icb, &target->loc)) {
 1861 error = 0;
 1862 goto out;
 1863 }
 1864
 1865 for (;;) {
 1866 DPRINTF(NODE, ("udf_on_rootpath : "
 1867 "source vp %p, looking at vp %p\n",
 1868 source->vnode, res_node->vnode));
 1869
 1870 /* sanity check */
 1871 if (res_node->vnode->v_type != VDIR) {
 1872 error = ENOTDIR;
 1873 goto out;
1850 } 1874 }
 1875
1851 /* go down one level */ 1876 /* go down one level */
1852 error = udf_lookup_name_in_dir(tdnode->vnode, name, namelen, 1877 error = udf_lookup_name_in_dir(res_node->vnode, name, namelen,
1853 &icb_loc, &found); 1878 &icb_loc, &found);
1854 
1855 DPRINTF(NODE, ("\tlookup of '..' resulted in error %d, " 1879 DPRINTF(NODE, ("\tlookup of '..' resulted in error %d, "
1856 "found %d\n", error, found)); 1880 "found %d\n", error, found));
1857 /* DPRINTF(NODE, ("\tvput %p\n", tdnode->vnode)); */ 
1858 vput(tdnode->vnode); 
1859 1881
1860 if (error) /* now what? bail out */ 1882 if (!found)
1861 return EINVAL; 1883 error = ENOENT;
1862 if (!found) /* unlikely */ 1884 if (error)
1863 return EINVAL; 1885 goto out;
1864 1886
1865 DPRINTF(NODE, ("\tgetting .. node\n")); 1887 /* did we encounter source node? */
 1888 if (udf_check_icb_equal(&icb_loc, &source->loc)) {
 1889 error = EINVAL;
 1890 goto out;
 1891 }
 1892
 1893 /* did we encounter the root node? */
 1894 if (udf_check_icb_equal(&icb_loc, root_icb)) {
 1895 error = 0;
 1896 goto out;
 1897 }
 1898
 1899 /* push our intermediate node, we're done with it */
 1900 /* DPRINTF(NODE, ("\tvput %p\n", target->vnode)); */
 1901 vput(res_node->vnode);
 1902
 1903 DPRINTF(NODE, ("\tgetting the .. node\n"));
1866 error = udf_get_node(ump, &icb_loc, &res_node); 1904 error = udf_get_node(ump, &icb_loc, &res_node);
1867 DPRINTF(NODE, ("\treported error %d\n", error)); 
1868 if (error) /* argh, bail out */ 
1869 return EINVAL; 
1870 1905
1871 tdnode = res_node; 1906 if (error) { /* argh, bail out */
 1907 KASSERT(res_node == NULL);
 1908 // res_node = NULL;
 1909 goto out;
 1910 }
1872 } 1911 }
1873 DPRINTF(NODE, ("\tCOUGHT: invalid\n")); 1912out:
1874 vput(tdnode->vnode); 1913 DPRINTF(NODE, ("\tresult: %svalid, error = %d\n", error?"in":"", error));
1875 1914
1876 return EINVAL; 1915 /* put our last node */
 1916 if (res_node)
 1917 vput(res_node->vnode);
 1918
 1919 return error;
1877} 1920}
1878 1921
1879/* note: i tried to follow the logics of the tmpfs rename code */ 1922/* note: i tried to follow the logics of the tmpfs rename code */
1880int 1923int
1881udf_rename(void *v) 1924udf_rename(void *v)
1882{ 1925{
1883 struct vop_rename_args /* { 1926 struct vop_rename_args /* {
1884 struct vnode *a_fdvp; 1927 struct vnode *a_fdvp;
1885 struct vnode *a_fvp; 1928 struct vnode *a_fvp;
1886 struct componentname *a_fcnp; 1929 struct componentname *a_fcnp;
1887 struct vnode *a_tdvp; 1930 struct vnode *a_tdvp;
1888 struct vnode *a_tvp; 1931 struct vnode *a_tvp;
1889 struct componentname *a_tcnp; 1932 struct componentname *a_tcnp;
@@ -1940,35 +1983,58 @@ udf_rename(void *v) @@ -1940,35 +1983,58 @@ udf_rename(void *v)
1940 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 1983 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1941 error = ENOTDIR; 1984 error = ENOTDIR;
1942 goto out; 1985 goto out;
1943 } 1986 }
1944 /* if we're moving a non-directory, make sure dest is no dir */ 1987 /* if we're moving a non-directory, make sure dest is no dir */
1945 if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 1988 if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1946 error = EISDIR; 1989 error = EISDIR;
1947 goto out; 1990 goto out;
1948 } 1991 }
1949 } 1992 }
1950 1993
1951 /* check if moving a directory to a new parent is allowed */ 1994 /* check if moving a directory to a new parent is allowed */
1952 if ((fdnode != tdnode) && (fvp->v_type == VDIR)) { 1995 if ((fdnode != tdnode) && (fvp->v_type == VDIR)) {
 1996 /* release tvp since we might encounter it and lock up */
 1997 if (tvp)
 1998 vput(tvp);
 1999
 2000 /* vref tdvp since we lose its ref in udf_on_rootpath */
1953 vref(tdvp); 2001 vref(tdvp);
 2002
 2003 /* search if fnode is a component of tdnode's path to root */
1954 error = udf_on_rootpath(fnode, tdnode); 2004 error = udf_on_rootpath(fnode, tdnode);
 2005
1955 DPRINTF(NODE, ("Dir rename allowed ? %s\n", error ? "NO":"YES")); 2006 DPRINTF(NODE, ("Dir rename allowed ? %s\n", error ? "NO":"YES"));
1956 2007
1957 /* tdnode is vput()'ed, relock */ 2008 if (error) {
1958 (void) vn_lock(tdvp, LK_EXCLUSIVE | LK_RETRY); 2009 /* compensate for our vref earlier */
 2010 vrele(tdvp);
 2011 goto out;
 2012 }
 2013
 2014 /* relock tdvp; its still here due to the vref earlier */
 2015 vn_lock(tdvp, LK_EXCLUSIVE | LK_RETRY);
1959 2016
1960 if (error) 2017 /*
 2018 * re-lookup tvp since the parent has been unlocked, so could
 2019 * have changed/removed in the meantime.
 2020 */
 2021 tcnp->cn_flags &= ~SAVESTART;
 2022 error = relookup(tdvp, &tvp, tcnp);
 2023 if (error) {
 2024 vput(tdvp);
1961 goto out; 2025 goto out;
 2026 }
 2027 tnode = (tvp == NULL) ? NULL : VTOI(tvp);
1962 } 2028 }
1963 2029
1964 /* remove existing entry if present */ 2030 /* remove existing entry if present */
1965 if (tvp)  2031 if (tvp)
1966 udf_dir_detach(tdnode->ump, tdnode, tnode, tcnp); 2032 udf_dir_detach(tdnode->ump, tdnode, tnode, tcnp);
1967 2033
1968 /* create new directory entry for the node */ 2034 /* create new directory entry for the node */
1969 error = udf_dir_attach(tdnode->ump, tdnode, fnode, &fvap, tcnp); 2035 error = udf_dir_attach(tdnode->ump, tdnode, fnode, &fvap, tcnp);
1970 if (error) 2036 if (error)
1971 goto out; 2037 goto out;
1972 2038
1973 /* unlink old directory entry for the node, if failing, unattach new */ 2039 /* unlink old directory entry for the node, if failing, unattach new */
1974 error = udf_dir_detach(tdnode->ump, fdnode, fnode, fcnp); 2040 error = udf_dir_detach(tdnode->ump, fdnode, fnode, fcnp);