Blame view

fs/cifs/fscache.c 9.85 KB
488f1d2d6   Suresh Jayaraman   cifs: define serv...
1
2
3
4
  /*
   *   fs/cifs/fscache.c - CIFS filesystem cache interface
   *
   *   Copyright (c) 2010 Novell, Inc.
b81209de2   Suresh Jayaraman   cifs: enable fsca...
5
   *   Author(s): Suresh Jayaraman <sjayaraman@suse.de>
488f1d2d6   Suresh Jayaraman   cifs: define serv...
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
   *
   *   This library is free software; you can redistribute it and/or modify
   *   it under the terms of the GNU Lesser General Public License as published
   *   by the Free Software Foundation; either version 2.1 of the License, or
   *   (at your option) any later version.
   *
   *   This library is distributed in the hope that it will be useful,
   *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
   *   the GNU Lesser General Public License for more details.
   *
   *   You should have received a copy of the GNU Lesser General Public License
   *   along with this library; if not, write to the Free Software
   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
   */
  #include "fscache.h"
  #include "cifsglob.h"
  #include "cifs_debug.h"
9451a9a52   Suresh Jayaraman   cifs: define inod...
24
  #include "cifs_fs_sb.h"
488f1d2d6   Suresh Jayaraman   cifs: define serv...
25

402cb8dda   David Howells   fscache: Attach t...
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
  /*
   * Key layout of CIFS server cache index object
   */
  struct cifs_server_key {
  	struct {
  		uint16_t	family;		/* address family */
  		__be16		port;		/* IP port */
  	} hdr;
  	union {
  		struct in_addr	ipv4_addr;
  		struct in6_addr	ipv6_addr;
  	};
  } __packed;
  
  /*
   * Get a cookie for a server object keyed by {IPaddress,port,family} tuple
   */
488f1d2d6   Suresh Jayaraman   cifs: define serv...
43
44
  void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server)
  {
402cb8dda   David Howells   fscache: Attach t...
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
  	const struct sockaddr *sa = (struct sockaddr *) &server->dstaddr;
  	const struct sockaddr_in *addr = (struct sockaddr_in *) sa;
  	const struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) sa;
  	struct cifs_server_key key;
  	uint16_t key_len = sizeof(key.hdr);
  
  	memset(&key, 0, sizeof(key));
  
  	/*
  	 * Should not be a problem as sin_family/sin6_family overlays
  	 * sa_family field
  	 */
  	key.hdr.family = sa->sa_family;
  	switch (sa->sa_family) {
  	case AF_INET:
  		key.hdr.port = addr->sin_port;
  		key.ipv4_addr = addr->sin_addr;
  		key_len += sizeof(key.ipv4_addr);
  		break;
  
  	case AF_INET6:
  		key.hdr.port = addr6->sin6_port;
  		key.ipv6_addr = addr6->sin6_addr;
  		key_len += sizeof(key.ipv6_addr);
  		break;
  
  	default:
  		cifs_dbg(VFS, "Unknown network family '%d'
  ", sa->sa_family);
  		server->fscache = NULL;
  		return;
  	}
488f1d2d6   Suresh Jayaraman   cifs: define serv...
77
78
  	server->fscache =
  		fscache_acquire_cookie(cifs_fscache_netfs.primary_index,
402cb8dda   David Howells   fscache: Attach t...
79
80
81
  				       &cifs_fscache_server_index_def,
  				       &key, key_len,
  				       NULL, 0,
ee1235a9a   David Howells   fscache: Pass obj...
82
  				       server, 0, true);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
83
84
85
  	cifs_dbg(FYI, "%s: (0x%p/0x%p)
  ",
  		 __func__, server, server->fscache);
488f1d2d6   Suresh Jayaraman   cifs: define serv...
86
87
88
89
  }
  
  void cifs_fscache_release_client_cookie(struct TCP_Server_Info *server)
  {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
90
91
92
  	cifs_dbg(FYI, "%s: (0x%p/0x%p)
  ",
  		 __func__, server, server->fscache);
402cb8dda   David Howells   fscache: Attach t...
93
  	fscache_relinquish_cookie(server->fscache, NULL, false);
488f1d2d6   Suresh Jayaraman   cifs: define serv...
94
95
  	server->fscache = NULL;
  }
