]> 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 0c9a2ee54c91dfde34d502737e821e93d5a765ad..438770f8867fc2fe1289472f30fe52103251ab36 100644 (file)
@@ -317,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);
 }
 
 /*
@@ -804,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;
@@ -900,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);
 }
@@ -916,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,
@@ -931,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 = {