linux-rdma.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] RDMA/srp: don't set a max_segment_size when virt_boundary_mask is set
  2025-06-23  8:02 fix virt_boundary_mask handling in SCSI Christoph Hellwig
@ 2025-06-23  8:02 ` Christoph Hellwig
  2025-06-23 15:31   ` Bart Van Assche
  2025-06-24  5:57   ` Hannes Reinecke
  0 siblings, 2 replies; 10+ messages in thread
From: Christoph Hellwig @ 2025-06-23  8:02 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Bart Van Assche, Ming Lei, K. Y. Srinivasan, Haiyang Zhang,
	Wei Liu, Ewan D. Milne, Laurence Oberman, linux-rdma, linux-scsi,
	linux-block

virt_boundary_mask implies an unlimited max_segment_size.  Setting both
can lead to data corruption, and we're going to check for this in the
SCSI midlayer soon.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/infiniband/ulp/srp/ib_srp.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 1378651735f6..23ed2fc688f0 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -3705,9 +3705,10 @@ static ssize_t add_target_store(struct device *dev,
 	target_host->max_id      = 1;
 	target_host->max_lun     = -1LL;
 	target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb;
-	target_host->max_segment_size = ib_dma_max_seg_size(ibdev);
 
-	if (!(ibdev->attrs.kernel_cap_flags & IBK_SG_GAPS_REG))
+	if (ibdev->attrs.kernel_cap_flags & IBK_SG_GAPS_REG)
+		target_host->max_segment_size = ib_dma_max_seg_size(ibdev);
+	else
 		target_host->virt_boundary_mask = ~srp_dev->mr_page_mask;
 
 	target = host_to_target(target_host);
-- 
2.47.2


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

* Re: [PATCH 1/2] RDMA/srp: don't set a max_segment_size when virt_boundary_mask is set
  2025-06-23  8:02 ` [PATCH 1/2] RDMA/srp: don't set a max_segment_size when virt_boundary_mask is set Christoph Hellwig
@ 2025-06-23 15:31   ` Bart Van Assche
  2025-06-24  5:57   ` Hannes Reinecke
  1 sibling, 0 replies; 10+ messages in thread
From: Bart Van Assche @ 2025-06-23 15:31 UTC (permalink / raw)
  To: Christoph Hellwig, Martin K. Petersen
  Cc: Ming Lei, K. Y. Srinivasan, Haiyang Zhang, Wei Liu, Ewan D. Milne,
	Laurence Oberman, linux-rdma, linux-scsi, linux-block

On 6/23/25 1:02 AM, Christoph Hellwig wrote:
> virt_boundary_mask implies an unlimited max_segment_size.  Setting both
> can lead to data corruption, and we're going to check for this in the
> SCSI midlayer soon.

Please make this patch description more detailed and mention that
__blk_rq_map_sg() may split sg-lists such that the virt_boundary_mask is
not respected if max_segment_size != UINT_MAX.

Thanks,

Bart.

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

* Re: [PATCH 1/2] RDMA/srp: don't set a max_segment_size when virt_boundary_mask is set
  2025-06-23  8:02 ` [PATCH 1/2] RDMA/srp: don't set a max_segment_size when virt_boundary_mask is set Christoph Hellwig
  2025-06-23 15:31   ` Bart Van Assche
