diff options
| -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 | ||
