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) |
