From: Anthony PERARD <anthony.perard@citrix.com> To: xen-devel@lists.xenproject.org Cc: Anthony PERARD <anthony.perard@citrix.com>, Wei Liu <wei.liu2@citrix.com>, Ian Jackson <ian.jackson@eu.citrix.com> Subject: [PATCH 6/9] libxl_disk: Cut libxl_cdrom_insert into steps .. Date: Tue, 9 Apr 2019 17:45:39 +0100 [thread overview] Message-ID: <20190409164542.30274-7-anthony.perard@citrix.com> (raw) In-Reply-To: <20190409164542.30274-1-anthony.perard@citrix.com> .. and use a new "slow" lock. This patch cut libxl_cdrom_insert into different step/function but there are still called synchronously. A later patch will call them asynchronously when QMP is involved. The json_lock has been replaced by the qmp_lock for protection against concurrent changes to the cdrom. The json_lock is now only used when reading/modifying the domain userdata. Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> --- tools/libxl/libxl_disk.c | 172 ++++++++++++++++++++++++++++++--------- 1 file changed, 135 insertions(+), 37 deletions(-) diff --git a/tools/libxl/libxl_disk.c b/tools/libxl/libxl_disk.c index f7a1b75ae1..14dfc67971 100644 --- a/tools/libxl/libxl_disk.c +++ b/tools/libxl/libxl_disk.c @@ -661,24 +661,38 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid, return rc; } +typedef struct { + libxl__ao *ao; + libxl_domid domid; + libxl_device_disk *disk; + libxl_device_disk disk_saved; + libxl__domain_qmp_lock *qmp_lock; + int dm_ver; +} libxl__cdrom_insert_state; + +static void cdrom_insert_ejected(libxl__egc *egc, + libxl__cdrom_insert_state *cis); +static void cdrom_insert_inserted(libxl__egc *egc, + libxl__cdrom_insert_state *cis); +static void cdrom_insert_done(libxl__egc *egc, + libxl__cdrom_insert_state *cis, + int rc); + int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, const libxl_asyncop_how *ao_how) { AO_CREATE(ctx, domid, ao_how); int num = 0, i; - libxl_device_disk *disks = NULL, disk_saved; - libxl_domain_config d_config; - int rc, dm_ver; - libxl__device device; - const char *be_path, *libxl_path; - char * tmp; - libxl__domain_userdata_lock *lock = NULL; - xs_transaction_t t = XBT_NULL; - flexarray_t *insert = NULL, *empty = NULL; + libxl_device_disk *disks = NULL; + int rc; + libxl__cdrom_insert_state *cis; - libxl_domain_config_init(&d_config); - libxl_device_disk_init(&disk_saved); - libxl_device_disk_copy(ctx, &disk_saved, disk); + GCNEW(cis); + cis->ao = ao; + cis->domid = domid; + cis->disk = disk; + libxl_device_disk_init(&cis->disk_saved); + libxl_device_disk_copy(ctx, &cis->disk_saved, disk); libxl_domain_type type = libxl__domain_type(gc, domid); if (type == LIBXL_DOMAIN_TYPE_INVALID) { @@ -697,8 +711,8 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, goto out; } - dm_ver = libxl__device_model_version_running(gc, domid); - if (dm_ver == -1) { + cis->dm_ver = libxl__device_model_version_running(gc, domid); + if (cis->dm_ver == -1) { LOGD(ERROR, domid, "Cannot determine device model version"); rc = ERROR_FAIL; goto out; @@ -727,17 +741,8 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, disk->format = LIBXL_DISK_FORMAT_EMPTY; } - rc = libxl__device_from_disk(gc, domid, disk, &device); - if (rc) goto out; - - be_path = libxl__device_backend_path(gc, &device); - libxl_path = libxl__device_libxl_path(gc, &device); - - /* Note: CTX lock is already held at this point so lock hierarchy - * is maintained. - */ - lock = libxl__lock_domain_userdata(gc, domid); - if (!lock) { + cis->qmp_lock = libxl__lock_domain_qmp(gc, domid); + if (!cis->qmp_lock) { rc = ERROR_LOCK_FAIL; goto out; } @@ -746,7 +751,7 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, * by inserting empty media. JSON is not updated. */ - if (dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) { + if (cis->dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) { libxl_device_disk disk_empty; libxl_device_disk_init(&disk_empty); @@ -761,6 +766,48 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, if (rc) goto out; } + rc = 0; + +out: + libxl__device_list_free(&libxl__disk_devtype, disks, num); + if (rc) { + cdrom_insert_done(egc, cis, rc); /* must be last */ + } else { + cdrom_insert_ejected(egc, cis); /* must be last */ + } + return AO_INPROGRESS; +} + +static void cdrom_insert_ejected(libxl__egc *egc, + libxl__cdrom_insert_state *cis) +{ + EGC_GC; + int rc; + libxl__domain_userdata_lock *data_lock = NULL; + libxl__device device; + const char *be_path, *libxl_path; + flexarray_t *empty = NULL; + xs_transaction_t t = XBT_NULL; + char *tmp; + libxl_domain_config d_config; + + /* convenience aliases */ + libxl_domid domid = cis->domid; + libxl_device_disk *disk = cis->disk; + + libxl_domain_config_init(&d_config); + + rc = libxl__device_from_disk(gc, domid, disk, &device); + if (rc) goto out; + be_path = libxl__device_backend_path(gc, &device); + libxl_path = libxl__device_libxl_path(gc, &device); + + data_lock = libxl__lock_domain_userdata(gc, domid); + if (!data_lock) { + rc = ERROR_LOCK_FAIL; + goto out; + } + empty = flexarray_make(gc, 4, 1); flexarray_append_pair(empty, "type", libxl__device_disk_string_of_backend(disk->backend)); @@ -799,16 +846,66 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, rc = libxl__get_domain_configuration(gc, domid, &d_config); if (rc) goto out; - device_add_domain_config(gc, &d_config, &libxl__disk_devtype, &disk_saved); + device_add_domain_config(gc, &d_config, &libxl__disk_devtype, + &cis->disk_saved); rc = libxl__dm_check_start(gc, &d_config, domid); if (rc) goto out; - if (dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) { + if (cis->dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) { rc = libxl__qmp_insert_cdrom(gc, domid, disk); if (rc) goto out; } + rc = 0; + +out: + libxl__xs_transaction_abort(gc, &t); + libxl_domain_config_dispose(&d_config); + if (data_lock) libxl__unlock_domain_userdata(data_lock); + if (rc) { + cdrom_insert_done(egc, cis, rc); /* must be last */ + } else { + cdrom_insert_inserted(egc, cis); /* must be last */ + } +} + +static void cdrom_insert_inserted(libxl__egc *egc, + libxl__cdrom_insert_state *cis) +{ + EGC_GC; + int rc; + libxl__domain_userdata_lock *data_lock = NULL; + libxl_domain_config d_config; + flexarray_t *insert = NULL; + xs_transaction_t t = XBT_NULL; + libxl__device device; + const char *be_path, *libxl_path; + char * tmp; + + /* convenience aliases */ + libxl_domid domid = cis->domid; + libxl_device_disk *disk = cis->disk; + + libxl_domain_config_init(&d_config); + + rc = libxl__device_from_disk(gc, domid, disk, &device); + if (rc) goto out; + be_path = libxl__device_backend_path(gc, &device); + libxl_path = libxl__device_libxl_path(gc, &device); + + data_lock = libxl__lock_domain_userdata(gc, domid); + if (!data_lock) { + rc = ERROR_LOCK_FAIL; + goto out; + } + + rc = libxl__get_domain_configuration(gc, domid, &d_config); + if (rc) goto out; + + device_add_domain_config(gc, &d_config, &libxl__disk_devtype, + &cis->disk_saved); + insert = flexarray_make(gc, 4, 1); flexarray_append_pair(insert, "type", libxl__device_disk_string_of_backend(disk->backend)); @@ -849,21 +946,22 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, if (rc < 0) goto out; } - /* success, no actual async */ - libxl__ao_complete(egc, ao, 0); - rc = 0; out: libxl__xs_transaction_abort(gc, &t); - libxl__device_list_free(&libxl__disk_devtype, disks, num); - libxl_device_disk_dispose(&disk_saved); libxl_domain_config_dispose(&d_config); + if (data_lock) libxl__unlock_domain_userdata(data_lock); + cdrom_insert_done(egc, cis, rc); /* must be last */ +} - if (lock) libxl__unlock_domain_userdata(lock); - - if (rc) return AO_CREATE_FAIL(rc); - return AO_INPROGRESS; +static void cdrom_insert_done(libxl__egc *egc, + libxl__cdrom_insert_state *cis, + int rc) +{ + if (cis->qmp_lock) libxl__unlock_domain_qmp(cis->qmp_lock); + libxl_device_disk_dispose(&cis->disk_saved); + libxl__ao_complete(egc, cis->ao, rc); } /* libxl__alloc_vdev only works on the local domain, that is the domain -- Anthony PERARD _______________________________________________ Xen-devel mailing list Xen-devel@lists.xenproject.org https://lists.xenproject.org/mailman/listinfo/xen-devel
WARNING: multiple messages have this Message-ID (diff)
From: Anthony PERARD <anthony.perard@citrix.com> To: <xen-devel@lists.xenproject.org> Cc: Anthony PERARD <anthony.perard@citrix.com>, Wei Liu <wei.liu2@citrix.com>, Ian Jackson <ian.jackson@eu.citrix.com> Subject: [Xen-devel] [PATCH 6/9] libxl_disk: Cut libxl_cdrom_insert into steps .. Date: Tue, 9 Apr 2019 17:45:39 +0100 [thread overview] Message-ID: <20190409164542.30274-7-anthony.perard@citrix.com> (raw) Message-ID: <20190409164539.5J9res_WmCwrBTRrMKXd1kRwoKj1rjw-dvyD74EY9wI@z> (raw) In-Reply-To: <20190409164542.30274-1-anthony.perard@citrix.com> .. and use a new "slow" lock. This patch cut libxl_cdrom_insert into different step/function but there are still called synchronously. A later patch will call them asynchronously when QMP is involved. The json_lock has been replaced by the qmp_lock for protection against concurrent changes to the cdrom. The json_lock is now only used when reading/modifying the domain userdata. Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> --- tools/libxl/libxl_disk.c | 172 ++++++++++++++++++++++++++++++--------- 1 file changed, 135 insertions(+), 37 deletions(-) diff --git a/tools/libxl/libxl_disk.c b/tools/libxl/libxl_disk.c index f7a1b75ae1..14dfc67971 100644 --- a/tools/libxl/libxl_disk.c +++ b/tools/libxl/libxl_disk.c @@ -661,24 +661,38 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid, return rc; } +typedef struct { + libxl__ao *ao; + libxl_domid domid; + libxl_device_disk *disk; + libxl_device_disk disk_saved; + libxl__domain_qmp_lock *qmp_lock; + int dm_ver; +} libxl__cdrom_insert_state; + +static void cdrom_insert_ejected(libxl__egc *egc, + libxl__cdrom_insert_state *cis); +static void cdrom_insert_inserted(libxl__egc *egc, + libxl__cdrom_insert_state *cis); +static void cdrom_insert_done(libxl__egc *egc, + libxl__cdrom_insert_state *cis, + int rc); + int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, const libxl_asyncop_how *ao_how) { AO_CREATE(ctx, domid, ao_how); int num = 0, i; - libxl_device_disk *disks = NULL, disk_saved; - libxl_domain_config d_config; - int rc, dm_ver; - libxl__device device; - const char *be_path, *libxl_path; - char * tmp; - libxl__domain_userdata_lock *lock = NULL; - xs_transaction_t t = XBT_NULL; - flexarray_t *insert = NULL, *empty = NULL; + libxl_device_disk *disks = NULL; + int rc; + libxl__cdrom_insert_state *cis; - libxl_domain_config_init(&d_config); - libxl_device_disk_init(&disk_saved); - libxl_device_disk_copy(ctx, &disk_saved, disk); + GCNEW(cis); + cis->ao = ao; + cis->domid = domid; + cis->disk = disk; + libxl_device_disk_init(&cis->disk_saved); + libxl_device_disk_copy(ctx, &cis->disk_saved, disk); libxl_domain_type type = libxl__domain_type(gc, domid); if (type == LIBXL_DOMAIN_TYPE_INVALID) { @@ -697,8 +711,8 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, goto out; } - dm_ver = libxl__device_model_version_running(gc, domid); - if (dm_ver == -1) { + cis->dm_ver = libxl__device_model_version_running(gc, domid); + if (cis->dm_ver == -1) { LOGD(ERROR, domid, "Cannot determine device model version"); rc = ERROR_FAIL; goto out; @@ -727,17 +741,8 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, disk->format = LIBXL_DISK_FORMAT_EMPTY; } - rc = libxl__device_from_disk(gc, domid, disk, &device); - if (rc) goto out; - - be_path = libxl__device_backend_path(gc, &device); - libxl_path = libxl__device_libxl_path(gc, &device); - - /* Note: CTX lock is already held at this point so lock hierarchy - * is maintained. - */ - lock = libxl__lock_domain_userdata(gc, domid); - if (!lock) { + cis->qmp_lock = libxl__lock_domain_qmp(gc, domid); + if (!cis->qmp_lock) { rc = ERROR_LOCK_FAIL; goto out; } @@ -746,7 +751,7 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, * by inserting empty media. JSON is not updated. */ - if (dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) { + if (cis->dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) { libxl_device_disk disk_empty; libxl_device_disk_init(&disk_empty); @@ -761,6 +766,48 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, if (rc) goto out; } + rc = 0; + +out: + libxl__device_list_free(&libxl__disk_devtype, disks, num); + if (rc) { + cdrom_insert_done(egc, cis, rc); /* must be last */ + } else { + cdrom_insert_ejected(egc, cis); /* must be last */ + } + return AO_INPROGRESS; +} + +static void cdrom_insert_ejected(libxl__egc *egc, + libxl__cdrom_insert_state *cis) +{ + EGC_GC; + int rc; + libxl__domain_userdata_lock *data_lock = NULL; + libxl__device device; + const char *be_path, *libxl_path; + flexarray_t *empty = NULL; + xs_transaction_t t = XBT_NULL; + char *tmp; + libxl_domain_config d_config; + + /* convenience aliases */ + libxl_domid domid = cis->domid; + libxl_device_disk *disk = cis->disk; + + libxl_domain_config_init(&d_config); + + rc = libxl__device_from_disk(gc, domid, disk, &device); + if (rc) goto out; + be_path = libxl__device_backend_path(gc, &device); + libxl_path = libxl__device_libxl_path(gc, &device); + + data_lock = libxl__lock_domain_userdata(gc, domid); + if (!data_lock) { + rc = ERROR_LOCK_FAIL; + goto out; + } + empty = flexarray_make(gc, 4, 1); flexarray_append_pair(empty, "type", libxl__device_disk_string_of_backend(disk->backend)); @@ -799,16 +846,66 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, rc = libxl__get_domain_configuration(gc, domid, &d_config); if (rc) goto out; - device_add_domain_config(gc, &d_config, &libxl__disk_devtype, &disk_saved); + device_add_domain_config(gc, &d_config, &libxl__disk_devtype, + &cis->disk_saved); rc = libxl__dm_check_start(gc, &d_config, domid); if (rc) goto out; - if (dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) { + if (cis->dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) { rc = libxl__qmp_insert_cdrom(gc, domid, disk); if (rc) goto out; } + rc = 0; + +out: + libxl__xs_transaction_abort(gc, &t); + libxl_domain_config_dispose(&d_config); + if (data_lock) libxl__unlock_domain_userdata(data_lock); + if (rc) { + cdrom_insert_done(egc, cis, rc); /* must be last */ + } else { + cdrom_insert_inserted(egc, cis); /* must be last */ + } +} + +static void cdrom_insert_inserted(libxl__egc *egc, + libxl__cdrom_insert_state *cis) +{ + EGC_GC; + int rc; + libxl__domain_userdata_lock *data_lock = NULL; + libxl_domain_config d_config; + flexarray_t *insert = NULL; + xs_transaction_t t = XBT_NULL; + libxl__device device; + const char *be_path, *libxl_path; + char * tmp; + + /* convenience aliases */ + libxl_domid domid = cis->domid; + libxl_device_disk *disk = cis->disk; + + libxl_domain_config_init(&d_config); + + rc = libxl__device_from_disk(gc, domid, disk, &device); + if (rc) goto out; + be_path = libxl__device_backend_path(gc, &device); + libxl_path = libxl__device_libxl_path(gc, &device); + + data_lock = libxl__lock_domain_userdata(gc, domid); + if (!data_lock) { + rc = ERROR_LOCK_FAIL; + goto out; + } + + rc = libxl__get_domain_configuration(gc, domid, &d_config); + if (rc) goto out; + + device_add_domain_config(gc, &d_config, &libxl__disk_devtype, + &cis->disk_saved); + insert = flexarray_make(gc, 4, 1); flexarray_append_pair(insert, "type", libxl__device_disk_string_of_backend(disk->backend)); @@ -849,21 +946,22 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, if (rc < 0) goto out; } - /* success, no actual async */ - libxl__ao_complete(egc, ao, 0); - rc = 0; out: libxl__xs_transaction_abort(gc, &t); - libxl__device_list_free(&libxl__disk_devtype, disks, num); - libxl_device_disk_dispose(&disk_saved); libxl_domain_config_dispose(&d_config); + if (data_lock) libxl__unlock_domain_userdata(data_lock); + cdrom_insert_done(egc, cis, rc); /* must be last */ +} - if (lock) libxl__unlock_domain_userdata(lock); - - if (rc) return AO_CREATE_FAIL(rc); - return AO_INPROGRESS; +static void cdrom_insert_done(libxl__egc *egc, + libxl__cdrom_insert_state *cis, + int rc) +{ + if (cis->qmp_lock) libxl__unlock_domain_qmp(cis->qmp_lock); + libxl_device_disk_dispose(&cis->disk_saved); + libxl__ao_complete(egc, cis->ao, rc); } /* libxl__alloc_vdev only works on the local domain, that is the domain -- Anthony PERARD _______________________________________________ Xen-devel mailing list Xen-devel@lists.xenproject.org https://lists.xenproject.org/mailman/listinfo/xen-devel
next prev parent reply other threads:[~2019-04-09 16:45 UTC|newest] Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-04-09 16:45 [PATCH 0/9] libxl: New slow lock + fix libxl_cdrom_insert with QEMU depriv Anthony PERARD 2019-04-09 16:45 ` [Xen-devel] " Anthony PERARD 2019-04-09 16:45 ` [PATCH 1/9] libxl_internal: Remove lost comment Anthony PERARD 2019-04-09 16:45 ` [Xen-devel] " Anthony PERARD 2019-04-10 9:18 ` Wei Liu 2019-04-10 9:18 ` [Xen-devel] " Wei Liu 2019-06-04 16:42 ` Ian Jackson 2019-04-09 16:45 ` [PATCH 2/9] libxl: Pointer on usage of libxl__domain_userdata_lock Anthony PERARD 2019-04-09 16:45 ` [Xen-devel] " Anthony PERARD 2019-06-04 16:46 ` Ian Jackson 2019-04-09 16:45 ` [PATCH 3/9] libxl_internal: Split out userdata lock function Anthony PERARD 2019-04-09 16:45 ` [Xen-devel] " Anthony PERARD 2019-06-04 16:55 ` Ian Jackson 2019-04-09 16:45 ` [PATCH 4/9] libxl_internal: Create new lock for devices hotplug via QMP Anthony PERARD 2019-04-09 16:45 ` [Xen-devel] " Anthony PERARD 2019-06-04 17:11 ` Ian Jackson 2019-06-05 14:10 ` Anthony PERARD 2019-06-05 14:32 ` Ian Jackson 2019-04-09 16:45 ` [PATCH 5/9] libxl_disk: Reorganise libxl_cdrom_insert Anthony PERARD 2019-04-09 16:45 ` [Xen-devel] " Anthony PERARD 2019-06-04 17:16 ` Ian Jackson 2019-04-09 16:45 ` Anthony PERARD [this message] 2019-04-09 16:45 ` [Xen-devel] [PATCH 6/9] libxl_disk: Cut libxl_cdrom_insert into steps Anthony PERARD 2019-06-04 17:29 ` Ian Jackson 2019-06-07 17:22 ` Anthony PERARD 2019-04-09 16:45 ` [PATCH 7/9] libxl: Move qmp_parameters_* prototypes to libxl_internal.h Anthony PERARD 2019-04-09 16:45 ` [Xen-devel] " Anthony PERARD 2019-06-04 17:32 ` Ian Jackson 2019-04-09 16:45 ` [PATCH 8/9] libxl_disk: Use ev_qmp in libxl_cdrom_insert Anthony PERARD 2019-04-09 16:45 ` [Xen-devel] " Anthony PERARD 2019-06-04 17:45 ` Ian Jackson 2019-04-09 16:45 ` [PATCH 9/9] libxl_disk: Implement missing timeout for libxl_cdrom_insert Anthony PERARD 2019-04-09 16:45 ` [Xen-devel] " Anthony PERARD 2019-06-04 17:47 ` Ian Jackson 2019-06-05 14:22 ` Anthony PERARD 2019-06-05 14:33 ` Ian Jackson 2019-06-04 10:54 ` [Xen-devel] Ping: [PATCH 0/9] libxl: New slow lock + fix libxl_cdrom_insert with QEMU depriv Anthony PERARD
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20190409164542.30274-7-anthony.perard@citrix.com \ --to=anthony.perard@citrix.com \ --cc=ian.jackson@eu.citrix.com \ --cc=wei.liu2@citrix.com \ --cc=xen-devel@lists.xenproject.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.