diff options
author | Jean-Pierre André <jpandre@users.sourceforge.net> | 2012-08-22 10:00:22 +0200 |
---|---|---|
committer | Jean-Pierre André <jpandre@users.sourceforge.net> | 2012-08-22 10:00:22 +0200 |
commit | 281002e1769079472a3dcc771ee0303f769e5852 (patch) | |
tree | d0fd7362136cd1ca58d576ee5230989dfae59736 | |
parent | 5b71fba328f376b08e08670e7e9043e058382a51 (diff) | |
download | illumos-fusefs-281002e1769079472a3dcc771ee0303f769e5852.tar.gz |
Applied renamings to the cached data
-rw-r--r-- | kernel/fuse_vnops.c | 52 |
1 files changed, 49 insertions, 3 deletions
diff --git a/kernel/fuse_vnops.c b/kernel/fuse_vnops.c index d0a4bf8..9e8cd02 100644 --- a/kernel/fuse_vnops.c +++ b/kernel/fuse_vnops.c @@ -2785,6 +2785,7 @@ fuse_rename(vnode_t *sdvp, char *oldname, vnode_t *tdvp, char *newname, { int err = EIO; int samedir; + fuse_session_t *sep; struct vnode *svp = NULL; struct vnode *tvp = NULL; @@ -2864,9 +2865,54 @@ fuse_rename(vnode_t *sdvp, char *oldname, vnode_t *tdvp, char *newname, goto errout; } } - /* Inform daemon to handle the rename operation */ - if ((err = fuse_rename_i(sdvp, oldname, tdvp, newname, credp))) - goto errout; + + /* Make sure to have everything ready for renaming */ + sep = fuse_minor_get_session(getminor(sdvp->v_rdev)); + if (sep) { + fuse_avl_cache_node_t find, *renamep; + char *wanted_name = (char*)NULL; + + find.facn_nodeid = VNODE_TO_NODEID(svp); + renamep = avl_find(&(sep->avl_cache), &find, NULL); + wanted_name = kmem_alloc(strlen(newname) + 1, KM_SLEEP); + if (renamep && wanted_name) { + /* Inform daemon to handle the rename operation */ + if ((err = fuse_rename_i(sdvp, oldname, tdvp, + newname, credp))) { + kmem_free(wanted_name, strlen(newname) + 1); + goto errout; + } else { + /* + * If renaming was successful, the cached entries + * do not match what is stored in the file system + * any more. + * The old target, if any, has been deleted, + * the source has kept its nodeid, but its name + * has changed, so do the same in the cache. + */ + if (tvp) { + VN_RELE(tvp); + if (tvp != svp) + fuse_vnode_free(tvp, sep); + tvp = (struct vnode*)NULL; + } + avl_remove(&(sep->avl_cache), renamep); + kmem_free(renamep->name, renamep->namelen); + renamep->par_nodeid = VNODE_TO_NODEID(tdvp); + renamep->namelen = strlen(newname) + 1; + renamep->name = wanted_name; + strlcpy(renamep->name, newname, + renamep->namelen); + avl_add(&(sep->avl_cache), renamep); + } + } else { + if (wanted_name) + kmem_free(wanted_name, strlen(newname) + 1); + err = ENOENT; + } + } else { + err = ENODEV; + } errout: if (svp) |