@ 2025-06-24  5:57   ` Hannes Reinecke
  1 sibling, 0 replies; 10+ messages in thread
From: Hannes Reinecke @ 2025-06-24  5:57 UTC (permalink / raw)
  To: Christoph Hellwig, Martin K. Petersen
  Cc: Bart Van Assche, Ming Lei, K. Y. Srinivasan, Haiyang Zhang,
	Wei Liu, Ewan D. Milne, Laurence Oberman, linux-rdma, linux-scsi,
	linux-block

On 6/23/25 10:02, Christoph Hellwig wrote:
> virt_boundary_mask implies an unlimited max_segment_size.  Setting both
> can lead to data corruption, and we're going to check for this in the
> SCSI midlayer soon.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
>   drivers/infiniband/ulp/srp/ib_srp.c | 5 +++--
>   1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
> index 1378651735f6..23ed2fc688f0 100644
> --- a/drivers/infiniband/ulp/srp/ib_srp.c
> +++ b/drivers/infiniband/ulp/srp/ib_srp.c
> @@ -3705,9 +3705,10 @@ static ssize_t add_target_store(struct device *dev,
>   	target_host->max_id      = 1;
>   	target_host->max_lun     = -1LL;
>   	target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb;
> -	target_host->max_segment_size = ib_dma_max_seg_size(ibdev);
>   
> -	if (!(ibdev->attrs.kernel_cap_flags & IBK_SG_GAPS_REG))
> +	if (ibdev->attrs.kernel_cap_flags & IBK_SG_GAPS_REG)
> +		target_host->max_segment_size = ib_dma_max_seg_size(ibdev);
> +	else
>   		target_host->virt_boundary_mask = ~srp_dev->mr_page_mask;
>   
>   	target = host_to_target(target_host);

Reviewed-by: Hannes Reinecke <hare@suse.de>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                  Kernel Storage Architect
hare@suse.de                                +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich

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

* fix virt_boundary_mask handling in SCSI v2
@ 2025-06-24 12:52 Christoph Hellwig
  2025-06-24 12:52 ` [PATCH 1/2] RDMA/srp: don't set a max_segment_size when virt_boundary_mask is set Christoph Hellwig
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Christoph Hellwig @ 2025-06-24 12:52 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Bart Van Assche, Ming Lei, K. Y. Srinivasan, Haiyang Zhang,
	Wei Liu, Ewan D. Milne, Laurence Oberman, linux-rdma, linux-scsi,
	linux-block

Hi all,

this series fixes a corruption when drivers using virt_boundary_mask set
a limited max_segment_size by accident, which Red Hat reported as causing
data corruption with storvsc.  I did audit the tree and also found that
this can affect SRP and iSER as well.

Changes since v1:
 - improve the srp commit log
 - slightly simplify the limits assignment in hosts.c

Diffstat:
 infiniband/ulp/srp/ib_srp.c |    5 +++--
 scsi/hosts.c                |   18 +++++++++++-------
 2 files changed, 14 insertions(+), 9 deletions(-)

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

* [PATCH 1/2] RDMA/srp: don't set a max_segment_size when virt_boundary_mask is set
  2025-06-24 12:52 fix virt_boundary_mask handling in SCSI v2 Christoph Hellwig
@ 2025-06-24 12:52 ` Christoph Hellwig
  2025-06-24 13:25   ` John Garry
  2025-06-24 15:54   ` Bart Van Assche
  2025-06-24 12:52 ` [PATCH 2/2] scsi: enforce unlimited " Christoph Hellwig
  2025-06-25  1:47 ` fix virt_boundary_mask handling in SCSI v2 Martin K. Petersen
  2 siblings, 2 replies; 10+ messages in thread
From: Christoph Hellwig @ 2025-06-24 12:52 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Bart Van Assche, Ming Lei, K. Y. Srinivasan, Haiyang Zhang,
	Wei Liu, Ewan D. Milne, Laurence Oberman, linux-rdma, linux-scsi,
	linux-block, Hannes Reinecke

virt_boundary_mask implies an unlimited max_segment_size.  Setting both
can lead to data corruption because __blk_rq_map_sg() can split requests
so that the virt_boundary_mask is not respected if max_segment_size is
not UINT_MAX.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
---
 drivers/infiniband/ulp/srp/ib_srp.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 1378651735f6..23ed2fc688f0 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -3705,9 +3705,10 @@ static ssize_t add_target_store(struct device *dev,
 	target_host->max_id      = 1;
 	target_host->max_lun     = -1LL;
 	target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb;
-	target_host->max_segment_size = ib_dma_max_seg_size(ibdev);
 
-	if (!(ibdev->attrs.kernel_cap_flags & IBK_SG_GAPS_REG))
+	if (ibdev->attrs.kernel_cap_flags & IBK_SG_GAPS_REG)
+		target_host->max_segment_size = ib_dma_max_seg_size(ibdev);
+	else
 		target_host->virt_boundary_mask = ~srp_dev->mr_page_mask;
 
 	target = host_to_target(target_host);
-- 
2.47.2


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

* [PATCH 2/2] scsi: enforce unlimited max_segment_size when virt_boundary_mask is set
  2025-06-24 12:52 fix virt_boundary_mask handling in SCSI v2 Christoph Hellwig
  2025-06-24 12:52 ` [PATCH 1/2] RDMA/srp: don't set a max_segment_size when virt_boundary_mask is set Christoph Hellwig
