All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH bpf-next 1/2] bpf: return target info when a tracing bpf_link is queried
@ 2021-04-08 19:57 Toke Høiland-Jørgensen
  2021-04-08 19:57 ` [PATCH bpf-next 2/2] selftests/bpf: add tests for target information in bpf_link info queries Toke Høiland-Jørgensen
  2021-04-13  3:41 ` [PATCH bpf-next 1/2] bpf: return target info when a tracing bpf_link is queried Andrii Nakryiko
  0 siblings, 2 replies; 7+ messages in thread
From: Toke Høiland-Jørgensen @ 2021-04-08 19:57 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann
  Cc: Toke Høiland-Jørgensen, Andrii Nakryiko,
	Martin KaFai Lau, Song Liu, Yonghong Song, John Fastabend,
	KP Singh, Stanislav Fomichev, bpf

There is currently no way to discover the target of a tracing program
attachment after the fact. Add this information to bpf_link_info and return
it when querying the bpf_link fd.

Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
---
 include/linux/bpf_verifier.h   | 9 +++++++++
 include/uapi/linux/bpf.h       | 2 ++
 kernel/bpf/syscall.c           | 3 +++
 tools/include/uapi/linux/bpf.h | 2 ++
 4 files changed, 16 insertions(+)

diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 51c2ffa3d901..6023a1367853 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -487,6 +487,15 @@ static inline u64 bpf_trampoline_compute_key(const struct bpf_prog *tgt_prog,
 		return ((u64)btf_obj_id(btf) << 32) | 0x80000000 | btf_id;
 }
 
