aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cache.c83
-rw-r--r--fs/cifs/cifsfs.c7
-rw-r--r--fs/cifs/cifsglob.h3
-rw-r--r--fs/cifs/file.c6
-rw-r--r--fs/cifs/fscache.c68
-rw-r--r--fs/cifs/fscache.h12
-rw-r--r--fs/cifs/inode.c4
7 files changed, 183 insertions, 0 deletions
diff --git a/fs/cifs/cache.c b/fs/cifs/cache.c
index 15532abdac14..b2649cfd3a04 100644
--- a/fs/cifs/cache.c
+++ b/fs/cifs/cache.c
@@ -215,3 +215,86 @@ const struct fscache_cookie_def cifs_fscache_super_index_def = {
215 .check_aux = cifs_fscache_super_check_aux, 215 .check_aux = cifs_fscache_super_check_aux,
216}; 216};
217 217
218/*
219 * Auxiliary data attached to CIFS inode within the cache
220 */
221struct cifs_fscache_inode_auxdata {
222 struct timespec last_write_time;
223 struct timespec last_change_time;
224 u64 eof;
225};
226
227static uint16_t cifs_fscache_inode_get_key(const void *cookie_netfs_data,
228 void *buffer, uint16_t maxbuf)
229{
230 const struct cifsInodeInfo *cifsi = cookie_netfs_data;
231 uint16_t keylen;
232
233 /* use the UniqueId as the key */
234 keylen = sizeof(cifsi->uniqueid);
235 if (keylen > maxbuf)
236 keylen = 0;
237 else
238 memcpy(buffer, &cifsi->uniqueid, keylen);
239
240 return keylen;
241}
242
243static void
244cifs_fscache_inode_get_attr(const void *cookie_netfs_data, uint64_t *size)
245{
246 const struct cifsInodeInfo *cifsi = cookie_netfs_data;
247
248 *size = cifsi->vfs_inode.i_size;
249}
250
251static uint16_t
252cifs_fscache_inode_get_aux(const void *cookie_netfs_data, void *buffer,
253 uint16_t maxbuf)
254{
255 struct cifs_fscache_inode_auxdata auxdata;
256 const struct cifsInodeInfo *cifsi = cookie_netfs_data;
257
258 memset(&auxdata, 0, sizeof(auxdata));
259 auxdata.eof = cifsi->server_eof;
260 auxdata.last_write_time = cifsi->vfs_inode.i_mtime;
261 auxdata.last_change_time = cifsi->vfs_inode.i_ctime;
262
263 if (maxbuf > sizeof(auxdata))
264 maxbuf = sizeof(auxdata);
265
266 memcpy(buffer, &auxdata, maxbuf);
267
268 return maxbuf;
269}
270
271static enum
272fscache_checkaux cifs_fscache_inode_check_aux(void *cookie_netfs_data,
273 const void *data,
274 uint16_t datalen)
275{
276 struct cifs_fscache_inode_auxdata auxdata;
277 struct cifsInodeInfo *cifsi = cookie_netfs_data;
278
279 if (datalen != sizeof(auxdata))
280 return FSCACHE_CHECKAUX_OBSOLETE;
281
282 memset(&auxdata, 0, sizeof(auxdata));
283 auxdata.eof = cifsi->server_eof;
284 auxdata.last_write_time = cifsi->vfs_inode.i_mtime;
285 auxdata.last_change_time = cifsi->vfs_inode.i_ctime;
286
287 if (memcmp(data, &auxdata, datalen) != 0)
288 return FSCACHE_CHECKAUX_OBSOLETE;
289
290 return FSCACHE_CHECKAUX_OKAY;
291}
292
293const struct fscache_cookie_def cifs_fscache_inode_object_def = {
294 .name = "CIFS.uniqueid",
295 .type = FSCACHE_COOKIE_TYPE_DATAFILE,
296 .get_key = cifs_fscache_inode_get_key,
297 .get_attr = cifs_fscache_inode_get_attr,
298 .get_aux = cifs_fscache_inode_get_aux,
299 .check_aux = cifs_fscache_inode_check_aux,
300};
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 24d7f4ab3b65..8a2cf129e535 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -330,6 +330,12 @@ cifs_destroy_inode(struct inode *inode)
330} 330}
331 331
332static void 332static void
333cifs_clear_inode(struct inode *inode)
334{
335 cifs_fscache_release_inode_cookie(inode);
336}
337
338static void
333cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) 339cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
334{ 340{
335 seq_printf(s, ",addr="); 341 seq_printf(s, ",addr=");
@@ -490,6 +496,7 @@ static const struct super_operations cifs_super_ops = {
490 .alloc_inode = cifs_alloc_inode, 496 .alloc_inode = cifs_alloc_inode,
491 .destroy_inode = cifs_destroy_inode, 497 .destroy_inode = cifs_destroy_inode,
492 .drop_inode = cifs_drop_inode, 498 .drop_inode = cifs_drop_inode,
499 .clear_inode = cifs_clear_inode,
493/* .delete_inode = cifs_delete_inode, */ /* Do not need above 500/* .delete_inode = cifs_delete_inode, */ /* Do not need above
494 function unless later we add lazy close of inodes or unless the 501 function unless later we add lazy close of inodes or unless the
495 kernel forgets to call us with the same number of releases (closes) 502 kernel forgets to call us with the same number of releases (closes)
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index a3e403e7e163..9b7cf9aa3a00 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -390,6 +390,9 @@ struct cifsInodeInfo {
390 bool invalid_mapping:1; /* pagecache is invalid */ 390 bool invalid_mapping:1; /* pagecache is invalid */
391 u64 server_eof; /* current file size on server */ 391 u64 server_eof; /* current file size on server */
392 u64 uniqueid; /* server inode number */ 392 u64 uniqueid; /* server inode number */
393#ifdef CONFIG_CIFS_FSCACHE
394 struct fscache_cookie *fscache;
395#endif
393 struct inode vfs_inode; 396 struct inode vfs_inode;
394}; 397};
395 398
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index b5fb2a0607b0..d302d941f9ac 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -40,6 +40,7 @@
40#include "cifs_unicode.h" 40#include "cifs_unicode.h"
41#include "cifs_debug.h" 41#include "cifs_debug.h"
42#include "cifs_fs_sb.h" 42#include "cifs_fs_sb.h"
43#include "fscache.h"
43 44
44static inline int cifs_convert_flags(unsigned int flags) 45static inline int cifs_convert_flags(unsigned int flags)
45{ 46{
@@ -282,6 +283,9 @@ int cifs_open(struct inode *inode, struct file *file)
282 CIFSSMBClose(xid, tcon, netfid); 283 CIFSSMBClose(xid, tcon, netfid);
283 rc = -ENOMEM; 284 rc = -ENOMEM;
284 } 285 }
286
287 cifs_fscache_set_inode_cookie(inode, file);
288
285 goto out; 289 goto out;
286 } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { 290 } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
287 if (tcon->ses->serverNOS) 291 if (tcon->ses->serverNOS)
@@ -373,6 +377,8 @@ int cifs_open(struct inode *inode, struct file *file)
373 goto out; 377 goto out;
374 } 378 }
375 379
380 cifs_fscache_set_inode_cookie(inode, file);
381
376 if (oplock & CIFS_CREATE_ACTION) { 382 if (oplock & CIFS_CREATE_ACTION) {
377 /* time to set mode which we can not set earlier due to 383 /* time to set mode which we can not set earlier due to
378 problems creating new read-only files */ 384 problems creating new read-only files */
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c
index eba9beb94a4c..6c8d96758ddb 100644
--- a/fs/cifs/fscache.c
+++ b/fs/cifs/fscache.c
@@ -21,6 +21,7 @@
21#include "fscache.h" 21#include "fscache.h"
22#include "cifsglob.h" 22#include "cifsglob.h"
23#include "cifs_debug.h" 23#include "cifs_debug.h"
24#include "cifs_fs_sb.h"
24 25
25void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) 26void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server)
26{ 27{
@@ -56,3 +57,70 @@ void cifs_fscache_release_super_cookie(struct cifsTconInfo *tcon)
56 fscache_relinquish_cookie(tcon->fscache, 0); 57 fscache_relinquish_cookie(tcon->fscache, 0);
57 tcon->fscache = NULL; 58 tcon->fscache = NULL;
58} 59}
60
61static 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
66 if (cifsi->fscache)
67 return;
68
69 cifsi->fscache = fscache_acquire_cookie(cifs_sb->tcon->fscache,
70 &cifs_fscache_inode_object_def,
71 cifsi);
72 cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)",
73 cifs_sb->tcon->fscache, cifsi->fscache);
74}
75
76void cifs_fscache_release_inode_cookie(struct inode *inode)
77{
78 struct cifsInodeInfo *cifsi = CIFS_I(inode);
79
80 if (cifsi->fscache) {
81 cFYI(1, "CIFS releasing inode cookie (0x%p)",
82 cifsi->fscache);
83 fscache_relinquish_cookie(cifsi->fscache, 0);
84 cifsi->fscache = NULL;
85 }
86}
87
88static void cifs_fscache_disable_inode_cookie(struct inode *inode)
89{
90 struct cifsInodeInfo *cifsi = CIFS_I(inode);
91
92 if (cifsi->fscache) {
93 cFYI(1, "CIFS disabling inode cookie (0x%p)",
94 cifsi->fscache);
95 fscache_relinquish_cookie(cifsi->fscache, 1);
96 cifsi->fscache = NULL;
97 }
98}
99
100void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
101{
102 if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
103 cifs_fscache_disable_inode_cookie(inode);
104 else {
105 cifs_fscache_enable_inode_cookie(inode);
106 cFYI(1, "CIFS: fscache inode cookie set");
107 }
108}
109
110void cifs_fscache_reset_inode_cookie(struct inode *inode)
111{
112 struct cifsInodeInfo *cifsi = CIFS_I(inode);
113 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
114 struct fscache_cookie *old = cifsi->fscache;
115
116 if (cifsi->fscache) {
117 /* retire the current fscache cache and get a new one */
118 fscache_relinquish_cookie(cifsi->fscache, 1);
119
120 cifsi->fscache = fscache_acquire_cookie(cifs_sb->tcon->fscache,
121 &cifs_fscache_inode_object_def,
122 cifsi);
123 cFYI(1, "CIFS: new cookie 0x%p oldcookie 0x%p",
124 cifsi->fscache, old);
125 }
126}
diff --git a/fs/cifs/fscache.h b/fs/cifs/fscache.h
index d2ba628b72cd..1008f4050835 100644
--- a/fs/cifs/fscache.h
+++ b/fs/cifs/fscache.h
@@ -30,6 +30,8 @@
30extern struct fscache_netfs cifs_fscache_netfs; 30extern struct fscache_netfs cifs_fscache_netfs;
31extern const struct fscache_cookie_def cifs_fscache_server_index_def; 31extern const struct fscache_cookie_def cifs_fscache_server_index_def;
32extern const struct fscache_cookie_def cifs_fscache_super_index_def; 32extern const struct fscache_cookie_def cifs_fscache_super_index_def;
33extern const struct fscache_cookie_def cifs_fscache_inode_object_def;
34
33 35
34extern int cifs_fscache_register(void); 36extern int cifs_fscache_register(void);
35extern void cifs_fscache_unregister(void); 37extern void cifs_fscache_unregister(void);
@@ -42,6 +44,10 @@ extern void cifs_fscache_release_client_cookie(struct TCP_Server_Info *);
42extern void cifs_fscache_get_super_cookie(struct cifsTconInfo *); 44extern void cifs_fscache_get_super_cookie(struct cifsTconInfo *);
43extern void cifs_fscache_release_super_cookie(struct cifsTconInfo *); 45extern void cifs_fscache_release_super_cookie(struct cifsTconInfo *);
44 46
47extern void cifs_fscache_release_inode_cookie(struct inode *);
48extern void cifs_fscache_set_inode_cookie(struct inode *, struct file *);
49extern void cifs_fscache_reset_inode_cookie(struct inode *);
50
45#else /* CONFIG_CIFS_FSCACHE */ 51#else /* CONFIG_CIFS_FSCACHE */
46static inline int cifs_fscache_register(void) { return 0; } 52static inline int cifs_fscache_register(void) { return 0; }
47static inline void cifs_fscache_unregister(void) {} 53static inline void cifs_fscache_unregister(void) {}
@@ -54,6 +60,12 @@ static inline void cifs_fscache_get_super_cookie(struct cifsTconInfo *tcon) {}
54static inline void 60static inline void
55cifs_fscache_release_super_cookie(struct cifsTconInfo *tcon) {} 61cifs_fscache_release_super_cookie(struct cifsTconInfo *tcon) {}
56 62
63static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {}
64static inline void cifs_fscache_set_inode_cookie(struct inode *inode,
65 struct file *filp) {}
66static inline void cifs_fscache_reset_inode_cookie(struct inode *inode) {}
67
68
57#endif /* CONFIG_CIFS_FSCACHE */ 69#endif /* CONFIG_CIFS_FSCACHE */
58 70
59#endif /* _CIFS_FSCACHE_H */ 71#endif /* _CIFS_FSCACHE_H */
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index f884cb51622a..5a68b92a0f9a 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -29,6 +29,7 @@
29#include "cifsproto.h" 29#include "cifsproto.h"
30#include "cifs_debug.h" 30#include "cifs_debug.h"
31#include "cifs_fs_sb.h" 31#include "cifs_fs_sb.h"
32#include "fscache.h"
32 33
33 34
34static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) 35static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral)
@@ -776,6 +777,8 @@ retry_iget5_locked:
776 inode->i_flags |= S_NOATIME | S_NOCMTIME; 777 inode->i_flags |= S_NOATIME | S_NOCMTIME;
777 if (inode->i_state & I_NEW) { 778 if (inode->i_state & I_NEW) {
778 inode->i_ino = hash; 779 inode->i_ino = hash;
780 /* initialize per-inode cache cookie pointer */
781 CIFS_I(inode)->fscache = NULL;
779 unlock_new_inode(inode); 782 unlock_new_inode(inode);
780 } 783 }
781 } 784 }
@@ -1571,6 +1574,7 @@ cifs_invalidate_mapping(struct inode *inode)
1571 cifs_i->write_behind_rc = rc; 1574 cifs_i->write_behind_rc = rc;
1572 } 1575 }
1573 invalidate_remote_inode(inode); 1576 invalidate_remote_inode(inode);
1577 cifs_fscache_reset_inode_cookie(inode);
1574} 1578}
1575 1579
1576int cifs_revalidate_file(struct file *filp) 1580int cifs_revalidate_file(struct file *filp)