@ 2025-06-24 12:52 ` Christoph Hellwig
  2025-06-24 15:56   ` Bart Van Assche
  2025-06-25  1:47 ` fix virt_boundary_mask handling in SCSI v2 Martin K. Petersen
  2 siblings, 1 reply; 10+ messages in thread
From: Christoph Hellwig @ 2025-06-24 12:52 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Bart Van Assche, Ming Lei, K. Y. Srinivasan, Haiyang Zhang,
	Wei Liu, Ewan D. Milne, Laurence Oberman, linux-rdma, linux-scsi,
	linux-block, John Garry, Hannes Reinecke

The virt_boundary_mask limit requires an unlimited max_segment_size for
bio splitting to not corrupt data.  Historically, the block layer tried
to validate this, although the check was half-hearted until the addition
of the atomic queue limits API.  The full blown check than triggered
issues with stacked devices incorrectly inheriting limits such as the
virt boundary and got disabled in commit b561ea56a264 ("block: allow
device to have both virt_boundary_mask and max segment size") instead of
fixing the issue properly.

Ensure that the SCSI mid layer doesn't set the default low
max_segment_size limit for this case, and check for invalid
max_segment_size values in the host template, similar to the original
block layer check given that SCSI devices can't be stacked.

This fixes reported data corruption on storvsc, although as far as I can
tell storvsc always failed to properly set the max_segment_size limit as
the SCSI APIs historically applied that when setting up the host, while
storvsc only set the virt_boundary_mask when configuring the scsi_device.

Fixes: 81988a0e6b03 ("storvsc: get rid of bounce buffer")
Fixes: b561ea56a264 ("block: allow device to have both virt_boundary_mask and max segment size")
Reported-by: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: John Garry <john.g.garry@oracle.com>
Reviewed-by: Ming Lei <ming.lei@redhat.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
---
 drivers/scsi/hosts.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index e021f1106bea..cc5d05dc395c 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -473,10 +473,17 @@ struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht, int priv
 	else
 		shost->max_sectors = SCSI_DEFAULT_MAX_SECTORS;
 
-	if (sht->max_segment_size)
-		shost->max_segment_size = sht->max_segment_size;
-	else
-		shost->max_segment_size = BLK_MAX_SEGMENT_SIZE;
+	shost->virt_boundary_mask = sht->virt_boundary_mask;
+	if (shost->virt_boundary_mask) {
+		WARN_ON_ONCE(sht->max_segment_size &&
+			     sht->max_segment_size != UINT_MAX);
+		shost->max_segment_size = UINT_MAX;
+	} else {
+		if (sht->max_segment_size)
+			shost->max_segment_size = sht->max_segment_size;
+		else
+			shost->max_segment_size = BLK_MAX_SEGMENT_SIZE;
+	}
 
 	/* 32-byte (dword) is a common minimum for HBAs. */
 	if (sht->dma_alignment)
@@ -492,9 +499,6 @@ struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht, int priv
 	else
 		shost->dma_boundary = 0xffffffff;
 
-	if (sht->virt_boundary_mask)
-		shost->virt_boundary_mask = sht->virt_boundary_mask;
-
 	device_initialize(&shost->shost_gendev);
 	dev_set_name(&shost->shost_gendev, "host%d", shost->host_no);
 	shost->shost_gendev.bus = &scsi_bus_type;
-- 
2.47.2


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

* Re: [PATCH 1/2] RDMA/srp: don't set a max_segment_size when virt_boundary_mask is set
  2025-06-24 12:52 ` [PATCH 1/2] RDMA/srp: don't set a max_segment_size when virt_boundary_mask is set Christoph Hellwig
@ 2025-06-24 13:25   ` John Garry
  2025-06-24 15:54   ` Bart Van Assche
  1 sibling, 0 replies; 10+ messages in thread
From: John Garry @ 2025-06-24 13:25 UTC (permalink / raw)
  To: Christoph Hellwig, Martin K. Petersen
  Cc: Bart Van Assche, Ming Lei, K. Y. Srinivasan, Haiyang Zhang,
	Wei Liu, Ewan D. Milne, Laurence Oberman, linux-rdma, linux-scsi,
	linux-block, Hannes Reinecke

