Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/fs/cifs/fscache.c
15109 views
1
/*
2
* fs/cifs/fscache.c - CIFS filesystem cache interface
3
*
4
* Copyright (c) 2010 Novell, Inc.
5
* Author(s): Suresh Jayaraman <[email protected]>
6
*
7
* This library is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU Lesser General Public License as published
9
* by the Free Software Foundation; either version 2.1 of the License, or
10
* (at your option) any later version.
11
*
12
* This library is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15
* the GNU Lesser General Public License for more details.
16
*
17
* You should have received a copy of the GNU Lesser General Public License
18
* along with this library; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
*/
21
#include "fscache.h"
22
#include "cifsglob.h"
23
#include "cifs_debug.h"
24
#include "cifs_fs_sb.h"
25
26
void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server)
27
{
28
server->fscache =
29
fscache_acquire_cookie(cifs_fscache_netfs.primary_index,
30
&cifs_fscache_server_index_def, server);
31
cFYI(1, "%s: (0x%p/0x%p)", __func__, server,
32
server->fscache);
33
}
34
35
void cifs_fscache_release_client_cookie(struct TCP_Server_Info *server)
36
{
37
cFYI(1, "%s: (0x%p/0x%p)", __func__, server,
38
server->fscache);
39
fscache_relinquish_cookie(server->fscache, 0);
40
server->fscache = NULL;
41
}
42
43
void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
44
{
45
struct TCP_Server_Info *server = tcon->ses->server;
46
47
tcon->fscache =
48
fscache_acquire_cookie(server->fscache,
49
&cifs_fscache_super_index_def, tcon);
50
cFYI(1, "%s: (0x%p/0x%p)", __func__, server->fscache,
51
tcon->fscache);
52
}
53
54
void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)
55
{
56
cFYI(1, "%s: (0x%p)", __func__, tcon->fscache);
57
fscache_relinquish_cookie(tcon->fscache, 0);
58
tcon->fscache = NULL;
59
}
60
61
static void cifs_fscache_enable_inode_cookie(struct inode *inode)
62
{
63
struct cifsInodeInfo *cifsi = CIFS_I(inode);
64
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
65
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
66
67
if (cifsi->fscache)
68
return;
69
70
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) {
71
cifsi->fscache = fscache_acquire_cookie(tcon->fscache,
72
&cifs_fscache_inode_object_def, cifsi);
73
cFYI(1, "%s: got FH cookie (0x%p/0x%p)", __func__,
74
tcon->fscache, cifsi->fscache);
75
}
76
}
77
78
void cifs_fscache_release_inode_cookie(struct inode *inode)
79
{
80
struct cifsInodeInfo *cifsi = CIFS_I(inode);
81
82
if (cifsi->fscache) {
83
cFYI(1, "%s: (0x%p)", __func__, cifsi->fscache);
84
fscache_relinquish_cookie(cifsi->fscache, 0);
85
cifsi->fscache = NULL;
86
}
87
}
88
89
static void cifs_fscache_disable_inode_cookie(struct inode *inode)
90
{
91
struct cifsInodeInfo *cifsi = CIFS_I(inode);
92
93
if (cifsi->fscache) {
94
cFYI(1, "%s: (0x%p)", __func__, cifsi->fscache);
95
fscache_uncache_all_inode_pages(cifsi->fscache, inode);
96
fscache_relinquish_cookie(cifsi->fscache, 1);
97
cifsi->fscache = NULL;
98
}
99
}
100
101
void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
102
{
103
if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
104
cifs_fscache_disable_inode_cookie(inode);
105
else
106
cifs_fscache_enable_inode_cookie(inode);
107
}
108
109
void cifs_fscache_reset_inode_cookie(struct inode *inode)
110
{
111
struct cifsInodeInfo *cifsi = CIFS_I(inode);
112
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
113
struct fscache_cookie *old = cifsi->fscache;
114
115
if (cifsi->fscache) {
116
/* retire the current fscache cache and get a new one */
117
fscache_relinquish_cookie(cifsi->fscache, 1);
118
119
cifsi->fscache = fscache_acquire_cookie(
120
cifs_sb_master_tcon(cifs_sb)->fscache,
121
&cifs_fscache_inode_object_def,
122
cifsi);
123
cFYI(1, "%s: new cookie 0x%p oldcookie 0x%p",
124
__func__, cifsi->fscache, old);
125
}
126
}
127
128
int cifs_fscache_release_page(struct page *page, gfp_t gfp)
129
{
130
if (PageFsCache(page)) {
131
struct inode *inode = page->mapping->host;
132
struct cifsInodeInfo *cifsi = CIFS_I(inode);
133
134
cFYI(1, "%s: (0x%p/0x%p)", __func__, page,
135
cifsi->fscache);
136
if (!fscache_maybe_release_page(cifsi->fscache, page, gfp))
137
return 0;
138
}
139
140
return 1;
141
}
142
143
static void cifs_readpage_from_fscache_complete(struct page *page, void *ctx,
144
int error)
145
{
146
cFYI(1, "%s: (0x%p/%d)", __func__, page, error);
147
if (!error)
148
SetPageUptodate(page);
149
unlock_page(page);
150
}
151
152
/*
153
* Retrieve a page from FS-Cache
154
*/
155
int __cifs_readpage_from_fscache(struct inode *inode, struct page *page)
156
{
157
int ret;
158
159
cFYI(1, "%s: (fsc:%p, p:%p, i:0x%p", __func__,
160
CIFS_I(inode)->fscache, page, inode);
161
ret = fscache_read_or_alloc_page(CIFS_I(inode)->fscache, page,
162
cifs_readpage_from_fscache_complete,
163
NULL,
164
GFP_KERNEL);
165
switch (ret) {
166
167
case 0: /* page found in fscache, read submitted */
168
cFYI(1, "%s: submitted", __func__);
169
return ret;
170
case -ENOBUFS: /* page won't be cached */
171
case -ENODATA: /* page not in cache */
172
cFYI(1, "%s: %d", __func__, ret);
173
return 1;
174
175
default:
176
cERROR(1, "unknown error ret = %d", ret);
177
}
178
return ret;
179
}
180
181
/*
182
* Retrieve a set of pages from FS-Cache
183
*/
184
int __cifs_readpages_from_fscache(struct inode *inode,
185
struct address_space *mapping,
186
struct list_head *pages,
187
unsigned *nr_pages)
188
{
189
int ret;
190
191
cFYI(1, "%s: (0x%p/%u/0x%p)", __func__,
192
CIFS_I(inode)->fscache, *nr_pages, inode);
193
ret = fscache_read_or_alloc_pages(CIFS_I(inode)->fscache, mapping,
194
pages, nr_pages,
195
cifs_readpage_from_fscache_complete,
196
NULL,
197
mapping_gfp_mask(mapping));
198
switch (ret) {
199
case 0: /* read submitted to the cache for all pages */
200
cFYI(1, "%s: submitted", __func__);
201
return ret;
202
203
case -ENOBUFS: /* some pages are not cached and can't be */
204
case -ENODATA: /* some pages are not cached */
205
cFYI(1, "%s: no page", __func__);
206
return 1;
207
208
default:
209
cFYI(1, "unknown error ret = %d", ret);
210
}
211
212
return ret;
213
}
214
215
void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
216
{
217
int ret;
218
219
cFYI(1, "%s: (fsc: %p, p: %p, i: %p)", __func__,
220
CIFS_I(inode)->fscache, page, inode);
221
ret = fscache_write_page(CIFS_I(inode)->fscache, page, GFP_KERNEL);
222
if (ret != 0)
223
fscache_uncache_page(CIFS_I(inode)->fscache, page);
224
}
225
226
void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode)
227
{
228
struct cifsInodeInfo *cifsi = CIFS_I(inode);
229
struct fscache_cookie *cookie = cifsi->fscache;
230
231
cFYI(1, "%s: (0x%p/0x%p)", __func__, page, cookie);
232
fscache_wait_on_page_write(cookie, page);
233
fscache_uncache_page(cookie, page);
234
}
235
236
237