diff options
author | Suresh Jayaraman <sjayaraman@suse.de> | 2010-07-05 08:42:45 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2010-08-02 08:40:36 -0400 |
commit | 9451a9a52f91a4c171cfaca2f6d7a2ce91867b8d (patch) | |
tree | e447d252996e554a053890a75b55456b9926d602 /fs | |
parent | d03382ce9a89dbe27cba25130f0b90c0d631d5c5 (diff) |
cifs: define inode-level cache object and register them
Define inode-level data storage objects (managed by cifsInodeInfo structs).
Each inode-level object is created in a super-block level object and is itself
a data storage object in to which pages from the inode are stored.
The inode object is keyed by UniqueId. The coherency data being used is
LastWriteTime, LastChangeTime and end of file reported by the server.
Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs')
-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) |