summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Pierre André <jpandre@users.sourceforge.net>2012-08-22 10:00:22 +0200
committerJean-Pierre André <jpandre@users.sourceforge.net>2012-08-22 10:00:22 +0200
commit3cc3a491a428082bd64a676cc96360dee643dcae (patch)
tree941b79d1e4080e3dd2a051f2332e8f41a209f0d5
parenta44a53d305769ddd979fb84e68a6e74db841a8d4 (diff)
downloadillumos-fusefs-3cc3a491a428082bd64a676cc96360dee643dcae.tar.gz
Made a full scan when searching for a file whose nodeid is unknown
-rw-r--r--kernel/fuse_queue.c6
-rw-r--r--kernel/fuse_vnops.c33
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);
/*