diff -NurpP --minimal linux-2.6.13-rc7-vs2.1.0-pre4.1/fs/namei.c linux-2.6.13-rc7-vs2.1.0-pre5/fs/namei.c --- linux-2.6.13-rc7-vs2.1.0-pre4.1/fs/namei.c 2005-08-25 05:58:01 +0200 +++ linux-2.6.13-rc7-vs2.1.0-pre5/fs/namei.c 2005-08-26 05:58:01 +0200 @@ -1381,8 +1381,10 @@ int may_open(struct nameidata *nd, int a if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE)) return -EISDIR; +#ifdef CONFIG_VSERVER_COWBL if (IS_COW_LINK(inode) && (flag & FMODE_WRITE)) return -EMLINK; +#endif error = permission(inode, acc_mode, nd); if (error) @@ -1472,6 +1474,11 @@ int open_namei(const char * pathname, in struct dentry *dir; int count = 0; +#ifdef CONFIG_VSERVER_COWBL + int rflag = flag; + int rmode = mode; +restart: +#endif acc_mode = ACC_MODE(flag); /* Allow the LSM permission hook to distinguish append @@ -1479,6 +1486,5 @@ int open_namei(const char * pathname, in nd->intent.open.flags = flag; nd->intent.open.create_mode = mode; -restart: /* * The simplest case - just a plain lookup. */ @@ -1576,6 +1583,8 @@ ok: goto exit; path_release(nd); vxdprintk(VXD_CBIT(misc, 2), "restarting open_namei() ..."); + flag = rflag; + mode = rmode; goto restart; } #endif @@ -2448,23 +2457,25 @@ int cow_break_link(struct dentry *dentry { int err = -EMLINK; int ret, mode, pathlen; - struct nameidata old_nd, new_nd; - struct dentry *new_dentry; + 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'; loff_t size; - vxdprintk(VXD_CBIT(misc, 2), "break link »%s«", pathname); + vxdprintk(VXD_CBIT(misc, 2), + "cow_break_link(%p,»%s«)", dentry, pathname); path = kmalloc(PATH_MAX, GFP_KERNEL); ret = path_lookup(pathname, LOOKUP_FOLLOW, &old_nd); vxdprintk(VXD_CBIT(misc, 2), "path_lookup(old): %d", ret); + old_dentry = old_nd.dentry; old_mnt = old_nd.mnt; - mode = old_nd.dentry->d_inode->i_mode; + mode = old_dentry->d_inode->i_mode; - to = d_path(old_nd.dentry, old_nd.mnt, path, PATH_MAX-2); + to = d_path(old_dentry, old_mnt, path, PATH_MAX-2); pathlen = strlen(to); vxdprintk(VXD_CBIT(misc, 2), "old path »%s«", to); @@ -2476,34 +2487,33 @@ retry: vxdprintk(VXD_CBIT(misc, 2), "temp copy »%s«", to); ret = path_lookup(to, - LOOKUP_PARENT | LOOKUP_OPEN | LOOKUP_CREATE, &new_nd); - vxdprintk(VXD_CBIT(misc, 2), "path_lookup(new): %d", ret); + LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE, &dir_nd); /* this puppy downs the inode sem */ - new_dentry = lookup_create(&new_nd, 0); + new_dentry = lookup_create(&dir_nd, 0); vxdprintk(VXD_CBIT(misc, 2), "lookup_create(new): %p", new_dentry); if (!new_dentry) { - path_release(&new_nd); + path_release(&dir_nd); goto retry; } - ret = vfs_create(new_nd.dentry->d_inode, new_dentry, mode, &new_nd); + 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) { - up(&new_nd.dentry->d_inode->i_sem); + up(&dir_nd.dentry->d_inode->i_sem); dput(new_dentry); - path_release(&new_nd); + path_release(&dir_nd); goto retry; } - new_mnt = new_nd.mnt; + new_mnt = dir_nd.mnt; - dget(dentry); + dget(old_dentry); mntget(old_mnt); /* this one cleans up the dentry in case of failure */ - old_file = dentry_open(dentry, old_mnt, O_RDONLY); + old_file = dentry_open(old_dentry, old_mnt, O_RDONLY); vxdprintk(VXD_CBIT(misc, 2), "dentry_open(old): %p", old_file); if (!old_file) @@ -2529,8 +2539,8 @@ retry: if (ret < 0) goto out_fput_both; - ret = vfs_rename(new_nd.dentry->d_inode, new_dentry, - new_nd.dentry->d_inode, dentry); + 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); if (!ret) err = 0; @@ -2548,10 +2558,10 @@ out_fput_old: fput(old_file); out_rel_both: - up(&new_nd.dentry->d_inode->i_sem); + up(&dir_nd.dentry->d_inode->i_sem); dput(new_dentry); - path_release(&new_nd); + path_release(&dir_nd); out_rel_old: path_release(&old_nd);