wrong type for 'magic' argument in simple_fill_super()
[safe/jmp/linux-2.6] / fs / fuse / file.c
index c5de60e..ada0ade 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/module.h>
 
 static const struct file_operations fuse_direct_io_file_operations;
 
@@ -100,8 +101,8 @@ static void fuse_file_put(struct fuse_file *ff)
        }
 }
 
-static int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
-                       bool isdir)
+int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
+                bool isdir)
 {
        struct fuse_open_out outarg;
        struct fuse_file *ff;
@@ -128,6 +129,7 @@ static int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(fuse_do_open);
 
 void fuse_finish_open(struct inode *inode, struct file *file)
 {
@@ -232,6 +234,7 @@ void fuse_sync_release(struct fuse_file *ff, int flags)
        fuse_put_request(ff->fc, ff->reserved_req);
        kfree(ff);
 }
+EXPORT_SYMBOL_GPL(fuse_sync_release);
 
 /*
  * Scramble the ID space with XTEA, so that the value of the files_struct
@@ -348,10 +351,9 @@ static void fuse_sync_writes(struct inode *inode)
        fuse_release_nowrite(inode);
 }
 
-int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
-                     int isdir)
+int fuse_fsync_common(struct file *file, int datasync, int isdir)
 {
-       struct inode *inode = de->d_inode;
+       struct inode *inode = file->f_mapping->host;
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_file *ff = file->private_data;
        struct fuse_req *req;
@@ -400,9 +402,9 @@ int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
        return err;
 }
 
-static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
+static int fuse_fsync(struct file *file, int datasync)
 {
-       return fuse_fsync_common(file, de, datasync, 0);
+       return fuse_fsync_common(file, datasync, 0);
 }
 
 void fuse_read_fill(struct fuse_req *req, struct file *file, loff_t pos,
@@ -514,17 +516,26 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req)
        int i;
        size_t count = req->misc.read.in.size;
        size_t num_read = req->out.args[0].size;
-       struct inode *inode = req->pages[0]->mapping->host;
+       struct address_space *mapping = NULL;
 
-       /*
-        * Short read means EOF.  If file size is larger, truncate it
-        */
-       if (!req->out.h.error && num_read < count) {
-               loff_t pos = page_offset(req->pages[0]) + num_read;
-               fuse_read_update_size(inode, pos, req->misc.read.attr_ver);
-       }
+       for (i = 0; mapping == NULL && i < req->num_pages; i++)
+               mapping = req->pages[i]->mapping;
 
-       fuse_invalidate_attr(inode); /* atime changed */
+       if (mapping) {
+               struct inode *inode = mapping->host;
+
+               /*
+                * Short read means EOF. If file size is larger, truncate it
+                */
+               if (!req->out.h.error && num_read < count) {
+                       loff_t pos;
+
+                       pos = page_offset(req->pages[0]) + num_read;
+                       fuse_read_update_size(inode, pos,
+                                             req->misc.read.attr_ver);
+               }
+               fuse_invalidate_attr(inode); /* atime changed */
+       }
 
        for (i = 0; i < req->num_pages; i++) {
                struct page *page = req->pages[i];
@@ -533,6 +544,7 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req)
                else
                        SetPageError(page);
                unlock_page(page);
+               page_cache_release(page);
        }
        if (req->ff)
                fuse_file_put(req->ff);
@@ -547,6 +559,7 @@ static void fuse_send_readpages(struct fuse_req *req, struct file *file)
 
        req->out.argpages = 1;
        req->out.page_zeroing = 1;
+       req->out.page_replace = 1;
        fuse_read_fill(req, file, pos, count, FUSE_READ);
        req->misc.read.attr_ver = fuse_get_attr_version(fc);
        if (fc->async_read) {
@@ -586,6 +599,7 @@ static int fuse_readpages_fill(void *_data, struct page *page)
                        return PTR_ERR(req);
                }
        }
+       page_cache_get(page);
        req->pages[req->num_pages] = page;
        req->num_pages++;
        return 0;
@@ -825,6 +839,9 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req,
                if (!page)
                        break;
 
+               if (mapping_writably_mapped(mapping))
+                       flush_dcache_page(page);
+
                pagefault_disable();
                tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes);
                pagefault_enable();
