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
;
99 struct cifs_fscache_super_auxdata auxdata
;
101 sharename
= extract_sharename(tcon
->treeName
);
102 if (IS_ERR(sharename
)) {
103 cifs_dbg(FYI
, "%s: couldn't extract sharename\n", __func__
);
104 tcon
->fscache
= NULL
;
108 memset(&auxdata
, 0, sizeof(auxdata
));
109 auxdata
.resource_id
= tcon
->resource_id
;
110 auxdata
.vol_create_time
= tcon
->vol_create_time
;
111 auxdata
.vol_serial_number
= tcon
->vol_serial_number
;
114 fscache_acquire_cookie(server
->fscache
,
115 &cifs_fscache_super_index_def
,
116 sharename
, strlen(sharename
),
117 &auxdata
, sizeof(auxdata
),
120 cifs_dbg(FYI
, "%s: (0x%p/0x%p)\n",
121 __func__
, server
->fscache
, tcon
->fscache
);
124 void cifs_fscache_release_super_cookie(struct cifs_tcon
*tcon
)
126 struct cifs_fscache_super_auxdata auxdata
;
128 memset(&auxdata
, 0, sizeof(auxdata
));
129 auxdata
.resource_id
= tcon
->resource_id
;
130 auxdata
.vol_create_time
= tcon
->vol_create_time
;
131 auxdata
.vol_serial_number
= tcon
->vol_serial_number
;
133 cifs_dbg(FYI
, "%s: (0x%p)\n", __func__
, tcon
->fscache
);
134 fscache_relinquish_cookie(tcon
->fscache
, &auxdata
, false);
135 tcon
->fscache
= NULL
;
138 static void cifs_fscache_acquire_inode_cookie(struct cifsInodeInfo
*cifsi
,
139 struct cifs_tcon
*tcon
)
141 struct cifs_fscache_inode_auxdata auxdata
;
143 memset(&auxdata
, 0, sizeof(auxdata
));
144 auxdata
.eof
= cifsi
->server_eof
;
145 auxdata
.last_write_time_sec
= cifsi
->vfs_inode
.i_mtime
.tv_sec
;
146 auxdata
.last_change_time_sec
= cifsi
->vfs_inode
.i_ctime
.tv_sec
;
147 auxdata
.last_write_time_nsec
= cifsi
->vfs_inode
.i_mtime
.tv_nsec
;
148 auxdata
.last_change_time_nsec
= cifsi
->vfs_inode
.i_ctime
.tv_nsec
;
151 fscache_acquire_cookie(tcon
->fscache
,
152 &cifs_fscache_inode_object_def
,
153 &cifsi
->uniqueid
, sizeof(cifsi
->uniqueid
),
154 &auxdata
, sizeof(auxdata
),
155 cifsi
, cifsi
->vfs_inode
.i_size
, true);
158 static void cifs_fscache_enable_inode_cookie(struct inode
*inode
)
160 struct cifsInodeInfo
*cifsi
= CIFS_I(inode
);
161 struct cifs_sb_info
*cifs_sb
= CIFS_SB(inode
->i_sb
);
162 struct cifs_tcon
*tcon
= cifs_sb_master_tcon(cifs_sb
);
167 if (!(cifs_sb
->mnt_cifs_flags
& CIFS_MOUNT_FSCACHE
))
170 cifs_fscache_acquire_inode_cookie(cifsi
, tcon
);
172 cifs_dbg(FYI
, "%s: got FH cookie (0x%p/0x%p)\n",
173 __func__
, tcon
->fscache
, cifsi
->fscache
);
176 void cifs_fscache_release_inode_cookie(struct inode
*inode
)
178 struct cifs_fscache_inode_auxdata auxdata
;
179 struct cifsInodeInfo
*cifsi
= CIFS_I(inode
);
181 if (cifsi
->fscache
) {
182 memset(&auxdata
, 0, sizeof(auxdata
));
183 auxdata
.eof
= cifsi
->server_eof
;
184 auxdata
.last_write_time_sec
= cifsi
->vfs_inode
.i_mtime
.tv_sec
;
185 auxdata
.last_change_time_sec
= cifsi
->vfs_inode
.i_ctime
.tv_sec
;
186 auxdata
.last_write_time_nsec
= cifsi
->vfs_inode
.i_mtime
.tv_nsec
;
187 auxdata
.last_change_time_nsec
= cifsi
->vfs_inode
.i_ctime
.tv_nsec
;
189 cifs_dbg(FYI
, "%s: (0x%p)\n", __func__
, cifsi
->fscache
);
190 fscache_relinquish_cookie(cifsi
->fscache
, &auxdata
, false);
191 cifsi
->fscache
= NULL
;
195 static void cifs_fscache_disable_inode_cookie(struct inode
*inode
)
197 struct cifsInodeInfo
*cifsi
= CIFS_I(inode
);
199 if (cifsi
->fscache
) {
200 cifs_dbg(FYI
, "%s: (0x%p)\n", __func__
, cifsi
->fscache
);
201 fscache_uncache_all_inode_pages(cifsi
->fscache
, inode
);
202 fscache_relinquish_cookie(cifsi
->fscache
, NULL
, true);
203 cifsi
->fscache
= NULL
;
207 void cifs_fscache_set_inode_cookie(struct inode
*inode
, struct file
*filp
)
209 if ((filp
->f_flags
& O_ACCMODE
) != O_RDONLY
)
210 cifs_fscache_disable_inode_cookie(inode
);
212 cifs_fscache_enable_inode_cookie(inode
);
215 void cifs_fscache_reset_inode_cookie(struct inode
*inode
)
217 struct cifsInodeInfo
*cifsi
= CIFS_I(inode
);
218 struct cifs_sb_info
*cifs_sb
= CIFS_SB(inode
->i_sb
);
219 struct cifs_tcon
*tcon
= cifs_sb_master_tcon(cifs_sb
);
220 struct fscache_cookie
*old
= cifsi
->fscache
;
222 if (cifsi
->fscache
) {
223 /* retire the current fscache cache and get a new one */
224 fscache_relinquish_cookie(cifsi
->fscache
, NULL
, true);
226 cifs_fscache_acquire_inode_cookie(cifsi
, tcon
);
227 cifs_dbg(FYI
, "%s: new cookie 0x%p oldcookie 0x%p\n",
228 __func__
, cifsi
->fscache
, old
);
232 int cifs_fscache_release_page(struct page
*page
, gfp_t gfp
)
234 if (PageFsCache(page
)) {
235 struct inode
*inode
= page
->mapping
->host
;
236 struct cifsInodeInfo
*cifsi
= CIFS_I(inode
);
238 cifs_dbg(FYI
, "%s: (0x%p/0x%p)\n",
239 __func__
, page
, cifsi
->fscache
);
240 if (!fscache_maybe_release_page(cifsi
->fscache
, page
, gfp
))
247 static void cifs_readpage_from_fscache_complete(struct page
*page
, void *ctx
,
250 cifs_dbg(FYI
, "%s: (0x%p/%d)\n", __func__
, page
, error
);
252 SetPageUptodate(page
);
257 * Retrieve a page from FS-Cache
259 int __cifs_readpage_from_fscache(struct inode
*inode
, struct page
*page
)
263 cifs_dbg(FYI
, "%s: (fsc:%p, p:%p, i:0x%p\n",
264 __func__
, CIFS_I(inode
)->fscache
, page
, inode
);
265 ret
= fscache_read_or_alloc_page(CIFS_I(inode
)->fscache
, page
,
266 cifs_readpage_from_fscache_complete
,
271 case 0: /* page found in fscache, read submitted */
272 cifs_dbg(FYI
, "%s: submitted\n", __func__
);
274 case -ENOBUFS
: /* page won't be cached */
275 case -ENODATA
: /* page not in cache */
276 cifs_dbg(FYI
, "%s: %d\n", __func__
, ret
);
280 cifs_dbg(VFS
, "unknown error ret = %d\n", ret
);
286 * Retrieve a set of pages from FS-Cache
288 int __cifs_readpages_from_fscache(struct inode
*inode
,
289 struct address_space
*mapping
,
290 struct list_head
*pages
,
295 cifs_dbg(FYI
, "%s: (0x%p/%u/0x%p)\n",
296 __func__
, CIFS_I(inode
)->fscache
, *nr_pages
, inode
);
297 ret
= fscache_read_or_alloc_pages(CIFS_I(inode
)->fscache
, mapping
,
299 cifs_readpage_from_fscache_complete
,
301 mapping_gfp_mask(mapping
));
303 case 0: /* read submitted to the cache for all pages */
304 cifs_dbg(FYI
, "%s: submitted\n", __func__
);
307 case -ENOBUFS
: /* some pages are not cached and can't be */
308 case -ENODATA
: /* some pages are not cached */
309 cifs_dbg(FYI
, "%s: no page\n", __func__
);
313 cifs_dbg(FYI
, "unknown error ret = %d\n", ret
);
319 void __cifs_readpage_to_fscache(struct inode
*inode
, struct page
*page
)
321 struct cifsInodeInfo
*cifsi
= CIFS_I(inode
);
324 cifs_dbg(FYI
, "%s: (fsc: %p, p: %p, i: %p)\n",
325 __func__
, cifsi
->fscache
, page
, inode
);
326 ret
= fscache_write_page(cifsi
->fscache
, page
,
327 cifsi
->vfs_inode
.i_size
, GFP_KERNEL
);
329 fscache_uncache_page(cifsi
->fscache
, page
);
332 void __cifs_fscache_readpages_cancel(struct inode
*inode
, struct list_head
*pages
)
334 cifs_dbg(FYI
, "%s: (fsc: %p, i: %p)\n",
335 __func__
, CIFS_I(inode
)->fscache
, inode
);
336 fscache_readpages_cancel(CIFS_I(inode
)->fscache
, pages
);
339 void __cifs_fscache_invalidate_page(struct page
*page
, struct inode
*inode
)
341 struct cifsInodeInfo
*cifsi
= CIFS_I(inode
);
342 struct fscache_cookie
*cookie
= cifsi
->fscache
;
344 cifs_dbg(FYI
, "%s: (0x%p/0x%p)\n", __func__
, page
, cookie
);
345 fscache_wait_on_page_write(cookie
, page
);
346 fscache_uncache_page(cookie
, page
);