diff -NurpP --minimal linux-2.6.22.9-vs2.3.0.28.3/fs/namei.c linux-2.6.22.9-vs2.3.0.28.4.2/fs/namei.c
--- linux-2.6.22.9-vs2.3.0.28.3/fs/namei.c	2007-10-25 13:30:54 +0200
+++ linux-2.6.22.9-vs2.3.0.28.4.2/fs/namei.c	2007-10-25 18:04:41 +0200
@@ -2775,7 +2775,7 @@ long do_cow_splice(struct file *in, stru
 
 struct dentry *cow_break_link(const char *pathname)
 {
-	int ret, mode, pathlen;
+	int ret, redo, mode, pathlen;
 	struct nameidata old_nd, dir_nd;
 	struct dentry *old_dentry, *new_dentry;
 	struct dentry *res, *dir;
@@ -2787,14 +2787,13 @@ 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);
+	ret = -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;
 
@@ -2808,10 +2807,10 @@ struct dentry *cow_break_link(const char
 		old_dentry->d_name.len, old_dentry->d_name.name,
 		old_dentry->d_name.len);
 
-	to[pathlen+1] = 0;
+	to[pathlen + 1] = 0;
 retry:
 	to[pathlen] = pad--;
-	res = ERR_PTR(-EMLINK);
+	ret = -EMLINK;
 	if (pad <= '\240')
 		goto out_rel_old;
 
@@ -2845,16 +2844,13 @@ retry:
 		path_release(&dir_nd);
 		goto retry;
 	}
-	else if (ret < 0) {
-		res = ERR_PTR(ret);
+	else if (ret < 0)
 		goto out_unlock_new;
-	}
 
-	/* drop out early */
-	if (d_unhashed(old_dentry)) {
-		res = ERR_PTR(-ENOENT);
+	/* drop out early, ret passes ENOENT */
+	ret = -ENOENT;
+	if ((redo = d_unhashed(old_dentry)))
 		goto out_unlock_new;
-	}
 
 	new_mnt = dir_nd.mnt;
 	dget(old_dentry);
@@ -2874,19 +2870,18 @@ retry:
 	new_file = dentry_open(new_dentry, new_mnt, O_WRONLY);
 	vxdprintk(VXD_CBIT(misc, 2),
 		"dentry_open(new): %p", new_file);
-	if (!new_file || IS_ERR(new_file)) {
-		res = IS_ERR(new_file) ? (void *) new_file : res;
+
+	ret = IS_ERR(new_file) ? PTR_ERR(new_file) : -ENOENT;
+	if (!new_file || IS_ERR(new_file))
 		goto out_fput_old;
-	}
 
 	size = i_size_read(old_file->f_dentry->d_inode);
 	ret = do_cow_splice(old_file, new_file, size);
 	vxdprintk(VXD_CBIT(misc, 2), "do_splice_direct: %d", ret);
 	if (ret < 0) {
-		res = ERR_PTR(ret);
 		goto out_fput_both;
 	} else if (ret < size) {
-		res = ERR_PTR(-ENOSPC);
+		ret = -ENOSPC;
 		goto out_fput_both;
 	} else {
 		struct inode *old_inode = old_dentry->d_inode;
@@ -2898,15 +2893,15 @@ retry:
 			};
 
 		ret = inode_setattr(new_inode, &attr);
-		if (ret) {
-			res = ERR_PTR(ret);
+		if (ret)
 			goto out_fput_both;
-		}
 	}
 
 	mutex_lock(&old_dentry->d_inode->i_sb->s_vfs_rename_mutex);
+
+	/* drop out late */
 	ret = -ENOENT;
-	if (d_unhashed(old_dentry))
+	if ((redo = d_unhashed(old_dentry)))
 		goto out_unlock;
 
 	vxdprintk(VXD_CBIT(misc, 2),
@@ -2918,17 +2913,11 @@ retry:
 	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);
+	res = new_dentry;
 
 out_unlock:
 	mutex_unlock(&old_dentry->d_inode->i_sb->s_vfs_rename_mutex);
 
-	if (!ret) {
-		res = new_dentry;
-		dget(new_dentry);
-	}
-	else
-		res = ERR_PTR(ret);
-
 out_fput_both:
 	vxdprintk(VXD_CBIT(misc, 3),
 		"fput(new_file=%p[#%d])", new_file,
@@ -2943,8 +2932,11 @@ out_fput_old:
 
 out_unlock_new:
 	mutex_unlock(&dir->d_inode->i_mutex);
-	if (IS_ERR(res))
-		vfs_unlink(dir->d_inode, new_dentry, &dir_nd);
+	if (!ret)
+		goto out_rel_both;
+
+	/* error path cleanup */
+	vfs_unlink(dir->d_inode, new_dentry, &dir_nd);
 	dput(new_dentry);
 out_rel_both:
 	path_release(&dir_nd);
@@ -2953,6 +2945,8 @@ out_rel_old:
 out_free_path:
 	kfree(path);
 out:
+	if (ret)
+		res = ERR_PTR(ret);
 	return res;
 }