aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-04-07 12:08:24 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-07 12:08:24 -0400
commit62f8e6c5dcb6666e7da402aea28fcf846eea144c (patch)
tree2fb8ea1b55b4f0b0592fce715dc7816533609a23 /fs/ceph
parentf605ba97fb80522656c7dce9825a908f1e765b57 (diff)
parentec0328e46d6e5d0f17372eb90ab8e333c2ac7ca9 (diff)
Merge tag 'fscache-next-20180406' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs
Pull fscache updates from David Howells: "Three patches that fix some of AFS's usage of fscache: (1) Need to invalidate the cache if a foreign data change is detected on the server. (2) Move the vnode ID uniquifier (equivalent to i_generation) from the auxiliary data to the index key to prevent a race between file delete and a subsequent file create seeing the same index key. (3) Need to retire cookies that correspond to files that we think got deleted on the server. Four patches to fix some things in fscache and cachefiles: (4) Fix a couple of checker warnings. (5) Correctly indicate to the end-of-operation callback whether an operation completed or was cancelled. (6) Add a check for multiple cookie relinquishment. (7) Fix a path through the asynchronous write that doesn't wake up a waiter for a page if the cache decides not to write that page, but discards it instead. A couple of patches to add tracepoints to fscache and cachefiles: (8) Add tracepoints for cookie operators, object state machine execution, cachefiles object management and cachefiles VFS operations. (9) Add tracepoints for fscache operation management and page wrangling. And then three development patches: (10) Attach the index key and auxiliary data to the cookie, pass this information through various fscache-netfs API functions and get rid of the callbacks to the netfs to get it. This means that the cache can get at this information, even if the netfs goes away. It also means that the cache can be lazy in updating the coherency data. (11) Pass the object data size through various fscache-netfs API rather than calling back to the netfs for it, and store the value in the object. This makes it easier to correctly resize the object, as the size is updated on writes to the cache, rather than calling back out to the netfs. (12) Maintain a catalogue of allocated cookies. This makes it possible to catch cookie collision up front rather than down in the bowels of the cache being run from a service thread from the object state machine. This will also make it possible in the future to reconnect to a cookie that's not gone dead yet because it's waiting for finalisation of the storage and also make it possible to bring cookies online if the cache is added after the cookie has been obtained" * tag 'fscache-next-20180406' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs: fscache: Maintain a catalogue of allocated cookies fscache: Pass object size in rather than calling back for it fscache: Attach the index key and aux data to the cookie fscache: Add more tracepoints fscache: Add tracepoints fscache: Fix hanging wait on page discarded by writeback fscache: Detect multiple relinquishment of a cookie fscache: Pass the correct cancelled indications to fscache_op_complete() fscache, cachefiles: Fix checker warnings afs: Be more aggressive in retiring cached vnodes afs: Use the vnode ID uniquifier in the cache key not the aux data afs: Invalidate cache on server data change
Diffstat (limited to 'fs/ceph')
-rw-r--r--fs/ceph/cache.c113
1 files changed, 31 insertions, 82 deletions
diff --git a/fs/ceph/cache.c b/fs/ceph/cache.c
index a3ab265d3215..33a211b364ed 100644
--- a/fs/ceph/cache.c
+++ b/fs/ceph/cache.c
@@ -27,7 +27,6 @@
27struct ceph_aux_inode { 27struct ceph_aux_inode {
28 u64 version; 28 u64 version;
29 struct timespec mtime; 29 struct timespec mtime;
30 loff_t size;
31}; 30};
32 31
33struct fscache_netfs ceph_cache_netfs = { 32struct fscache_netfs ceph_cache_netfs = {
@@ -41,34 +40,15 @@ static LIST_HEAD(ceph_fscache_list);
41struct ceph_fscache_entry { 40struct ceph_fscache_entry {
42 struct list_head list; 41 struct list_head list;
43 struct fscache_cookie *fscache; 42 struct fscache_cookie *fscache;
44 struct ceph_fsid fsid;
45 size_t uniq_len; 43 size_t uniq_len;
44 /* The following members must be last */
45 struct ceph_fsid fsid;
46 char uniquifier[0]; 46 char uniquifier[0];
47}; 47};
48 48
49static uint16_t ceph_fscache_session_get_key(const void *cookie_netfs_data,
50 void *buffer, uint16_t maxbuf)
51{
52 const struct ceph_fs_client* fsc = cookie_netfs_data;
53 const char *fscache_uniq = fsc->mount_options->fscache_uniq;
54 uint16_t fsid_len, uniq_len;
55
56 fsid_len = sizeof(fsc->client->fsid);
57 uniq_len = fscache_uniq ? strlen(fscache_uniq) : 0;
58 if (fsid_len + uniq_len > maxbuf)
59 return 0;
60
61 memcpy(buffer, &fsc->client->fsid, fsid_len);
62 if (uniq_len)
63 memcpy(buffer + fsid_len, fscache_uniq, uniq_len);
64
65 return fsid_len + uniq_len;
66}
67
68static const struct fscache_cookie_def ceph_fscache_fsid_object_def = { 49static const struct fscache_cookie_def ceph_fscache_fsid_object_def = {
69 .name = "CEPH.fsid", 50 .name = "CEPH.fsid",
70 .type = FSCACHE_COOKIE_TYPE_INDEX, 51 .type = FSCACHE_COOKIE_TYPE_INDEX,
71 .get_key = ceph_fscache_session_get_key,
72}; 52};
73 53
74int ceph_fscache_register(void) 54int ceph_fscache_register(void)
@@ -110,16 +90,19 @@ int ceph_fscache_register_fs(struct ceph_fs_client* fsc)
110 goto out_unlock; 90 goto out_unlock;
111 } 91 }
112 92
93 memcpy(&ent->fsid, fsid, sizeof(*fsid));
94 if (uniq_len > 0) {
95 memcpy(&ent->uniquifier, fscache_uniq, uniq_len);
96 ent->uniq_len = uniq_len;
97 }
98
113 fsc->fscache = fscache_acquire_cookie(ceph_cache_netfs.primary_index, 99 fsc->fscache = fscache_acquire_cookie(ceph_cache_netfs.primary_index,
114 &ceph_fscache_fsid_object_def, 100 &ceph_fscache_fsid_object_def,
115 fsc, true); 101 &ent->fsid, sizeof(ent->fsid) + uniq_len,
102 NULL, 0,
103 fsc, 0, true);
116 104
117 if (fsc->fscache) { 105 if (fsc->fscache) {
118 memcpy(&ent->fsid, fsid, sizeof(*fsid));
119 if (uniq_len > 0) {
120 memcpy(&ent->uniquifier, fscache_uniq, uniq_len);
121 ent->uniq_len = uniq_len;
122 }
123 ent->fscache = fsc->fscache; 106 ent->fscache = fsc->fscache;
124 list_add_tail(&ent->list, &ceph_fscache_list); 107 list_add_tail(&ent->list, &ceph_fscache_list);
125 } else { 108 } else {
@@ -133,59 +116,21 @@ out_unlock:
133 return err; 116 return err;
134} 117}
135 118
136static uint16_t ceph_fscache_inode_get_key(const void *cookie_netfs_data,
137 void *buffer, uint16_t maxbuf)
138{
139 const struct ceph_inode_info* ci = cookie_netfs_data;
140 uint16_t klen;
141
142 /* use ceph virtual inode (id + snapshot) */
143 klen = sizeof(ci->i_vino);
144 if (klen > maxbuf)
145 return 0;
146
147 memcpy(buffer, &ci->i_vino, klen);
148 return klen;
149}
150
151static uint16_t ceph_fscache_inode_get_aux(const void *cookie_netfs_data,
152 void *buffer, uint16_t bufmax)
153{
154 struct ceph_aux_inode aux;
155 const struct ceph_inode_info* ci = cookie_netfs_data;
156 const struct inode* inode = &ci->vfs_inode;
157
158 memset(&aux, 0, sizeof(aux));
159 aux.version = ci->i_version;
160 aux.mtime = inode->i_mtime;
161 aux.size = i_size_read(inode);
162
163 memcpy(buffer, &aux, sizeof(aux));
164
165 return sizeof(aux);
166}
167
168static void ceph_fscache_inode_get_attr(const void *cookie_netfs_data,
169 uint64_t *size)
170{
171 const struct ceph_inode_info* ci = cookie_netfs_data;
172 *size = i_size_read(&ci->vfs_inode);
173}
174
175static enum fscache_checkaux ceph_fscache_inode_check_aux( 119static enum fscache_checkaux ceph_fscache_inode_check_aux(
176 void *cookie_netfs_data, const void *data, uint16_t dlen) 120 void *cookie_netfs_data, const void *data, uint16_t dlen,
121 loff_t object_size)
177{ 122{
178 struct ceph_aux_inode aux; 123 struct ceph_aux_inode aux;
179 struct ceph_inode_info* ci = cookie_netfs_data; 124 struct ceph_inode_info* ci = cookie_netfs_data;
180 struct inode* inode = &ci->vfs_inode; 125 struct inode* inode = &ci->vfs_inode;
181 126
182 if (dlen != sizeof(aux)) 127 if (dlen != sizeof(aux) ||
128 i_size_read(inode) != object_size)
183 return FSCACHE_CHECKAUX_OBSOLETE; 129 return FSCACHE_CHECKAUX_OBSOLETE;
184 130
185 memset(&aux, 0, sizeof(aux)); 131 memset(&aux, 0, sizeof(aux));
186 aux.version = ci->i_version; 132 aux.version = ci->i_version;
187 aux.mtime = inode->i_mtime; 133 aux.mtime = inode->i_mtime;
188 aux.size = i_size_read(inode);
189 134
190 if (memcmp(data, &aux, sizeof(aux)) != 0) 135 if (memcmp(data, &aux, sizeof(aux)) != 0)
191 return FSCACHE_CHECKAUX_OBSOLETE; 136 return FSCACHE_CHECKAUX_OBSOLETE;
@@ -197,9 +142,6 @@ static enum fscache_checkaux ceph_fscache_inode_check_aux(
197static const struct fscache_cookie_def ceph_fscache_inode_object_def = { 142static const struct fscache_cookie_def ceph_fscache_inode_object_def = {
198 .name = "CEPH.inode", 143 .name = "CEPH.inode",
199 .type = FSCACHE_COOKIE_TYPE_DATAFILE, 144 .type = FSCACHE_COOKIE_TYPE_DATAFILE,
200 .get_key = ceph_fscache_inode_get_key,
201 .get_attr = ceph_fscache_inode_get_attr,
202 .get_aux = ceph_fscache_inode_get_aux,
203 .check_aux = ceph_fscache_inode_check_aux, 145 .check_aux = ceph_fscache_inode_check_aux,
204}; 146};
205 147
@@ -207,6 +149,7 @@ void ceph_fscache_register_inode_cookie(struct inode *inode)
207{ 149{
208 struct ceph_inode_info *ci = ceph_inode(inode); 150 struct ceph_inode_info *ci = ceph_inode(inode);
209 struct ceph_fs_client *fsc = ceph_inode_to_client(inode); 151 struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
152 struct ceph_aux_inode aux;
210 153
211 /* No caching for filesystem */ 154 /* No caching for filesystem */
212 if (!fsc->fscache) 155 if (!fsc->fscache)
@@ -218,9 +161,14 @@ void ceph_fscache_register_inode_cookie(struct inode *inode)
218 161
219 inode_lock_nested(inode, I_MUTEX_CHILD); 162 inode_lock_nested(inode, I_MUTEX_CHILD);
220 if (!ci->fscache) { 163 if (!ci->fscache) {
164 memset(&aux, 0, sizeof(aux));
165 aux.version = ci->i_version;
166 aux.mtime = inode->i_mtime;
221 ci->fscache = fscache_acquire_cookie(fsc->fscache, 167 ci->fscache = fscache_acquire_cookie(fsc->fscache,
222 &ceph_fscache_inode_object_def, 168 &ceph_fscache_inode_object_def,
223 ci, false); 169 &ci->i_vino, sizeof(ci->i_vino),
170 &aux, sizeof(aux),
171 ci, i_size_read(inode), false);
224 } 172 }
225 inode_unlock(inode); 173 inode_unlock(inode);
226} 174}
@@ -235,7 +183,7 @@ void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info* ci)
235 ci->fscache = NULL; 183 ci->fscache = NULL;
236 184
237 fscache_uncache_all_inode_pages(cookie, &ci->vfs_inode); 185 fscache_uncache_all_inode_pages(cookie, &ci->vfs_inode);
238 fscache_relinquish_cookie(cookie, 0); 186 fscache_relinquish_cookie(cookie, &ci->i_vino, false);
239} 187}
240 188
241static bool ceph_fscache_can_enable(void *data) 189static bool ceph_fscache_can_enable(void *data)
@@ -254,11 +202,11 @@ void ceph_fscache_file_set_cookie(struct inode *inode, struct file *filp)
254 if (inode_is_open_for_write(inode)) { 202 if (inode_is_open_for_write(inode)) {
255 dout("fscache_file_set_cookie %p %p disabling cache\n", 203 dout("fscache_file_set_cookie %p %p disabling cache\n",
256 inode, filp); 204 inode, filp);
257 fscache_disable_cookie(ci->fscache, false); 205 fscache_disable_cookie(ci->fscache, &ci->i_vino, false);
258 fscache_uncache_all_inode_pages(ci->fscache, inode); 206 fscache_uncache_all_inode_pages(ci->fscache, inode);
259 } else { 207 } else {
260 fscache_enable_cookie(ci->fscache, ceph_fscache_can_enable, 208 fscache_enable_cookie(ci->fscache, &ci->i_vino, i_size_read(inode),
261 inode); 209 ceph_fscache_can_enable, inode);
262 if (fscache_cookie_enabled(ci->fscache)) { 210 if (fscache_cookie_enabled(ci->fscache)) {
263 dout("fscache_file_set_cookie %p %p enabling cache\n", 211 dout("fscache_file_set_cookie %p %p enabling cache\n",
264 inode, filp); 212 inode, filp);
@@ -351,7 +299,8 @@ void ceph_readpage_to_fscache(struct inode *inode, struct page *page)
351 if (!cache_valid(ci)) 299 if (!cache_valid(ci))
352 return; 300 return;
353 301
354 ret = fscache_write_page(ci->fscache, page, GFP_KERNEL); 302 ret = fscache_write_page(ci->fscache, page, i_size_read(inode),
303 GFP_KERNEL);
355 if (ret) 304 if (ret)
356 fscache_uncache_page(ci->fscache, page); 305 fscache_uncache_page(ci->fscache, page);
357} 306}
@@ -385,7 +334,7 @@ void ceph_fscache_unregister_fs(struct ceph_fs_client* fsc)
385 WARN_ON_ONCE(!found); 334 WARN_ON_ONCE(!found);
386 mutex_unlock(&ceph_fscache_lock); 335 mutex_unlock(&ceph_fscache_lock);
387 336
388 __fscache_relinquish_cookie(fsc->fscache, 0); 337 __fscache_relinquish_cookie(fsc->fscache, NULL, false);
389 } 338 }
390 fsc->fscache = NULL; 339 fsc->fscache = NULL;
391} 340}
@@ -402,7 +351,7 @@ void ceph_fscache_revalidate_cookie(struct ceph_inode_info *ci)
402 * truncate while the caller holds CEPH_CAP_FILE_RD */ 351 * truncate while the caller holds CEPH_CAP_FILE_RD */
403 mutex_lock(&ci->i_truncate_mutex); 352 mutex_lock(&ci->i_truncate_mutex);
404 if (!cache_valid(ci)) { 353 if (!cache_valid(ci)) {
405 if (fscache_check_consistency(ci->fscache)) 354 if (fscache_check_consistency(ci->fscache, &ci->i_vino))
406 fscache_invalidate(ci->fscache); 355 fscache_invalidate(ci->fscache);
407 spin_lock(&ci->i_ceph_lock); 356 spin_lock(&ci->i_ceph_lock);
408 ci->i_fscache_gen = ci->i_rdcache_gen; 357 ci->i_fscache_gen = ci->i_rdcache_gen;