summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--netfs.c3
-rw-r--r--procfs.c26
-rw-r--r--procfs.h5
3 files changed, 30 insertions, 4 deletions
diff --git a/netfs.c b/netfs.c
index 58665085..6b105f91 100644
--- a/netfs.c
+++ b/netfs.c
@@ -151,10 +151,11 @@ error_t netfs_attempt_lookup (struct iouser *user, struct node *dir,
error_t err;
err = procfs_lookup (dir, name, np);
+ mutex_unlock (&dir->lock);
+
if (! err)
mutex_lock (&(*np)->lock);
- mutex_unlock (&dir->lock);
return err;
}
diff --git a/procfs.c b/procfs.c
index 573bb72f..c5f19497 100644
--- a/procfs.c
+++ b/procfs.c
@@ -14,6 +14,9 @@ struct netnode
/* (cached) contents of the node */
void *contents;
size_t contents_len;
+
+ /* parent directory, if applicable */
+ struct node *parent;
};
void
@@ -97,8 +100,24 @@ error_t procfs_lookup (struct node *np, const char *name, struct node **npp)
{
error_t err = ENOENT;
- if (np->nn->ops->lookup)
- err = np->nn->ops->lookup (np->nn->hook, name, npp);
+ if (err && ! strcmp (name, "."))
+ {
+ netfs_nref(*npp = np);
+ err = 0;
+ }
+
+ if (err && np->nn->parent && ! strcmp (name, ".."))
+ {
+ netfs_nref(*npp = np->nn->parent);
+ err = 0;
+ }
+
+ if (err && np->nn->ops->lookup)
+ {
+ err = np->nn->ops->lookup (np->nn->hook, name, npp);
+ if (! err)
+ netfs_nref ((*npp)->nn->parent = np);
+ }
return err;
}
@@ -111,5 +130,8 @@ void procfs_cleanup (struct node *np)
if (np->nn->ops->cleanup)
np->nn->ops->cleanup (np->nn->hook);
+ if (np->nn->parent)
+ netfs_nrele (np->nn->parent);
+
free (np->nn);
}
diff --git a/procfs.h b/procfs.h
index b44db6e3..42eed0e2 100644
--- a/procfs.h
+++ b/procfs.h
@@ -22,7 +22,10 @@ struct procfs_node_ops
/* Lookup NAME in this directory, and store the result in *np. The
returned node should be created by lookup() using procfs_make_node()
- or a derived function. */
+ or a derived function. Note that the parent will be kept alive as
+ long as the child exists, so you can safely reference the parent's
+ data from the child. You may want to consider locking if there's
+ any mutation going on, though. */
error_t (*lookup) (void *hook, const char *name, struct node **np);
/* Destroy this node. */