diff -NurpP linux-2.6.22.9-vs2.3.0.27/Makefile linux-2.6.22.9-vs2.3.0.27.2/Makefile
--- linux-2.6.22.9-vs2.3.0.27/Makefile	2007-10-11 02:53:26 +0200
+++ linux-2.6.22.9-vs2.3.0.27.2/Makefile	2007-10-17 17:04:44 +0200
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 22
-EXTRAVERSION = .9-vs2.3.0.27
+EXTRAVERSION = .9-vs2.3.0.27.2
 NAME = Holy Dancing Manatees, Batman!
 
 # *DOCUMENTATION*
Files linux-2.6.22.9-vs2.3.0.27/fs/.namei.c.swn and linux-2.6.22.9-vs2.3.0.27.2/fs/.namei.c.swn differ
Files linux-2.6.22.9-vs2.3.0.27/fs/.namei.c.swo and linux-2.6.22.9-vs2.3.0.27.2/fs/.namei.c.swo differ
diff -NurpP linux-2.6.22.9-vs2.3.0.27/fs/namei.c linux-2.6.22.9-vs2.3.0.27.2/fs/namei.c
--- linux-2.6.22.9-vs2.3.0.27/fs/namei.c	2007-10-11 01:10:22 +0200
+++ linux-2.6.22.9-vs2.3.0.27.2/fs/namei.c	2007-10-17 16:52:04 +0200
@@ -2777,12 +2777,81 @@ long do_cow_splice(struct file *in, stru
 	return do_splice_direct(in, &ppos, out, len, 0);
 }
 
