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 | 3cc3a491a428082bd64a676cc96360dee643dcae (patch) | |
tree | 941b79d1e4080e3dd2a051f2332e8f41a209f0d5 | |
parent | a44a53d305769ddd979fb84e68a6e74db841a8d4 (diff) | |
download | illumos-fusefs-3cc3a491a428082bd64a676cc96360dee643dcae.tar.gz |
Made a full scan when searching for a file whose nodeid is unknown
-rw-r--r-- | kernel/fuse_queue.c | 6 | ||||
-rw-r--r-- | kernel/fuse_vnops.c | 33 |
2 files changed, 37 insertions, 2 deletions
diff --git a/kernel/fuse_queue.c b/kernel/fuse_queue.c index 3db8bb7..04a1aae 100644 --- a/kernel/fuse_queue.c +++ b/kernel/fuse_queue.c @@ -329,6 +329,12 @@ fuse_avl_compare(const void *x1, const void *x2) * validate with the remaining fields of a node */ if (new->facn_nodeid == FUSE_NULL_ID) { + /* + * JPA This is awfully wrong : the tree is based on + * nodeid's, it cannot help if the nodeid's are missing. + * A second tree would be needed. For now, avoid this + * situation and do a full scan instead. + */ if (new->namelen == old->namelen && new->par_nodeid == old->par_nodeid) { /* Compare the names for a match */ diff --git a/kernel/fuse_vnops.c b/kernel/fuse_vnops.c index f58587f..a6e8526 100644 --- a/kernel/fuse_vnops.c +++ b/kernel/fuse_vnops.c @@ -218,6 +218,29 @@ _NOTE(CONSTCOND) } while (0) if (VTOFD(vp)) \ bzero(&(VTOFD(vp)->cached_attrs_bound), sizeof (timestruc_t)); +/* + * Scan the avl-tree for a file whose nodeid in unknown + * + * The tree is based on nodeid's, so avl_find() cannot help + */ + +static fuse_avl_cache_node_t *avl_scan(avl_tree_t *tree, + fuse_avl_cache_node_t *tofind) +{ + fuse_avl_cache_node_t *record; + + record = (fuse_avl_cache_node_t*)avl_first(tree); + while (record + && ((record->namelen != tofind->namelen) + || (record->par_nodeid != tofind->par_nodeid) + || strncmp(record->name, tofind->name, tofind->namelen))) { + record = AVL_NEXT(tree, record); + } + if (record && !record->facn_vnode_p) + record = NULL; + return (record); +} + /* Function which allocates the requested amount of size for message passing */ void fuse_buf_alloc(struct fuse_iov *iov, size_t len) @@ -1936,8 +1959,14 @@ fuse_getvnode(uint64_t nodeid, struct vnode **vpp, v_getmode vmode, int create_new = 0; tofind.facn_nodeid = nodeid; - if ((foundp = avl_find(&(sep->avl_cache), &tofind, - NULL)) != NULL) { + tofind.namelen = namelen; + tofind.name = name; + tofind.par_nodeid = parent_nid; + if (nodeid == FUSE_NULL_ID) + foundp = avl_scan(&(sep->avl_cache), &tofind); + else + foundp = avl_find(&(sep->avl_cache), &tofind, NULL); + if (foundp) { *vpp = foundp->facn_vnode_p; ASSERT(*vpp); /* |