Commit 85ccce43 authored by Sage Weil's avatar Sage Weil

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: default avatarSage Weil <sage@newdream.net>
parent 5ce6e9db
...@@ -128,6 +128,7 @@ static int caps_total_count; /* total caps allocated */ ...@@ -128,6 +128,7 @@ static int caps_total_count; /* total caps allocated */
static int caps_use_count; /* in use */ static int caps_use_count; /* in use */
static int caps_reserve_count; /* unused, reserved */ static int caps_reserve_count; /* unused, reserved */
static int caps_avail_count; /* unused, unreserved */ static int caps_avail_count; /* unused, unreserved */
static int caps_min_count; /* keep at least this many (unreserved) */
void __init ceph_caps_init(void) void __init ceph_caps_init(void)
{ {
...@@ -149,6 +150,15 @@ void ceph_caps_finalize(void) ...@@ -149,6 +150,15 @@ void ceph_caps_finalize(void)
caps_avail_count = 0; caps_avail_count = 0;
caps_use_count = 0; caps_use_count = 0;
caps_reserve_count = 0; caps_reserve_count = 0;
caps_min_count = 0;
spin_unlock(&caps_list_lock);
}
void ceph_adjust_min_caps(int delta)
{
spin_lock(&caps_list_lock);
caps_min_count += delta;
BUG_ON(caps_min_count < 0);
spin_unlock(&caps_list_lock); spin_unlock(&caps_list_lock);
} }
...@@ -265,12 +275,10 @@ static void put_cap(struct ceph_cap *cap, ...@@ -265,12 +275,10 @@ static void put_cap(struct ceph_cap *cap,
caps_reserve_count, caps_avail_count); caps_reserve_count, caps_avail_count);
caps_use_count--; caps_use_count--;
/* /*
* Keep some preallocated caps around, at least enough to do a * Keep some preallocated caps around (ceph_min_count), to
* readdir (which needs to preallocate lots of them), to avoid * avoid lots of free/alloc churn.
* lots of free/alloc churn.
*/ */
if (caps_avail_count >= caps_reserve_count + if (caps_avail_count >= caps_reserve_count + caps_min_count) {
ceph_client(cap->ci->vfs_inode.i_sb)->mount_args->max_readdir) {
caps_total_count--; caps_total_count--;
kmem_cache_free(ceph_cap_cachep, cap); kmem_cache_free(ceph_cap_cachep, cap);
} else { } else {
...@@ -289,7 +297,8 @@ static void put_cap(struct ceph_cap *cap, ...@@ -289,7 +297,8 @@ static void put_cap(struct ceph_cap *cap,
} }
void ceph_reservation_status(struct ceph_client *client, void ceph_reservation_status(struct ceph_client *client,
int *total, int *avail, int *used, int *reserved) int *total, int *avail, int *used, int *reserved,
int *min)
{ {
if (total) if (total)
*total = caps_total_count; *total = caps_total_count;
...@@ -299,6 +308,8 @@ void ceph_reservation_status(struct ceph_client *client, ...@@ -299,6 +308,8 @@ void ceph_reservation_status(struct ceph_client *client,
*used = caps_use_count; *used = caps_use_count;
if (reserved) if (reserved)
*reserved = caps_reserve_count; *reserved = caps_reserve_count;
if (min)
*min = caps_min_count;
} }
/* /*
......
...@@ -255,14 +255,15 @@ static int osdc_show(struct seq_file *s, void *pp) ...@@ -255,14 +255,15 @@ static int osdc_show(struct seq_file *s, void *pp)
static int caps_show(struct seq_file *s, void *p) static int caps_show(struct seq_file *s, void *p)
{ {
struct ceph_client *client = p; struct ceph_client *client = p;
int total, avail, used, reserved; int total, avail, used, reserved, min;
ceph_reservation_status(client, &total, &avail, &used, &reserved); ceph_reservation_status(client, &total, &avail, &used, &reserved, &min);
seq_printf(s, "total\t\t%d\n" seq_printf(s, "total\t\t%d\n"
"avail\t\t%d\n" "avail\t\t%d\n"
"used\t\t%d\n" "used\t\t%d\n"
"reserved\t%d\n", "reserved\t%d\n"
total, avail, used, reserved); "min\t%d\n",
total, avail, used, reserved, min);
return 0; return 0;
} }
......
...@@ -578,6 +578,9 @@ static struct ceph_client *ceph_create_client(struct ceph_mount_args *args) ...@@ -578,6 +578,9 @@ static struct ceph_client *ceph_create_client(struct ceph_mount_args *args)
if (!client->wb_pagevec_pool) if (!client->wb_pagevec_pool)
goto fail_trunc_wq; goto fail_trunc_wq;
/* caps */
client->min_caps = args->max_readdir;
ceph_adjust_min_caps(client->min_caps);
/* subsystems */ /* subsystems */
err = ceph_monc_init(&client->monc, client); err = ceph_monc_init(&client->monc, client);
...@@ -619,6 +622,8 @@ static void ceph_destroy_client(struct ceph_client *client) ...@@ -619,6 +622,8 @@ static void ceph_destroy_client(struct ceph_client *client)
ceph_monc_stop(&client->monc); ceph_monc_stop(&client->monc);
ceph_osdc_stop(&client->osdc); ceph_osdc_stop(&client->osdc);
ceph_adjust_min_caps(-client->min_caps);
ceph_debugfs_client_cleanup(client); ceph_debugfs_client_cleanup(client);
destroy_workqueue(client->wb_wq); destroy_workqueue(client->wb_wq);
destroy_workqueue(client->pg_inv_wq); destroy_workqueue(client->pg_inv_wq);
......
...@@ -129,6 +129,8 @@ struct ceph_client { ...@@ -129,6 +129,8 @@ struct ceph_client {
int auth_err; int auth_err;
int min_caps; /* min caps i added */
struct ceph_messenger *msgr; /* messenger instance */ struct ceph_messenger *msgr; /* messenger instance */
struct ceph_mon_client monc; struct ceph_mon_client monc;
struct ceph_mds_client mdsc; struct ceph_mds_client mdsc;
...@@ -557,11 +559,12 @@ extern int __ceph_caps_mds_wanted(struct ceph_inode_info *ci); ...@@ -557,11 +559,12 @@ extern int __ceph_caps_mds_wanted(struct ceph_inode_info *ci);
extern void ceph_caps_init(void); extern void ceph_caps_init(void);
extern void ceph_caps_finalize(void); extern void ceph_caps_finalize(void);
extern void ceph_adjust_min_caps(int delta);
extern int ceph_reserve_caps(struct ceph_cap_reservation *ctx, int need); extern int ceph_reserve_caps(struct ceph_cap_reservation *ctx, int need);
extern int ceph_unreserve_caps(struct ceph_cap_reservation *ctx); extern int ceph_unreserve_caps(struct ceph_cap_reservation *ctx);
extern void ceph_reservation_status(struct ceph_client *client, extern void ceph_reservation_status(struct ceph_client *client,
int *total, int *avail, int *used, int *total, int *avail, int *used,
int *reserved); int *reserved, int *min);
static inline struct ceph_client *ceph_inode_to_client(struct inode *inode) static inline struct ceph_client *ceph_inode_to_client(struct inode *inode)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment