static enum calc_target_result calc_target(struct ceph_osd_client *osdc,
                                           struct ceph_osd_request_target *t,
+                                          struct ceph_connection *con,
                                           bool any_change)
 {
        struct ceph_pg_pool_info *pi;
        bool force_resend = false;
        bool unpaused = false;
        bool legacy_change;
+       bool split = false;
        bool need_check_tiering = false;
        bool sort_bitwise = ceph_osdmap_flag(osdc, CEPH_OSDMAP_SORTBITWISE);
        enum calc_target_result ct_res;
        }
        legacy_change = ceph_pg_compare(&t->pgid, &pgid) ||
                        ceph_osds_changed(&t->acting, &acting, any_change);
+       if (t->pg_num)
+               split = ceph_pg_is_split(&last_pgid, t->pg_num, pi->pg_num);
 
-       if (legacy_change || force_resend) {
+       if (legacy_change || force_resend || split) {
                t->pgid = pgid; /* struct */
                ceph_pg_to_primary_shard(osdc->osdmap, &pgid, &t->spgid);
                ceph_osds_copy(&t->acting, &acting);
                t->osd = acting.primary;
        }
 
-       if (unpaused || legacy_change || force_resend)
+       if (unpaused || legacy_change || force_resend ||
+           (split && con && CEPH_HAVE_FEATURE(con->peer_features,
+                                              RESEND_ON_SPLIT)))
                ct_res = CALC_TARGET_NEED_RESEND;
        else
                ct_res = CALC_TARGET_NO_ACTION;
        dout("%s req %p wrlocked %d\n", __func__, req, wrlocked);
 
 again:
-       ct_res = calc_target(osdc, &req->r_t, false);
+       ct_res = calc_target(osdc, &req->r_t, NULL, false);
        if (ct_res == CALC_TARGET_POOL_DNE && !wrlocked)
                goto promote;
 
        struct ceph_osd_client *osdc = lreq->osdc;
        struct ceph_osd *osd;
 
-       calc_target(osdc, &lreq->t, false);
+       calc_target(osdc, &lreq->t, NULL, false);
        osd = lookup_create_osd(osdc, lreq->t.osd, true);
        link_linger(osd, lreq);
 
        struct ceph_osd_client *osdc = lreq->osdc;
        enum calc_target_result ct_res;
 
-       ct_res = calc_target(osdc, &lreq->t, true);
+       ct_res = calc_target(osdc, &lreq->t, NULL, true);
        if (ct_res == CALC_TARGET_NEED_RESEND) {
                struct ceph_osd *osd;
 
                n = rb_next(n); /* unlink_request(), check_pool_dne() */
 
                dout("%s req %p tid %llu\n", __func__, req, req->r_tid);
-               ct_res = calc_target(osdc, &req->r_t, false);
+               ct_res = calc_target(osdc, &req->r_t, &req->r_osd->o_con,
+                                    false);
                switch (ct_res) {
                case CALC_TARGET_NO_ACTION:
                        force_resend_writes = cleared_full ||
                erase_request(need_resend, req); /* before link_request() */
 
                WARN_ON(req->r_osd);
-               calc_target(osdc, &req->r_t, false);
+               calc_target(osdc, &req->r_t, NULL, false);
                osd = lookup_create_osd(osdc, req->r_t.osd, true);
                link_request(osd, req);
                if (!req->r_linger) {
 
        dest->primary = src->primary;
 }
 
-static bool is_split(const struct ceph_pg *pgid,
-                    u32 old_pg_num,
-                    u32 new_pg_num)
+bool ceph_pg_is_split(const struct ceph_pg *pgid, u32 old_pg_num,
+                     u32 new_pg_num)
 {
        int old_bits = calc_bits_of(old_pg_num);
        int old_mask = (1 << old_bits) - 1;
               !osds_equal(old_up, new_up) ||
               old_size != new_size ||
               old_min_size != new_min_size ||
-              is_split(pgid, old_pg_num, new_pg_num) ||
+              ceph_pg_is_split(pgid, old_pg_num, new_pg_num) ||
               old_sort_bitwise != new_sort_bitwise;
 }