Merge tag 'v3.10.73' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / fs / fuse / dev.c
index 1d55f94654000dbc8e8c0de37e0cb32471e3791a..74651ad806b60907a60f30723f4d9d4a012788d1 100644 (file)
@@ -7,6 +7,7 @@
 */
 
 #include "fuse_i.h"
+#include "fuse.h"
 
 #include <linux/init.h>
 #include <linux/module.h>
@@ -20,6 +21,7 @@
 #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");
@@ -464,7 +466,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)
@@ -484,6 +489,14 @@ __acquires(fc->lock)
        }
 }
 
+#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);
@@ -504,10 +517,32 @@ static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req)
        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);
 
@@ -539,10 +574,21 @@ static void fuse_request_send_nowait(struct fuse_conn *fc, struct fuse_req *req)
        }
 }
 
-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);
 
@@ -819,8 +865,8 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
 
        newpage = buf->page;
 
-       if (WARN_ON(!PageUptodate(newpage)))
-               return -EIO;
+       if (!PageUptodate(newpage))
+               SetPageUptodate(newpage);
 
        ClearPageMappedToDisk(newpage);
 
@@ -1296,22 +1342,6 @@ static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov,
        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)
@@ -1358,7 +1388,11 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
                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++;
@@ -1737,6 +1771,9 @@ copy_finish:
 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);