diff -NurpP linux-2.6.16.20-vs2.1.1-rc22.2.1/fs/namei.c linux-2.6.16.20-vs2.1.1-rc23/fs/namei.c --- linux-2.6.16.20-vs2.1.1-rc22.2.1/fs/namei.c 2006-05-21 23:34:46 +0200 +++ linux-2.6.16.20-vs2.1.1-rc23/fs/namei.c 2006-06-10 04:03:24 +0200 @@ -2654,13 +2654,14 @@ int vfs_follow_link(struct nameidata *nd int cow_break_link(struct dentry *dentry, const char *pathname) { int err = -EMLINK; + int retry = 16; int ret, mode, pathlen; struct nameidata old_nd, dir_nd; struct dentry *old_dentry, *new_dentry; struct vfsmount *old_mnt, *new_mnt; struct file *old_file; struct file *new_file; - char *to, *path, pad='\251'; + char *to, *path; loff_t size; vxdprintk(VXD_CBIT(misc, 2), @@ -2679,9 +2680,7 @@ int cow_break_link(struct dentry *dentry to[pathlen+1] = 0; retry: - to[pathlen] = pad--; - if (pad <= '\240') - goto out_rel_old; + to[pathlen] = '\240' + retry; vxdprintk(VXD_CBIT(misc, 2), "temp copy »%s«", to); ret = path_lookup(to, @@ -2691,21 +2690,18 @@ retry: new_dentry = lookup_create(&dir_nd, 0); vxdprintk(VXD_CBIT(misc, 2), "lookup_create(new): %p", new_dentry); - if (!new_dentry) { - path_release(&dir_nd); - goto retry; - } + if (!new_dentry) + goto out_rel_path; ret = vfs_create(dir_nd.dentry->d_inode, new_dentry, mode, &dir_nd); vxdprintk(VXD_CBIT(misc, 2), "vfs_create(new): %d", ret); - if (ret == -EEXIST) { - - mutex_unlock(&dir_nd.dentry->d_inode->i_mutex); - dput(new_dentry); - path_release(&dir_nd); - goto retry; + if (ret != -EEXIST) { + err = ret; + retry = 0; } + if (ret) + goto out_rel_both; new_mnt = dir_nd.mnt; @@ -2755,9 +2751,11 @@ out_fput_old: out_rel_both: mutex_unlock(&dir_nd.dentry->d_inode->i_mutex); dput(new_dentry); - +out_rel_path: path_release(&dir_nd); -out_rel_old: + if (retry--) + goto retry; + path_release(&old_nd); kfree(path); return err;