aboutsummaryrefslogtreecommitdiffstats
path: root/dev.c
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2001-10-24 14:37:13 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2001-10-24 14:37:13 +0000
commit79b52f63303c15d4545a7464775f4b1beab8d2c9 (patch)
tree7f3c12670af489f58740408ad755e775e27803ef /dev.c
parentd8318555890588b0982749fdd23826d9ddb02098 (diff)
downloadlibfuse-79b52f63303c15d4545a7464775f4b1beab8d2c9.tar.gz
improvements
Diffstat (limited to 'dev.c')
-rw-r--r--dev.c130
1 files changed, 108 insertions, 22 deletions
diff --git a/dev.c b/dev.c
index c7dd247..159d8d6 100644
--- a/dev.c
+++ b/dev.c
@@ -10,69 +10,155 @@
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/smp_lock.h>
#include <linux/poll.h>
-#include <linux/file.h>
#include <linux/proc_fs.h>
static struct proc_dir_entry *proc_fs_fuse;
struct proc_dir_entry *proc_fuse_dev;
+static struct fuse_req *request_wait(struct fuse_conn *fc)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ struct fuse_req *req;
+
+ spin_lock(&fuse_lock);
+ add_wait_queue(&fc->waitq, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ while(list_empty(&fc->pending)) {
+ if(signal_pending(current))
+ break;
+
+ spin_unlock(&fuse_lock);
+ schedule();
+ spin_lock(&fuse_lock);
+ }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&fc->waitq, &wait);
+
+ if(list_empty(&fc->pending))
+ return NULL;
+
+ req = list_entry(fc->pending.next, struct fuse_req, list);
+ list_del(&req->list);
+ spin_unlock(&fuse_lock);
+
+ return req;
+}
+
+static void request_processing(struct fuse_conn *fc, struct fuse_req *req)
+{
+ spin_lock(&fuse_lock);
+ list_add_tail(&req->list, &fc->processing);
+ fc->outstanding ++;
+ spin_unlock(&fuse_lock);
+}
+
+static void request_free(struct fuse_req *req)
+{
+ kfree(req);
+}
+
static ssize_t fuse_dev_read(struct file *file, char *buf, size_t nbytes,
loff_t *off)
{
- printk(KERN_DEBUG "fuse_dev_read\n");
- return 0;
+ ssize_t res;
+ struct fuse_conn *fc = file->private_data;
+ struct fuse_req *req;
+
+ printk(KERN_DEBUG "fuse_dev_read[%i]\n", fc->id);
+
+ res = -ERESTARTSYS;
+ req = request_wait(fc);
+ if(req == NULL)
+ goto err;
+
+ res = -EIO;
+ if(nbytes < req->size) {
+ printk("fuse_dev_read: buffer too small (%i)\n", req->size);
+ goto err_free_req;
+ }
+
+ res = -EFAULT;
+ if(copy_to_user(buf, req->data, req->size))
+ goto err_free_req;
+
+ request_processing(fc, req);
+ return req->size;
+
+ err_free_req:
+ request_free(req);
+ err:
+ return res;
}
static ssize_t fuse_dev_write(struct file *file, const char *buf,
size_t nbytes, loff_t *off)
{
- printk(KERN_DEBUG "fuse_dev_write <%.*s>\n", (int) nbytes, buf);
+ struct fuse_conn *fc = file->private_data;
+
+ printk(KERN_DEBUG "fuse_dev_write[%i] <%.*s>\n", fc->id, (int) nbytes,
+ buf);
return nbytes;
}
static unsigned int fuse_dev_poll(struct file *file, poll_table *wait)
{
- printk(KERN_DEBUG "fuse_dev_poll\n");
+ struct fuse_conn *fc = file->private_data;
+
+ printk(KERN_DEBUG "fuse_dev_poll[%i]\n", fc->id);
return 0;
}
+static struct fuse_conn *new_conn(void)
+{
+ static int connctr = 1;
+ struct fuse_conn *fc;
+
+ fc = kmalloc(sizeof(*fc), GFP_KERNEL);
+ if(fc != NULL) {
+ fc->sb = NULL;
+ fc->file = NULL;
+ init_waitqueue_head(&fc->waitq);
+ INIT_LIST_HEAD(&fc->pending);
+ INIT_LIST_HEAD(&fc->processing);
+ fc->outstanding = 0;
+
+ spin_lock(&fuse_lock);
+ fc->id = connctr ++;
+ spin_unlock(&fuse_lock);
+ }
+ return fc;
+}
+
static int fuse_dev_open(struct inode *inode, struct file *file)
{
- int res;
struct fuse_conn *fc;
printk(KERN_DEBUG "fuse_dev_open\n");
- res = -ENOMEM;
- fc = kmalloc(sizeof(*fc), GFP_KERNEL);
+ fc = new_conn();
if(!fc)
- goto out;
-
- fc->sb = NULL;
+ return -ENOMEM;
+
fc->file = file;
-
- lock_kernel();
file->private_data = fc;
- unlock_kernel();
- res = 0;
-
- out:
- return res;
+
+ printk(KERN_DEBUG "new connection: %i\n", fc->id);
+
+ return 0;
}
static int fuse_dev_release(struct inode *inode, struct file *file)
{
struct fuse_conn *fc = file->private_data;
- printk(KERN_DEBUG "fuse_dev_release\n");
+ printk(KERN_DEBUG "fuse_dev_release[%i]\n", fc->id);
- lock_kernel();
+ spin_lock(&fuse_lock);
fc->file = NULL;
fuse_release_conn(fc);
- unlock_kernel();
+ spin_unlock(&fuse_lock);
return 0;
}