static int htab_save_later_pass(QEMUFile *f, sPAPREnvironment *spapr,

                                int64_t max_ns)

{

    bool final = max_ns < 0;

    int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64;

    int examined = 0, sent = 0;

    int index = spapr->htab_save_index;

    int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);



    assert(!spapr->htab_first_pass);



    do {

        int chunkstart, invalidstart;



        /* Consume non-dirty HPTEs */

        while ((index < htabslots)

               && !HPTE_DIRTY(HPTE(spapr->htab, index))) {

            index++;

            examined++;

        }



        chunkstart = index;

        /* Consume valid dirty HPTEs */

        while ((index < htabslots)

               && HPTE_DIRTY(HPTE(spapr->htab, index))

               && HPTE_VALID(HPTE(spapr->htab, index))) {

            CLEAN_HPTE(HPTE(spapr->htab, index));

            index++;

            examined++;

        }



        invalidstart = index;

        /* Consume invalid dirty HPTEs */

        while ((index < htabslots)

               && HPTE_DIRTY(HPTE(spapr->htab, index))

               && !HPTE_VALID(HPTE(spapr->htab, index))) {

            CLEAN_HPTE(HPTE(spapr->htab, index));

            index++;

            examined++;

        }



        if (index > chunkstart) {

            int n_valid = invalidstart - chunkstart;

            int n_invalid = index - invalidstart;



            qemu_put_be32(f, chunkstart);

            qemu_put_be16(f, n_valid);

            qemu_put_be16(f, n_invalid);

            qemu_put_buffer(f, HPTE(spapr->htab, chunkstart),

                            HASH_PTE_SIZE_64 * n_valid);

            sent += index - chunkstart;



            if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) {

                break;

            }

        }



        if (examined >= htabslots) {

            break;

        }



        if (index >= htabslots) {

            assert(index == htabslots);

            index = 0;

        }

    } while ((examined < htabslots) && (!qemu_file_rate_limit(f) || final));



    if (index >= htabslots) {

        assert(index == htabslots);

        index = 0;

    }



    spapr->htab_save_index = index;



    return (examined >= htabslots) && (sent == 0) ? 1 : 0;

}
