diff options
author | Abhishek Kulkarni <adkulkar@umail.iu.edu> | 2009-09-23 14:00:27 -0400 |
---|---|---|
committer | Eric Van Hensbergen <ericvh@strongmad.austin.ibm.com> | 2009-09-23 14:03:46 -0400 |
commit | 60e78d2c993e58d890596d951fff77d5965adcd6 (patch) | |
tree | 3d53ed7254c613ef8d8de36fdceda25bc493f4f7 /fs/9p/vfs_addr.c | |
parent | 637d020a02cd734bf27acfc56c6d942cddd9eb80 (diff) |
9p: Add fscache support to 9p
This patch adds a persistent, read-only caching facility for
9p clients using the FS-Cache caching backend.
When the fscache facility is enabled, each inode is associated
with a corresponding vcookie which is an index into the FS-Cache
indexing tree. The FS-Cache indexing tree is indexed at 3 levels:
- session object associated with each mount.
- inode/vcookie
- actual data (pages)
A cache tag is chosen randomly for each session. These tags can
be read off /sys/fs/9p/caches and can be passed as a mount-time
parameter to re-attach to the specified caching session.
Signed-off-by: Abhishek Kulkarni <adkulkar@umail.iu.edu>
Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
Diffstat (limited to 'fs/9p/vfs_addr.c')
-rw-r--r-- | fs/9p/vfs_addr.c | 88 |
1 files changed, 87 insertions, 1 deletions
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index 92828281a30b..90e38449f4b3 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c | |||
@@ -38,6 +38,7 @@ | |||
38 | 38 | ||
39 | #include "v9fs.h" | 39 | #include "v9fs.h" |
40 | #include "v9fs_vfs.h" | 40 | #include "v9fs_vfs.h" |
41 | #include "cache.h" | ||
41 | 42 | ||
42 | /** | 43 | /** |
43 | * v9fs_vfs_readpage - read an entire page in from 9P | 44 | * v9fs_vfs_readpage - read an entire page in from 9P |
@@ -52,18 +53,31 @@ static int v9fs_vfs_readpage(struct file *filp, struct page *page) | |||
52 | int retval; | 53 | int retval; |
53 | loff_t offset; | 54 | loff_t offset; |
54 | char *buffer; | 55 | char *buffer; |
56 | struct inode *inode; | ||
55 | 57 | ||
58 | inode = page->mapping->host; | ||
56 | P9_DPRINTK(P9_DEBUG_VFS, "\n"); | 59 | P9_DPRINTK(P9_DEBUG_VFS, "\n"); |
60 | |||
61 | BUG_ON(!PageLocked(page)); | ||
62 | |||
63 | retval = v9fs_readpage_from_fscache(inode, page); | ||
64 | if (retval == 0) | ||
65 | return retval; | ||
66 | |||
57 | buffer = kmap(page); | 67 | buffer = kmap(page); |
58 | offset = page_offset(page); | 68 | offset = page_offset(page); |
59 | 69 | ||
60 | retval = v9fs_file_readn(filp, buffer, NULL, PAGE_CACHE_SIZE, offset); | 70 | retval = v9fs_file_readn(filp, buffer, NULL, PAGE_CACHE_SIZE, offset); |
61 | if (retval < 0) | 71 | if (retval < 0) { |
72 | v9fs_uncache_page(inode, page); | ||
62 | goto done; | 73 | goto done; |
74 | } | ||
63 | 75 | ||
64 | memset(buffer + retval, 0, PAGE_CACHE_SIZE - retval); | 76 | memset(buffer + retval, 0, PAGE_CACHE_SIZE - retval); |
65 | flush_dcache_page(page); | 77 | flush_dcache_page(page); |
66 | SetPageUptodate(page); | 78 | SetPageUptodate(page); |
79 | |||
80 | v9fs_readpage_to_fscache(inode, page); | ||
67 | retval = 0; | 81 | retval = 0; |
68 | 82 | ||
69 | done: | 83 | done: |
@@ -72,6 +86,78 @@ done: | |||
72 | return retval; | 86 | return retval; |
73 | } | 87 | } |
74 | 88 | ||
89 | /** | ||
90 | * v9fs_vfs_readpages - read a set of pages from 9P | ||
91 | * | ||
92 | * @filp: file being read | ||
93 | * @mapping: the address space | ||
94 | * @pages: list of pages to read | ||
95 | * @nr_pages: count of pages to read | ||
96 | * | ||
97 | */ | ||
98 | |||
99 | static int v9fs_vfs_readpages(struct file *filp, struct address_space *mapping, | ||
100 | struct list_head *pages, unsigned nr_pages) | ||
101 | { | ||
102 | int ret = 0; | ||
103 | struct inode *inode; | ||
104 | |||
105 | inode = mapping->host; | ||
106 | P9_DPRINTK(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, filp); | ||
107 | |||
108 | ret = v9fs_readpages_from_fscache(inode, mapping, pages, &nr_pages); | ||
109 | if (ret == 0) | ||
110 | return ret; | ||
111 | |||
112 | ret = read_cache_pages(mapping, pages, (void *)v9fs_vfs_readpage, filp); | ||
113 | P9_DPRINTK(P9_DEBUG_VFS, " = %d\n", ret); | ||
114 | return ret; | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * v9fs_release_page - release the private state associated with a page | ||
119 | * | ||
120 | * Returns 1 if the page can be released, false otherwise. | ||
121 | */ | ||
122 | |||
123 | static int v9fs_release_page(struct page *page, gfp_t gfp) | ||
124 | { | ||
125 | if (PagePrivate(page)) | ||
126 | return 0; | ||
127 | |||
128 | return v9fs_fscache_release_page(page, gfp); | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * v9fs_invalidate_page - Invalidate a page completely or partially | ||
133 | * | ||
134 | * @page: structure to page | ||
135 | * @offset: offset in the page | ||
136 | */ | ||
137 | |||
138 | static void v9fs_invalidate_page(struct page *page, unsigned long offset) | ||
139 | { | ||
140 | if (offset == 0) | ||
141 | v9fs_fscache_invalidate_page(page); | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * v9fs_launder_page - Writeback a dirty page | ||
146 | * Since the writes go directly to the server, we simply return a 0 | ||
147 | * here to indicate success. | ||
148 | * | ||
149 | * Returns 0 on success. | ||
150 | */ | ||
151 | |||
152 | static int v9fs_launder_page(struct page *page) | ||
153 | { | ||
154 | return 0; | ||
155 | } | ||
156 | |||
75 | const struct address_space_operations v9fs_addr_operations = { | 157 | const struct address_space_operations v9fs_addr_operations = { |
76 | .readpage = v9fs_vfs_readpage, | 158 | .readpage = v9fs_vfs_readpage, |
159 | .readpages = v9fs_vfs_readpages, | ||
160 | .releasepage = v9fs_release_page, | ||
161 | .invalidatepage = v9fs_invalidate_page, | ||
162 | .launder_page = v9fs_launder_page, | ||
77 | }; | 163 | }; |