Module Name:    src
Committed By:   reinoud
Date:           Wed Jul  3 14:35:29 UTC 2013

Modified Files:
        src/sys/fs/udf: udf_vnops.c

Log Message:
On removing a directory make sure the leaf directory doesn't have a valid '..'
link anymore. In a corner case this leaf can be held by a process as a CWD. It
is guaranteed to be empty at this stage so we trunc it removing the only valid
FID, being the '..' entry.

Solves part of PR kern/47987
Solves tests/vfs/t_vnops udf_dir_rmdirdotdot


To generate a diff of this commit:
cvs rdiff -u -r1.77 -r1.78 src/sys/fs/udf/udf_vnops.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/fs/udf/udf_vnops.c
diff -u src/sys/fs/udf/udf_vnops.c:1.77 src/sys/fs/udf/udf_vnops.c:1.78
--- src/sys/fs/udf/udf_vnops.c:1.77	Wed Jul  3 12:55:34 2013
+++ src/sys/fs/udf/udf_vnops.c	Wed Jul  3 14:35:28 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: udf_vnops.c,v 1.77 2013/07/03 12:55:34 reinoud Exp $ */
+/* $NetBSD: udf_vnops.c,v 1.78 2013/07/03 14:35:28 reinoud Exp $ */
 
 /*
  * Copyright (c) 2006, 2008 Reinoud Zandijk
@@ -32,7 +32,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.77 2013/07/03 12:55:34 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.78 2013/07/03 14:35:28 reinoud Exp $");
 #endif /* not lint */
 
 
@@ -58,6 +58,8 @@ __KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,
 
 #include <fs/udf/ecma167-udf.h>
 #include <fs/udf/udf_mount.h>
+#include <sys/dirhash.h>
+
 #include "udf.h"
 #include "udf_subr.h"
 #include "udf_bswap.h"
@@ -2166,7 +2168,7 @@ udf_rmdir(void *v)
 	struct udf_mount *ump = dir_node->ump;
 	int refcnt, error;
 
-	DPRINTF(NOTIMPL, ("udf_rmdir called\n"));
+	DPRINTF(NOTIMPL, ("udf_rmdir '%s' called\n", cnp->cn_nameptr));
 
 	/* don't allow '.' to be deleted */
 	if (dir_node == udf_node) {
@@ -2189,11 +2191,20 @@ udf_rmdir(void *v)
 		return ENOTEMPTY;
 	}
 
-	/* detach the node from the directory */
+	/* detach the node from the directory, udf_node is an empty dir here */
 	error = udf_dir_detach(ump, dir_node, udf_node, cnp);
 	if (error == 0) {
 		cache_purge(vp);
 //		cache_purge(dvp);	/* XXX from msdosfs, why? */
+		/*
+		 * Bug alert: we need to remove '..' from the detaching
+		 * udf_node so further lookups of this are not possible. This
+		 * prevents a process in a deleted directory from going to its
+		 * deleted parent. Since `udf_node' is garanteed to be empty
+		 * here, trunc it so no fids are there.
+		 */
+		dirhash_purge(&udf_node->dir_hash);
+		udf_shrink_node(udf_node, 0);
 		VN_KNOTE(vp, NOTE_DELETE);
 	}
 	DPRINTFIF(NODE, error, ("\tgot error removing dir\n"));

Reply via email to