diff options
author | Sage Weil <sage@newdream.net> | 2010-02-17 13:02:43 -0500 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2010-02-17 13:02:43 -0500 |
commit | 85ccce43a3fc15a40ded6ae1603e3f68a17f4d24 (patch) | |
tree | 1e15fb7dc7df43da4a3feacff671c8169e96291d /fs | |
parent | 5ce6e9dbe6805ab8ee67e21936d17f431adc63c6 (diff) |
ceph: clean up readdir caps reservation
Use a global counter for the minimum number of allocated caps instead of
hard coding a check against readdir_max. This takes into account multiple
client instances, and avoids examining the superblock mount options when a
cap is dropped.
Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ceph/caps.c | 23 | ||||
-rw-r--r-- | fs/ceph/debugfs.c | 13 | ||||
-rw-r--r-- | fs/ceph/super.c | 5 | ||||
-rw-r--r-- | fs/ceph/super.h | 5 |
4 files changed, 33 insertions, 13 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index ab9b571dda11..f94b56faba3b 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -128,6 +128,7 @@ static int caps_total_count; /* total caps allocated */ | |||
128 | static int caps_use_count; /* in use */ | 128 | static int caps_use_count; /* in use */ |
129 | static int caps_reserve_count; /* unused, reserved */ | 129 | static int caps_reserve_count; /* unused, reserved */ |
130 | static int caps_avail_count; /* unused, unreserved */ | 130 | static int caps_avail_count; /* unused, unreserved */ |
131 | static int caps_min_count; /* keep at least this many (unreserved) */ | ||
131 | 132 | ||
132 | void __init ceph_caps_init(void) | 133 | void __init ceph_caps_init(void) |
133 | { | 134 | { |
@@ -149,6 +150,15 @@ void ceph_caps_finalize(void) | |||
149 | caps_avail_count = 0; | 150 | caps_avail_count = 0; |
150 | caps_use_count = 0; | 151 | caps_use_count = 0; |
151 | caps_reserve_count = 0; | 152 | caps_reserve_count = 0; |
153 | caps_min_count = 0; | ||
154 | spin_unlock(&caps_list_lock); | ||
155 | } | ||
156 | |||
157 | void ceph_adjust_min_caps(int delta) | ||
158 | { | ||
159 | spin_lock(&caps_list_lock); | ||
160 | caps_min_count += delta; | ||
161 | BUG_ON(caps_min_count < 0); | ||
152 | spin_unlock(&caps_list_lock); | 162 | spin_unlock(&caps_list_lock); |
153 | } | 163 | } |
154 | 164 | ||
@@ -265,12 +275,10 @@ static void put_cap(struct ceph_cap *cap, | |||
265 | caps_reserve_count, caps_avail_count); | 275 | caps_reserve_count, caps_avail_count); |
266 | caps_use_count--; | 276 | caps_use_count--; |
267 | /* | 277 | /* |
268 | * Keep some preallocated caps around, at least enough to do a | 278 | * Keep some preallocated caps around (ceph_min_count), to |
269 | * readdir (which needs to preallocate lots of them), to avoid | 279 | * avoid lots of free/alloc churn. |
270 | * lots of free/alloc churn. | ||
271 | */ | 280 | */ |
272 | if (caps_avail_count >= caps_reserve_count + | 281 | if (caps_avail_count >= caps_reserve_count + caps_min_count) { |
273 | ceph_client(cap->ci->vfs_inode.i_sb)->mount_args->max_readdir) { | ||
274 | caps_total_count--; | 282 | caps_total_count--; |
275 | kmem_cache_free(ceph_cap_cachep, cap); | 283 | kmem_cache_free(ceph_cap_cachep, cap); |
276 | } else { | 284 | } else { |
@@ -289,7 +297,8 @@ static void put_cap(struct ceph_cap *cap, | |||
289 | } | 297 | } |
290 | 298 | ||
291 | void ceph_reservation_status(struct ceph_client *client, | 299 | void ceph_reservation_status(struct ceph_client *client, |
292 | int *total, int *avail, int *used, int *reserved) | 300 | int *total, int *avail, int *used, int *reserved, |
301 | int *min) | ||
293 | { | 302 | { |
294 | if (total) | 303 | if (total) |
295 | *total = caps_total_count; | 304 | *total = caps_total_count; |
@@ -299,6 +308,8 @@ void ceph_reservation_status(struct ceph_client *client, | |||
299 | *used = caps_use_count; | 308 | *used = caps_use_count; |
300 | if (reserved) | 309 | if (reserved) |
301 | *reserved = caps_reserve_count; | 310 | *reserved = caps_reserve_count; |
311 | if (min) | ||
312 | *min = caps_min_count; | ||
302 | } | 313 | } |
303 | 314 | ||
304 | /* | 315 | /* |
diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c index b58bd9188692..1a47b5c25b5f 100644 --- a/fs/ceph/debugfs.c +++ b/fs/ceph/debugfs.c | |||
@@ -255,14 +255,15 @@ static int osdc_show(struct seq_file *s, void *pp) | |||
255 | static int caps_show(struct seq_file *s, void *p) | 255 | static int caps_show(struct seq_file *s, void *p) |
256 | { | 256 | { |
257 | struct ceph_client *client = p; | 257 | struct ceph_client *client = p; |
258 | int total, avail, used, reserved; | 258 | int total, avail, used, reserved, min; |
259 | 259 | ||
260 | ceph_reservation_status(client, &total, &avail, &used, &reserved); | 260 | ceph_reservation_status(client, &total, &avail, &used, &reserved, &min); |
261 | seq_printf(s, "total\t\t%d\n" | 261 | seq_printf(s, "total\t\t%d\n" |
262 | "avail\t\t%d\n" | 262 | "avail\t\t%d\n" |
263 | "used\t\t%d\n" | 263 | "used\t\t%d\n" |
264 | "reserved\t%d\n", | 264 | "reserved\t%d\n" |
265 | total, avail, used, reserved); | 265 | "min\t%d\n", |
266 | total, avail, used, reserved, min); | ||
266 | return 0; | 267 | return 0; |
267 | } | 268 | } |
268 | 269 | ||
diff --git a/fs/ceph/super.c b/fs/ceph/super.c index 39aaf29a04a0..74953be75f8f 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c | |||
@@ -578,6 +578,9 @@ static struct ceph_client *ceph_create_client(struct ceph_mount_args *args) | |||
578 | if (!client->wb_pagevec_pool) | 578 | if (!client->wb_pagevec_pool) |
579 | goto fail_trunc_wq; | 579 | goto fail_trunc_wq; |
580 | 580 | ||
581 | /* caps */ | ||
582 | client->min_caps = args->max_readdir; | ||
583 | ceph_adjust_min_caps(client->min_caps); | ||
581 | 584 | ||
582 | /* subsystems */ | 585 | /* subsystems */ |
583 | err = ceph_monc_init(&client->monc, client); | 586 | err = ceph_monc_init(&client->monc, client); |
@@ -619,6 +622,8 @@ static void ceph_destroy_client(struct ceph_client *client) | |||
619 | ceph_monc_stop(&client->monc); | 622 | ceph_monc_stop(&client->monc); |
620 | ceph_osdc_stop(&client->osdc); | 623 | ceph_osdc_stop(&client->osdc); |
621 | 624 | ||
625 | ceph_adjust_min_caps(-client->min_caps); | ||
626 | |||
622 | ceph_debugfs_client_cleanup(client); | 627 | ceph_debugfs_client_cleanup(client); |
623 | destroy_workqueue(client->wb_wq); | 628 | destroy_workqueue(client->wb_wq); |
624 | destroy_workqueue(client->pg_inv_wq); | 629 | destroy_workqueue(client->pg_inv_wq); |
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 1f3928785e12..3b5faf9980f8 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
@@ -129,6 +129,8 @@ struct ceph_client { | |||
129 | 129 | ||
130 | int auth_err; | 130 | int auth_err; |
131 | 131 | ||
132 | int min_caps; /* min caps i added */ | ||
133 | |||
132 | struct ceph_messenger *msgr; /* messenger instance */ | 134 | struct ceph_messenger *msgr; /* messenger instance */ |
133 | struct ceph_mon_client monc; | 135 | struct ceph_mon_client monc; |
134 | struct ceph_mds_client mdsc; | 136 | struct ceph_mds_client mdsc; |
@@ -557,11 +559,12 @@ extern int __ceph_caps_mds_wanted(struct ceph_inode_info *ci); | |||
557 | 559 | ||
558 | extern void ceph_caps_init(void); | 560 | extern void ceph_caps_init(void); |
559 | extern void ceph_caps_finalize(void); | 561 | extern void ceph_caps_finalize(void); |
562 | extern void ceph_adjust_min_caps(int delta); | ||
560 | extern int ceph_reserve_caps(struct ceph_cap_reservation *ctx, int need); | 563 | extern int ceph_reserve_caps(struct ceph_cap_reservation *ctx, int need); |
561 | extern int ceph_unreserve_caps(struct ceph_cap_reservation *ctx); | 564 | extern int ceph_unreserve_caps(struct ceph_cap_reservation *ctx); |
562 | extern void ceph_reservation_status(struct ceph_client *client, | 565 | extern void ceph_reservation_status(struct ceph_client *client, |
563 | int *total, int *avail, int *used, | 566 | int *total, int *avail, int *used, |
564 | int *reserved); | 567 | int *reserved, int *min); |
565 | 568 | ||
566 | static inline struct ceph_client *ceph_inode_to_client(struct inode *inode) | 569 | static inline struct ceph_client *ceph_inode_to_client(struct inode *inode) |
567 | { | 570 | { |