+#define OUT_DENTRY(n, d)						\
+	vxdprintk(VXD_CBIT(misc, 1), n " %p[»%*s«:%d]",			\
+		d, (d)->d_name.len, (d)->d_name.name, (d)->d_name.len);
+
+
+static inline struct dentry *__cow_lookup_hash(struct nameidata *nd)
+{
+	return __lookup_hash_kern(&nd->last, nd->dentry, nd);
+}
+
+int cow_rename_copy(struct nameidata *old_nd, struct nameidata *new_nd)
+{
+	int error;
+	struct dentry *old_dir, *new_dir;
+	struct dentry *old_dentry, *new_dentry;
+	struct dentry *trap;
+
+	error = -EXDEV;
+	if (old_nd->mnt != new_nd->mnt)
+		goto out;
+
+	old_dir = old_nd->dentry;
+	new_dir = new_nd->dentry;
+
+	trap = lock_rename(new_dir, old_dir);
+
+	old_dentry = __cow_lookup_hash(old_nd);
+	vxdprintk(VXD_CBIT(misc, 2), "lookup_hash(old_nd): %p", old_dentry);
+	error = PTR_ERR(old_dentry);
+	if (IS_ERR(old_dentry))
+		goto out_unlock;
+	/* source must exist */
+	error = -ENOENT;
+	if (!old_dentry->d_inode)
+		goto out_put_old;
+	/* source should not be ancestor of target */
+	error = -EINVAL;
+	if (old_dentry == trap)
+		goto out_put_old;
+
+	new_dentry = __cow_lookup_hash(new_nd);
+	vxdprintk(VXD_CBIT(misc, 2), "lookup_hash(new_nd): %p", new_dentry);
+	error = PTR_ERR(new_dentry);
+	if (IS_ERR(new_dentry))
+		goto out_put_old;
+	/* target should not be an ancestor of source */
+	error = -ENOTEMPTY;
+	if (new_dentry == trap)
+		goto out_put_both;
+
+	vxdprintk(VXD_CBIT(misc, 2),
+		"vfs_rename: [»%*s«:%d] -> [»%*s«:%d]",
+		old_dentry->d_name.len, old_dentry->d_name.name,
+		old_dentry->d_name.len,
+		new_dentry->d_name.len, new_dentry->d_name.name,
+		new_dentry->d_name.len);
+	error = vfs_rename(old_dir->d_inode, old_dentry,
+		new_dir->d_inode, new_dentry);
+	vxdprintk(VXD_CBIT(misc, 2), "vfs_rename: %d", error);
+out_put_both:
+	dput(new_dentry);
+out_put_old:
+	dput(old_dentry);
+out_unlock:
+	unlock_rename(new_dir, old_dir);
+out:
+	return error;
+}
+
 struct dentry *cow_break_link(const char *pathname)
 {
 	int ret, mode, pathlen;
 	struct nameidata old_nd, dir_nd;
 	struct dentry *old_dentry, *new_dentry;
-	struct dentry *res = ERR_PTR(-EMLINK);
+	struct dentry *res;
 	struct vfsmount *old_mnt, *new_mnt;
 	struct file *old_file;
 	struct file *new_file;
@@ -2791,11 +2860,14 @@ struct dentry *cow_break_link(const char
 
 	vxdprintk(VXD_CBIT(misc, 1), "cow_break_link(»%s«)", pathname);
 	path = kmalloc(PATH_MAX, GFP_KERNEL);
+	res = ERR_PTR(-ENOMEM);
 	if (!path)
 		goto out;
 
+	/* old_nd will have refs to dentry and mnt */
 	ret = path_lookup(pathname, LOOKUP_FOLLOW, &old_nd);
 	vxdprintk(VXD_CBIT(misc, 2), "path_lookup(old): %d", ret);
+	res = ERR_PTR(ret);
 	if (ret < 0)
 		goto out_free_path;
 
@@ -2805,34 +2877,44 @@ struct dentry *cow_break_link(const char
 
 	to = d_path(old_dentry, old_mnt, path, PATH_MAX-2);
 	pathlen = strlen(to);
-	vxdprintk(VXD_CBIT(misc, 2), "old path »%s«", to);
+	vxdprintk(VXD_CBIT(misc, 2), "old path »%s« [»%*s«:%d]", to,
+		old_dentry->d_name.len, old_dentry->d_name.name,
+		old_dentry->d_name.len);
 
 	to[pathlen+1] = 0;
 retry:
 	to[pathlen] = pad--;
+	res = ERR_PTR(-EMLINK);
 	if (pad <= '\240')
 		goto out_rel_old;
 
 	vxdprintk(VXD_CBIT(misc, 1), "temp copy »%s«", to);
+	OUT_DENTRY("old_dentry", old_dentry);
+	/* dir_nd will have refs to dentry and mnt */
 	ret = path_lookup(to,
 		LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE, &dir_nd);
 	vxdprintk(VXD_CBIT(misc, 2),
 		"path_lookup(new): %d", ret);
+	OUT_DENTRY("old_dentry", old_dentry);
 	if (ret < 0)
 		goto retry;
 
-	/* this puppy downs the inode sem */
+	/* this puppy downs the inode mutex */
 	new_dentry = lookup_create(&dir_nd, 0);
 	vxdprintk(VXD_CBIT(misc, 2),
-		"lookup_create(new): %p", new_dentry);
+		"lookup_create(new): %p [»%*s«:%d]", new_dentry,
+		new_dentry->d_name.len, new_dentry->d_name.name,
+		new_dentry->d_name.len);
 	if (!new_dentry || IS_ERR(new_dentry)) {
 		path_release(&dir_nd);
 		goto retry;
 	}
 
+	OUT_DENTRY("old_dentry", old_dentry);
 	ret = vfs_create(dir_nd.dentry->d_inode, new_dentry, mode, &dir_nd);
 	vxdprintk(VXD_CBIT(misc, 2),
 		"vfs_create(new): %d", ret);
+	OUT_DENTRY("old_dentry", old_dentry);
 	if (ret == -EEXIST) {
 		mutex_unlock(&dir_nd.dentry->d_inode->i_mutex);
 		dput(new_dentry);
@@ -2845,13 +2927,17 @@ retry:
 	}
 
 	new_mnt = dir_nd.mnt;
+	/* drop lock on copy destination */
+	mutex_unlock(&dir_nd.dentry->d_inode->i_mutex);
 
 	dget(old_dentry);
 	mntget(old_mnt);
-	/* this one cleans up the dentry in case of failure */
+	OUT_DENTRY("old_dentry", old_dentry);
+	/* this one cleans up the dentry/mnt in case of failure */
 	old_file = dentry_open(old_dentry, old_mnt, O_RDONLY);
 	vxdprintk(VXD_CBIT(misc, 2),
 		"dentry_open(old): %p", old_file);
+	OUT_DENTRY("old_dentry", old_dentry);
 	if (!old_file || IS_ERR(old_file)) {
 		res = IS_ERR(old_file) ? (void *) old_file : res;
 		goto out_rel_both;
@@ -2859,17 +2945,21 @@ retry:
 
 	dget(new_dentry);
 	mntget(new_mnt);
-	/* this one cleans up the dentry in case of failure */
+	OUT_DENTRY("old_dentry", old_dentry);
+	/* this one cleans up the dentry/mnt in case of failure */
 	new_file = dentry_open(new_dentry, new_mnt, O_WRONLY);
 	vxdprintk(VXD_CBIT(misc, 2),
 		"dentry_open(new): %p", new_file);
+	OUT_DENTRY("old_dentry", old_dentry);
 	if (!new_file || IS_ERR(new_file)) {
 		res = IS_ERR(new_file) ? (void *) new_file : res;
 		goto out_fput_old;
 	}
 
 	size = i_size_read(old_file->f_dentry->d_inode);
+	OUT_DENTRY("old_dentry", old_dentry);
 	ret = do_cow_splice(old_file, new_file, size);
+	OUT_DENTRY("old_dentry", old_dentry);
 	vxdprintk(VXD_CBIT(misc, 2), "do_splice_direct: %d", ret);
 	if (ret < 0) {
 		res = ERR_PTR(ret);
@@ -2886,19 +2976,27 @@ retry:
 			.ia_valid = ATTR_UID | ATTR_GID
 			};
 
-		inode_setattr(new_inode, &attr);
+		OUT_DENTRY("old_dentry", old_dentry);
+		ret = inode_setattr(new_inode, &attr);
+		OUT_DENTRY("old_dentry", old_dentry);
+		if (ret) {
+			res = ERR_PTR(ret);
+			goto out_fput_both;
+		}
 	}
 
-	ret = vfs_rename(dir_nd.dentry->d_inode, new_dentry,
-		old_nd.dentry->d_parent->d_inode, old_dentry);
-	vxdprintk(VXD_CBIT(misc, 2), "vfs_rename: %d", ret);
+	/* note: old_nd is the new one and dir_nd the old */
+	ret = cow_rename_copy(&dir_nd, &old_nd);
+	vxdprintk(VXD_CBIT(misc, 2), "cow_rename_copy: %d", ret);
 	if (!ret) {
-		res = new_dentry;
-		dget(new_dentry);
+		res = lookup_hash(&dir_nd);
+		// res = new_dentry;
+		dget(res);
 	}
 	else
 		res = ERR_PTR(ret);
 
+
 out_fput_both:
 	vxdprintk(VXD_CBIT(misc, 3),
 		"fput(new_file=%p[#%d])", new_file,
@@ -2912,11 +3010,10 @@ out_fput_old:
 	fput(old_file);
 
 out_rel_both:
-	mutex_unlock(&dir_nd.dentry->d_inode->i_mutex);
 	if (IS_ERR(res))
 		vfs_unlink(dir_nd.dentry->d_inode, new_dentry, &dir_nd);
 	dput(new_dentry);
-
+out_rel_new:
 	path_release(&dir_nd);
 out_rel_old:
 	path_release(&old_nd);
diff -NurpP linux-2.6.22.9-vs2.3.0.27/include/linux/vserver/debug.h linux-2.6.22.9-vs2.3.0.27.2/include/linux/vserver/debug.h
--- linux-2.6.22.9-vs2.3.0.27/include/linux/vserver/debug.h	2007-10-01 14:57:41 +0200
+++ linux-2.6.22.9-vs2.3.0.27.2/include/linux/vserver/debug.h	2007-10-17 13:48:26 +0200
@@ -39,11 +39,14 @@ extern unsigned int vx_debug_misc;
 
 
 #define VX_LOGLEVEL	"vxD: "
+#define VX_PROC_FMT	"%p: "
+#define VX_PROCESS	current
 
 #define vxdprintk(c, f, x...)					\
 	do {							\
 		if (c)						\
-			printk(VX_LOGLEVEL f "\n" , ##x);	\
+			printk(VX_LOGLEVEL VX_PROC_FMT f "\n",	\
+				VX_PROCESS , ##x);		\
 	} while (0)
 
 #define vxlprintk(c, f, x...)					\
