mm: Don't decref files while holding a lock
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 29 Mar 2018 21:33:16 +0000 (17:33 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 30 Apr 2018 18:36:28 +0000 (14:36 -0400)
Yes, this code is nasty and needs an overhaul - notably the removal of that
spinlock.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/include/mm.h
kern/src/mm.c

index 1e82917..fce2467 100644 (file)
@@ -13,6 +13,7 @@
 #include <sys/queue.h>
 #include <slab.h>
 #include <kref.h>
+#include <rcu.h>
 
 struct chan;
 struct fd_table;
@@ -25,6 +26,7 @@ struct file_or_chan {
        struct chan *chan;
        struct fs_file *fsf;    /* weak ref, set during mmap. */
        struct kref kref;
+       struct rcu_head rcu;
 };
 
 char *foc_to_name(struct file_or_chan *foc);
index 1cc8783..2c5c8a8 100644 (file)
@@ -92,9 +92,9 @@ ssize_t foc_read(struct file_or_chan *foc, void *buf, size_t amt, off64_t off)
        panic("unknown F_OR_C type");
 }
 
-static void foc_release(struct kref *kref)
+static void __foc_free_rcu(struct rcu_head *head)
 {
-       struct file_or_chan *foc = container_of(kref, struct file_or_chan, kref);
+       struct file_or_chan *foc = container_of(head, struct file_or_chan, rcu);
 
        switch (foc->type) {
        case F_OR_C_CHAN:
@@ -106,6 +106,15 @@ static void foc_release(struct kref *kref)
        kfree(foc);
 }
 
+static void foc_release(struct kref *kref)
+{
+       struct file_or_chan *foc = container_of(kref, struct file_or_chan, kref);
+
+       /* A lot of places decref while holding a spinlock, but we can't free then,
+        * since the cclose() might block. */
+       call_rcu(&foc->rcu, __foc_free_rcu);
+}
+
 static struct file_or_chan *foc_alloc(void)
 {
        struct file_or_chan *foc;