diff options
author | Suresh Jayaraman <sjayaraman@suse.de> | 2010-07-05 08:43:25 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2010-08-02 08:40:37 -0400 |
commit | 56698236e1294848c63d4768673865ae5a9c69e0 (patch) | |
tree | ce6d43104a236595763759fe68c26ca3089abdd1 /fs/cifs | |
parent | 9dc06558c223bbc08290917ac44c25963bc09e43 (diff) |
cifs: read pages from FS-Cache
Read pages from a FS-Cache data storage object into a CIFS inode.
Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
Acked-by: David Howells <dhowells@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/file.c | 17 | ||||
-rw-r--r-- | fs/cifs/fscache.c | 73 | ||||
-rw-r--r-- | fs/cifs/fscache.h | 40 |
3 files changed, 129 insertions, 1 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index ff726c86b290..fa04a00d126d 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -1977,6 +1977,15 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
1977 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 1977 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
1978 | pTcon = cifs_sb->tcon; | 1978 | pTcon = cifs_sb->tcon; |
1979 | 1979 | ||
1980 | /* | ||
1981 | * Reads as many pages as possible from fscache. Returns -ENOBUFS | ||
1982 | * immediately if the cookie is negative | ||
1983 | */ | ||
1984 | rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list, | ||
1985 | &num_pages); | ||
1986 | if (rc == 0) | ||
1987 | goto read_complete; | ||
1988 | |||
1980 | cFYI(DBG2, "rpages: num pages %d", num_pages); | 1989 | cFYI(DBG2, "rpages: num pages %d", num_pages); |
1981 | for (i = 0; i < num_pages; ) { | 1990 | for (i = 0; i < num_pages; ) { |
1982 | unsigned contig_pages; | 1991 | unsigned contig_pages; |
@@ -2087,6 +2096,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
2087 | smb_read_data = NULL; | 2096 | smb_read_data = NULL; |
2088 | } | 2097 | } |
2089 | 2098 | ||
2099 | read_complete: | ||
2090 | FreeXid(xid); | 2100 | FreeXid(xid); |
2091 | return rc; | 2101 | return rc; |
2092 | } | 2102 | } |
@@ -2097,6 +2107,11 @@ static int cifs_readpage_worker(struct file *file, struct page *page, | |||
2097 | char *read_data; | 2107 | char *read_data; |
2098 | int rc; | 2108 | int rc; |
2099 | 2109 | ||
2110 | /* Is the page cached? */ | ||
2111 | rc = cifs_readpage_from_fscache(file->f_path.dentry->d_inode, page); | ||
2112 | if (rc == 0) | ||
2113 | goto read_complete; | ||
2114 | |||
2100 | page_cache_get(page); | 2115 | page_cache_get(page); |
2101 | read_data = kmap(page); | 2116 | read_data = kmap(page); |
2102 | /* for reads over a certain size could initiate async read ahead */ | 2117 | /* for reads over a certain size could initiate async read ahead */ |
@@ -2125,6 +2140,8 @@ static int cifs_readpage_worker(struct file *file, struct page *page, | |||
2125 | io_error: | 2140 | io_error: |
2126 | kunmap(page); | 2141 | kunmap(page); |
2127 | page_cache_release(page); | 2142 | page_cache_release(page); |
2143 | |||
2144 | read_complete: | ||
2128 | return rc; | 2145 | return rc; |
2129 | } | 2146 | } |
2130 | 2147 | ||
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c index 3b1636704c85..9f3f5c4be161 100644 --- a/fs/cifs/fscache.c +++ b/fs/cifs/fscache.c | |||
@@ -140,6 +140,79 @@ int cifs_fscache_release_page(struct page *page, gfp_t gfp) | |||
140 | return 1; | 140 | return 1; |
141 | } | 141 | } |
142 | 142 | ||
143 | static void cifs_readpage_from_fscache_complete(struct page *page, void *ctx, | ||
144 | int error) | ||
145 | { | ||
146 | cFYI(1, "CFS: readpage_from_fscache_complete (0x%p/%d)", | ||
147 | page, error); | ||
148 | if (!error) | ||
149 | SetPageUptodate(page); | ||
150 | unlock_page(page); | ||
151 | } | ||
152 | |||
153 | /* | ||
154 | * Retrieve a page from FS-Cache | ||
155 | */ | ||
156 | int __cifs_readpage_from_fscache(struct inode *inode, struct page *page) | ||
157 | { | ||
158 | int ret; | ||
159 | |||
160 | cFYI(1, "CIFS: readpage_from_fscache(fsc:%p, p:%p, i:0x%p", | ||
161 | CIFS_I(inode)->fscache, page, inode); | ||
162 | ret = fscache_read_or_alloc_page(CIFS_I(inode)->fscache, page, | ||
163 | cifs_readpage_from_fscache_complete, | ||
164 | NULL, | ||
165 | GFP_KERNEL); | ||
166 | switch (ret) { | ||
167 | |||
168 | case 0: /* page found in fscache, read submitted */ | ||
169 | cFYI(1, "CIFS: readpage_from_fscache: submitted"); | ||
170 | return ret; | ||
171 | case -ENOBUFS: /* page won't be cached */ | ||
172 | case -ENODATA: /* page not in cache */ | ||
173 | cFYI(1, "CIFS: readpage_from_fscache %d", ret); | ||
174 | return 1; | ||
175 | |||
176 | default: | ||
177 | cERROR(1, "unknown error ret = %d", ret); | ||
178 | } | ||
179 | return ret; | ||
180 | } | ||
181 | |||
182 | /* | ||
183 | * Retrieve a set of pages from FS-Cache | ||
184 | */ | ||
185 | int __cifs_readpages_from_fscache(struct inode *inode, | ||
186 | struct address_space *mapping, | ||
187 | struct list_head *pages, | ||
188 | unsigned *nr_pages) | ||
189 | { | ||
190 | int ret; | ||
191 | |||
192 | cFYI(1, "CIFS: __cifs_readpages_from_fscache (0x%p/%u/0x%p)", | ||
193 | CIFS_I(inode)->fscache, *nr_pages, inode); | ||
194 | ret = fscache_read_or_alloc_pages(CIFS_I(inode)->fscache, mapping, | ||
195 | pages, nr_pages, | ||
196 | cifs_readpage_from_fscache_complete, | ||
197 | NULL, | ||
198 | mapping_gfp_mask(mapping)); | ||
199 | switch (ret) { | ||
200 | case 0: /* read submitted to the cache for all pages */ | ||
201 | cFYI(1, "CIFS: readpages_from_fscache: submitted"); | ||
202 | return ret; | ||
203 | |||
204 | case -ENOBUFS: /* some pages are not cached and can't be */ | ||
205 | case -ENODATA: /* some pages are not cached */ | ||
206 | cFYI(1, "CIFS: readpages_from_fscache: no page"); | ||
207 | return 1; | ||
208 | |||
209 | default: | ||
210 | cFYI(1, "unknown error ret = %d", ret); | ||
211 | } | ||
212 | |||
213 | return ret; | ||
214 | } | ||
215 | |||
143 | void __cifs_readpage_to_fscache(struct inode *inode, struct page *page) | 216 | void __cifs_readpage_to_fscache(struct inode *inode, struct page *page) |
144 | { | 217 | { |
145 | int ret; | 218 | int ret; |
diff --git a/fs/cifs/fscache.h b/fs/cifs/fscache.h index 1a00d70bca97..79164c66797e 100644 --- a/fs/cifs/fscache.h +++ b/fs/cifs/fscache.h | |||
@@ -32,7 +32,6 @@ extern const struct fscache_cookie_def cifs_fscache_server_index_def; | |||
32 | extern const struct fscache_cookie_def cifs_fscache_super_index_def; | 32 | extern const struct fscache_cookie_def cifs_fscache_super_index_def; |
33 | extern const struct fscache_cookie_def cifs_fscache_inode_object_def; | 33 | extern const struct fscache_cookie_def cifs_fscache_inode_object_def; |
34 | 34 | ||
35 | |||
36 | extern int cifs_fscache_register(void); | 35 | extern int cifs_fscache_register(void); |
37 | extern void cifs_fscache_unregister(void); | 36 | extern void cifs_fscache_unregister(void); |
38 | 37 | ||
@@ -50,6 +49,11 @@ extern void cifs_fscache_reset_inode_cookie(struct inode *); | |||
50 | 49 | ||
51 | extern void __cifs_fscache_invalidate_page(struct page *, struct inode *); | 50 | extern void __cifs_fscache_invalidate_page(struct page *, struct inode *); |
52 | extern int cifs_fscache_release_page(struct page *page, gfp_t gfp); | 51 | extern int cifs_fscache_release_page(struct page *page, gfp_t gfp); |
52 | extern int __cifs_readpage_from_fscache(struct inode *, struct page *); | ||
53 | extern int __cifs_readpages_from_fscache(struct inode *, | ||
54 | struct address_space *, | ||
55 | struct list_head *, | ||
56 | unsigned *); | ||
53 | 57 | ||
54 | extern void __cifs_readpage_to_fscache(struct inode *, struct page *); | 58 | extern void __cifs_readpage_to_fscache(struct inode *, struct page *); |
55 | 59 | ||
@@ -60,6 +64,26 @@ static inline void cifs_fscache_invalidate_page(struct page *page, | |||
60 | __cifs_fscache_invalidate_page(page, inode); | 64 | __cifs_fscache_invalidate_page(page, inode); |
61 | } | 65 | } |
62 | 66 | ||
67 | static inline int cifs_readpage_from_fscache(struct inode *inode, | ||
68 | struct page *page) | ||
69 | { | ||
70 | if (CIFS_I(inode)->fscache) | ||
71 | return __cifs_readpage_from_fscache(inode, page); | ||
72 | |||
73 | return -ENOBUFS; | ||
74 | } | ||
75 | |||
76 | static inline int cifs_readpages_from_fscache(struct inode *inode, | ||
77 | struct address_space *mapping, | ||
78 | struct list_head *pages, | ||
79 | unsigned *nr_pages) | ||
80 | { | ||
81 | if (CIFS_I(inode)->fscache) | ||
82 | return __cifs_readpages_from_fscache(inode, mapping, pages, | ||
83 | nr_pages); | ||
84 | return -ENOBUFS; | ||
85 | } | ||
86 | |||
63 | static inline void cifs_readpage_to_fscache(struct inode *inode, | 87 | static inline void cifs_readpage_to_fscache(struct inode *inode, |
64 | struct page *page) | 88 | struct page *page) |
65 | { | 89 | { |
@@ -90,6 +114,20 @@ static inline void cifs_fscache_release_page(struct page *page, gfp_t gfp) | |||
90 | 114 | ||
91 | static inline int cifs_fscache_invalidate_page(struct page *page, | 115 | static inline int cifs_fscache_invalidate_page(struct page *page, |
92 | struct inode *) {} | 116 | struct inode *) {} |
117 | static inline int | ||
118 | cifs_readpage_from_fscache(struct inode *inode, struct page *page) | ||
119 | { | ||
120 | return -ENOBUFS; | ||
121 | } | ||
122 | |||
123 | static inline int cifs_readpages_from_fscache(struct inode *inode, | ||
124 | struct address_space *mapping, | ||
125 | struct list_head *pages, | ||
126 | unsigned *nr_pages) | ||
127 | { | ||
128 | return -ENOBUFS; | ||
129 | } | ||
130 | |||
93 | static inline void cifs_readpage_to_fscache(struct inode *inode, | 131 | static inline void cifs_readpage_to_fscache(struct inode *inode, |
94 | struct page *page) {} | 132 | struct page *page) {} |
95 | 133 | ||