#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,
};