|
12 | 12 | #include "super.h"
|
13 | 13 | #include "cache.h"
|
14 | 14 |
|
15 |
| -struct fscache_netfs ceph_cache_netfs = { |
16 |
| - .name = "ceph", |
17 |
| - .version = 0, |
18 |
| -}; |
19 |
| - |
20 |
| -static DEFINE_MUTEX(ceph_fscache_lock); |
21 |
| -static LIST_HEAD(ceph_fscache_list); |
22 |
| - |
23 |
| -struct ceph_fscache_entry { |
24 |
| - struct list_head list; |
25 |
| - struct fscache_cookie *fscache; |
26 |
| - size_t uniq_len; |
27 |
| - /* The following members must be last */ |
28 |
| - struct ceph_fsid fsid; |
29 |
| - char uniquifier[]; |
30 |
| -}; |
31 |
| - |
32 |
| -static const struct fscache_cookie_def ceph_fscache_fsid_object_def = { |
33 |
| - .name = "CEPH.fsid", |
34 |
| - .type = FSCACHE_COOKIE_TYPE_INDEX, |
35 |
| -}; |
36 |
| - |
37 |
| -int __init ceph_fscache_register(void) |
38 |
| -{ |
39 |
| - return fscache_register_netfs(&ceph_cache_netfs); |
40 |
| -} |
41 |
| - |
42 |
| -void ceph_fscache_unregister(void) |
43 |
| -{ |
44 |
| - fscache_unregister_netfs(&ceph_cache_netfs); |
45 |
| -} |
46 |
| - |
47 |
| -int ceph_fscache_register_fs(struct ceph_fs_client* fsc, struct fs_context *fc) |
| 15 | +void ceph_fscache_register_inode_cookie(struct inode *inode) |
48 | 16 | {
|
49 |
| - const struct ceph_fsid *fsid = &fsc->client->fsid; |
50 |
| - const char *fscache_uniq = fsc->mount_options->fscache_uniq; |
51 |
| - size_t uniq_len = fscache_uniq ? strlen(fscache_uniq) : 0; |
52 |
| - struct ceph_fscache_entry *ent; |
53 |
| - int err = 0; |
| 17 | + struct ceph_inode_info *ci = ceph_inode(inode); |
| 18 | + struct ceph_fs_client *fsc = ceph_inode_to_client(inode); |
54 | 19 |
|
55 |
| - mutex_lock(&ceph_fscache_lock); |
56 |
| - list_for_each_entry(ent, &ceph_fscache_list, list) { |
57 |
| - if (memcmp(&ent->fsid, fsid, sizeof(*fsid))) |
58 |
| - continue; |
59 |
| - if (ent->uniq_len != uniq_len) |
60 |
| - continue; |
61 |
| - if (uniq_len && memcmp(ent->uniquifier, fscache_uniq, uniq_len)) |
62 |
| - continue; |
63 |
| - |
64 |
| - errorfc(fc, "fscache cookie already registered for fsid %pU, use fsc=<uniquifier> option", |
65 |
| - fsid); |
66 |
| - err = -EBUSY; |
67 |
| - goto out_unlock; |
68 |
| - } |
| 20 | + /* No caching for filesystem? */ |
| 21 | + if (!fsc->fscache) |
| 22 | + return; |
69 | 23 |
|
70 |
| - ent = kzalloc(sizeof(*ent) + uniq_len, GFP_KERNEL); |
71 |
| - if (!ent) { |
72 |
| - err = -ENOMEM; |
73 |
| - goto out_unlock; |
74 |
| - } |
| 24 | + /* Regular files only */ |
| 25 | + if (!S_ISREG(inode->i_mode)) |
| 26 | + return; |
75 | 27 |
|
76 |
| - memcpy(&ent->fsid, fsid, sizeof(*fsid)); |
77 |
| - if (uniq_len > 0) { |
78 |
| - memcpy(&ent->uniquifier, fscache_uniq, uniq_len); |
79 |
| - ent->uniq_len = uniq_len; |
80 |
| - } |
| 28 | + /* Only new inodes! */ |
| 29 | + if (!(inode->i_state & I_NEW)) |
| 30 | + return; |
81 | 31 |
|
82 |
| - fsc->fscache = fscache_acquire_cookie(ceph_cache_netfs.primary_index, |
83 |
| - &ceph_fscache_fsid_object_def, |
84 |
| - &ent->fsid, sizeof(ent->fsid) + uniq_len, |
85 |
| - NULL, 0, |
86 |
| - fsc, 0, true); |
| 32 | + WARN_ON_ONCE(ci->fscache); |
87 | 33 |
|
88 |
| - if (fsc->fscache) { |
89 |
| - ent->fscache = fsc->fscache; |
90 |
| - list_add_tail(&ent->list, &ceph_fscache_list); |
91 |
| - } else { |
92 |
| - kfree(ent); |
93 |
| - errorfc(fc, "unable to register fscache cookie for fsid %pU", |
94 |
| - fsid); |
95 |
| - /* all other fs ignore this error */ |
96 |
| - } |
97 |
| -out_unlock: |
98 |
| - mutex_unlock(&ceph_fscache_lock); |
99 |
| - return err; |
| 34 | + ci->fscache = fscache_acquire_cookie(fsc->fscache, 0, |
| 35 | + &ci->i_vino, sizeof(ci->i_vino), |
| 36 | + &ci->i_version, sizeof(ci->i_version), |
| 37 | + i_size_read(inode)); |
100 | 38 | }
|
101 | 39 |
|
102 |
| -static enum fscache_checkaux ceph_fscache_inode_check_aux( |
103 |
| - void *cookie_netfs_data, const void *data, uint16_t dlen, |
104 |
| - loff_t object_size) |
| 40 | +void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info* ci) |
105 | 41 | {
|
106 |
| - struct ceph_inode_info* ci = cookie_netfs_data; |
107 |
| - struct inode* inode = &ci->vfs_inode; |
| 42 | + struct fscache_cookie *cookie = ci->fscache; |
108 | 43 |
|
109 |
| - if (dlen != sizeof(ci->i_version) || |
110 |
| - i_size_read(inode) != object_size) |
111 |
| - return FSCACHE_CHECKAUX_OBSOLETE; |
| 44 | + fscache_relinquish_cookie(cookie, false); |
| 45 | +} |
112 | 46 |
|
113 |
| - if (*(u64 *)data != ci->i_version) |
114 |
| - return FSCACHE_CHECKAUX_OBSOLETE; |
| 47 | +void ceph_fscache_use_cookie(struct inode *inode, bool will_modify) |
| 48 | +{ |
| 49 | + struct ceph_inode_info *ci = ceph_inode(inode); |
115 | 50 |
|
116 |
| - dout("ceph inode 0x%p cached okay\n", ci); |
117 |
| - return FSCACHE_CHECKAUX_OKAY; |
| 51 | + fscache_use_cookie(ci->fscache, will_modify); |
118 | 52 | }
|
119 | 53 |
|
120 |
| -static const struct fscache_cookie_def ceph_fscache_inode_object_def = { |
121 |
| - .name = "CEPH.inode", |
122 |
| - .type = FSCACHE_COOKIE_TYPE_DATAFILE, |
123 |
| - .check_aux = ceph_fscache_inode_check_aux, |
124 |
| -}; |
125 |
| - |
126 |
| -void ceph_fscache_register_inode_cookie(struct inode *inode) |
| 54 | +void ceph_fscache_unuse_cookie(struct inode *inode, bool update) |
127 | 55 | {
|
128 | 56 | struct ceph_inode_info *ci = ceph_inode(inode);
|
129 |
| - struct ceph_fs_client *fsc = ceph_inode_to_client(inode); |
130 |
| - |
131 |
| - /* No caching for filesystem */ |
132 |
| - if (!fsc->fscache) |
133 |
| - return; |
134 | 57 |
|
135 |
| - /* Only cache for regular files that are read only */ |
136 |
| - if (!S_ISREG(inode->i_mode)) |
137 |
| - return; |
| 58 | + if (update) { |
| 59 | + loff_t i_size = i_size_read(inode); |
138 | 60 |
|
139 |
| - inode_lock_nested(inode, I_MUTEX_CHILD); |
140 |
| - if (!ci->fscache) { |
141 |
| - ci->fscache = fscache_acquire_cookie(fsc->fscache, |
142 |
| - &ceph_fscache_inode_object_def, |
143 |
| - &ci->i_vino, sizeof(ci->i_vino), |
144 |
| - &ci->i_version, sizeof(ci->i_version), |
145 |
| - ci, i_size_read(inode), false); |
| 61 | + fscache_unuse_cookie(ci->fscache, &ci->i_version, &i_size); |
| 62 | + } else { |
| 63 | + fscache_unuse_cookie(ci->fscache, NULL, NULL); |
146 | 64 | }
|
147 |
| - inode_unlock(inode); |
148 | 65 | }
|
149 | 66 |
|
150 |
| -void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info* ci) |
| 67 | +void ceph_fscache_update(struct inode *inode) |
151 | 68 | {
|
152 |
| - struct fscache_cookie* cookie; |
153 |
| - |
154 |
| - if ((cookie = ci->fscache) == NULL) |
155 |
| - return; |
156 |
| - |
157 |
| - ci->fscache = NULL; |
| 69 | + struct ceph_inode_info *ci = ceph_inode(inode); |
| 70 | + loff_t i_size = i_size_read(inode); |
158 | 71 |
|
159 |
| - fscache_relinquish_cookie(cookie, &ci->i_vino, false); |
| 72 | + fscache_update_cookie(ci->fscache, &ci->i_version, &i_size); |
160 | 73 | }
|
161 | 74 |
|
162 |
| -static bool ceph_fscache_can_enable(void *data) |
| 75 | +void ceph_fscache_invalidate(struct inode *inode, bool dio_write) |
163 | 76 | {
|
164 |
| - struct inode *inode = data; |
165 |
| - return !inode_is_open_for_write(inode); |
| 77 | + struct ceph_inode_info *ci = ceph_inode(inode); |
| 78 | + |
| 79 | + fscache_invalidate(ceph_inode(inode)->fscache, |
| 80 | + &ci->i_version, i_size_read(inode), |
| 81 | + dio_write ? FSCACHE_INVAL_DIO_WRITE : 0); |
166 | 82 | }
|
167 | 83 |
|
168 |
| -void ceph_fscache_file_set_cookie(struct inode *inode, struct file *filp) |
| 84 | +int ceph_fscache_register_fs(struct ceph_fs_client* fsc, struct fs_context *fc) |
169 | 85 | {
|
170 |
| - struct ceph_inode_info *ci = ceph_inode(inode); |
| 86 | + const struct ceph_fsid *fsid = &fsc->client->fsid; |
| 87 | + const char *fscache_uniq = fsc->mount_options->fscache_uniq; |
| 88 | + size_t uniq_len = fscache_uniq ? strlen(fscache_uniq) : 0; |
| 89 | + char *name; |
| 90 | + int err = 0; |
171 | 91 |
|
172 |
| - if (!fscache_cookie_valid(ci->fscache)) |
173 |
| - return; |
| 92 | + name = kasprintf(GFP_KERNEL, "ceph,%pU%s%s", fsid, uniq_len ? "," : "", |
| 93 | + uniq_len ? fscache_uniq : ""); |
| 94 | + if (!name) |
| 95 | + return -ENOMEM; |
174 | 96 |
|
175 |
| - if (inode_is_open_for_write(inode)) { |
176 |
| - dout("fscache_file_set_cookie %p %p disabling cache\n", |
177 |
| - inode, filp); |
178 |
| - fscache_disable_cookie(ci->fscache, &ci->i_vino, false); |
179 |
| - } else { |
180 |
| - fscache_enable_cookie(ci->fscache, &ci->i_vino, i_size_read(inode), |
181 |
| - ceph_fscache_can_enable, inode); |
182 |
| - if (fscache_cookie_enabled(ci->fscache)) { |
183 |
| - dout("fscache_file_set_cookie %p %p enabling cache\n", |
184 |
| - inode, filp); |
185 |
| - } |
| 97 | + fsc->fscache = fscache_acquire_volume(name, NULL, NULL, 0); |
| 98 | + if (IS_ERR_OR_NULL(fsc->fscache)) { |
| 99 | + errorfc(fc, "Unable to register fscache cookie for %s", name); |
| 100 | + err = fsc->fscache ? PTR_ERR(fsc->fscache) : -EOPNOTSUPP; |
| 101 | + fsc->fscache = NULL; |
186 | 102 | }
|
| 103 | + kfree(name); |
| 104 | + return err; |
187 | 105 | }
|
188 | 106 |
|
189 | 107 | void ceph_fscache_unregister_fs(struct ceph_fs_client* fsc)
|
190 | 108 | {
|
191 |
| - if (fscache_cookie_valid(fsc->fscache)) { |
192 |
| - struct ceph_fscache_entry *ent; |
193 |
| - bool found = false; |
194 |
| - |
195 |
| - mutex_lock(&ceph_fscache_lock); |
196 |
| - list_for_each_entry(ent, &ceph_fscache_list, list) { |
197 |
| - if (ent->fscache == fsc->fscache) { |
198 |
| - list_del(&ent->list); |
199 |
| - kfree(ent); |
200 |
| - found = true; |
201 |
| - break; |
202 |
| - } |
203 |
| - } |
204 |
| - WARN_ON_ONCE(!found); |
205 |
| - mutex_unlock(&ceph_fscache_lock); |
206 |
| - |
207 |
| - __fscache_relinquish_cookie(fsc->fscache, NULL, false); |
208 |
| - } |
209 |
| - fsc->fscache = NULL; |
| 109 | + fscache_relinquish_volume(fsc->fscache, NULL, false); |
210 | 110 | }
|
0 commit comments