+/* unpack the IDs from the key as constructed above */
+static inline void bpf_trampoline_unpack_key(u64 key, u32 *obj_id, u32 *btf_id)
+{
+	if (obj_id)
+		*obj_id = key >> 32;
+	if (btf_id)
+		*btf_id = key & 0x7FFFFFFF;
+}
+
 int bpf_check_attach_target(struct bpf_verifier_log *log,
 			    const struct bpf_prog *prog,
 			    const struct bpf_prog *tgt_prog,
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 49371eba98ba..397884396671 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -5379,6 +5379,8 @@ struct bpf_link_info {
 		} raw_tracepoint;
 		struct {
 			__u32 attach_type;
+			__u32 target_obj_id; /* prog_id for PROG_EXT, otherwise btf object id */
+			__u32 target_btf_id; /* BTF type id inside the object */
 		} tracing;
 		struct {
 			__u64 cgroup_id;
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 6428634da57e..fd495190115e 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -2551,6 +2551,9 @@ static int bpf_tracing_link_fill_link_info(const struct bpf_link *link,
 		container_of(link, struct bpf_tracing_link, link);
 
 	info->tracing.attach_type = tr_link->attach_type;
+	bpf_trampoline_unpack_key(tr_link->trampoline->key,
+				  &info->tracing.target_obj_id,
+				  &info->tracing.target_btf_id);
 
 	return 0;
 }
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 69902603012c..1a240be873d7 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -5373,6 +5373,8 @@ struct bpf_link_info {
 		} raw_tracepoint;
 		struct {
 			__u32 attach_type;
+			__u32 target_obj_id; /* prog_id for PROG_EXT, otherwise btf object id */
+			__u32 target_btf_id; /* BTF type id inside the object */
 		} tracing;
 		struct {
 			__u64 cgroup_id;
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH bpf-next 2/2] selftests/bpf: add tests for target information in bpf_link info queries
  2021-04-08 19:57 [PATCH bpf-next 1/2] bpf: return target info when a tracing bpf_link is queried Toke Høiland-Jørgensen
@ 2021-04-08 19:57 ` Toke Høiland-Jørgensen
  2021-04-13  3:46   ` Andrii Nakryiko
  2021-04-13  3:41 ` [PATCH bpf-next 1/2] bpf: return target info when a tracing bpf_link is queried Andrii Nakryiko
  1 sibling, 1 reply; 7+ messages in thread
From: Toke Høiland-Jørgensen @ 2021-04-08 19:57 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann
  Cc: Toke Høiland-Jørgensen, Andrii Nakryiko,
	Martin KaFai Lau, Song Liu, Yonghong Song, John Fastabend,
	KP Singh, Stanislav Fomichev, bpf

Extend the fexit_bpf2bpf test to check that the info for the bpf_link
returned by the kernel matches the expected values.

While we're updating the test, change existing uses of CHEC() to use the
much easier to read ASSERT_*() macros.

Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
---
 .../selftests/bpf/prog_tests/fexit_bpf2bpf.c  | 50 +++++++++++++++----
 1 file changed, 39 insertions(+), 11 deletions(-)

diff --git a/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c b/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
index 5c0448910426..019a46d8e98e 100644
--- a/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
+++ b/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
@@ -57,11 +57,13 @@ static void test_fexit_bpf2bpf_common(const char *obj_file,
 				      bool run_prog,
 				      test_cb cb)
 {
+	__u32 duration = 0, retval, tgt_prog_id, info_len;
 	struct bpf_object *obj = NULL, *tgt_obj;
+	struct bpf_prog_info prog_info = {};
 	struct bpf_program **prog = NULL;
 	struct bpf_link **link = NULL;
-	__u32 duration = 0, retval;
 	int err, tgt_fd, i;
+	struct btf *btf;
 
 	err = bpf_prog_load(target_obj_file, BPF_PROG_TYPE_UNSPEC,
 			    &tgt_obj, &tgt_fd);
@@ -72,28 +74,55 @@ static void test_fexit_bpf2bpf_common(const char *obj_file,
 			    .attach_prog_fd = tgt_fd,
 			   );
 
+	info_len = sizeof(prog_info);
+	err = bpf_obj_get_info_by_fd(tgt_fd, &prog_info, &info_len);
+	if (!ASSERT_OK(err, "tgt_fd_get_info"))
+		goto close_prog;
+
+	tgt_prog_id = prog_info.id;
+	btf = bpf_object__btf(tgt_obj);
+
 	link = calloc(sizeof(struct bpf_link *), prog_cnt);
 	prog = calloc(sizeof(struct bpf_program *), prog_cnt);
-	if (CHECK(!link || !prog, "alloc_memory", "failed to alloc memory"))
+	if (!ASSERT_OK_PTR(link, "link_ptr") || !ASSERT_OK_PTR(prog, "prog_ptr"))
 		goto close_prog;
 
 	obj = bpf_object__open_file(obj_file, &opts);
-	if (CHECK(IS_ERR_OR_NULL(obj), "obj_open",
-		  "failed to open %s: %ld\n", obj_file,
-		  PTR_ERR(obj)))
+	if (!ASSERT_OK_PTR(obj, "obj_open"))
 		goto close_prog;
 
 	err = bpf_object__load(obj);
-	if (CHECK(err, "obj_load", "err %d\n", err))
+	if (!ASSERT_OK(err, "obj_load"))
 		goto close_prog;
 
 	for (i = 0; i < prog_cnt; i++) {
+		struct bpf_link_info link_info;
+		char *tgt_name;
+		__s32 btf_id;
+
+		tgt_name = strstr(prog_name[i], "/");
+		if (!ASSERT_OK_PTR(tgt_name, "tgt_name"))
+			goto close_prog;
+		btf_id = btf__find_by_name_kind(btf, tgt_name + 1, BTF_KIND_FUNC);
+
 		prog[i] = bpf_object__find_program_by_title(obj, prog_name[i]);
-		if (CHECK(!prog[i], "find_prog", "prog %s not found\n", prog_name[i]))
+		if (!ASSERT_OK_PTR(prog[i], prog_name[i]))
 			goto close_prog;
+
 		link[i] = bpf_program__attach_trace(prog[i]);
-		if (CHECK(IS_ERR(link[i]), "attach_trace", "failed to link\n"))
+		if (!ASSERT_OK_PTR(link[i], "attach_trace"))
 			goto close_prog;
+
+		info_len = sizeof(link_info);
+		memset(&link_info, 0, sizeof(link_info));
+		err = bpf_obj_get_info_by_fd(bpf_link__fd(link[i]),
+					     &link_info, &info_len);
+		ASSERT_OK(err, "link_fd_get_info");
+		ASSERT_EQ(link_info.tracing.attach_type,
+			  bpf_program__get_expected_attach_type(prog[i]),
+			  "link_attach_type");
+		ASSERT_EQ(link_info.tracing.target_obj_id, tgt_prog_id, "link_tgt_obj_id");
+		ASSERT_EQ(link_info.tracing.target_btf_id, btf_id, "link_tgt_btf_id");
 	}
 
 	if (cb) {
@@ -107,9 +136,8 @@ static void test_fexit_bpf2bpf_common(const char *obj_file,
 
 	err = bpf_prog_test_run(tgt_fd, 1, &pkt_v6, sizeof(pkt_v6),
 				NULL, NULL, &retval, &duration);
-	CHECK(err || retval, "ipv6",
-	      "err %d errno %d retval %d duration %d\n",
-	      err, errno, retval, duration);
+	ASSERT_OK(err, "prog_run");
+	ASSERT_EQ(retval, 0, "prog_run_ret");
 
 	if (check_data_map(obj, prog_cnt, false))
 		goto close_prog;
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf-next 1/2] bpf: return target info when a tracing bpf_link is queried
  2021-04-08 19:57 [PATCH bpf-next 1/2] bpf: return target info when a tracing bpf_link is queried Toke Høiland-Jørgensen
  2021-04-08 19:57 ` [PATCH bpf-next 2/2] selftests/bpf: add tests for target information in bpf_link info queries Toke Høiland-Jørgensen
@ 2021-04-13  3:41 ` Andrii Nakryiko
  1 sibling, 0 replies; 7+ messages in thread
From: Andrii Nakryiko @ 2021-04-13  3:41 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Martin KaFai Lau, Song Liu, Yonghong Song, John Fastabend,
	KP Singh, Stanislav Fomichev, bpf

On Thu, Apr 8, 2021 at 12:57 PM Toke Høiland-Jørgensen <toke@redhat.com> wrote:
>
> There is currently no way to discover the target of a tracing program
> attachment after the fact. Add this information to bpf_link_info and return
> it when querying the bpf_link fd.
>
> Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
> ---

LGTM.

Acked-by: Andrii Nakryiko <andrii@kernel.org>

>  include/linux/bpf_verifier.h   | 9 +++++++++
>  include/uapi/linux/bpf.h       | 2 ++
>  kernel/bpf/syscall.c           | 3 +++
>  tools/include/uapi/linux/bpf.h | 2 ++
>  4 files changed, 16 insertions(+)
>

[...]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf-next 2/2] selftests/bpf: add tests for target information in bpf_link info queries
  2021-04-08 19:57 ` [PATCH bpf-next 2/2] selftests/bpf: add tests for target information in bpf_link info queries Toke Høiland-Jørgensen
@ 2021-04-13  3:46   ` Andrii Nakryiko
  2021-04-13  8:52     ` Toke Høiland-Jørgensen
  2021-04-13  9:07     ` Toke Høiland-Jørgensen
  0 siblings, 2 replies; 7+ messages in thread
From: Andrii Nakryiko @ 2021-04-13  3:46 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Martin KaFai Lau, Song Liu, Yonghong Song, John Fastabend,
	KP Singh, Stanislav Fomichev, bpf

On Thu, Apr 8, 2021 at 12:57 PM Toke Høiland-Jørgensen <toke@redhat.com> wrote:
>
> Extend the fexit_bpf2bpf test to check that the info for the bpf_link
> returned by the kernel matches the expected values.
>
> While we're updating the test, change existing uses of CHEC() to use the
> much easier to read ASSERT_*() macros.
>
> Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
> ---

Just a minor nit below. Looks good, thanks.

Acked-by: Andrii Nakryiko <andrii@kernel.org>

>  .../selftests/bpf/prog_tests/fexit_bpf2bpf.c  | 50 +++++++++++++++----
>  1 file changed, 39 insertions(+), 11 deletions(-)
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c b/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
> index 5c0448910426..019a46d8e98e 100644
> --- a/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
> +++ b/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
> @@ -57,11 +57,13 @@ static void test_fexit_bpf2bpf_common(const char *obj_file,
>                                       bool run_prog,
>                                       test_cb cb)
>  {
> +       __u32 duration = 0, retval, tgt_prog_id, info_len;

if not CHECK() is used, duration shouldn't be needed anymore

>         struct bpf_object *obj = NULL, *tgt_obj;
> +       struct bpf_prog_info prog_info = {};
>         struct bpf_program **prog = NULL;
>         struct bpf_link **link = NULL;
> -       __u32 duration = 0, retval;
>         int err, tgt_fd, i;
> +       struct btf *btf;
>
>         err = bpf_prog_load(target_obj_file, BPF_PROG_TYPE_UNSPEC,
>                             &tgt_obj, &tgt_fd);
> @@ -72,28 +74,55 @@ static void test_fexit_bpf2bpf_common(const char *obj_file,
>                             .attach_prog_fd = tgt_fd,
>                            );
>
> +       info_len = sizeof(prog_info);
> +       err = bpf_obj_get_info_by_fd(tgt_fd, &prog_info, &info_len);
> +       if (!ASSERT_OK(err, "tgt_fd_get_info"))
> +               goto close_prog;
> +
> +       tgt_prog_id = prog_info.id;
> +       btf = bpf_object__btf(tgt_obj);
> +
>         link = calloc(sizeof(struct bpf_link *), prog_cnt);
>         prog = calloc(sizeof(struct bpf_program *), prog_cnt);
> -       if (CHECK(!link || !prog, "alloc_memory", "failed to alloc memory"))
> +       if (!ASSERT_OK_PTR(link, "link_ptr") || !ASSERT_OK_PTR(prog, "prog_ptr"))

nit: can you split them into two independent ifs now? Just one extra
`goto close_prog` is no big deal, but reads nicer

>                 goto close_prog;
>
>         obj = bpf_object__open_file(obj_file, &opts);
> -       if (CHECK(IS_ERR_OR_NULL(obj), "obj_open",
> -                 "failed to open %s: %ld\n", obj_file,
> -                 PTR_ERR(obj)))
> +       if (!ASSERT_OK_PTR(obj, "obj_open"))
>                 goto close_prog;
>
>         err = bpf_object__load(obj);
> -       if (CHECK(err, "obj_load", "err %d\n", err))
> +       if (!ASSERT_OK(err, "obj_load"))
>                 goto close_prog;
>

[...]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf-next 2/2] selftests/bpf: add tests for target information in bpf_link info queries
  2021-04-13  3:46   ` Andrii Nakryiko
@ 2021-04-13  8:52     ` Toke Høiland-Jørgensen
  2021-04-13  9:07     ` Toke Høiland-Jørgensen
  1 sibling, 0 replies; 7+ messages in thread
From: Toke Høiland-Jørgensen @ 2021-04-13  8:52 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Martin KaFai Lau, Song Liu, Yonghong Song, John Fastabend,
	KP Singh, Stanislav Fomichev, bpf

Andrii Nakryiko <andrii.nakryiko@gmail.com> writes:

> On Thu, Apr 8, 2021 at 12:57 PM Toke Høiland-Jørgensen <toke@redhat.com> wrote:
>>
>> Extend the fexit_bpf2bpf test to check that the info for the bpf_link
>> returned by the kernel matches the expected values.
>>
>> While we're updating the test, change existing uses of CHEC() to use the
>> much easier to read ASSERT_*() macros.
>>
>> Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
>> ---
>
> Just a minor nit below. Looks good, thanks.

Right, will fix those and respin - thanks! :)

-Toke


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf-next 2/2] selftests/bpf: add tests for target information in bpf_link info queries
  2021-04-13  3:46   ` Andrii Nakryiko
  2021-04-13  8:52     ` Toke Høiland-Jørgensen
