1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * fs/cifs/fscache.c - CIFS filesystem cache interface
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (c) 2010 Novell, Inc.
5*4882a593Smuzhiyun * Author(s): Suresh Jayaraman <sjayaraman@suse.de>
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * This library is free software; you can redistribute it and/or modify
8*4882a593Smuzhiyun * it under the terms of the GNU Lesser General Public License as published
9*4882a593Smuzhiyun * by the Free Software Foundation; either version 2.1 of the License, or
10*4882a593Smuzhiyun * (at your option) any later version.
11*4882a593Smuzhiyun *
12*4882a593Smuzhiyun * This library is distributed in the hope that it will be useful,
13*4882a593Smuzhiyun * but WITHOUT ANY WARRANTY; without even the implied warranty of
14*4882a593Smuzhiyun * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15*4882a593Smuzhiyun * the GNU Lesser General Public License for more details.
16*4882a593Smuzhiyun *
17*4882a593Smuzhiyun * You should have received a copy of the GNU Lesser General Public License
18*4882a593Smuzhiyun * along with this library; if not, write to the Free Software
19*4882a593Smuzhiyun * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20*4882a593Smuzhiyun */
21*4882a593Smuzhiyun #include "fscache.h"
22*4882a593Smuzhiyun #include "cifsglob.h"
23*4882a593Smuzhiyun #include "cifs_debug.h"
24*4882a593Smuzhiyun #include "cifs_fs_sb.h"
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun /*
27*4882a593Smuzhiyun * Key layout of CIFS server cache index object
28*4882a593Smuzhiyun */
29*4882a593Smuzhiyun struct cifs_server_key {
30*4882a593Smuzhiyun struct {
31*4882a593Smuzhiyun uint16_t family; /* address family */
32*4882a593Smuzhiyun __be16 port; /* IP port */
33*4882a593Smuzhiyun } hdr;
34*4882a593Smuzhiyun union {
35*4882a593Smuzhiyun struct in_addr ipv4_addr;
36*4882a593Smuzhiyun struct in6_addr ipv6_addr;
37*4882a593Smuzhiyun };
38*4882a593Smuzhiyun } __packed;
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun /*
41*4882a593Smuzhiyun * Get a cookie for a server object keyed by {IPaddress,port,family} tuple
42*4882a593Smuzhiyun */
cifs_fscache_get_client_cookie(struct TCP_Server_Info * server)43*4882a593Smuzhiyun void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun const struct sockaddr *sa = (struct sockaddr *) &server->dstaddr;
46*4882a593Smuzhiyun const struct sockaddr_in *addr = (struct sockaddr_in *) sa;
47*4882a593Smuzhiyun const struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) sa;
48*4882a593Smuzhiyun struct cifs_server_key key;
49*4882a593Smuzhiyun uint16_t key_len = sizeof(key.hdr);
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun memset(&key, 0, sizeof(key));
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun /*
54*4882a593Smuzhiyun * Should not be a problem as sin_family/sin6_family overlays
55*4882a593Smuzhiyun * sa_family field
56*4882a593Smuzhiyun */
57*4882a593Smuzhiyun key.hdr.family = sa->sa_family;
58*4882a593Smuzhiyun switch (sa->sa_family) {
59*4882a593Smuzhiyun case AF_INET:
60*4882a593Smuzhiyun key.hdr.port = addr->sin_port;
61*4882a593Smuzhiyun key.ipv4_addr = addr->sin_addr;
62*4882a593Smuzhiyun key_len += sizeof(key.ipv4_addr);
63*4882a593Smuzhiyun break;
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun case AF_INET6:
66*4882a593Smuzhiyun key.hdr.port = addr6->sin6_port;
67*4882a593Smuzhiyun key.ipv6_addr = addr6->sin6_addr;
68*4882a593Smuzhiyun key_len += sizeof(key.ipv6_addr);
69*4882a593Smuzhiyun break;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun default:
72*4882a593Smuzhiyun cifs_dbg(VFS, "Unknown network family '%d'\n", sa->sa_family);
73*4882a593Smuzhiyun server->fscache = NULL;
74*4882a593Smuzhiyun return;
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun server->fscache =
78*4882a593Smuzhiyun fscache_acquire_cookie(cifs_fscache_netfs.primary_index,
79*4882a593Smuzhiyun &cifs_fscache_server_index_def,
80*4882a593Smuzhiyun &key, key_len,
81*4882a593Smuzhiyun NULL, 0,
82*4882a593Smuzhiyun server, 0, true);
83*4882a593Smuzhiyun cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
84*4882a593Smuzhiyun __func__, server, server->fscache);
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun
cifs_fscache_release_client_cookie(struct TCP_Server_Info * server)87*4882a593Smuzhiyun void cifs_fscache_release_client_cookie(struct TCP_Server_Info *server)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
90*4882a593Smuzhiyun __func__, server, server->fscache);
91*4882a593Smuzhiyun fscache_relinquish_cookie(server->fscache, NULL, false);
92*4882a593Smuzhiyun server->fscache = NULL;
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun
cifs_fscache_get_super_cookie(struct cifs_tcon * tcon)95*4882a593Smuzhiyun void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
96*4882a593Smuzhiyun {
97*4882a593Smuzhiyun struct TCP_Server_Info *server = tcon->ses->server;
98*4882a593Smuzhiyun char *sharename;
99*4882a593Smuzhiyun struct cifs_fscache_super_auxdata auxdata;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun sharename = extract_sharename(tcon->treeName);
102*4882a593Smuzhiyun if (IS_ERR(sharename)) {
103*4882a593Smuzhiyun cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__);
104*4882a593Smuzhiyun tcon->fscache = NULL;
105*4882a593Smuzhiyun return;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun memset(&auxdata, 0, sizeof(auxdata));
109*4882a593Smuzhiyun auxdata.resource_id = tcon->resource_id;
110*4882a593Smuzhiyun auxdata.vol_create_time = tcon->vol_create_time;
111*4882a593Smuzhiyun auxdata.vol_serial_number = tcon->vol_serial_number;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun tcon->fscache =
114*4882a593Smuzhiyun fscache_acquire_cookie(server->fscache,
115*4882a593Smuzhiyun &cifs_fscache_super_index_def,
116*4882a593Smuzhiyun sharename, strlen(sharename),
117*4882a593Smuzhiyun &auxdata, sizeof(auxdata),
118*4882a593Smuzhiyun tcon, 0, true);
119*4882a593Smuzhiyun kfree(sharename);
120*4882a593Smuzhiyun cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
121*4882a593Smuzhiyun __func__, server->fscache, tcon->fscache);
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun
cifs_fscache_release_super_cookie(struct cifs_tcon * tcon)124*4882a593Smuzhiyun void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun struct cifs_fscache_super_auxdata auxdata;
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun memset(&auxdata, 0, sizeof(auxdata));
129*4882a593Smuzhiyun auxdata.resource_id = tcon->resource_id;
130*4882a593Smuzhiyun auxdata.vol_create_time = tcon->vol_create_time;
131*4882a593Smuzhiyun auxdata.vol_serial_number = tcon->vol_serial_number;
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun cifs_dbg(FYI, "%s: (0x%p)\n", __func__, tcon->fscache);
134*4882a593Smuzhiyun fscache_relinquish_cookie(tcon->fscache, &auxdata, false);
135*4882a593Smuzhiyun tcon->fscache = NULL;
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun
cifs_fscache_acquire_inode_cookie(struct cifsInodeInfo * cifsi,struct cifs_tcon * tcon)138*4882a593Smuzhiyun static void cifs_fscache_acquire_inode_cookie(struct cifsInodeInfo *cifsi,
139*4882a593Smuzhiyun struct cifs_tcon *tcon)
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun struct cifs_fscache_inode_auxdata auxdata;
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun memset(&auxdata, 0, sizeof(auxdata));
144*4882a593Smuzhiyun auxdata.eof = cifsi->server_eof;
145*4882a593Smuzhiyun auxdata.last_write_time_sec = cifsi->vfs_inode.i_mtime.tv_sec;
146*4882a593Smuzhiyun auxdata.last_change_time_sec = cifsi->vfs_inode.i_ctime.tv_sec;
147*4882a593Smuzhiyun auxdata.last_write_time_nsec = cifsi->vfs_inode.i_mtime.tv_nsec;
148*4882a593Smuzhiyun auxdata.last_change_time_nsec = cifsi->vfs_inode.i_ctime.tv_nsec;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun cifsi->fscache =
151*4882a593Smuzhiyun fscache_acquire_cookie(tcon->fscache,
152*4882a593Smuzhiyun &cifs_fscache_inode_object_def,
153*4882a593Smuzhiyun &cifsi->uniqueid, sizeof(cifsi->uniqueid),
154*4882a593Smuzhiyun &auxdata, sizeof(auxdata),
155*4882a593Smuzhiyun cifsi, cifsi->vfs_inode.i_size, true);
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
cifs_fscache_enable_inode_cookie(struct inode * inode)158*4882a593Smuzhiyun static void cifs_fscache_enable_inode_cookie(struct inode *inode)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun struct cifsInodeInfo *cifsi = CIFS_I(inode);
161*4882a593Smuzhiyun struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
162*4882a593Smuzhiyun struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun if (cifsi->fscache)
165*4882a593Smuzhiyun return;
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE))
168*4882a593Smuzhiyun return;
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun cifs_fscache_acquire_inode_cookie(cifsi, tcon);
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun cifs_dbg(FYI, "%s: got FH cookie (0x%p/0x%p)\n",
173*4882a593Smuzhiyun __func__, tcon->fscache, cifsi->fscache);
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun
cifs_fscache_release_inode_cookie(struct inode * inode)176*4882a593Smuzhiyun void cifs_fscache_release_inode_cookie(struct inode *inode)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun struct cifs_fscache_inode_auxdata auxdata;
179*4882a593Smuzhiyun struct cifsInodeInfo *cifsi = CIFS_I(inode);
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun if (cifsi->fscache) {
182*4882a593Smuzhiyun memset(&auxdata, 0, sizeof(auxdata));
183*4882a593Smuzhiyun auxdata.eof = cifsi->server_eof;
184*4882a593Smuzhiyun auxdata.last_write_time_sec = cifsi->vfs_inode.i_mtime.tv_sec;
185*4882a593Smuzhiyun auxdata.last_change_time_sec = cifsi->vfs_inode.i_ctime.tv_sec;
186*4882a593Smuzhiyun auxdata.last_write_time_nsec = cifsi->vfs_inode.i_mtime.tv_nsec;
187*4882a593Smuzhiyun auxdata.last_change_time_nsec = cifsi->vfs_inode.i_ctime.tv_nsec;
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache);
190*4882a593Smuzhiyun fscache_relinquish_cookie(cifsi->fscache, &auxdata, false);
191*4882a593Smuzhiyun cifsi->fscache = NULL;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun
cifs_fscache_disable_inode_cookie(struct inode * inode)195*4882a593Smuzhiyun static void cifs_fscache_disable_inode_cookie(struct inode *inode)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun struct cifsInodeInfo *cifsi = CIFS_I(inode);
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun if (cifsi->fscache) {
200*4882a593Smuzhiyun cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache);
201*4882a593Smuzhiyun fscache_uncache_all_inode_pages(cifsi->fscache, inode);
202*4882a593Smuzhiyun fscache_relinquish_cookie(cifsi->fscache, NULL, true);
203*4882a593Smuzhiyun cifsi->fscache = NULL;
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun
cifs_fscache_set_inode_cookie(struct inode * inode,struct file * filp)207*4882a593Smuzhiyun void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
208*4882a593Smuzhiyun {
209*4882a593Smuzhiyun if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
210*4882a593Smuzhiyun cifs_fscache_disable_inode_cookie(inode);
211*4882a593Smuzhiyun else
212*4882a593Smuzhiyun cifs_fscache_enable_inode_cookie(inode);
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun
cifs_fscache_reset_inode_cookie(struct inode * inode)215*4882a593Smuzhiyun void cifs_fscache_reset_inode_cookie(struct inode *inode)
216*4882a593Smuzhiyun {
217*4882a593Smuzhiyun struct cifsInodeInfo *cifsi = CIFS_I(inode);
218*4882a593Smuzhiyun struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
219*4882a593Smuzhiyun struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
220*4882a593Smuzhiyun struct fscache_cookie *old = cifsi->fscache;
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun if (cifsi->fscache) {
223*4882a593Smuzhiyun /* retire the current fscache cache and get a new one */
224*4882a593Smuzhiyun fscache_relinquish_cookie(cifsi->fscache, NULL, true);
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun cifs_fscache_acquire_inode_cookie(cifsi, tcon);
227*4882a593Smuzhiyun cifs_dbg(FYI, "%s: new cookie 0x%p oldcookie 0x%p\n",
228*4882a593Smuzhiyun __func__, cifsi->fscache, old);
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
cifs_fscache_release_page(struct page * page,gfp_t gfp)232*4882a593Smuzhiyun int cifs_fscache_release_page(struct page *page, gfp_t gfp)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun if (PageFsCache(page)) {
235*4882a593Smuzhiyun struct inode *inode = page->mapping->host;
236*4882a593Smuzhiyun struct cifsInodeInfo *cifsi = CIFS_I(inode);
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
239*4882a593Smuzhiyun __func__, page, cifsi->fscache);
240*4882a593Smuzhiyun if (!fscache_maybe_release_page(cifsi->fscache, page, gfp))
241*4882a593Smuzhiyun return 0;
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun return 1;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
cifs_readpage_from_fscache_complete(struct page * page,void * ctx,int error)247*4882a593Smuzhiyun static void cifs_readpage_from_fscache_complete(struct page *page, void *ctx,
248*4882a593Smuzhiyun int error)
249*4882a593Smuzhiyun {
250*4882a593Smuzhiyun cifs_dbg(FYI, "%s: (0x%p/%d)\n", __func__, page, error);
251*4882a593Smuzhiyun if (!error)
252*4882a593Smuzhiyun SetPageUptodate(page);
253*4882a593Smuzhiyun unlock_page(page);
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun /*
257*4882a593Smuzhiyun * Retrieve a page from FS-Cache
258*4882a593Smuzhiyun */
__cifs_readpage_from_fscache(struct inode * inode,struct page * page)259*4882a593Smuzhiyun int __cifs_readpage_from_fscache(struct inode *inode, struct page *page)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun int ret;
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun cifs_dbg(FYI, "%s: (fsc:%p, p:%p, i:0x%p\n",
264*4882a593Smuzhiyun __func__, CIFS_I(inode)->fscache, page, inode);
265*4882a593Smuzhiyun ret = fscache_read_or_alloc_page(CIFS_I(inode)->fscache, page,
266*4882a593Smuzhiyun cifs_readpage_from_fscache_complete,
267*4882a593Smuzhiyun NULL,
268*4882a593Smuzhiyun GFP_KERNEL);
269*4882a593Smuzhiyun switch (ret) {
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun case 0: /* page found in fscache, read submitted */
272*4882a593Smuzhiyun cifs_dbg(FYI, "%s: submitted\n", __func__);
273*4882a593Smuzhiyun return ret;
274*4882a593Smuzhiyun case -ENOBUFS: /* page won't be cached */
275*4882a593Smuzhiyun case -ENODATA: /* page not in cache */
276*4882a593Smuzhiyun cifs_dbg(FYI, "%s: %d\n", __func__, ret);
277*4882a593Smuzhiyun return 1;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun default:
280*4882a593Smuzhiyun cifs_dbg(VFS, "unknown error ret = %d\n", ret);
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun return ret;
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun /*
286*4882a593Smuzhiyun * Retrieve a set of pages from FS-Cache
287*4882a593Smuzhiyun */
__cifs_readpages_from_fscache(struct inode * inode,struct address_space * mapping,struct list_head * pages,unsigned * nr_pages)288*4882a593Smuzhiyun int __cifs_readpages_from_fscache(struct inode *inode,
289*4882a593Smuzhiyun struct address_space *mapping,
290*4882a593Smuzhiyun struct list_head *pages,
291*4882a593Smuzhiyun unsigned *nr_pages)
292*4882a593Smuzhiyun {
293*4882a593Smuzhiyun int ret;
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun cifs_dbg(FYI, "%s: (0x%p/%u/0x%p)\n",
296*4882a593Smuzhiyun __func__, CIFS_I(inode)->fscache, *nr_pages, inode);
297*4882a593Smuzhiyun ret = fscache_read_or_alloc_pages(CIFS_I(inode)->fscache, mapping,
298*4882a593Smuzhiyun pages, nr_pages,
299*4882a593Smuzhiyun cifs_readpage_from_fscache_complete,
300*4882a593Smuzhiyun NULL,
301*4882a593Smuzhiyun mapping_gfp_mask(mapping));
302*4882a593Smuzhiyun switch (ret) {
303*4882a593Smuzhiyun case 0: /* read submitted to the cache for all pages */
304*4882a593Smuzhiyun cifs_dbg(FYI, "%s: submitted\n", __func__);
305*4882a593Smuzhiyun return ret;
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun case -ENOBUFS: /* some pages are not cached and can't be */
308*4882a593Smuzhiyun case -ENODATA: /* some pages are not cached */
309*4882a593Smuzhiyun cifs_dbg(FYI, "%s: no page\n", __func__);
310*4882a593Smuzhiyun return 1;
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun default:
313*4882a593Smuzhiyun cifs_dbg(FYI, "unknown error ret = %d\n", ret);
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun return ret;
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun
__cifs_readpage_to_fscache(struct inode * inode,struct page * page)319*4882a593Smuzhiyun void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun struct cifsInodeInfo *cifsi = CIFS_I(inode);
322*4882a593Smuzhiyun int ret;
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun cifs_dbg(FYI, "%s: (fsc: %p, p: %p, i: %p)\n",
325*4882a593Smuzhiyun __func__, cifsi->fscache, page, inode);
326*4882a593Smuzhiyun ret = fscache_write_page(cifsi->fscache, page,
327*4882a593Smuzhiyun cifsi->vfs_inode.i_size, GFP_KERNEL);
328*4882a593Smuzhiyun if (ret != 0)
329*4882a593Smuzhiyun fscache_uncache_page(cifsi->fscache, page);
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun
__cifs_fscache_readpages_cancel(struct inode * inode,struct list_head * pages)332*4882a593Smuzhiyun void __cifs_fscache_readpages_cancel(struct inode *inode, struct list_head *pages)
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun cifs_dbg(FYI, "%s: (fsc: %p, i: %p)\n",
335*4882a593Smuzhiyun __func__, CIFS_I(inode)->fscache, inode);
336*4882a593Smuzhiyun fscache_readpages_cancel(CIFS_I(inode)->fscache, pages);
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun
__cifs_fscache_invalidate_page(struct page * page,struct inode * inode)339*4882a593Smuzhiyun void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode)
340*4882a593Smuzhiyun {
341*4882a593Smuzhiyun struct cifsInodeInfo *cifsi = CIFS_I(inode);
342*4882a593Smuzhiyun struct fscache_cookie *cookie = cifsi->fscache;
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", __func__, page, cookie);
345*4882a593Smuzhiyun fscache_wait_on_page_write(cookie, page);
346*4882a593Smuzhiyun fscache_uncache_page(cookie, page);
347*4882a593Smuzhiyun }
348