diff options
-rw-r--r-- | fs/cifs/cache.c | 83 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 7 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 3 | ||||
-rw-r--r-- | fs/cifs/file.c | 6 | ||||
-rw-r--r-- | fs/cifs/fscache.c | 68 | ||||
-rw-r--r-- | fs/cifs/fscache.h | 12 | ||||
-rw-r--r-- | fs/cifs/inode.c | 4 |
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 | */ | ||
221 | struct cifs_fscache_inode_auxdata { | ||
222 | struct timespec last_write_time; | ||
223 | struct timespec last_change_time; | ||
224 | u64 eof; | ||
225 | }; | ||
226 | |||
227 | static 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 | |||
243 | static void | ||
244 | cifs_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 | |||
251 | static uint16_t | ||
252 | cifs_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 | |||
271 | static enum | ||
272 | fscache_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 | |||
293 | const 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 | ||
332 | static void | 332 | static void |
333 | cifs_clear_inode(struct inode *inode) | ||
334 | { | ||
335 | cifs_fscache_release_inode_cookie(inode); | ||
336 | } | ||
337 | |||
338 | static void | ||
333 | cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) | 339 | cifs_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 | ||
44 | static inline int cifs_convert_flags(unsigned int flags) | 45 | static 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 | ||
25 | void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) | 26 | void 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 | |||
61 | static 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 | |||
76 | void 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 | |||
88 | static 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 | |||
100 | void 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 | |||
110 | void 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 @@ | |||
30 | extern struct fscache_netfs cifs_fscache_netfs; | 30 | extern struct fscache_netfs cifs_fscache_netfs; |
31 | extern const struct fscache_cookie_def cifs_fscache_server_index_def; | 31 | extern const struct fscache_cookie_def cifs_fscache_server_index_def; |
32 | extern const struct fscache_cookie_def cifs_fscache_super_index_def; | 32 | extern const struct fscache_cookie_def cifs_fscache_super_index_def; |
33 | extern const struct fscache_cookie_def cifs_fscache_inode_object_def; | ||
34 | |||
33 | 35 | ||
34 | extern int cifs_fscache_register(void); | 36 | extern int cifs_fscache_register(void); |
35 | extern void cifs_fscache_unregister(void); | 37 | extern void cifs_fscache_unregister(void); |
@@ -42,6 +44,10 @@ extern void cifs_fscache_release_client_cookie(struct TCP_Server_Info *); | |||
42 | extern void cifs_fscache_get_super_cookie(struct cifsTconInfo *); | 44 | extern void cifs_fscache_get_super_cookie(struct cifsTconInfo *); |
43 | extern void cifs_fscache_release_super_cookie(struct cifsTconInfo *); | 45 | extern void cifs_fscache_release_super_cookie(struct cifsTconInfo *); |
44 | 46 | ||
47 | extern void cifs_fscache_release_inode_cookie(struct inode *); | ||
48 | extern void cifs_fscache_set_inode_cookie(struct inode *, struct file *); | ||
49 | extern void cifs_fscache_reset_inode_cookie(struct inode *); | ||
50 | |||
45 | #else /* CONFIG_CIFS_FSCACHE */ | 51 | #else /* CONFIG_CIFS_FSCACHE */ |
46 | static inline int cifs_fscache_register(void) { return 0; } | 52 | static inline int cifs_fscache_register(void) { return 0; } |
47 | static inline void cifs_fscache_unregister(void) {} | 53 | static inline void cifs_fscache_unregister(void) {} |
@@ -54,6 +60,12 @@ static inline void cifs_fscache_get_super_cookie(struct cifsTconInfo *tcon) {} | |||
54 | static inline void | 60 | static inline void |
55 | cifs_fscache_release_super_cookie(struct cifsTconInfo *tcon) {} | 61 | cifs_fscache_release_super_cookie(struct cifsTconInfo *tcon) {} |
56 | 62 | ||
63 | static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {} | ||
64 | static inline void cifs_fscache_set_inode_cookie(struct inode *inode, | ||
65 | struct file *filp) {} | ||
66 | static 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 | ||
34 | static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) | 35 | static 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 | ||
1576 | int cifs_revalidate_file(struct file *filp) | 1580 | int cifs_revalidate_file(struct file *filp) |