@ 2021-04-13  9:07     ` Toke Høiland-Jørgensen
  2021-04-13  9:16       ` Toke Høiland-Jørgensen
  1 sibling, 1 reply; 7+ messages in thread
From: Toke Høiland-Jørgensen @ 2021-04-13  9:07 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Martin KaFai Lau, Song Liu, Yonghong Song, John Fastabend,
	KP Singh, Stanislav Fomichev, bpf

Andrii Nakryiko <andrii.nakryiko@gmail.com> writes:

> On Thu, Apr 8, 2021 at 12:57 PM Toke Høiland-Jørgensen <toke@redhat.com> wrote:
>>
>> Extend the fexit_bpf2bpf test to check that the info for the bpf_link
>> returned by the kernel matches the expected values.
>>
>> While we're updating the test, change existing uses of CHEC() to use the
>> much easier to read ASSERT_*() macros.
>>
>> Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
>> ---
>
> Just a minor nit below. Looks good, thanks.
>
> Acked-by: Andrii Nakryiko <andrii@kernel.org>
>
>>  .../selftests/bpf/prog_tests/fexit_bpf2bpf.c  | 50 +++++++++++++++----
>>  1 file changed, 39 insertions(+), 11 deletions(-)
>>
>> diff --git a/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c b/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
>> index 5c0448910426..019a46d8e98e 100644
>> --- a/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
>> +++ b/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
>> @@ -57,11 +57,13 @@ static void test_fexit_bpf2bpf_common(const char *obj_file,
>>                                       bool run_prog,
>>                                       test_cb cb)
>>  {
>> +       __u32 duration = 0, retval, tgt_prog_id, info_len;
>
> if not CHECK() is used, duration shouldn't be needed anymore

Oh, and duration is still needed for bpf_prog_test_run(), so I'll keep
that; but removing it did make the compiler point out that I missed one
CHECK() at the beginning of the function when converting, so will fix
that instead :)

