2 * fs/cifs/fscache.c - CIFS filesystem cache interface
4 * Copyright (c) 2010 Novell, Inc.
5 * Author(s): Suresh Jayaraman <sjayaraman@suse.de>
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.
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.
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
23 #include "cifs_debug.h"
24 #include "cifs_fs_sb.h"
27 * Key layout of CIFS server cache index object
29 struct cifs_server_key
{
31 uint16_t family
; /* address family */
32 __be16 port
; /* IP port */
35 struct in_addr ipv4_addr
;
36 struct in6_addr ipv6_addr
;
41 * Get a cookie for a server object keyed by {IPaddress,port,family} tuple
43 void cifs_fscache_get_client_cookie(struct TCP_Server_Info
*server
)
45 const struct sockaddr
*sa
= (struct sockaddr
*) &server
->dstaddr
;
46 const struct sockaddr_in
*addr
= (struct sockaddr_in
*) sa
;
47 const struct sockaddr_in6
*addr6
= (struct sockaddr_in6
*) sa
;
48 struct cifs_server_key key
;
49 uint16_t key_len
= sizeof(key
.hdr
);
51 memset(&key
, 0, sizeof(key
));
54 * Should not be a problem as sin_family/sin6_family overlays
57 key
.hdr
.family
= sa
->sa_family
;
58 switch (sa
->sa_family
) {
60 key
.hdr
.port
= addr
->sin_port
;
61 key
.ipv4_addr
= addr
->sin_addr
;
62 key_len
+= sizeof(key
.ipv4_addr
);
66 key
.hdr
.port
= addr6
->sin6_port
;
67 key
.ipv6_addr
= addr6
->sin6_addr
;
68 key_len
+= sizeof(key
.ipv6_addr
);
72 cifs_dbg(VFS
, "Unknown network family '%d'\n", sa
->sa_family
);
73 server
->fscache
= NULL
;
78 fscache_acquire_cookie(cifs_fscache_netfs
.primary_index
,
79 &cifs_fscache_server_index_def
,
83 cifs_dbg(FYI
, "%s: (0x%p/0x%p)\n",
84 __func__
, server
, server
->fscache
);
87 void cifs_fscache_release_client_cookie(struct TCP_Server_Info
*server
)
89 cifs_dbg(FYI
, "%s: (0x%p/0x%p)\n",
90 __func__
, server
, server
->fscache
);
91 fscache_relinquish_cookie(server
->fscache
, NULL
, false);
92 server
->fscache
= NULL
;
95 void cifs_fscache_get_super_cookie(struct cifs_tcon
*tcon
)
97 struct TCP_Server_Info
*server
= tcon
->ses
->server
;
100 sharename
= extract_sharename(tcon
->treeName
);
101 if (IS_ERR(sharename
)) {
102 cifs_dbg(FYI
, "%s: couldn't extract sharename\n", __func__
);
103 tcon
->fscache
= NULL
;
108 fscache_acquire_cookie(server
->fscache
,
109 &cifs_fscache_super_index_def
,
110 sharename
, strlen(sharename
),
111 &tcon
->resource_id
, sizeof(tcon
->resource_id
),
114 cifs_dbg(FYI
, "%s: (0x%p/0x%p)\n",
115 __func__
, server
->fscache
, tcon
->fscache
);
118 void cifs_fscache_release_super_cookie(struct cifs_tcon
*tcon
)
120 cifs_dbg(FYI
, "%s: (0x%p)\n", __func__
, tcon
->fscache
);
121 fscache_relinquish_cookie(tcon
->fscache
, &tcon
->resource_id
, false);
122 tcon
->fscache
= NULL
;
125 static void cifs_fscache_acquire_inode_cookie(struct cifsInodeInfo
*cifsi
,
126 struct cifs_tcon
*tcon
)
128 struct cifs_fscache_inode_auxdata auxdata
;
130 memset(&auxdata
, 0, sizeof(auxdata
));
131 auxdata
.eof
= cifsi
->server_eof
;
132 auxdata
.last_write_time_sec
= cifsi
->vfs_inode
.i_mtime
.tv_sec
;
133 auxdata
.last_change_time_sec
= cifsi
->vfs_inode
.i_ctime
.tv_sec
;
134 auxdata
.last_write_time_nsec
= cifsi
->vfs_inode
.i_mtime
.tv_nsec
;
135 auxdata
.last_change_time_nsec
= cifsi
->vfs_inode
.i_ctime
.tv_nsec
;
138 fscache_acquire_cookie(tcon
->fscache
,
139 &cifs_fscache_inode_object_def
,
140 &cifsi
->uniqueid
, sizeof(cifsi
->uniqueid
),
141 &auxdata
, sizeof(auxdata
),
142 cifsi
, cifsi
->vfs_inode
.i_size
, true);
145 static void cifs_fscache_enable_inode_cookie(struct inode
*inode
)
147 struct cifsInodeInfo
*cifsi
= CIFS_I(inode
);
148 struct cifs_sb_info
*cifs_sb
= CIFS_SB(inode
->i_sb
);
149 struct cifs_tcon
*tcon
= cifs_sb_master_tcon(cifs_sb
);
154 if (!(cifs_sb
->mnt_cifs_flags
& CIFS_MOUNT_FSCACHE
))
157 cifs_fscache_acquire_inode_cookie(cifsi
, tcon
);
159 cifs_dbg(FYI
, "%s: got FH cookie (0x%p/0x%p)\n",
160 __func__
, tcon
->fscache
, cifsi
->fscache
);
163 void cifs_fscache_release_inode_cookie(struct inode
*inode
)
165 struct cifs_fscache_inode_auxdata auxdata
;
166 struct cifsInodeInfo
*cifsi
= CIFS_I(inode
);
168 if (cifsi
->fscache
) {
169 memset(&auxdata
, 0, sizeof(auxdata
));
170 auxdata
.eof
= cifsi
->server_eof
;
171 auxdata
.last_write_time_sec
= cifsi
->vfs_inode
.i_mtime
.tv_sec
;
172 auxdata
.last_change_time_sec
= cifsi
->vfs_inode
.i_ctime
.tv_sec
;
173 auxdata
.last_write_time_nsec
= cifsi
->vfs_inode
.i_mtime
.tv_nsec
;
174 auxdata
.last_change_time_nsec
= cifsi
->vfs_inode
.i_ctime
.tv_nsec
;
176 cifs_dbg(FYI
, "%s: (0x%p)\n", __func__
, cifsi
->fscache
);
177 fscache_relinquish_cookie(cifsi
->fscache
, &auxdata
, false);
178 cifsi
->fscache
= NULL
;
182 static void cifs_fscache_disable_inode_cookie(struct inode
*inode
)
184 struct cifsInodeInfo
*cifsi
= CIFS_I(inode
);
186 if (cifsi
->fscache
) {
187 cifs_dbg(FYI
, "%s: (0x%p)\n", __func__
, cifsi
->fscache
);
188 fscache_uncache_all_inode_pages(cifsi
->fscache
, inode
);
189 fscache_relinquish_cookie(cifsi
->fscache
, NULL
, true);
190 cifsi
->fscache
= NULL
;
194 void cifs_fscache_set_inode_cookie(struct inode
*inode
, struct file
*filp
)
196 if ((filp
->f_flags
& O_ACCMODE
) != O_RDONLY
)
197 cifs_fscache_disable_inode_cookie(inode
);
199 cifs_fscache_enable_inode_cookie(inode
);
202 void cifs_fscache_reset_inode_cookie(struct inode
*inode
)
204 struct cifsInodeInfo
*cifsi
= CIFS_I(inode
);
205 struct cifs_sb_info
*cifs_sb
= CIFS_SB(inode
->i_sb
);
206 struct cifs_tcon
*tcon
= cifs_sb_master_tcon(cifs_sb
);
207 struct fscache_cookie
*old
= cifsi
->fscache
;
209 if (cifsi
->fscache
) {
210 /* retire the current fscache cache and get a new one */
211 fscache_relinquish_cookie(cifsi
->fscache
, NULL
, true);
213 cifs_fscache_acquire_inode_cookie(cifsi
, tcon
);
214 cifs_dbg(FYI
, "%s: new cookie 0x%p oldcookie 0x%p\n",
215 __func__
, cifsi
->fscache
, old
);
219 int cifs_fscache_release_page(struct page
*page
, gfp_t gfp
)
221 if (PageFsCache(page
)) {
222 struct inode
*inode
= page
->mapping
->host
;
223 struct cifsInodeInfo
*cifsi
= CIFS_I(inode
);
225 cifs_dbg(FYI
, "%s: (0x%p/0x%p)\n",
226 __func__
, page
, cifsi
->fscache
);
227 if (!fscache_maybe_release_page(cifsi
->fscache
, page
, gfp
))
234 static void cifs_readpage_from_fscache_complete(struct page
*page
, void *ctx
,
237 cifs_dbg(FYI
, "%s: (0x%p/%d)\n", __func__
, page
, error
);
239 SetPageUptodate(page
);
244 * Retrieve a page from FS-Cache
246 int __cifs_readpage_from_fscache(struct inode
*inode
, struct page
*page
)
250 cifs_dbg(FYI
, "%s: (fsc:%p, p:%p, i:0x%p\n",
251 __func__
, CIFS_I(inode
)->fscache
, page
, inode
);
252 ret
= fscache_read_or_alloc_page(CIFS_I(inode
)->fscache
, page
,
253 cifs_readpage_from_fscache_complete
,
258 case 0: /* page found in fscache, read submitted */
259 cifs_dbg(FYI
, "%s: submitted\n", __func__
);
261 case -ENOBUFS
: /* page won't be cached */
262 case -ENODATA
: /* page not in cache */
263 cifs_dbg(FYI
, "%s: %d\n", __func__
, ret
);
267 cifs_dbg(VFS
, "unknown error ret = %d\n", ret
);
273 * Retrieve a set of pages from FS-Cache
275 int __cifs_readpages_from_fscache(struct inode
*inode
,
276 struct address_space
*mapping
,
277 struct list_head
*pages
,
282 cifs_dbg(FYI
, "%s: (0x%p/%u/0x%p)\n",
283 __func__
, CIFS_I(inode
)->fscache
, *nr_pages
, inode
);
284 ret
= fscache_read_or_alloc_pages(CIFS_I(inode
)->fscache
, mapping
,
286 cifs_readpage_from_fscache_complete
,
288 mapping_gfp_mask(mapping
));
290 case 0: /* read submitted to the cache for all pages */
291 cifs_dbg(FYI
, "%s: submitted\n", __func__
);
294 case -ENOBUFS
: /* some pages are not cached and can't be */
295 case -ENODATA
: /* some pages are not cached */
296 cifs_dbg(FYI
, "%s: no page\n", __func__
);
300 cifs_dbg(FYI
, "unknown error ret = %d\n", ret
);
306 void __cifs_readpage_to_fscache(struct inode
*inode
, struct page
*page
)
308 struct cifsInodeInfo
*cifsi
= CIFS_I(inode
);
311 cifs_dbg(FYI
, "%s: (fsc: %p, p: %p, i: %p)\n",
312 __func__
, cifsi
->fscache
, page
, inode
);
313 ret
= fscache_write_page(cifsi
->fscache
, page
,
314 cifsi
->vfs_inode
.i_size
, GFP_KERNEL
);
316 fscache_uncache_page(cifsi
->fscache
, page
);
319 void __cifs_fscache_readpages_cancel(struct inode
*inode
, struct list_head
*pages
)
321 cifs_dbg(FYI
, "%s: (fsc: %p, i: %p)\n",
322 __func__
, CIFS_I(inode
)->fscache
, inode
);
323 fscache_readpages_cancel(CIFS_I(inode
)->fscache
, pages
);
326 void __cifs_fscache_invalidate_page(struct page
*page
, struct inode
*inode
)
328 struct cifsInodeInfo
*cifsi
= CIFS_I(inode
);
329 struct fscache_cookie
*cookie
= cifsi
->fscache
;
331 cifs_dbg(FYI
, "%s: (0x%p/0x%p)\n", __func__
, page
, cookie
);
332 fscache_wait_on_page_write(cookie
, page
);
333 fscache_uncache_page(cookie
, page
);