bpf.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* linux-next: manual merge of the bpf-next tree with Linus' tree
@ 2022-01-24 21:56 Stephen Rothwell
  0 siblings, 0 replies; 4+ messages in thread
From: Stephen Rothwell @ 2022-01-24 21:56 UTC (permalink / raw)
  To: Daniel Borkmann, Alexei Starovoitov, Andrii Nakryiko, bpf, Networking
  Cc: Linux Kernel Mailing List, Linux Next Mailing List,
	Toke Høiland-Jørgensen

[-- Attachment #1: Type: text/plain, Size: 4688 bytes --]

Hi all,

Today's linux-next merge of the bpf-next tree got a conflict in:

  tools/testing/selftests/bpf/prog_tests/xdp_link.c

between commit:

  4b27480dcaa7 ("bpf/selftests: convert xdp_link test to ASSERT_* macros")

from Linus' tree and commit:

  544356524dd6 ("selftests/bpf: switch to new libbpf XDP APIs")

from the bpf-next tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc tools/testing/selftests/bpf/prog_tests/xdp_link.c
index b2b357f8c74c,0c5e4ea8eaae..000000000000
--- a/tools/testing/selftests/bpf/prog_tests/xdp_link.c
+++ b/tools/testing/selftests/bpf/prog_tests/xdp_link.c
@@@ -8,9 -8,9 +8,9 @@@
  
  void serial_test_xdp_link(void)
  {
- 	DECLARE_LIBBPF_OPTS(bpf_xdp_set_link_opts, opts, .old_fd = -1);
 -	__u32 duration = 0, id1, id2, id0 = 0, prog_fd1, prog_fd2, err;
  	struct test_xdp_link *skel1 = NULL, *skel2 = NULL;
 +	__u32 id1, id2, id0 = 0, prog_fd1, prog_fd2;
+ 	LIBBPF_OPTS(bpf_xdp_attach_opts, opts);
  	struct bpf_link_info link_info;
  	struct bpf_prog_info prog_info;
  	struct bpf_link *link;
@@@ -41,14 -40,14 +41,14 @@@
  	id2 = prog_info.id;
  
  	/* set initial prog attachment */
- 	err = bpf_set_link_xdp_fd_opts(IFINDEX_LO, prog_fd1, XDP_FLAGS_REPLACE, &opts);
+ 	err = bpf_xdp_attach(IFINDEX_LO, prog_fd1, XDP_FLAGS_REPLACE, &opts);
 -	if (CHECK(err, "fd_attach", "initial prog attach failed: %d\n", err))
 +	if (!ASSERT_OK(err, "fd_attach"))
  		goto cleanup;
  
  	/* validate prog ID */
- 	err = bpf_get_link_xdp_id(IFINDEX_LO, &id0, 0);
+ 	err = bpf_xdp_query_id(IFINDEX_LO, 0, &id0);
 -	CHECK(err || id0 != id1, "id1_check",
 -	      "loaded prog id %u != id1 %u, err %d", id0, id1, err);
 +	if (!ASSERT_OK(err, "id1_check_err") || !ASSERT_EQ(id0, id1, "id1_check_val"))
 +		goto cleanup;
  
  	/* BPF link is not allowed to replace prog attachment */
  	link = bpf_program__attach_xdp(skel1->progs.xdp_handler, IFINDEX_LO);
@@@ -61,9 -60,9 +61,9 @@@
  	}
  
  	/* detach BPF program */
- 	opts.old_fd = prog_fd1;
- 	err = bpf_set_link_xdp_fd_opts(IFINDEX_LO, -1, XDP_FLAGS_REPLACE, &opts);
+ 	opts.old_prog_fd = prog_fd1;
+ 	err = bpf_xdp_detach(IFINDEX_LO, XDP_FLAGS_REPLACE, &opts);
 -	if (CHECK(err, "prog_detach", "failed %d\n", err))
 +	if (!ASSERT_OK(err, "prog_detach"))
  		goto cleanup;
  
  	/* now BPF link should attach successfully */
@@@ -73,24 -72,25 +73,24 @@@
  	skel1->links.xdp_handler = link;
  
  	/* validate prog ID */
- 	err = bpf_get_link_xdp_id(IFINDEX_LO, &id0, 0);
+ 	err = bpf_xdp_query_id(IFINDEX_LO, 0, &id0);
 -	if (CHECK(err || id0 != id1, "id1_check",
 -		  "loaded prog id %u != id1 %u, err %d", id0, id1, err))
 +	if (!ASSERT_OK(err, "id1_check_err") || !ASSERT_EQ(id0, id1, "id1_check_val"))
  		goto cleanup;
  
  	/* BPF prog attach is not allowed to replace BPF link */
- 	opts.old_fd = prog_fd1;
- 	err = bpf_set_link_xdp_fd_opts(IFINDEX_LO, prog_fd2, XDP_FLAGS_REPLACE, &opts);
+ 	opts.old_prog_fd = prog_fd1;
+ 	err = bpf_xdp_attach(IFINDEX_LO, prog_fd2, XDP_FLAGS_REPLACE, &opts);
 -	if (CHECK(!err, "prog_attach_fail", "unexpected success\n"))
 +	if (!ASSERT_ERR(err, "prog_attach_fail"))
  		goto cleanup;
  
  	/* Can't force-update when BPF link is active */
- 	err = bpf_set_link_xdp_fd(IFINDEX_LO, prog_fd2, 0);
+ 	err = bpf_xdp_attach(IFINDEX_LO, prog_fd2, 0, NULL);
 -	if (CHECK(!err, "prog_update_fail", "unexpected success\n"))
 +	if (!ASSERT_ERR(err, "prog_update_fail"))
  		goto cleanup;
  
  	/* Can't force-detach when BPF link is active */
- 	err = bpf_set_link_xdp_fd(IFINDEX_LO, -1, 0);
+ 	err = bpf_xdp_detach(IFINDEX_LO, 0, NULL);
 -	if (CHECK(!err, "prog_detach_fail", "unexpected success\n"))
 +	if (!ASSERT_ERR(err, "prog_detach_fail"))
  		goto cleanup;
  
  	/* BPF link is not allowed to replace another BPF link */
@@@ -109,8 -109,9 +109,8 @@@
  		goto cleanup;
  	skel2->links.xdp_handler = link;
  
- 	err = bpf_get_link_xdp_id(IFINDEX_LO, &id0, 0);
+ 	err = bpf_xdp_query_id(IFINDEX_LO, 0, &id0);
 -	if (CHECK(err || id0 != id2, "id2_check",
 -		  "loaded prog id %u != id2 %u, err %d", id0, id1, err))
 +	if (!ASSERT_OK(err, "id2_check_err") || !ASSERT_EQ(id0, id2, "id2_check_val"))
  		goto cleanup;
  
  	/* updating program under active BPF link works as expected */

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: linux-next: manual merge of the bpf-next tree with Linus' tree
  2023-01-23 22:44 Stephen Rothwell
@ 2023-01-23 22:58 ` Stanislav Fomichev
  0 siblings, 0 replies; 4+ messages in thread
From: Stanislav Fomichev @ 2023-01-23 22:58 UTC (permalink / raw)
  To: Stephen Rothwell
  Cc: Daniel Borkmann, Alexei Starovoitov, Andrii Nakryiko, bpf,
	Networking, Linux Kernel Mailing List, Linux Next Mailing List,
	Martin KaFai Lau, Paul Moore

On Mon, Jan 23, 2023 at 2:44 PM Stephen Rothwell <sfr@canb.auug.org.au> wrote:
>
> Hi all,
>
> Today's linux-next merge of the bpf-next tree got a conflict in:
>
>   kernel/bpf/offload.c
>
> between commit:
>
>   ef01f4e25c17 ("bpf: restore the ebpf program ID for BPF_AUDIT_UNLOAD and PERF_BPF_EVENT_PROG_UNLOAD")
>
> from Linus' tree and commit:
>
>   89bbc53a4dbb ("bpf: Reshuffle some parts of bpf/offload.c")
>
> from the bpf-next tree.
>
> I fixed it up (see below) and can carry the fix as necessary. This
> is now fixed as far as linux-next is concerned, but any non trivial
> conflicts should be mentioned to your upstream maintainer when your tree
> is submitted for merging.  You may also want to consider cooperating
> with the maintainer of the conflicting tree to minimise any particularly
> complex conflicts.

Yeah, that looks like a correct resolution, thank you!
Not sure what would've been the correct way to handle it in bpf-next
(except waiting for bpf tree to be merged)?

> --
> Cheers,
> Stephen Rothwell
>
> diff --cc kernel/bpf/offload.c
> index 190d9f9dc987,e87cab2ed710..000000000000
> --- a/kernel/bpf/offload.c
> +++ b/kernel/bpf/offload.c
> @@@ -75,20 -74,124 +74,121 @@@ bpf_offload_find_netdev(struct net_devi
>         return rhashtable_lookup_fast(&offdevs, &netdev, offdevs_params);
>   }
>
> - int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr)
> + static int __bpf_offload_dev_netdev_register(struct bpf_offload_dev *offdev,
> +                                            struct net_device *netdev)
>   {
>         struct bpf_offload_netdev *ondev;
> -       struct bpf_prog_offload *offload;
>         int err;
>
> -       if (attr->prog_type != BPF_PROG_TYPE_SCHED_CLS &&
> -           attr->prog_type != BPF_PROG_TYPE_XDP)
> -               return -EINVAL;
> +       ondev = kzalloc(sizeof(*ondev), GFP_KERNEL);
> +       if (!ondev)
> +               return -ENOMEM;
>
> -       if (attr->prog_flags)
> -               return -EINVAL;
> +       ondev->netdev = netdev;
> +       ondev->offdev = offdev;
> +       INIT_LIST_HEAD(&ondev->progs);
> +       INIT_LIST_HEAD(&ondev->maps);
> +
> +       err = rhashtable_insert_fast(&offdevs, &ondev->l, offdevs_params);
> +       if (err) {
> +               netdev_warn(netdev, "failed to register for BPF offload\n");
> +               goto err_free;
> +       }
> +
> +       if (offdev)
> +               list_add(&ondev->offdev_netdevs, &offdev->netdevs);
> +       return 0;
> +
> + err_free:
> +       kfree(ondev);
> +       return err;
> + }
> +
> + static void __bpf_prog_offload_destroy(struct bpf_prog *prog)
> + {
> +       struct bpf_prog_offload *offload = prog->aux->offload;
> +
> +       if (offload->dev_state)
> +               offload->offdev->ops->destroy(prog);
> +
>  -      /* Make sure BPF_PROG_GET_NEXT_ID can't find this dead program */
>  -      bpf_prog_free_id(prog, true);
>  -
> +       list_del_init(&offload->offloads);
> +       kfree(offload);
> +       prog->aux->offload = NULL;
> + }
> +
> + static int bpf_map_offload_ndo(struct bpf_offloaded_map *offmap,
> +                              enum bpf_netdev_command cmd)
> + {
> +       struct netdev_bpf data = {};
> +       struct net_device *netdev;
> +
> +       ASSERT_RTNL();
> +
> +       data.command = cmd;
> +       data.offmap = offmap;
> +       /* Caller must make sure netdev is valid */
> +       netdev = offmap->netdev;
> +
> +       return netdev->netdev_ops->ndo_bpf(netdev, &data);
> + }
> +
> + static void __bpf_map_offload_destroy(struct bpf_offloaded_map *offmap)
> + {
> +       WARN_ON(bpf_map_offload_ndo(offmap, BPF_OFFLOAD_MAP_FREE));
> +       /* Make sure BPF_MAP_GET_NEXT_ID can't find this dead map */
> +       bpf_map_free_id(&offmap->map, true);
> +       list_del_init(&offmap->offloads);
> +       offmap->netdev = NULL;
> + }
> +
> + static void __bpf_offload_dev_netdev_unregister(struct bpf_offload_dev *offdev,
> +                                               struct net_device *netdev)
> + {
> +       struct bpf_offload_netdev *ondev, *altdev = NULL;
> +       struct bpf_offloaded_map *offmap, *mtmp;
> +       struct bpf_prog_offload *offload, *ptmp;
> +
> +       ASSERT_RTNL();
> +
> +       ondev = rhashtable_lookup_fast(&offdevs, &netdev, offdevs_params);
> +       if (WARN_ON(!ondev))
> +               return;
> +
> +       WARN_ON(rhashtable_remove_fast(&offdevs, &ondev->l, offdevs_params));
> +
> +       /* Try to move the objects to another netdev of the device */
> +       if (offdev) {
> +               list_del(&ondev->offdev_netdevs);
> +               altdev = list_first_entry_or_null(&offdev->netdevs,
> +                                                 struct bpf_offload_netdev,
> +                                                 offdev_netdevs);
> +       }
> +
> +       if (altdev) {
> +               list_for_each_entry(offload, &ondev->progs, offloads)
> +                       offload->netdev = altdev->netdev;
> +               list_splice_init(&ondev->progs, &altdev->progs);
> +
> +               list_for_each_entry(offmap, &ondev->maps, offloads)
> +                       offmap->netdev = altdev->netdev;
> +               list_splice_init(&ondev->maps, &altdev->maps);
> +       } else {
> +               list_for_each_entry_safe(offload, ptmp, &ondev->progs, offloads)
> +                       __bpf_prog_offload_destroy(offload->prog);
> +               list_for_each_entry_safe(offmap, mtmp, &ondev->maps, offloads)
> +                       __bpf_map_offload_destroy(offmap);
> +       }
> +
> +       WARN_ON(!list_empty(&ondev->progs));
> +       WARN_ON(!list_empty(&ondev->maps));
> +       kfree(ondev);
> + }
> +
> + static int __bpf_prog_dev_bound_init(struct bpf_prog *prog, struct net_device *netdev)
> + {
> +       struct bpf_offload_netdev *ondev;
> +       struct bpf_prog_offload *offload;
> +       int err;
>
>         offload = kzalloc(sizeof(*offload), GFP_USER);
>         if (!offload)

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

* linux-next: manual merge of the bpf-next tree with Linus' tree
@ 2023-01-23 22:44 Stephen Rothwell
  2023-01-23 22:58 ` Stanislav Fomichev
  0 siblings, 1 reply; 4+ messages in thread
From: Stephen Rothwell @ 2023-01-23 22:44 UTC (permalink / raw)
  To: Daniel Borkmann, Alexei Starovoitov, Andrii Nakryiko
  Cc: bpf, Networking, Linux Kernel Mailing List,
	Linux Next Mailing List, Martin KaFai Lau, Paul Moore,
	Stanislav Fomichev

[-- Attachment #1: Type: text/plain, Size: 4880 bytes --]

Hi all,

Today's linux-next merge of the bpf-next tree got a conflict in:

  kernel/bpf/offload.c

between commit:

  ef01f4e25c17 ("bpf: restore the ebpf program ID for BPF_AUDIT_UNLOAD and PERF_BPF_EVENT_PROG_UNLOAD")

from Linus' tree and commit:

  89bbc53a4dbb ("bpf: Reshuffle some parts of bpf/offload.c")

from the bpf-next tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc kernel/bpf/offload.c
index 190d9f9dc987,e87cab2ed710..000000000000
--- a/kernel/bpf/offload.c
+++ b/kernel/bpf/offload.c
@@@ -75,20 -74,124 +74,121 @@@ bpf_offload_find_netdev(struct net_devi
  	return rhashtable_lookup_fast(&offdevs, &netdev, offdevs_params);
  }
  
- int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr)
+ static int __bpf_offload_dev_netdev_register(struct bpf_offload_dev *offdev,
+ 					     struct net_device *netdev)
  {
  	struct bpf_offload_netdev *ondev;
- 	struct bpf_prog_offload *offload;
  	int err;
  
- 	if (attr->prog_type != BPF_PROG_TYPE_SCHED_CLS &&
- 	    attr->prog_type != BPF_PROG_TYPE_XDP)
- 		return -EINVAL;
+ 	ondev = kzalloc(sizeof(*ondev), GFP_KERNEL);
+ 	if (!ondev)
+ 		return -ENOMEM;
  
- 	if (attr->prog_flags)
- 		return -EINVAL;
+ 	ondev->netdev = netdev;
+ 	ondev->offdev = offdev;
+ 	INIT_LIST_HEAD(&ondev->progs);
+ 	INIT_LIST_HEAD(&ondev->maps);
+ 
+ 	err = rhashtable_insert_fast(&offdevs, &ondev->l, offdevs_params);
+ 	if (err) {
+ 		netdev_warn(netdev, "failed to register for BPF offload\n");
+ 		goto err_free;
+ 	}
+ 
+ 	if (offdev)
+ 		list_add(&ondev->offdev_netdevs, &offdev->netdevs);
+ 	return 0;
+ 
+ err_free:
+ 	kfree(ondev);
+ 	return err;
+ }
+ 
+ static void __bpf_prog_offload_destroy(struct bpf_prog *prog)
+ {
+ 	struct bpf_prog_offload *offload = prog->aux->offload;
+ 
+ 	if (offload->dev_state)
+ 		offload->offdev->ops->destroy(prog);
+ 
 -	/* Make sure BPF_PROG_GET_NEXT_ID can't find this dead program */
 -	bpf_prog_free_id(prog, true);
 -
+ 	list_del_init(&offload->offloads);
+ 	kfree(offload);
+ 	prog->aux->offload = NULL;
+ }
+ 
+ static int bpf_map_offload_ndo(struct bpf_offloaded_map *offmap,
+ 			       enum bpf_netdev_command cmd)
+ {
+ 	struct netdev_bpf data = {};
+ 	struct net_device *netdev;
+ 
+ 	ASSERT_RTNL();
+ 
+ 	data.command = cmd;
+ 	data.offmap = offmap;
+ 	/* Caller must make sure netdev is valid */
+ 	netdev = offmap->netdev;
+ 
+ 	return netdev->netdev_ops->ndo_bpf(netdev, &data);
+ }
+ 
+ static void __bpf_map_offload_destroy(struct bpf_offloaded_map *offmap)
+ {
+ 	WARN_ON(bpf_map_offload_ndo(offmap, BPF_OFFLOAD_MAP_FREE));
+ 	/* Make sure BPF_MAP_GET_NEXT_ID can't find this dead map */
+ 	bpf_map_free_id(&offmap->map, true);
+ 	list_del_init(&offmap->offloads);
+ 	offmap->netdev = NULL;
+ }
+ 
+ static void __bpf_offload_dev_netdev_unregister(struct bpf_offload_dev *offdev,
+ 						struct net_device *netdev)
+ {
+ 	struct bpf_offload_netdev *ondev, *altdev = NULL;
+ 	struct bpf_offloaded_map *offmap, *mtmp;
+ 	struct bpf_prog_offload *offload, *ptmp;
+ 
+ 	ASSERT_RTNL();
+ 
+ 	ondev = rhashtable_lookup_fast(&offdevs, &netdev, offdevs_params);
+ 	if (WARN_ON(!ondev))
+ 		return;
+ 
+ 	WARN_ON(rhashtable_remove_fast(&offdevs, &ondev->l, offdevs_params));
+ 
+ 	/* Try to move the objects to another netdev of the device */
+ 	if (offdev) {
+ 		list_del(&ondev->offdev_netdevs);
+ 		altdev = list_first_entry_or_null(&offdev->netdevs,
+ 						  struct bpf_offload_netdev,
+ 						  offdev_netdevs);
+ 	}
+ 
+ 	if (altdev) {
+ 		list_for_each_entry(offload, &ondev->progs, offloads)
+ 			offload->netdev = altdev->netdev;
+ 		list_splice_init(&ondev->progs, &altdev->progs);
+ 
+ 		list_for_each_entry(offmap, &ondev->maps, offloads)
+ 			offmap->netdev = altdev->netdev;
+ 		list_splice_init(&ondev->maps, &altdev->maps);
+ 	} else {
+ 		list_for_each_entry_safe(offload, ptmp, &ondev->progs, offloads)
+ 			__bpf_prog_offload_destroy(offload->prog);
+ 		list_for_each_entry_safe(offmap, mtmp, &ondev->maps, offloads)
+ 			__bpf_map_offload_destroy(offmap);
+ 	}
+ 
+ 	WARN_ON(!list_empty(&ondev->progs));
+ 	WARN_ON(!list_empty(&ondev->maps));
+ 	kfree(ondev);
+ }
+ 
+ static int __bpf_prog_dev_bound_init(struct bpf_prog *prog, struct net_device *netdev)
+ {
+ 	struct bpf_offload_netdev *ondev;
+ 	struct bpf_prog_offload *offload;
+ 	int err;
  
  	offload = kzalloc(sizeof(*offload), GFP_USER);
  	if (!offload)

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 484 bytes --]

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

* linux-next: manual merge of the bpf-next tree with Linus' tree
@ 2022-01-24 21:43 Stephen Rothwell
  0 siblings, 0 replies; 4+ messages in thread
From: Stephen Rothwell @ 2022-01-24 21:43 UTC (permalink / raw)
  To: Daniel Borkmann, Alexei Starovoitov, Andrii Nakryiko, bpf, Networking
  Cc: Kumar Kartikeya Dwivedi, Linux Kernel Mailing List,
	Linux Next Mailing List

[-- Attachment #1: Type: text/plain, Size: 1527 bytes --]

Hi all,

Today's linux-next merge of the bpf-next tree got a conflict in:

  include/linux/bpf_verifier.h

between commit:

  be80a1d3f9db ("bpf: Generalize check_ctx_reg for reuse with other types")

from Linus' tree and commit:

  d583691c47dc ("bpf: Introduce mem, size argument pair support for kfunc")

from the bpf-next tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc include/linux/bpf_verifier.h
index e9993172f892,ac4797155412..000000000000
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@@ -519,8 -519,10 +519,10 @@@ bpf_prog_offload_replace_insn(struct bp
  void
  bpf_prog_offload_remove_insns(struct bpf_verifier_env *env, u32 off, u32 cnt);
  
 -int check_ctx_reg(struct bpf_verifier_env *env,
 -		  const struct bpf_reg_state *reg, int regno);
 +int check_ptr_off_reg(struct bpf_verifier_env *env,
 +		      const struct bpf_reg_state *reg, int regno);
+ int check_kfunc_mem_size_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg,
+ 			     u32 regno);
  int check_mem_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg,
  		   u32 regno, u32 mem_size);
  

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

end of thread, other threads:[~2023-01-23 22:59 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-24 21:56 linux-next: manual merge of the bpf-next tree with Linus' tree Stephen Rothwell
  -- strict thread matches above, loose matches on Subject: below --
2023-01-23 22:44 Stephen Rothwell
2023-01-23 22:58 ` Stanislav Fomichev
2022-01-24 21:43 Stephen Rothwell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).