aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
authorcodeworkx <daniel.hillenbrand@codeworkx.de>2012-06-02 13:09:29 +0200
committercodeworkx <daniel.hillenbrand@codeworkx.de>2012-06-02 13:09:29 +0200
commitc6da2cfeb05178a11c6d062a06f8078150ee492f (patch)
treef3b4021d252c52d6463a9b3c1bb7245e399b009c /fs/fuse
parentc6d7c4dbff353eac7919342ae6b3299a378160a6 (diff)
downloadkernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.zip
kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.tar.gz
kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.tar.bz2
samsung update 1
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/dev.c67
-rw-r--r--fs/fuse/fuse_i.h11
-rw-r--r--fs/fuse/inode.c18
3 files changed, 71 insertions, 25 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 2aaf3ea..5a6c6dc 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -19,6 +19,9 @@
#include <linux/pipe_fs_i.h>
#include <linux/swap.h>
#include <linux/splice.h>
+#include <linux/iocontext.h>
+#include <linux/ioprio.h>
+#include <linux/freezer.h>
MODULE_ALIAS_MISCDEV(FUSE_MINOR);
MODULE_ALIAS("devname:fuse");
@@ -237,17 +240,39 @@ static u64 fuse_get_unique(struct fuse_conn *fc)
return fc->reqctr;
}
+static inline int is_rt(struct fuse_conn *fc)
+{
+ /* Returns 1 if request is RT class */
+ /* && FUSE_HANDLE_RT_CLASS bit of fc->flags is set. */
+ /* FUSE_HANDLE_RT_CLASS bit is set by 'handle_rt_class' */
+ /* mount option while mounting a file system. */
+ struct io_context *ioc;
+
+ if (!fc)
+ return 0;
+
+ if (!(fc->flags & FUSE_HANDLE_RT_CLASS)) /* Don't handle RT class */
+ return 0;
+
+ ioc = get_io_context(GFP_NOWAIT, 0);
+ if (ioc && IOPRIO_PRIO_CLASS(ioc->ioprio) == IOPRIO_CLASS_RT)
+ return 1;
+
+ return 0;
+}
+
+
static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
{
req->in.h.len = sizeof(struct fuse_in_header) +
len_args(req->in.numargs, (struct fuse_arg *) req->in.args);
- list_add_tail(&req->list, &fc->pending);
+ list_add_tail(&req->list, &fc->pending[is_rt(fc)]);
req->state = FUSE_REQ_PENDING;
if (!req->waiting) {
req->waiting = 1;
atomic_inc(&fc->num_waiting);
}
- wake_up(&fc->waitq);
+ wake_up(&fc->waitq[is_rt(fc)]);
kill_fasync(&fc->fasync, SIGIO, POLL_IN);
}
@@ -261,7 +286,7 @@ void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget,
if (fc->connected) {
fc->forget_list_tail->next = forget;
fc->forget_list_tail = forget;
- wake_up(&fc->waitq);
+ wake_up(&fc->waitq[is_rt(fc)]);
kill_fasync(&fc->fasync, SIGIO, POLL_IN);
} else {
kfree(forget);
@@ -337,8 +362,8 @@ __acquires(fc->lock)
static void queue_interrupt(struct fuse_conn *fc, struct fuse_req *req)
{
- list_add_tail(&req->intr_entry, &fc->interrupts);
- wake_up(&fc->waitq);
+ list_add_tail(&req->intr_entry, &fc->interrupts[is_rt(fc)]);
+ wake_up(&fc->waitq[is_rt(fc)]);
kill_fasync(&fc->fasync, SIGIO, POLL_IN);
}
@@ -387,7 +412,10 @@ __acquires(fc->lock)
* Wait it out.
*/
spin_unlock(&fc->lock);
- wait_event(req->waitq, req->state == FUSE_REQ_FINISHED);
+
+ while (req->state != FUSE_REQ_FINISHED)
+ wait_event_freezable(req->waitq,
+ req->state == FUSE_REQ_FINISHED);
spin_lock(&fc->lock);
if (!req->aborted)
@@ -913,8 +941,8 @@ static int forget_pending(struct fuse_conn *fc)
static int request_pending(struct fuse_conn *fc)
{
- return !list_empty(&fc->pending) || !list_empty(&fc->interrupts) ||
- forget_pending(fc);
+ return !list_empty(&fc->pending[is_rt(fc)]) ||
+ !list_empty(&fc->interrupts[is_rt(fc)]) || forget_pending(fc);
}
/* Wait until a request is available on the pending list */
@@ -924,7 +952,7 @@ __acquires(fc->lock)
{
DECLARE_WAITQUEUE(wait, current);
- add_wait_queue_exclusive(&fc->waitq, &wait);
+ add_wait_queue_exclusive(&fc->waitq[is_rt(fc)], &wait);
while (fc->connected && !request_pending(fc)) {
set_current_state(TASK_INTERRUPTIBLE);
if (signal_pending(current))
@@ -935,7 +963,7 @@ __acquires(fc->lock)
spin_lock(&fc->lock);
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(&fc->waitq, &wait);
+ remove_wait_queue(&fc->waitq[is_rt(fc)], &wait);
}
/*
@@ -1122,21 +1150,22 @@ static ssize_t fuse_dev_do_read(struct fuse_conn *fc, struct file *file,
if (!request_pending(fc))
goto err_unlock;
- if (!list_empty(&fc->interrupts)) {
- req = list_entry(fc->interrupts.next, struct fuse_req,
- intr_entry);
+ if (!list_empty(&fc->interrupts[is_rt(fc)])) {
+ req = list_entry(fc->interrupts[is_rt(fc)].next,
+ struct fuse_req, intr_entry);
return fuse_read_interrupt(fc, cs, nbytes, req);
}
if (forget_pending(fc)) {
- if (list_empty(&fc->pending) || fc->forget_batch-- > 0)
+ if (list_empty(&fc->pending[is_rt(fc)]) ||
+ fc->forget_batch-- > 0)
return fuse_read_forget(fc, cs, nbytes);
if (fc->forget_batch <= -8)
fc->forget_batch = 16;
}
- req = list_entry(fc->pending.next, struct fuse_req, list);
+ req = list_entry(fc->pending[is_rt(fc)].next, struct fuse_req, list);
req->state = FUSE_REQ_READING;
list_move(&req->list, &fc->io);
@@ -1838,7 +1867,7 @@ static unsigned fuse_dev_poll(struct file *file, poll_table *wait)
if (!fc)
return POLLERR;
- poll_wait(file, &fc->waitq, wait);
+ poll_wait(file, &fc->waitq[is_rt(fc)], wait);
spin_lock(&fc->lock);
if (!fc->connected)
@@ -1911,7 +1940,8 @@ __acquires(fc->lock)
{
fc->max_background = UINT_MAX;
flush_bg_queue(fc);
- end_requests(fc, &fc->pending);
+ end_requests(fc, &fc->pending[0]);
+ end_requests(fc, &fc->pending[1]);
end_requests(fc, &fc->processing);
while (forget_pending(fc))
kfree(dequeue_forget(fc, 1, NULL));
@@ -1960,7 +1990,8 @@ void fuse_abort_conn(struct fuse_conn *fc)
end_io_requests(fc);
end_queued_requests(fc);
end_polls(fc);
- wake_up_all(&fc->waitq);
+ wake_up_all(&fc->waitq[0]);
+ wake_up_all(&fc->waitq[1]);
wake_up_all(&fc->blocked_waitq);
kill_fasync(&fc->fasync, SIGIO, POLL_IN);
}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index b788bec..ee6e76e 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -44,6 +44,11 @@
doing the mount will be allowed to access the filesystem */
#define FUSE_ALLOW_OTHER (1 << 1)
+/** If the FUSE_HANDLE_RT_CLASS flag is given,
+ then fuse handle RT class I/O in different request queue */
+#define FUSE_HANDLE_RT_CLASS (1 << 2)
+
+
/** List of active connections */
extern struct list_head fuse_conn_list;
@@ -342,10 +347,10 @@ struct fuse_conn {
unsigned max_write;
/** Readers of the connection are waiting on this */
- wait_queue_head_t waitq;
+ wait_queue_head_t waitq[2];
/** The list of pending requests */
- struct list_head pending;
+ struct list_head pending[2];
/** The list of requests being processed */
struct list_head processing;
@@ -375,7 +380,7 @@ struct fuse_conn {
struct list_head bg_queue;
/** Pending interrupts */
- struct list_head interrupts;
+ struct list_head interrupts[2];
/** Queue of pending forgets */
struct fuse_forget_link forget_list_head;
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 38f84cd..f23806b 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -329,7 +329,8 @@ void fuse_conn_kill(struct fuse_conn *fc)
spin_unlock(&fc->lock);
/* Flush all readers on this fs */
kill_fasync(&fc->fasync, SIGIO, POLL_IN);
- wake_up_all(&fc->waitq);
+ wake_up_all(&fc->waitq[0]);
+ wake_up_all(&fc->waitq[1]);
wake_up_all(&fc->blocked_waitq);
wake_up_all(&fc->reserved_req_waitq);
mutex_lock(&fuse_mutex);
@@ -405,6 +406,7 @@ enum {
OPT_ALLOW_OTHER,
OPT_MAX_READ,
OPT_BLKSIZE,
+ OPT_HANDLE_RT_CLASS,
OPT_ERR
};
@@ -417,6 +419,7 @@ static const match_table_t tokens = {
{OPT_ALLOW_OTHER, "allow_other"},
{OPT_MAX_READ, "max_read=%u"},
{OPT_BLKSIZE, "blksize=%u"},
+ {OPT_HANDLE_RT_CLASS, "handle_rt_class"},
{OPT_ERR, NULL}
};
@@ -452,6 +455,10 @@ static int parse_fuse_opt(char *opt, struct fuse_mount_data *d, int is_bdev)
d->rootmode_present = 1;
break;
+ case OPT_HANDLE_RT_CLASS:
+ d->flags |= FUSE_HANDLE_RT_CLASS;
+ break;
+
case OPT_USER_ID:
if (match_int(&args[0], &value))
return 0;
@@ -523,13 +530,16 @@ void fuse_conn_init(struct fuse_conn *fc)
mutex_init(&fc->inst_mutex);
init_rwsem(&fc->killsb);
atomic_set(&fc->count, 1);
- init_waitqueue_head(&fc->waitq);
+ init_waitqueue_head(&fc->waitq[0]);
+ init_waitqueue_head(&fc->waitq[1]);
init_waitqueue_head(&fc->blocked_waitq);
init_waitqueue_head(&fc->reserved_req_waitq);
- INIT_LIST_HEAD(&fc->pending);
+ INIT_LIST_HEAD(&fc->pending[0]);
+ INIT_LIST_HEAD(&fc->pending[1]);
INIT_LIST_HEAD(&fc->processing);
INIT_LIST_HEAD(&fc->io);
- INIT_LIST_HEAD(&fc->interrupts);
+ INIT_LIST_HEAD(&fc->interrupts[0]);
+ INIT_LIST_HEAD(&fc->interrupts[1]);
INIT_LIST_HEAD(&fc->bg_queue);
INIT_LIST_HEAD(&fc->entry);
fc->forget_list_tail = &fc->forget_list_head;