On 24/06/2025 13:52, Christoph Hellwig wrote:
> virt_boundary_mask implies an unlimited max_segment_size.  Setting both
> can lead to data corruption because __blk_rq_map_sg() can split requests
> so that the virt_boundary_mask is not respected if max_segment_size is
> not UINT_MAX.
> 
> Signed-off-by: Christoph Hellwig<hch@lst.de>
> Reviewed-by: Hannes Reinecke<hare@suse.de>

Reviewed-by: John Garry <john.g.garry@oracle.com>

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

* Re: [PATCH 1/2] RDMA/srp: don't set a max_segment_size when virt_boundary_mask is set
  2025-06-24 12:52 ` [PATCH 1/2] RDMA/srp: don't set a max_segment_size when virt_boundary_mask is set Christoph Hellwig
  2025-06-24 13:25   ` John Garry
@ 2025-06-24 15:54   ` Bart Van Assche
  1 sibling, 0 replies; 10+ messages in thread
From: Bart Van Assche @ 2025-06-24 15:54 UTC (permalink / raw)
  To: Christoph Hellwig, Martin K. Petersen
  Cc: Ming Lei, K. Y. Srinivasan, Haiyang Zhang, Wei Liu, Ewan D. Milne,
	Laurence Oberman, linux-rdma, linux-scsi, linux-block,
	Hannes Reinecke

On 6/24/25 5:52 AM, Christoph Hellwig wrote:
> virt_boundary_mask implies an unlimited max_segment_size.  Setting both
> can lead to data corruption because __blk_rq_map_sg() can split requests
> so that the virt_boundary_mask is not respected if max_segment_size is
> not UINT_MAX.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Reviewed-by: Hannes Reinecke <hare@suse.de>
> ---
>   drivers/infiniband/ulp/srp/ib_srp.c | 5 +++--
>   1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
> index 1378651735f6..23ed2fc688f0 100644
> --- a/drivers/infiniband/ulp/srp/ib_srp.c
> +++ b/drivers/infiniband/ulp/srp/ib_srp.c
> @@ -3705,9 +3705,10 @@ static ssize_t add_target_store(struct device *dev,
>   	target_host->max_id      = 1;
>   	target_host->max_lun     = -1LL;
>   	target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb;
> -	target_host->max_segment_size = ib_dma_max_seg_size(ibdev);
>   
> -	if (!(ibdev->attrs.kernel_cap_flags & IBK_SG_GAPS_REG))
> +	if (ibdev->attrs.kernel_cap_flags & IBK_SG_GAPS_REG)
> +		target_host->max_segment_size = ib_dma_max_seg_size(ibdev);
> +	else
>   		target_host->virt_boundary_mask = ~srp_dev->mr_page_mask;
>   
>   	target = host_to_target(target_host);

Acked-by: Bart Van Assche <bvanassche@acm.org>

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

* Re: [PATCH 2/2] scsi: enforce unlimited max_segment_size when virt_boundary_mask is set
  2025-06-24 12:52 ` [PATCH 2/2] scsi: enforce unlimited " Christoph Hellwig
