diff options
author | Ilya Dryomov <idryomov@gmail.com> | 2017-06-15 10:30:55 -0400 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2017-07-07 11:25:16 -0400 |
commit | 04c7d789e269c2b82bbd08106049a5a979cdb3fd (patch) | |
tree | db72e960611bfbcffe75d0a5a0efff8642cc3eb6 | |
parent | a10bcb19ae02cea7d5e6650fbc2de3ced46b4e5d (diff) |
libceph: make sure need_resend targets reflect latest map
Otherwise we may miss events like PG splits, pool deletions, etc when
we get multiple incremental maps at once. Because check_pool_dne() can
now be fed an unlinked request, finish_request() needed to be taught to
handle unlinked requests.
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
-rw-r--r-- | include/linux/ceph/osd_client.h | 1 | ||||
-rw-r--r-- | net/ceph/debugfs.c | 2 | ||||
-rw-r--r-- | net/ceph/osd_client.c | 33 |
3 files changed, 27 insertions, 9 deletions
diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h index bca2718ac253..62c672bcbb31 100644 --- a/include/linux/ceph/osd_client.h +++ b/include/linux/ceph/osd_client.h | |||
@@ -149,6 +149,7 @@ struct ceph_osd_request_target { | |||
149 | unsigned int flags; /* CEPH_OSD_FLAG_* */ | 149 | unsigned int flags; /* CEPH_OSD_FLAG_* */ |
150 | bool paused; | 150 | bool paused; |
151 | 151 | ||
152 | u32 epoch; | ||
152 | u32 last_force_resend; | 153 | u32 last_force_resend; |
153 | 154 | ||
154 | int osd; | 155 | int osd; |
diff --git a/net/ceph/debugfs.c b/net/ceph/debugfs.c index 50ab1bdb16e2..c0089f8ccaeb 100644 --- a/net/ceph/debugfs.c +++ b/net/ceph/debugfs.c | |||
@@ -166,7 +166,7 @@ static void dump_target(struct seq_file *s, struct ceph_osd_request_target *t) | |||
166 | seq_printf(s, "]/%d\t[", t->up.primary); | 166 | seq_printf(s, "]/%d\t[", t->up.primary); |
167 | for (i = 0; i < t->acting.size; i++) | 167 | for (i = 0; i < t->acting.size; i++) |
168 | seq_printf(s, "%s%d", (!i ? "" : ","), t->acting.osds[i]); | 168 | seq_printf(s, "%s%d", (!i ? "" : ","), t->acting.osds[i]); |
169 | seq_printf(s, "]/%d\t", t->acting.primary); | 169 | seq_printf(s, "]/%d\te%u\t", t->acting.primary, t->epoch); |
170 | if (t->target_oloc.pool_ns) { | 170 | if (t->target_oloc.pool_ns) { |
171 | seq_printf(s, "%*pE/%*pE\t0x%x", | 171 | seq_printf(s, "%*pE/%*pE\t0x%x", |
172 | (int)t->target_oloc.pool_ns->len, | 172 | (int)t->target_oloc.pool_ns->len, |
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 576101b635ef..173ab9c68eb6 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
@@ -386,6 +386,7 @@ static void target_copy(struct ceph_osd_request_target *dest, | |||
386 | dest->flags = src->flags; | 386 | dest->flags = src->flags; |
387 | dest->paused = src->paused; | 387 | dest->paused = src->paused; |
388 | 388 | ||
389 | dest->epoch = src->epoch; | ||
389 | dest->last_force_resend = src->last_force_resend; | 390 | dest->last_force_resend = src->last_force_resend; |
390 | 391 | ||
391 | dest->osd = src->osd; | 392 | dest->osd = src->osd; |
@@ -1334,6 +1335,7 @@ static enum calc_target_result calc_target(struct ceph_osd_client *osdc, | |||
1334 | enum calc_target_result ct_res; | 1335 | enum calc_target_result ct_res; |
1335 | int ret; | 1336 | int ret; |
1336 | 1337 | ||
1338 | t->epoch = osdc->osdmap->epoch; | ||
1337 | pi = ceph_pg_pool_by_id(osdc->osdmap, t->base_oloc.pool); | 1339 | pi = ceph_pg_pool_by_id(osdc->osdmap, t->base_oloc.pool); |
1338 | if (!pi) { | 1340 | if (!pi) { |
1339 | t->osd = CEPH_HOMELESS_OSD; | 1341 | t->osd = CEPH_HOMELESS_OSD; |
@@ -1720,10 +1722,11 @@ static void send_request(struct ceph_osd_request *req) | |||
1720 | 1722 | ||
1721 | encode_request_partial(req, req->r_request); | 1723 | encode_request_partial(req, req->r_request); |
1722 | 1724 | ||
1723 | dout("%s req %p tid %llu to pgid %llu.%x spgid %llu.%xs%d osd%d flags 0x%x attempt %d\n", | 1725 | dout("%s req %p tid %llu to pgid %llu.%x spgid %llu.%xs%d osd%d e%u flags 0x%x attempt %d\n", |
1724 | __func__, req, req->r_tid, req->r_t.pgid.pool, req->r_t.pgid.seed, | 1726 | __func__, req, req->r_tid, req->r_t.pgid.pool, req->r_t.pgid.seed, |
1725 | req->r_t.spgid.pgid.pool, req->r_t.spgid.pgid.seed, | 1727 | req->r_t.spgid.pgid.pool, req->r_t.spgid.pgid.seed, |
1726 | req->r_t.spgid.shard, osd->o_osd, req->r_flags, req->r_attempts); | 1728 | req->r_t.spgid.shard, osd->o_osd, req->r_t.epoch, req->r_flags, |
1729 | req->r_attempts); | ||
1727 | 1730 | ||
1728 | req->r_t.paused = false; | 1731 | req->r_t.paused = false; |
1729 | req->r_stamp = jiffies; | 1732 | req->r_stamp = jiffies; |
@@ -1863,13 +1866,12 @@ static void submit_request(struct ceph_osd_request *req, bool wrlocked) | |||
1863 | static void finish_request(struct ceph_osd_request *req) | 1866 | static void finish_request(struct ceph_osd_request *req) |
1864 | { | 1867 | { |
1865 | struct ceph_osd_client *osdc = req->r_osdc; | 1868 | struct ceph_osd_client *osdc = req->r_osdc; |
1866 | struct ceph_osd *osd = req->r_osd; | ||
1867 | 1869 | ||
1868 | verify_osd_locked(osd); | 1870 | WARN_ON(lookup_request_mc(&osdc->map_checks, req->r_tid)); |
1869 | dout("%s req %p tid %llu\n", __func__, req, req->r_tid); | 1871 | dout("%s req %p tid %llu\n", __func__, req, req->r_tid); |
1870 | 1872 | ||
1871 | WARN_ON(lookup_request_mc(&osdc->map_checks, req->r_tid)); | 1873 | if (req->r_osd) |
1872 | unlink_request(osd, req); | 1874 | unlink_request(req->r_osd, req); |
1873 | atomic_dec(&osdc->num_requests); | 1875 | atomic_dec(&osdc->num_requests); |
1874 | 1876 | ||
1875 | /* | 1877 | /* |
@@ -3356,8 +3358,25 @@ static void kick_requests(struct ceph_osd_client *osdc, | |||
3356 | struct list_head *need_resend_linger) | 3358 | struct list_head *need_resend_linger) |
3357 | { | 3359 | { |
3358 | struct ceph_osd_linger_request *lreq, *nlreq; | 3360 | struct ceph_osd_linger_request *lreq, *nlreq; |
3361 | enum calc_target_result ct_res; | ||
3359 | struct rb_node *n; | 3362 | struct rb_node *n; |
3360 | 3363 | ||
3364 | /* make sure need_resend targets reflect latest map */ | ||
3365 | for (n = rb_first(need_resend); n; ) { | ||
3366 | struct ceph_osd_request *req = | ||
3367 | rb_entry(n, struct ceph_osd_request, r_node); | ||
3368 | |||
3369 | n = rb_next(n); | ||
3370 | |||
3371 | if (req->r_t.epoch < osdc->osdmap->epoch) { | ||
3372 | ct_res = calc_target(osdc, &req->r_t, NULL, false); | ||
3373 | if (ct_res == CALC_TARGET_POOL_DNE) { | ||
3374 | erase_request(need_resend, req); | ||
3375 | check_pool_dne(req); | ||
3376 | } | ||
3377 | } | ||
3378 | } | ||
3379 | |||
3361 | for (n = rb_first(need_resend); n; ) { | 3380 | for (n = rb_first(need_resend); n; ) { |
3362 | struct ceph_osd_request *req = | 3381 | struct ceph_osd_request *req = |
3363 | rb_entry(n, struct ceph_osd_request, r_node); | 3382 | rb_entry(n, struct ceph_osd_request, r_node); |
@@ -3366,8 +3385,6 @@ static void kick_requests(struct ceph_osd_client *osdc, | |||
3366 | n = rb_next(n); | 3385 | n = rb_next(n); |
3367 | erase_request(need_resend, req); /* before link_request() */ | 3386 | erase_request(need_resend, req); /* before link_request() */ |
3368 | 3387 | ||
3369 | WARN_ON(req->r_osd); | ||
3370 | calc_target(osdc, &req->r_t, NULL, false); | ||
3371 | osd = lookup_create_osd(osdc, req->r_t.osd, true); | 3388 | osd = lookup_create_osd(osdc, req->r_t.osd, true); |
3372 | link_request(osd, req); | 3389 | link_request(osd, req); |
3373 | if (!req->r_linger) { | 3390 | if (!req->r_linger) { |