diff options
author | Chengguang Xu <cgxu519@icloud.com> | 2018-02-24 05:36:02 -0500 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2018-04-02 04:12:47 -0400 |
commit | 79cd674aed7363a043222af3c8f97d0ea0a078cf (patch) | |
tree | 86fe0a19a23723b1b8ef0b0d81ebe18b04c8d4d1 | |
parent | b517c1d87faafba0c33a38ffdd551e8b399f0a31 (diff) |
ceph: optimizing cap reservation
When caps_avail_count is in a low level, most newly
trimmed caps will probably go into ->caps_list and
caps_avail_count will be increased. Hence after trimming,
should recheck caps_avail_count to effectly reuse
newly trimmed caps. Also, when releasing unnecessary
caps follow the same rule of ceph_put_cap.
Signed-off-by: Chengguang Xu <cgxu519@icloud.com>
Reviewed-by: "Yan, Zheng" <zyan@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
-rw-r--r-- | fs/ceph/caps.c | 88 |
1 files changed, 59 insertions, 29 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index b9b5c47efd06..25141b6683e9 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -184,36 +184,54 @@ int ceph_reserve_caps(struct ceph_mds_client *mdsc, | |||
184 | mdsc->caps_avail_count); | 184 | mdsc->caps_avail_count); |
185 | spin_unlock(&mdsc->caps_list_lock); | 185 | spin_unlock(&mdsc->caps_list_lock); |
186 | 186 | ||
187 | for (i = have; i < need; i++) { | 187 | for (i = have; i < need; ) { |
188 | retry: | ||
189 | cap = kmem_cache_alloc(ceph_cap_cachep, GFP_NOFS); | 188 | cap = kmem_cache_alloc(ceph_cap_cachep, GFP_NOFS); |
190 | if (!cap) { | 189 | if (cap) { |
191 | if (!trimmed) { | 190 | list_add(&cap->caps_item, &newcaps); |
192 | for (j = 0; j < mdsc->max_sessions; j++) { | 191 | alloc++; |
193 | s = __ceph_lookup_mds_session(mdsc, j); | 192 | i++; |
194 | if (!s) | 193 | continue; |
195 | continue; | 194 | } |
196 | mutex_unlock(&mdsc->mutex); | ||
197 | 195 | ||
198 | mutex_lock(&s->s_mutex); | 196 | if (!trimmed) { |
199 | max_caps = s->s_nr_caps - (need - i); | 197 | for (j = 0; j < mdsc->max_sessions; j++) { |
200 | ceph_trim_caps(mdsc, s, max_caps); | 198 | s = __ceph_lookup_mds_session(mdsc, j); |
201 | mutex_unlock(&s->s_mutex); | 199 | if (!s) |
200 | continue; | ||
201 | mutex_unlock(&mdsc->mutex); | ||
202 | 202 | ||
203 | ceph_put_mds_session(s); | 203 | mutex_lock(&s->s_mutex); |
204 | mutex_lock(&mdsc->mutex); | 204 | max_caps = s->s_nr_caps - (need - i); |
205 | } | 205 | ceph_trim_caps(mdsc, s, max_caps); |
206 | trimmed = true; | 206 | mutex_unlock(&s->s_mutex); |
207 | goto retry; | 207 | |
208 | } else { | 208 | ceph_put_mds_session(s); |
209 | pr_warn("reserve caps ctx=%p ENOMEM " | 209 | mutex_lock(&mdsc->mutex); |
210 | "need=%d got=%d\n", | ||
211 | ctx, need, have + alloc); | ||
212 | goto out_nomem; | ||
213 | } | 210 | } |
211 | trimmed = true; | ||
212 | |||
213 | spin_lock(&mdsc->caps_list_lock); | ||
214 | if (mdsc->caps_avail_count) { | ||
215 | int more_have; | ||
216 | if (mdsc->caps_avail_count >= need - i) | ||
217 | more_have = need - i; | ||
218 | else | ||
219 | more_have = mdsc->caps_avail_count; | ||
220 | |||
221 | i += more_have; | ||
222 | have += more_have; | ||
223 | mdsc->caps_avail_count -= more_have; | ||
224 | mdsc->caps_reserve_count += more_have; | ||
225 | |||
226 | } | ||
227 | spin_unlock(&mdsc->caps_list_lock); | ||
228 | |||
229 | continue; | ||
214 | } | 230 | } |
215 | list_add(&cap->caps_item, &newcaps); | 231 | |
216 | alloc++; | 232 | pr_warn("reserve caps ctx=%p ENOMEM need=%d got=%d\n", |
233 | ctx, need, have + alloc); | ||
234 | goto out_nomem; | ||
217 | } | 235 | } |
218 | BUG_ON(have + alloc != need); | 236 | BUG_ON(have + alloc != need); |
219 | 237 | ||
@@ -234,16 +252,28 @@ retry: | |||
234 | return 0; | 252 | return 0; |
235 | 253 | ||
236 | out_nomem: | 254 | out_nomem: |
255 | |||
256 | spin_lock(&mdsc->caps_list_lock); | ||
257 | mdsc->caps_avail_count += have; | ||
258 | mdsc->caps_reserve_count -= have; | ||
259 | |||
237 | while (!list_empty(&newcaps)) { | 260 | while (!list_empty(&newcaps)) { |
238 | cap = list_first_entry(&newcaps, | 261 | cap = list_first_entry(&newcaps, |
239 | struct ceph_cap, caps_item); | 262 | struct ceph_cap, caps_item); |
240 | list_del(&cap->caps_item); | 263 | list_del(&cap->caps_item); |
241 | kmem_cache_free(ceph_cap_cachep, cap); | 264 | |
265 | /* Keep some preallocated caps around (ceph_min_count), to | ||
266 | * avoid lots of free/alloc churn. */ | ||
267 | if (mdsc->caps_avail_count >= | ||
268 | mdsc->caps_reserve_count + mdsc->caps_min_count) { | ||
269 | kmem_cache_free(ceph_cap_cachep, cap); | ||
270 | } else { | ||
271 | mdsc->caps_avail_count++; | ||
272 | mdsc->caps_total_count++; | ||
273 | list_add(&cap->caps_item, &mdsc->caps_list); | ||
274 | } | ||
242 | } | 275 | } |
243 | 276 | ||
244 | spin_lock(&mdsc->caps_list_lock); | ||
245 | mdsc->caps_avail_count += have; | ||
246 | mdsc->caps_reserve_count -= have; | ||
247 | BUG_ON(mdsc->caps_total_count != mdsc->caps_use_count + | 277 | BUG_ON(mdsc->caps_total_count != mdsc->caps_use_count + |
248 | mdsc->caps_reserve_count + | 278 | mdsc->caps_reserve_count + |
249 | mdsc->caps_avail_count); | 279 | mdsc->caps_avail_count); |