*/
#include "fuse_i.h"
+#include "fuse.h"
#include <linux/init.h>
#include <linux/module.h>
#include <linux/swap.h>
#include <linux/splice.h>
#include <linux/aio.h>
+#include <linux/freezer.h>
MODULE_ALIAS_MISCDEV(FUSE_MINOR);
MODULE_ALIAS("devname:fuse");
* 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)
}
}
+#define CREATE_TRACE_POINTS
+#include <linux/met_ftrace_fuse.h>
+
+void met_fuse(int t_pid, char *t_name, unsigned int op, unsigned int size, struct timespec s_time, struct timespec e_time)
+{
+ MET_FTRACE_PRINTK(met_fuse, t_pid, t_name, op, size, s_time, e_time);
+}
+
static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req)
{
BUG_ON(req->background);
spin_unlock(&fc->lock);
}
-void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req)
+void fuse_request_send_ex(struct fuse_conn *fc, struct fuse_req *req,
+ __u32 size)
{
+#ifdef MET_FUSEIO_TRACE
+ char name[TASK_COMM_LEN];
+#endif
+
+ MET_FUSE_IOLOG_INIT();
+ FUSE_IOLOG_INIT();
req->isreply = 1;
+ FUSE_IOLOG_START();
+ MET_FUSE_IOLOG_START();
__fuse_request_send(fc, req);
+ MET_FUSE_IOLOG_END();
+ FUSE_IOLOG_END();
+ FUSE_IOLOG_PRINT(size, req->in.h.opcode);
+
+#ifdef MET_FUSEIO_TRACE
+ met_fuse(task_pid_nr(current), get_task_comm(name, current), req->in.h.opcode, size, met_fuse_start_time, met_fuse_end_time);
+#endif
+}
+EXPORT_SYMBOL_GPL(fuse_request_send_ex);
+
+void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req)
+{
+ fuse_request_send_ex(fc, req, 0);
}
EXPORT_SYMBOL_GPL(fuse_request_send);
}
}
-void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req)
+void fuse_request_send_background_ex(struct fuse_conn *fc, struct fuse_req *req,
+ __u32 size)
{
+ FUSE_IOLOG_INIT();
+ FUSE_IOLOG_START();
req->isreply = 1;
fuse_request_send_nowait(fc, req);
+ FUSE_IOLOG_END();
+ FUSE_IOLOG_PRINT(size, req->in.h.opcode);
+}
+EXPORT_SYMBOL_GPL(fuse_request_send_background_ex);
+
+void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req)
+{
+ fuse_request_send_background_ex(fc, req, 0);
}
EXPORT_SYMBOL_GPL(fuse_request_send_background);
newpage = buf->page;
- if (WARN_ON(!PageUptodate(newpage)))
- return -EIO;
+ if (!PageUptodate(newpage))
+ SetPageUptodate(newpage);
ClearPageMappedToDisk(newpage);
return fuse_dev_do_read(fc, file, &cs, iov_length(iov, nr_segs));
}
-static int fuse_dev_pipe_buf_steal(struct pipe_inode_info *pipe,
- struct pipe_buffer *buf)
-{
- return 1;
-}
-
-static const struct pipe_buf_operations fuse_dev_pipe_buf_ops = {
- .can_merge = 0,
- .map = generic_pipe_buf_map,
- .unmap = generic_pipe_buf_unmap,
- .confirm = generic_pipe_buf_confirm,
- .release = generic_pipe_buf_release,
- .steal = fuse_dev_pipe_buf_steal,
- .get = generic_pipe_buf_get,
-};
-
static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
struct pipe_inode_info *pipe,
size_t len, unsigned int flags)
buf->page = bufs[page_nr].page;
buf->offset = bufs[page_nr].offset;
buf->len = bufs[page_nr].len;
- buf->ops = &fuse_dev_pipe_buf_ops;
+ /*
+ * Need to be careful about this. Having buf->ops in module
+ * code can Oops if the buffer persists after module unload.
+ */
+ buf->ops = &nosteal_pipe_buf_ops;
pipe->nrbufs++;
page_nr++;
static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code,
unsigned int size, struct fuse_copy_state *cs)
{
+ /* Don't try to move pages (yet) */
+ cs->move_pages = 0;
+
switch (code) {
case FUSE_NOTIFY_POLL:
return fuse_notify_poll(fc, size, cs);