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/ceph/caps.c | |
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/ceph/caps.c')
-rw-r--r-- | fs/ceph/caps.c | 23 |
1 files changed, 17 insertions, 6 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 | /* |