aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/dev.c25
-rw-r--r--kernel/fuse_i.h3
-rw-r--r--kernel/inode.c3
3 files changed, 30 insertions, 1 deletions
diff --git a/kernel/dev.c b/kernel/dev.c
index d7c45d1..d9ffd43 100644
--- a/kernel/dev.c
+++ b/kernel/dev.c
@@ -357,6 +357,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);
}
/*
@@ -669,6 +670,12 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
err = -EPERM;
if (!fc)
goto err_unlock;
+
+ err = -EAGAIN;
+ if((file->f_flags & O_NONBLOCK) && fc->connected &&
+ list_empty(&fc->pending))
+ goto err_unlock;
+
request_wait(fc);
err = -ENODEV;
if (!fc->connected)
@@ -951,6 +958,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);
}
@@ -967,12 +975,26 @@ static int fuse_dev_release(struct inode *inode, struct file *file)
end_requests(fc, &fc->processing);
}
spin_unlock(&fuse_lock);
- if (fc)
+ if (fc) {
kobject_put(&fc->kobj);
+ fasync_helper(-1, file, 0, &fc->fasync);
+ fc->fasync = NULL;
+ }
return 0;
}
+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);
+}
+
struct file_operations fuse_dev_operations = {
.owner = THIS_MODULE,
.llseek = no_llseek,
@@ -982,6 +1004,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 = {
diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h
index b37b6aa..11f556d 100644
--- a/kernel/fuse_i.h
+++ b/kernel/fuse_i.h
@@ -417,6 +417,9 @@ struct fuse_conn {
/** kobject */
struct kobject kobj;
+
+ /** O_ASYNC requests */
+ struct fasync_struct *fasync;
};
static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
diff --git a/kernel/inode.c b/kernel/inode.c
index 572951d..f65dd5e 100644
--- a/kernel/inode.c
+++ b/kernel/inode.c
@@ -21,6 +21,7 @@
#else
#include "compat/parser.h"
#endif
+#include <linux/poll.h>
MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
MODULE_DESCRIPTION("Filesystem in Userspace");
@@ -290,6 +291,7 @@ static void fuse_put_super(struct super_block *sb)
spin_unlock(&fuse_lock);
up_write(&fc->sbput_sem);
/* Flush all readers on this fs */
+ kill_fasync(&fc->fasync, SIGIO, POLL_IN);
wake_up_all(&fc->waitq);
#ifdef KERNEL_2_6
kobject_del(&fc->kobj);
@@ -518,6 +520,7 @@ static struct fuse_conn *new_conn(void)
fc->bdi.unplug_io_fn = default_unplug_io_fn;
#endif
fc->reqctr = 0;
+ fc->fasync = NULL;
}
return fc;
}