96daf2b09   Steve French   [CIFS] Rename thr...
96
  void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
d03382ce9   Suresh Jayaraman   cifs: define supe...
97
98
  {
  	struct TCP_Server_Info *server = tcon->ses->server;
402cb8dda   David Howells   fscache: Attach t...
99
  	char *sharename;
586598541   Steve French   smb3: extend fsca...
100
  	struct cifs_fscache_super_auxdata auxdata;
402cb8dda   David Howells   fscache: Attach t...
101
102
103
104
105
106
107
108
  
  	sharename = extract_sharename(tcon->treeName);
  	if (IS_ERR(sharename)) {
  		cifs_dbg(FYI, "%s: couldn't extract sharename
  ", __func__);
  		tcon->fscache = NULL;
  		return;
  	}
d03382ce9   Suresh Jayaraman   cifs: define supe...
109

586598541   Steve French   smb3: extend fsca...
110
111
112
113
  	memset(&auxdata, 0, sizeof(auxdata));
  	auxdata.resource_id = tcon->resource_id;
  	auxdata.vol_create_time = tcon->vol_create_time;
  	auxdata.vol_serial_number = tcon->vol_serial_number;
d03382ce9   Suresh Jayaraman   cifs: define supe...
114
115
  	tcon->fscache =
  		fscache_acquire_cookie(server->fscache,
402cb8dda   David Howells   fscache: Attach t...
116
117
  				       &cifs_fscache_super_index_def,
  				       sharename, strlen(sharename),
586598541   Steve French   smb3: extend fsca...
118
  				       &auxdata, sizeof(auxdata),
ee1235a9a   David Howells   fscache: Pass obj...
119
  				       tcon, 0, true);
402cb8dda   David Howells   fscache: Attach t...
120
  	kfree(sharename);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
121
122
123
  	cifs_dbg(FYI, "%s: (0x%p/0x%p)
  ",
  		 __func__, server->fscache, tcon->fscache);
d03382ce9   Suresh Jayaraman   cifs: define supe...
124
  }
96daf2b09   Steve French   [CIFS] Rename thr...
125
  void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)
d03382ce9   Suresh Jayaraman   cifs: define supe...
126
  {
586598541   Steve French   smb3: extend fsca...
127
128
129
130
131
132
  	struct cifs_fscache_super_auxdata auxdata;
  
  	memset(&auxdata, 0, sizeof(auxdata));
  	auxdata.resource_id = tcon->resource_id;
  	auxdata.vol_create_time = tcon->vol_create_time;
  	auxdata.vol_serial_number = tcon->vol_serial_number;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
133
134
  	cifs_dbg(FYI, "%s: (0x%p)
  ", __func__, tcon->fscache);
586598541   Steve French   smb3: extend fsca...
135
  	fscache_relinquish_cookie(tcon->fscache, &auxdata, false);
d03382ce9   Suresh Jayaraman   cifs: define supe...
136
137
  	tcon->fscache = NULL;
  }
9451a9a52   Suresh Jayaraman   cifs: define inod...
138

402cb8dda   David Howells   fscache: Attach t...
139
140
141
142
143
144
145
  static void cifs_fscache_acquire_inode_cookie(struct cifsInodeInfo *cifsi,
  					      struct cifs_tcon *tcon)
  {
  	struct cifs_fscache_inode_auxdata auxdata;
  
  	memset(&auxdata, 0, sizeof(auxdata));
  	auxdata.eof = cifsi->server_eof;
cbedeadf9   Arnd Bergmann   cifs: use 64-bit ...
146
147
148
149
  	auxdata.last_write_time_sec = cifsi->vfs_inode.i_mtime.tv_sec;
  	auxdata.last_change_time_sec = cifsi->vfs_inode.i_ctime.tv_sec;
  	auxdata.last_write_time_nsec = cifsi->vfs_inode.i_mtime.tv_nsec;
  	auxdata.last_change_time_nsec = cifsi->vfs_inode.i_ctime.tv_nsec;
402cb8dda   David Howells   fscache: Attach t...
150
151
152
153
154
155
  
  	cifsi->fscache =
  		fscache_acquire_cookie(tcon->fscache,
  				       &cifs_fscache_inode_object_def,
  				       &cifsi->uniqueid, sizeof(cifsi->uniqueid),
  				       &auxdata, sizeof(auxdata),
ee1235a9a   David Howells   fscache: Pass obj...
156
  				       cifsi, cifsi->vfs_inode.i_size, true);
402cb8dda   David Howells   fscache: Attach t...
157
  }
9451a9a52   Suresh Jayaraman   cifs: define inod...
158
159
160
161
  static void cifs_fscache_enable_inode_cookie(struct inode *inode)
  {
  	struct cifsInodeInfo *cifsi = CIFS_I(inode);
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
96daf2b09   Steve French   [CIFS] Rename thr...
162
  	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
9451a9a52   Suresh Jayaraman   cifs: define inod...
163
164
165
  
  	if (cifsi->fscache)
  		return;
402cb8dda   David Howells   fscache: Attach t...
166
167
168
169
170
171
172
173
  	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE))
  		return;
  
  	cifs_fscache_acquire_inode_cookie(cifsi, tcon);
  
  	cifs_dbg(FYI, "%s: got FH cookie (0x%p/0x%p)
  ",
  		 __func__, tcon->fscache, cifsi->fscache);
