]> err.no Git - linux-2.6/blobdiff - fs/fuse/dev.c
[PATCH] fuse: add O_ASYNC support to FUSE device
[linux-2.6] / fs / fuse / dev.c
index f556a0d5c0d31010b86552ff958dcb55b20947f5..438770f8867fc2fe1289472f30fe52103251ab36 100644 (file)
@@ -66,6 +66,12 @@ static void restore_sigs(sigset_t *oldset)
        sigprocmask(SIG_SETMASK, oldset, NULL);
 }
 
+/*
+ * Reset request, so that it can be reused
+ *
+ * The caller must be _very_ careful to make sure, that it is holding
+ * the only reference to req
+ */
 void fuse_reset_request(struct fuse_req *req)
 {
        int preallocated = req->preallocated;
@@ -311,6 +317,7 @@ static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
        list_add_tail(&req->list, &fc->pending);
        req->state = FUSE_REQ_PENDING;
        wake_up(&fc->waitq);
+       kill_fasync(&fc->fasync, SIGIO, POLL_IN);
 }
 
 /*
@@ -798,17 +805,18 @@ static ssize_t fuse_dev_write(struct file *file, const char __user *buf,
 
 static unsigned fuse_dev_poll(struct file *file, poll_table *wait)
 {
-       struct fuse_conn *fc = fuse_get_conn(file);
        unsigned mask = POLLOUT | POLLWRNORM;
-
+       struct fuse_conn *fc = fuse_get_conn(file);
        if (!fc)
-               return -ENODEV;
+               return POLLERR;
 
        poll_wait(file, &fc->waitq, wait);
 
        spin_lock(&fuse_lock);
-       if (!list_empty(&fc->pending))
-                mask |= POLLIN | POLLRDNORM;
+       if (!fc->connected)
+               mask = POLLERR;
+       else if (!list_empty(&fc->pending))
+               mask |= POLLIN | POLLRDNORM;
        spin_unlock(&fuse_lock);
 
        return mask;
@@ -894,6 +902,7 @@ void fuse_abort_conn(struct fuse_conn *fc)
                end_requests(fc, &fc->pending);
                end_requests(fc, &fc->processing);
                wake_up_all(&fc->waitq);
+               kill_fasync(&fc->fasync, SIGIO, POLL_IN);
        }
        spin_unlock(&fuse_lock);
 }
@@ -910,13 +919,25 @@ static int fuse_dev_release(struct inode *inode, struct file *file)
                end_requests(fc, &fc->processing);
        }
        spin_unlock(&fuse_lock);
-       if (fc)
+       if (fc) {
+               fasync_helper(-1, file, 0, &fc->fasync);
                kobject_put(&fc->kobj);
+       }
 
        return 0;
 }
 
-struct file_operations fuse_dev_operations = {
+static int fuse_dev_fasync(int fd, struct file *file, int on)
+{
+       struct fuse_conn *fc = fuse_get_conn(file);
+       if (!fc)
+               return -ENODEV;
+
+       /* No locking - fasync_helper does its own locking */
+       return fasync_helper(fd, file, on, &fc->fasync);
+}
+
+const struct file_operations fuse_dev_operations = {
        .owner          = THIS_MODULE,
        .llseek         = no_llseek,
        .read           = fuse_dev_read,
@@ -925,6 +946,7 @@ struct file_operations fuse_dev_operations = {
        .writev         = fuse_dev_writev,
        .poll           = fuse_dev_poll,
        .release        = fuse_dev_release,
+       .fasync         = fuse_dev_fasync,
 };
 
 static struct miscdevice fuse_miscdevice = {