@ 2025-06-24 15:56   ` Bart Van Assche
  0 siblings, 0 replies; 10+ messages in thread
From: Bart Van Assche @ 2025-06-24 15:56 UTC (permalink / raw)
  To: Christoph Hellwig, Martin K. Petersen
  Cc: Ming Lei, K. Y. Srinivasan, Haiyang Zhang, Wei Liu, Ewan D. Milne,
	Laurence Oberman, linux-rdma, linux-scsi, linux-block, John Garry,
	Hannes Reinecke

On 6/24/25 5:52 AM, Christoph Hellwig wrote:
> diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
> index e021f1106bea..cc5d05dc395c 100644
> --- a/drivers/scsi/hosts.c
> +++ b/drivers/scsi/hosts.c
> @@ -473,10 +473,17 @@ struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht, int priv
>   	else
>   		shost->max_sectors = SCSI_DEFAULT_MAX_SECTORS;
>   
> -	if (sht->max_segment_size)
> -		shost->max_segment_size = sht->max_segment_size;
> -	else
> -		shost->max_segment_size = BLK_MAX_SEGMENT_SIZE;
> +	shost->virt_boundary_mask = sht->virt_boundary_mask;
> +	if (shost->virt_boundary_mask) {
> +		WARN_ON_ONCE(sht->max_segment_size &&
> +			     sht->max_segment_size != UINT_MAX);
> +		shost->max_segment_size = UINT_MAX;
> +	} else {
> +		if (sht->max_segment_size)
> +			shost->max_segment_size = sht->max_segment_size;
> +		else
> +			shost->max_segment_size = BLK_MAX_SEGMENT_SIZE;
> +	}
>   
>   	/* 32-byte (dword) is a common minimum for HBAs. */
>   	if (sht->dma_alignment)
> @@ -492,9 +499,6 @@ struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht, int priv
>   	else
>   		shost->dma_boundary = 0xffffffff;
>   
> -	if (sht->virt_boundary_mask)
> -		shost->virt_boundary_mask = sht->virt_boundary_mask;
> -
>   	device_initialize(&shost->shost_gendev);
>   	dev_set_name(&shost->shost_gendev, "host%d", shost->host_no);
>   	shost->shost_gendev.bus = &scsi_bus_type;

Reviewed-by: Bart Van Assche <bvanassche@acm.org>

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

* Re: fix virt_boundary_mask handling in SCSI v2
  2025-06-24 12:52 fix virt_boundary_mask handling in SCSI v2 Christoph Hellwig
  2025-06-24 12:52 ` [PATCH 1/2] RDMA/srp: don't set a max_segment_size when virt_boundary_mask is set Christoph Hellwig
  2025-06-24 12:52 ` [PATCH 2/2] scsi: enforce unlimited " Christoph Hellwig
@ 2025-06-25  1:47 ` Martin K. Petersen
  2 siblings, 0 replies; 10+ messages in thread
From: Martin K. Petersen @ 2025-06-25  1:47 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Martin K . Petersen, Bart Van Assche, Ming Lei, K. Y. Srinivasan,
	Haiyang Zhang, Wei Liu, Ewan D. Milne, Laurence Oberman,
	linux-rdma, linux-scsi, linux-block

On Tue, 24 Jun 2025 14:52:26 +0200, Christoph Hellwig wrote:

> this series fixes a corruption when drivers using virt_boundary_mask set
> a limited max_segment_size by accident, which Red Hat reported as causing
> data corruption with storvsc.  I did audit the tree and also found that
> this can affect SRP and iSER as well.
> 
> Changes since v1:
>  - improve the srp commit log
>  - slightly simplify the limits assignment in hosts.c
> 
> [...]

Applied to 6.16/scsi-fixes, thanks!

[1/2] RDMA/srp: don't set a max_segment_size when virt_boundary_mask is set
      https://git.kernel.org/mkp/scsi/c/844c6a160e69
[2/2] scsi: enforce unlimited max_segment_size when virt_boundary_mask is set
      https://git.kernel.org/mkp/scsi/c/4937e604ca24

-- 
Martin K. Petersen	Oracle Linux Engineering

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

end of thread, other threads:[~2025-06-25  1:48 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-24 12:52 fix virt_boundary_mask handling in SCSI v2 Christoph Hellwig
2025-06-24 12:52 ` [PATCH 1/2] RDMA/srp: don't set a max_segment_size when virt_boundary_mask is set Christoph Hellwig
2025-06-24 13:25   ` John Garry
2025-06-24 15:54   ` Bart Van Assche
2025-06-24 12:52 ` [PATCH 2/2] scsi: enforce unlimited " Christoph Hellwig
2025-06-24 15:56   ` Bart Van Assche
2025-06-25  1:47 ` fix virt_boundary_mask handling in SCSI v2 Martin K. Petersen
  -- strict thread matches above, loose matches on Subject: below --
2025-06-23  8:02 fix virt_boundary_mask handling in SCSI Christoph Hellwig
2025-06-23  8:02 ` [PATCH 1/2] RDMA/srp: don't set a max_segment_size when virt_boundary_mask is set Christoph Hellwig
2025-06-23 15:31   ` Bart Van Assche
2025-06-24  5:57   ` Hannes Reinecke

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).