@@ -988,10 +1005,7 @@ static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf,
        nbytes = min_t(size_t, nbytes, FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT);
        npages = (nbytes + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
        npages = clamp(npages, 1, FUSE_MAX_PAGES_PER_REQ);
-       down_read(&current->mm->mmap_sem);
-       npages = get_user_pages(current, current->mm, user_addr, npages, !write,
-                               0, req->pages, NULL);
-       up_read(&current->mm->mmap_sem);
+       npages = get_user_pages_fast(user_addr, npages, !write, req->pages);
        if (npages < 0)
                return npages;
 
@@ -1009,8 +1023,8 @@ static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf,
        return 0;
 }
 
-static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
-                             size_t count, loff_t *ppos, int write)
+ssize_t fuse_direct_io(struct file *file, const char __user *buf,
+                      size_t count, loff_t *ppos, int write)
 {
        struct fuse_file *ff = file->private_data;
        struct fuse_conn *fc = ff->fc;
@@ -1060,12 +1074,14 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
                                break;
                }
        }
-       fuse_put_request(fc, req);
+       if (!IS_ERR(req))
+               fuse_put_request(fc, req);
        if (res > 0)
                *ppos = pos;
 
        return res;
 }
+EXPORT_SYMBOL_GPL(fuse_direct_io);
 
 static ssize_t fuse_direct_read(struct file *file, char __user *buf,
                                     size_t count, loff_t *ppos)
@@ -1309,7 +1325,7 @@ static int fuse_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
        return 0;
 }
 
-static struct vm_operations_struct fuse_file_vm_ops = {
+static const struct vm_operations_struct fuse_file_vm_ops = {
        .close          = fuse_vma_close,
        .fault          = filemap_fault,
        .page_mkwrite   = fuse_page_mkwrite,
@@ -1572,9 +1588,9 @@ static int fuse_ioctl_copy_user(struct page **pages, struct iovec *iov,
        while (iov_iter_count(&ii)) {
                struct page *page = pages[page_idx++];
                size_t todo = min_t(size_t, PAGE_SIZE, iov_iter_count(&ii));
-               void *kaddr, *map;
+               void *kaddr;
 
-               kaddr = map = kmap(page);
+               kaddr = kmap(page);
 
                while (todo) {
                        char __user *uaddr = ii.iov->iov_base + ii.iov_offset;
@@ -1595,7 +1611,7 @@ static int fuse_ioctl_copy_user(struct page **pages, struct iovec *iov,
                        kaddr += copy;
                }
 
-               kunmap(map);
+               kunmap(page);
        }
 
        return 0;
@@ -1647,8 +1663,8 @@ static int fuse_ioctl_copy_user(struct page **pages, struct iovec *iov,
  * limits ioctl data transfers to well-formed ioctls and is the forced
  * behavior for all FUSE servers.
  */
-static long fuse_do_ioctl(struct file *file, unsigned int cmd,
-                         unsigned long arg, unsigned int flags)
+long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
+                  unsigned int flags)
 {
        struct fuse_file *ff = file->private_data;
        struct fuse_conn *fc = ff->fc;
@@ -1813,6 +1829,7 @@ static long fuse_do_ioctl(struct file *file, unsigned int cmd,
 
        return err ? err : outarg.result;
 }
+EXPORT_SYMBOL_GPL(fuse_do_ioctl);
 
 static long fuse_file_ioctl_common(struct file *file, unsigned int cmd,
                                   unsigned long arg, unsigned int flags)
@@ -1892,7 +1909,7 @@ static void fuse_register_polled_file(struct fuse_conn *fc,
        spin_unlock(&fc->lock);
 }
 
-static unsigned fuse_file_poll(struct file *file, poll_table *wait)
+unsigned fuse_file_poll(struct file *file, poll_table *wait)
 {
        struct fuse_file *ff = file->private_data;
        struct fuse_conn *fc = ff->fc;
@@ -1917,7 +1934,7 @@ static unsigned fuse_file_poll(struct file *file, poll_table *wait)
 
        req = fuse_get_req(fc);
        if (IS_ERR(req))
-               return PTR_ERR(req);
+               return POLLERR;
 
        req->in.h.opcode = FUSE_POLL;
        req->in.h.nodeid = ff->nodeid;
@@ -1939,6 +1956,7 @@ static unsigned fuse_file_poll(struct file *file, poll_table *wait)
        }
        return POLLERR;
 }
+EXPORT_SYMBOL_GPL(fuse_file_poll);
 
 /*
  * This is called from fuse_handle_notify() on FUSE_NOTIFY_POLL and