diff options
author | Ilya Dryomov <idryomov@gmail.com> | 2016-04-28 10:07:26 -0400 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2016-05-25 19:12:30 -0400 |
commit | 9dd2845ccb40452d4ac943231ea34aade4a02c68 (patch) | |
tree | d7c5be5f87c642b45a92eec573a657207b27b899 | |
parent | 7a28f59bf9fb220cdf56ac6ab539fc4a0ae59414 (diff) |
libceph: protect osdc->osd_lru list with a spinlock
OSD client is getting moved from the big per-client lock to a set of
per-session locks. The big rwlock would only be held for read most of
the time, so a global osdc->osd_lru needs additional protection.
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
-rw-r--r-- | include/linux/ceph/osd_client.h | 1 | ||||
-rw-r--r-- | net/ceph/osd_client.c | 29 |
2 files changed, 19 insertions, 11 deletions
diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h index 2415dc0cb008..486d681694c4 100644 --- a/include/linux/ceph/osd_client.h +++ b/include/linux/ceph/osd_client.h | |||
@@ -224,6 +224,7 @@ struct ceph_osd_client { | |||
224 | struct mutex request_mutex; | 224 | struct mutex request_mutex; |
225 | struct rb_root osds; /* osds */ | 225 | struct rb_root osds; /* osds */ |
226 | struct list_head osd_lru; /* idle osds */ | 226 | struct list_head osd_lru; /* idle osds */ |
227 | spinlock_t osd_lru_lock; | ||
227 | u64 last_tid; /* tid of last request */ | 228 | u64 last_tid; /* tid of last request */ |
228 | struct rb_root requests; /* pending requests */ | 229 | struct rb_root requests; /* pending requests */ |
229 | struct list_head req_lru; /* in-flight lru */ | 230 | struct list_head req_lru; /* in-flight lru */ |
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index b6950c2c6cc4..d1c8e06f1261 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
@@ -1101,31 +1101,37 @@ static void remove_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) | |||
1101 | } | 1101 | } |
1102 | } | 1102 | } |
1103 | 1103 | ||
1104 | static void __move_osd_to_lru(struct ceph_osd_client *osdc, | 1104 | static void __move_osd_to_lru(struct ceph_osd *osd) |
1105 | struct ceph_osd *osd) | ||
1106 | { | 1105 | { |
1107 | dout("%s %p\n", __func__, osd); | 1106 | struct ceph_osd_client *osdc = osd->o_osdc; |
1107 | |||
1108 | dout("%s osd %p osd%d\n", __func__, osd, osd->o_osd); | ||
1108 | BUG_ON(!list_empty(&osd->o_osd_lru)); | 1109 | BUG_ON(!list_empty(&osd->o_osd_lru)); |
1109 | 1110 | ||
1111 | spin_lock(&osdc->osd_lru_lock); | ||
1110 | list_add_tail(&osd->o_osd_lru, &osdc->osd_lru); | 1112 | list_add_tail(&osd->o_osd_lru, &osdc->osd_lru); |
1113 | spin_unlock(&osdc->osd_lru_lock); | ||
1114 | |||
1111 | osd->lru_ttl = jiffies + osdc->client->options->osd_idle_ttl; | 1115 | osd->lru_ttl = jiffies + osdc->client->options->osd_idle_ttl; |
1112 | } | 1116 | } |
1113 | 1117 | ||
1114 | static void maybe_move_osd_to_lru(struct ceph_osd_client *osdc, | 1118 | static void maybe_move_osd_to_lru(struct ceph_osd *osd) |
1115 | struct ceph_osd *osd) | ||
1116 | { | 1119 | { |
1117 | dout("%s %p\n", __func__, osd); | ||
1118 | |||
1119 | if (list_empty(&osd->o_requests) && | 1120 | if (list_empty(&osd->o_requests) && |
1120 | list_empty(&osd->o_linger_requests)) | 1121 | list_empty(&osd->o_linger_requests)) |
1121 | __move_osd_to_lru(osdc, osd); | 1122 | __move_osd_to_lru(osd); |
1122 | } | 1123 | } |
1123 | 1124 | ||
1124 | static void __remove_osd_from_lru(struct ceph_osd *osd) | 1125 | static void __remove_osd_from_lru(struct ceph_osd *osd) |
1125 | { | 1126 | { |
1126 | dout("__remove_osd_from_lru %p\n", osd); | 1127 | struct ceph_osd_client *osdc = osd->o_osdc; |
1128 | |||
1129 | dout("%s osd %p osd%d\n", __func__, osd, osd->o_osd); | ||
1130 | |||
1131 | spin_lock(&osdc->osd_lru_lock); | ||
1127 | if (!list_empty(&osd->o_osd_lru)) | 1132 | if (!list_empty(&osd->o_osd_lru)) |
1128 | list_del_init(&osd->o_osd_lru); | 1133 | list_del_init(&osd->o_osd_lru); |
1134 | spin_unlock(&osdc->osd_lru_lock); | ||
1129 | } | 1135 | } |
1130 | 1136 | ||
1131 | /* | 1137 | /* |
@@ -1199,7 +1205,7 @@ static void __unregister_request(struct ceph_osd_client *osdc, | |||
1199 | ceph_msg_revoke(req->r_request); | 1205 | ceph_msg_revoke(req->r_request); |
1200 | 1206 | ||
1201 | list_del_init(&req->r_osd_item); | 1207 | list_del_init(&req->r_osd_item); |
1202 | maybe_move_osd_to_lru(osdc, req->r_osd); | 1208 | maybe_move_osd_to_lru(req->r_osd); |
1203 | if (list_empty(&req->r_linger_osd_item)) | 1209 | if (list_empty(&req->r_linger_osd_item)) |
1204 | req->r_osd = NULL; | 1210 | req->r_osd = NULL; |
1205 | } | 1211 | } |
@@ -1248,7 +1254,7 @@ static void __unregister_linger_request(struct ceph_osd_client *osdc, | |||
1248 | 1254 | ||
1249 | if (req->r_osd) { | 1255 | if (req->r_osd) { |
1250 | list_del_init(&req->r_linger_osd_item); | 1256 | list_del_init(&req->r_linger_osd_item); |
1251 | maybe_move_osd_to_lru(osdc, req->r_osd); | 1257 | maybe_move_osd_to_lru(req->r_osd); |
1252 | if (list_empty(&req->r_osd_item)) | 1258 | if (list_empty(&req->r_osd_item)) |
1253 | req->r_osd = NULL; | 1259 | req->r_osd = NULL; |
1254 | } | 1260 | } |
@@ -2792,6 +2798,7 @@ int ceph_osdc_init(struct ceph_osd_client *osdc, struct ceph_client *client) | |||
2792 | osdc->last_tid = 0; | 2798 | osdc->last_tid = 0; |
2793 | osdc->osds = RB_ROOT; | 2799 | osdc->osds = RB_ROOT; |
2794 | INIT_LIST_HEAD(&osdc->osd_lru); | 2800 | INIT_LIST_HEAD(&osdc->osd_lru); |
2801 | spin_lock_init(&osdc->osd_lru_lock); | ||
2795 | osdc->requests = RB_ROOT; | 2802 | osdc->requests = RB_ROOT; |
2796 | INIT_LIST_HEAD(&osdc->req_lru); | 2803 | INIT_LIST_HEAD(&osdc->req_lru); |
2797 | INIT_LIST_HEAD(&osdc->req_unsent); | 2804 | INIT_LIST_HEAD(&osdc->req_unsent); |