-Toke


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf-next 2/2] selftests/bpf: add tests for target information in bpf_link info queries
  2021-04-13  9:07     ` Toke Høiland-Jørgensen
@ 2021-04-13  9:16       ` Toke Høiland-Jørgensen
  0 siblings, 0 replies; 7+ messages in thread
From: Toke Høiland-Jørgensen @ 2021-04-13  9:16 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Martin KaFai Lau, Song Liu, Yonghong Song, John Fastabend,
	KP Singh, Stanislav Fomichev, bpf

Toke Høiland-Jørgensen <toke@redhat.com> writes:

> Andrii Nakryiko <andrii.nakryiko@gmail.com> writes:
>
>> On Thu, Apr 8, 2021 at 12:57 PM Toke Høiland-Jørgensen <toke@redhat.com> wrote:
>>>
>>> Extend the fexit_bpf2bpf test to check that the info for the bpf_link
>>> returned by the kernel matches the expected values.
>>>
>>> While we're updating the test, change existing uses of CHEC() to use the
>>> much easier to read ASSERT_*() macros.
>>>
>>> Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
>>> ---
>>
>> Just a minor nit below. Looks good, thanks.
>>
>> Acked-by: Andrii Nakryiko <andrii@kernel.org>
>>
>>>  .../selftests/bpf/prog_tests/fexit_bpf2bpf.c  | 50 +++++++++++++++----
>>>  1 file changed, 39 insertions(+), 11 deletions(-)
>>>
>>> diff --git a/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c b/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
>>> index 5c0448910426..019a46d8e98e 100644
>>> --- a/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
>>> +++ b/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
>>> @@ -57,11 +57,13 @@ static void test_fexit_bpf2bpf_common(const char *obj_file,
>>>                                       bool run_prog,
>>>                                       test_cb cb)
>>>  {
>>> +       __u32 duration = 0, retval, tgt_prog_id, info_len;
>>
>> if not CHECK() is used, duration shouldn't be needed anymore
>
> Oh, and duration is still needed for bpf_prog_test_run(), so I'll keep
> that; but removing it did make the compiler point out that I missed one
> CHECK() at the beginning of the function when converting, so will fix
> that instead :)

Argh, no, bpf_prog_test_run() will accept a NULL pointer for duration;
sorry for the noise!

-Toke


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-04-13  9:16 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-08 19:57 [PATCH bpf-next 1/2] bpf: return target info when a tracing bpf_link is queried Toke Høiland-Jørgensen
2021-04-08 19:57 ` [PATCH bpf-next 2/2] selftests/bpf: add tests for target information in bpf_link info queries Toke Høiland-Jørgensen
2021-04-13  3:46   ` Andrii Nakryiko
2021-04-13  8:52     ` Toke Høiland-Jørgensen
2021-04-13  9:07     ` Toke Høiland-Jørgensen
2021-04-13  9:16       ` Toke Høiland-Jørgensen
2021-04-13  3:41 ` [PATCH bpf-next 1/2] bpf: return target info when a tracing bpf_link is queried Andrii Nakryiko

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.