Merge git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus
[safe/jmp/linux-2.6] / fs / 9p / vfs_addr.c
index cc24abf..90e3844 100644 (file)
 #include <linux/file.h>
 #include <linux/stat.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/inet.h>
 #include <linux/pagemap.h>
 #include <linux/idr.h>
+#include <linux/sched.h>
+#include <net/9p/9p.h>
+#include <net/9p/client.h>
 
-#include "debug.h"
 #include "v9fs.h"
-#include "9p.h"
 #include "v9fs_vfs.h"
-#include "fid.h"
+#include "cache.h"
 
 /**
  * v9fs_vfs_readpage - read an entire page in from 9P
  *
- * @file: file being read
+ * @filp: file being read
  * @page: structure to page
  *
  */
 
 static int v9fs_vfs_readpage(struct file *filp, struct page *page)
 {
-       char *buffer = NULL;
-       int retval = -EIO;
-       loff_t offset = page_offset(page);
-       int count = PAGE_CACHE_SIZE;
-       struct inode *inode = filp->f_path.dentry->d_inode;
-       struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
-       int rsize = v9ses->maxdata - V9FS_IOHDRSZ;
-       struct v9fs_fid *v9f = filp->private_data;
-       struct v9fs_fcall *fcall = NULL;
-       int fid = v9f->fid;
-       int total = 0;
-       int result = 0;
+       int retval;
+       loff_t offset;
+       char *buffer;
+       struct inode *inode;
 
-       buffer = kmap(page);
-       do {
-               if (count < rsize)
-                       rsize = count;
-
-               result = v9fs_t_read(v9ses, fid, offset, rsize, &fcall);
-
-               if (result < 0) {
-                       printk(KERN_ERR "v9fs_t_read returned %d\n",
-                              result);
+       inode = page->mapping->host;
+       P9_DPRINTK(P9_DEBUG_VFS, "\n");
 
-                       kfree(fcall);
-                       goto UnmapAndUnlock;
-               } else
-                       offset += result;
+       BUG_ON(!PageLocked(page));
 
-               memcpy(buffer, fcall->params.rread.data, result);
+       retval = v9fs_readpage_from_fscache(inode, page);
+       if (retval == 0)
+               return retval;
 
-               count -= result;
-               buffer += result;
-               total += result;
-
-               kfree(fcall);
+       buffer = kmap(page);
+       offset = page_offset(page);
 
-               if (result < rsize)
-                       break;
-       } while (count);
+       retval = v9fs_file_readn(filp, buffer, NULL, PAGE_CACHE_SIZE, offset);
+       if (retval < 0) {
+               v9fs_uncache_page(inode, page);
+               goto done;
+       }
 
-       memset(buffer, 0, count);
+       memset(buffer + retval, 0, PAGE_CACHE_SIZE - retval);
        flush_dcache_page(page);
        SetPageUptodate(page);
+
+       v9fs_readpage_to_fscache(inode, page);
        retval = 0;
 
-UnmapAndUnlock:
+done:
        kunmap(page);
        unlock_page(page);
        return retval;
 }
 
+/**
+ * v9fs_vfs_readpages - read a set of pages from 9P
+ *
+ * @filp: file being read
+ * @mapping: the address space
+ * @pages: list of pages to read
+ * @nr_pages: count of pages to read
+ *
+ */
+
+static int v9fs_vfs_readpages(struct file *filp, struct address_space *mapping,
+                            struct list_head *pages, unsigned nr_pages)
+{
+       int ret = 0;
+       struct inode *inode;
+
+       inode = mapping->host;
+       P9_DPRINTK(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, filp);
+
+       ret = v9fs_readpages_from_fscache(inode, mapping, pages, &nr_pages);
+       if (ret == 0)
+               return ret;
+
+       ret = read_cache_pages(mapping, pages, (void *)v9fs_vfs_readpage, filp);
+       P9_DPRINTK(P9_DEBUG_VFS, "  = %d\n", ret);
+       return ret;
+}
+
+/**
+ * v9fs_release_page - release the private state associated with a page
+ *
+ * Returns 1 if the page can be released, false otherwise.
+ */
+
+static int v9fs_release_page(struct page *page, gfp_t gfp)
+{
+       if (PagePrivate(page))
+               return 0;
+
+       return v9fs_fscache_release_page(page, gfp);
+}
+
+/**
+ * v9fs_invalidate_page - Invalidate a page completely or partially
+ *
+ * @page: structure to page
+ * @offset: offset in the page
+ */
+
+static void v9fs_invalidate_page(struct page *page, unsigned long offset)
+{
+       if (offset == 0)
+               v9fs_fscache_invalidate_page(page);
+}
+
+/**
+ * v9fs_launder_page - Writeback a dirty page
+ * Since the writes go directly to the server, we simply return a 0
+ * here to indicate success.
+ *
+ * Returns 0 on success.
+ */
+
+static int v9fs_launder_page(struct page *page)
+{
+       return 0;
+}
+
 const struct address_space_operations v9fs_addr_operations = {
       .readpage = v9fs_vfs_readpage,
+      .readpages = v9fs_vfs_readpages,
+      .releasepage = v9fs_release_page,
+      .invalidatepage = v9fs_invalidate_page,
+      .launder_page = v9fs_launder_page,
 };