9451a9a52   Suresh Jayaraman   cifs: define inod...
174
175
176
177
  }
  
  void cifs_fscache_release_inode_cookie(struct inode *inode)
  {
402cb8dda   David Howells   fscache: Attach t...
178
  	struct cifs_fscache_inode_auxdata auxdata;
9451a9a52   Suresh Jayaraman   cifs: define inod...
179
180
181
  	struct cifsInodeInfo *cifsi = CIFS_I(inode);
  
  	if (cifsi->fscache) {
402cb8dda   David Howells   fscache: Attach t...
182
183
  		memset(&auxdata, 0, sizeof(auxdata));
  		auxdata.eof = cifsi->server_eof;
cbedeadf9   Arnd Bergmann   cifs: use 64-bit ...
184
185
186
187
  		auxdata.last_write_time_sec = cifsi->vfs_inode.i_mtime.tv_sec;
  		auxdata.last_change_time_sec = cifsi->vfs_inode.i_ctime.tv_sec;
  		auxdata.last_write_time_nsec = cifsi->vfs_inode.i_mtime.tv_nsec;
  		auxdata.last_change_time_nsec = cifsi->vfs_inode.i_ctime.tv_nsec;
402cb8dda   David Howells   fscache: Attach t...
188

f96637be0   Joe Perches   [CIFS] cifs: Rena...
189
190
  		cifs_dbg(FYI, "%s: (0x%p)
  ", __func__, cifsi->fscache);
402cb8dda   David Howells   fscache: Attach t...
191
  		fscache_relinquish_cookie(cifsi->fscache, &auxdata, false);
9451a9a52   Suresh Jayaraman   cifs: define inod...
192
193
194
195
196
197
198
199
200
  		cifsi->fscache = NULL;
  	}
  }
  
  static void cifs_fscache_disable_inode_cookie(struct inode *inode)
  {
  	struct cifsInodeInfo *cifsi = CIFS_I(inode);
  
  	if (cifsi->fscache) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
201
202
  		cifs_dbg(FYI, "%s: (0x%p)
  ", __func__, cifsi->fscache);
c902ce1bf   David Howells   FS-Cache: Add a h...
203
  		fscache_uncache_all_inode_pages(cifsi->fscache, inode);
402cb8dda   David Howells   fscache: Attach t...
204
  		fscache_relinquish_cookie(cifsi->fscache, NULL, true);
9451a9a52   Suresh Jayaraman   cifs: define inod...
205
206
207
208
209
210
211
212
  		cifsi->fscache = NULL;
  	}
  }
  
  void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
  {
  	if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
  		cifs_fscache_disable_inode_cookie(inode);
b81209de2   Suresh Jayaraman   cifs: enable fsca...
213
  	else
9451a9a52   Suresh Jayaraman   cifs: define inod...
214
  		cifs_fscache_enable_inode_cookie(inode);
9451a9a52   Suresh Jayaraman   cifs: define inod...
215
216
217
218
219
220
  }
  
  void cifs_fscache_reset_inode_cookie(struct inode *inode)
  {
  	struct cifsInodeInfo *cifsi = CIFS_I(inode);
  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
402cb8dda   David Howells   fscache: Attach t...
221
  	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
9451a9a52   Suresh Jayaraman   cifs: define inod...
222
223
224
225
  	struct fscache_cookie *old = cifsi->fscache;
  
  	if (cifsi->fscache) {
  		/* retire the current fscache cache and get a new one */
402cb8dda   David Howells   fscache: Attach t...
226
  		fscache_relinquish_cookie(cifsi->fscache, NULL, true);
9451a9a52   Suresh Jayaraman   cifs: define inod...
227

402cb8dda   David Howells   fscache: Attach t...
228
  		cifs_fscache_acquire_inode_cookie(cifsi, tcon);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
229
230
231
  		cifs_dbg(FYI, "%s: new cookie 0x%p oldcookie 0x%p
  ",
  			 __func__, cifsi->fscache, old);
9451a9a52   Suresh Jayaraman   cifs: define inod...
232
233
  	}
  }
85f2d6b44   Suresh Jayaraman   cifs: FS-Cache pa...
234
235
236
237
238
239
  
  int cifs_fscache_release_page(struct page *page, gfp_t gfp)
  {
  	if (PageFsCache(page)) {
  		struct inode *inode = page->mapping->host;
  		struct cifsInodeInfo *cifsi = CIFS_I(inode);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
240
241
242
  		cifs_dbg(FYI, "%s: (0x%p/0x%p)
  ",
  			 __func__, page, cifsi->fscache);
85f2d6b44   Suresh Jayaraman   cifs: FS-Cache pa...
243
244
245
246
247
248
  		if (!fscache_maybe_release_page(cifsi->fscache, page, gfp))
  			return 0;
  	}
  
  	return 1;
  }
56698236e   Suresh Jayaraman   cifs: read pages ...
249
250
251
  static void cifs_readpage_from_fscache_complete(struct page *page, void *ctx,
  						int error)
  {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
252
253
  	cifs_dbg(FYI, "%s: (0x%p/%d)
  ", __func__, page, error);
56698236e   Suresh Jayaraman   cifs: read pages ...
254
255
256
257
258
259
260
261
262
263
264
  	if (!error)
  		SetPageUptodate(page);
  	unlock_page(page);
  }
  
  /*
   * Retrieve a page from FS-Cache
   */
  int __cifs_readpage_from_fscache(struct inode *inode, struct page *page)
  {
  	int ret;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
265
266
267
  	cifs_dbg(FYI, "%s: (fsc:%p, p:%p, i:0x%p
  ",
  		 __func__, CIFS_I(inode)->fscache, page, inode);
56698236e   Suresh Jayaraman   cifs: read pages ...
268
269
270
271
272
273
274
  	ret = fscache_read_or_alloc_page(CIFS_I(inode)->fscache, page,
  					 cifs_readpage_from_fscache_complete,
  					 NULL,
  					 GFP_KERNEL);
  	switch (ret) {
  
  	case 0: /* page found in fscache, read submitted */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
275
276
  		cifs_dbg(FYI, "%s: submitted
  ", __func__);
56698236e   Suresh Jayaraman   cifs: read pages ...
277
278
279
  		return ret;
  	case -ENOBUFS:	/* page won't be cached */
  	case -ENODATA:	/* page not in cache */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
280
281
  		cifs_dbg(FYI, "%s: %d
  ", __func__, ret);
56698236e   Suresh Jayaraman   cifs: read pages ...
282
283
284
  		return 1;
  
  	default:
f96637be0   Joe Perches   [CIFS] cifs: Rena...
285
286
  		cifs_dbg(VFS, "unknown error ret = %d
  ", ret);
56698236e   Suresh Jayaraman   cifs: read pages ...
287
288
289
290
291
292
293
294
295
296
297
298
299
  	}
  	return ret;
  }
  
  /*
   * Retrieve a set of pages from FS-Cache
   */
  int __cifs_readpages_from_fscache(struct inode *inode,
  				struct address_space *mapping,
  				struct list_head *pages,
  				unsigned *nr_pages)
  {
  	int ret;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
300
301
302
  	cifs_dbg(FYI, "%s: (0x%p/%u/0x%p)
  ",
  		 __func__, CIFS_I(inode)->fscache, *nr_pages, inode);
56698236e   Suresh Jayaraman   cifs: read pages ...
303
304
305
306
307
308
309
  	ret = fscache_read_or_alloc_pages(CIFS_I(inode)->fscache, mapping,
  					  pages, nr_pages,
  					  cifs_readpage_from_fscache_complete,
  					  NULL,
  					  mapping_gfp_mask(mapping));
  	switch (ret) {
  	case 0:	/* read submitted to the cache for all pages */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
310
311
  		cifs_dbg(FYI, "%s: submitted
  ", __func__);
56698236e   Suresh Jayaraman   cifs: read pages ...
312
313
314
315
  		return ret;
  
  	case -ENOBUFS:	/* some pages are not cached and can't be */
  	case -ENODATA:	/* some pages are not cached */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
316
317
  		cifs_dbg(FYI, "%s: no page
  ", __func__);
56698236e   Suresh Jayaraman   cifs: read pages ...
318
319
320
  		return 1;
  
  	default:
f96637be0   Joe Perches   [CIFS] cifs: Rena...
321
322
  		cifs_dbg(FYI, "unknown error ret = %d
  ", ret);
56698236e   Suresh Jayaraman   cifs: read pages ...
323
324
325
326
  	}
  
  	return ret;
  }
9dc06558c   Suresh Jayaraman   cifs: store pages...
327
328
  void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
  {
ee1235a9a   David Howells   fscache: Pass obj...
329
  	struct cifsInodeInfo *cifsi = CIFS_I(inode);
9dc06558c   Suresh Jayaraman   cifs: store pages...
330
  	int ret;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
331
332
  	cifs_dbg(FYI, "%s: (fsc: %p, p: %p, i: %p)
  ",
ee1235a9a   David Howells   fscache: Pass obj...
333
334
335
  		 __func__, cifsi->fscache, page, inode);
  	ret = fscache_write_page(cifsi->fscache, page,
  				 cifsi->vfs_inode.i_size, GFP_KERNEL);
9dc06558c   Suresh Jayaraman   cifs: store pages...
336
  	if (ret != 0)
ee1235a9a   David Howells   fscache: Pass obj...
337
  		fscache_uncache_page(cifsi->fscache, page);
9dc06558c   Suresh Jayaraman   cifs: store pages...
338
  }
54afa9905   David Howells   CIFS: FS-Cache: U...
339
340
341
342
343
344
345
  void __cifs_fscache_readpages_cancel(struct inode *inode, struct list_head *pages)
  {
  	cifs_dbg(FYI, "%s: (fsc: %p, i: %p)
  ",
  		 __func__, CIFS_I(inode)->fscache, inode);
  	fscache_readpages_cancel(CIFS_I(inode)->fscache, pages);
  }
85f2d6b44   Suresh Jayaraman   cifs: FS-Cache pa...
346
347
348
349
  void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode)
  {
  	struct cifsInodeInfo *cifsi = CIFS_I(inode);
  	struct fscache_cookie *cookie = cifsi->fscache;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
350
351
  	cifs_dbg(FYI, "%s: (0x%p/0x%p)
  ", __func__, page, cookie);
85f2d6b44   Suresh Jayaraman   cifs: FS-Cache pa...
352
353
354
  	fscache_wait_on_page_write(cookie, page);
  	fscache_uncache_page(cookie, page);
  }