From: James Simmons <jsimmons@infradead.org>
To: Andreas Dilger <adilger@whamcloud.com>,
Oleg Drokin <green@whamcloud.com>, NeilBrown <neilb@suse.de>
Cc: Lustre Development List <lustre-devel@lists.lustre.org>
Subject: [lustre-devel] [PATCH 25/50] lnet: convert nids in lnet_parse to lnet_nid
Date: Sun, 20 Mar 2022 09:30:39 -0400 [thread overview]
Message-ID: <1647783064-20688-26-git-send-email-jsimmons@infradead.org> (raw)
In-Reply-To: <1647783064-20688-1-git-send-email-jsimmons@infradead.org>
From: Mr NeilBrown <neilb@suse.de>
src_nid and dest_nid in lnet_parse() are changed to
struct lnet_nid, and this change propagates out to
affect a few support function.
WC-bug-id: https://jira.whamcloud.com/browse/LU-10391
Lustre-commit: ac439ce87b0acbff3 ("LU-10391 lnet: convert nids in lnet_parse to lnet_nid")
Signed-off-by: Mr NeilBrown <neilb@suse.de>
Reviewed-on: https://review.whamcloud.com/43613
Reviewed-by: James Simmons <jsimmons@infradead.org>
Reviewed-by: Serguei Smirnov <ssmirnov@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Signed-off-by: James Simmons <jsimmons@infradead.org>
---
include/linux/lnet/lib-lnet.h | 4 +--
net/lnet/lnet/api-ni.c | 13 -------
net/lnet/lnet/lib-move.c | 80 ++++++++++++++++++++-----------------------
net/lnet/lnet/peer.c | 7 ++--
4 files changed, 43 insertions(+), 61 deletions(-)
diff --git a/include/linux/lnet/lib-lnet.h b/include/linux/lnet/lib-lnet.h
index 297e5ef..fe2fd83 100644
--- a/include/linux/lnet/lib-lnet.h
+++ b/include/linux/lnet/lib-lnet.h
@@ -626,7 +626,6 @@ void lnet_rtr_transfer_to_peer(struct lnet_peer *src,
void lnet_net_clr_pref_rtrs(struct lnet_net *net);
int lnet_net_add_pref_rtr(struct lnet_net *net, struct lnet_nid *gw_nid);
-int lnet_islocalnid4(lnet_nid_t nid);
int lnet_islocalnid(struct lnet_nid *nid);
int lnet_islocalnet(u32 net);
int lnet_islocalnet_locked(u32 net);
@@ -912,7 +911,8 @@ struct lnet_peer_ni *lnet_peer_ni_get_locked(struct lnet_peer *lp,
struct lnet_peer *lnet_find_peer4(lnet_nid_t nid);
struct lnet_peer *lnet_find_peer(struct lnet_nid *nid);
void lnet_peer_net_added(struct lnet_net *net);
-void lnet_peer_primary_nid_locked(lnet_nid_t nid, struct lnet_nid *result);
+void lnet_peer_primary_nid_locked(struct lnet_nid *nid,
+ struct lnet_nid *result);
int lnet_discover_peer_locked(struct lnet_peer_ni *lpni, int cpt, bool block);
void lnet_peer_queue_message(struct lnet_peer *lp, struct lnet_msg *msg);
int lnet_peer_discovery_start(void);
diff --git a/net/lnet/lnet/api-ni.c b/net/lnet/lnet/api-ni.c
index d7ada85..0389a89 100644
--- a/net/lnet/lnet/api-ni.c
+++ b/net/lnet/lnet/api-ni.c
@@ -1636,19 +1636,6 @@ struct lnet_ni *
EXPORT_SYMBOL(lnet_nid_to_ni_addref);
int
-lnet_islocalnid4(lnet_nid_t nid)
-{
- struct lnet_ni *ni;
- int cpt;
-
- cpt = lnet_net_lock_current();
- ni = lnet_nid2ni_locked(nid, cpt);
- lnet_net_unlock(cpt);
-
- return !!ni;
-}
-
-int
lnet_islocalnid(struct lnet_nid *nid)
{
struct lnet_ni *ni;
diff --git a/net/lnet/lnet/lib-move.c b/net/lnet/lnet/lib-move.c
index 496c895..051bea1 100644
--- a/net/lnet/lnet/lib-move.c
+++ b/net/lnet/lnet/lib-move.c
@@ -239,16 +239,14 @@ void lnet_usr_translate_stats(struct lnet_ioctl_element_msg_stats *msg_stats,
}
static int
-fail_peer(lnet_nid_t nid4, int outgoing)
+fail_peer(struct lnet_nid *nid, int outgoing)
{
struct lnet_test_peer *tp;
struct list_head *el;
struct list_head *next;
- struct lnet_nid nid;
LIST_HEAD(cull);
int fail = 0;
- lnet_nid4_to_nid(nid4, &nid);
/* NB: use lnet_net_lock(0) to serialize operations on test peers */
lnet_net_lock(0);
@@ -269,7 +267,7 @@ void lnet_usr_translate_stats(struct lnet_ioctl_element_msg_stats *msg_stats,
}
if (LNET_NID_IS_ANY(&tp->tp_nid) || /* fail every peer */
- nid_same(&nid, &tp->tp_nid)) { /* fail this peer */
+ nid_same(nid, &tp->tp_nid)) { /* fail this peer */
fail = 1;
if (tp->tp_threshold != LNET_MD_THRESH_INF) {
@@ -4238,8 +4236,8 @@ void lnet_monitor_thr_stop(void)
struct lnet_msg *msg;
u32 payload_length;
lnet_pid_t dest_pid;
- lnet_nid_t dest_nid;
- lnet_nid_t src_nid;
+ struct lnet_nid dest_nid;
+ struct lnet_nid src_nid;
struct lnet_nid from_nid;
bool push = false;
int for_me;
@@ -4252,19 +4250,18 @@ void lnet_monitor_thr_stop(void)
lnet_nid4_to_nid(from_nid4, &from_nid);
type = hdr->type;
- src_nid = lnet_nid_to_nid4(&hdr->src_nid);
- dest_nid = lnet_nid_to_nid4(&hdr->dest_nid);
+ src_nid = hdr->src_nid;
+ dest_nid = hdr->dest_nid;
dest_pid = hdr->dest_pid;
payload_length = hdr->payload_length;
- /* FIXME handle large-addr nids */
- for_me = (lnet_nid_to_nid4(&ni->ni_nid) == dest_nid);
- cpt = lnet_cpt_of_nid(from_nid4, ni);
+ for_me = nid_same(&ni->ni_nid, &dest_nid);
+ cpt = lnet_nid2cpt(&from_nid, ni);
CDEBUG(D_NET, "TRACE: %s(%s) <- %s : %s\n",
- libcfs_nid2str(dest_nid),
+ libcfs_nidstr(&dest_nid),
libcfs_nidstr(&ni->ni_nid),
- libcfs_nid2str(src_nid),
+ libcfs_nidstr(&src_nid),
lnet_msgtyp2str(type));
switch (type) {
@@ -4273,7 +4270,7 @@ void lnet_monitor_thr_stop(void)
if (payload_length > 0) {
CERROR("%s, src %s: bad %s payload %d (0 expected)\n",
libcfs_nid2str(from_nid4),
- libcfs_nid2str(src_nid),
+ libcfs_nidstr(&src_nid),
lnet_msgtyp2str(type), payload_length);
return -EPROTO;
}
@@ -4285,7 +4282,7 @@ void lnet_monitor_thr_stop(void)
(u32)(for_me ? LNET_MAX_PAYLOAD : LNET_MTU)) {
CERROR("%s, src %s: bad %s payload %d (%d max expected)\n",
libcfs_nid2str(from_nid4),
- libcfs_nid2str(src_nid),
+ libcfs_nidstr(&src_nid),
lnet_msgtyp2str(type),
payload_length,
for_me ? LNET_MAX_PAYLOAD : LNET_MTU);
@@ -4296,7 +4293,7 @@ void lnet_monitor_thr_stop(void)
default:
CERROR("%s, src %s: Bad message type 0x%x\n",
libcfs_nid2str(from_nid4),
- libcfs_nid2str(src_nid), type);
+ libcfs_nidstr(&src_nid), type);
return -EPROTO;
}
@@ -4319,40 +4316,39 @@ void lnet_monitor_thr_stop(void)
* or malicious so we chop them off at the knees :)
*/
if (!for_me) {
- if (LNET_NIDNET(dest_nid) == LNET_NID_NET(&ni->ni_nid)) {
+ if (LNET_NID_NET(&dest_nid) == LNET_NID_NET(&ni->ni_nid)) {
/* should have gone direct */
CERROR("%s, src %s: Bad dest nid %s (should have been sent direct)\n",
libcfs_nid2str(from_nid4),
- libcfs_nid2str(src_nid),
- libcfs_nid2str(dest_nid));
+ libcfs_nidstr(&src_nid),
+ libcfs_nidstr(&dest_nid));
return -EPROTO;
}
- if (lnet_islocalnid4(dest_nid)) {
- /*
- * dest is another local NI; sender should have used
+ if (lnet_islocalnid(&dest_nid)) {
+ /* dest is another local NI; sender should have used
* this node's NID on its own network
*/
CERROR("%s, src %s: Bad dest nid %s (it's my nid but on a different network)\n",
libcfs_nid2str(from_nid4),
- libcfs_nid2str(src_nid),
- libcfs_nid2str(dest_nid));
+ libcfs_nidstr(&src_nid),
+ libcfs_nidstr(&dest_nid));
return -EPROTO;
}
if (rdma_req && type == LNET_MSG_GET) {
CERROR("%s, src %s: Bad optimized GET for %s (final destination must be me)\n",
libcfs_nid2str(from_nid4),
- libcfs_nid2str(src_nid),
- libcfs_nid2str(dest_nid));
+ libcfs_nidstr(&src_nid),
+ libcfs_nidstr(&dest_nid));
return -EPROTO;
}
if (!the_lnet.ln_routing) {
CERROR("%s, src %s: Dropping message for %s (routing not enabled)\n",
libcfs_nid2str(from_nid4),
- libcfs_nid2str(src_nid),
- libcfs_nid2str(dest_nid));
+ libcfs_nidstr(&src_nid),
+ libcfs_nidstr(&dest_nid));
goto drop;
}
}
@@ -4361,10 +4357,10 @@ void lnet_monitor_thr_stop(void)
* Message looks OK; we're not going to return an error, so we MUST
* call back lnd_recv() come what may...
*/
- if (!list_empty(&the_lnet.ln_test_peers) && /* normally we don't */
- fail_peer(src_nid, 0)) { /* shall we now? */
+ if (!list_empty(&the_lnet.ln_test_peers) && /* normally we don't */
+ fail_peer(&src_nid, 0)) { /* shall we now? */
CERROR("%s, src %s: Dropping %s to simulate failure\n",
- libcfs_nid2str(from_nid4), libcfs_nid2str(src_nid),
+ libcfs_nid2str(from_nid4), libcfs_nidstr(&src_nid),
lnet_msgtyp2str(type));
goto drop;
}
@@ -4373,15 +4369,15 @@ void lnet_monitor_thr_stop(void)
if (!list_empty(&the_lnet.ln_drop_rules) &&
lnet_drop_rule_match(hdr, lnet_nid_to_nid4(&ni->ni_nid), NULL)) {
CDEBUG(D_NET, "%s, src %s, dst %s: Dropping %s to simulate silent message loss\n",
- libcfs_nid2str(from_nid4), libcfs_nid2str(src_nid),
- libcfs_nid2str(dest_nid), lnet_msgtyp2str(type));
+ libcfs_nid2str(from_nid4), libcfs_nidstr(&src_nid),
+ libcfs_nidstr(&dest_nid), lnet_msgtyp2str(type));
goto drop;
}
msg = kmem_cache_zalloc(lnet_msg_cachep, GFP_NOFS);
if (!msg) {
CERROR("%s, src %s: Dropping %s (out of memory)\n",
- libcfs_nid2str(from_nid4), libcfs_nid2str(src_nid),
+ libcfs_nid2str(from_nid4), libcfs_nidstr(&src_nid),
lnet_msgtyp2str(type));
goto drop;
}
@@ -4401,7 +4397,7 @@ void lnet_monitor_thr_stop(void)
msg->msg_from = from_nid;
if (!for_me) {
msg->msg_target.pid = dest_pid;
- lnet_nid4_to_nid(dest_nid, &msg->msg_target.nid);
+ msg->msg_target.nid = dest_nid;
msg->msg_routing = 1;
}
@@ -4411,7 +4407,7 @@ void lnet_monitor_thr_stop(void)
lnet_net_unlock(cpt);
rc = PTR_ERR(lpni);
CERROR("%s, src %s: Dropping %s (error %d looking up sender)\n",
- libcfs_nid2str(from_nid4), libcfs_nid2str(src_nid),
+ libcfs_nid2str(from_nid4), libcfs_nidstr(&src_nid),
lnet_msgtyp2str(type), rc);
kfree(msg);
if (rc == -ESHUTDOWN)
@@ -4426,8 +4422,8 @@ void lnet_monitor_thr_stop(void)
*/
if (((lnet_drop_asym_route && for_me) ||
!lpni->lpni_peer_net->lpn_peer->lp_alive) &&
- LNET_NIDNET(src_nid) != LNET_NIDNET(from_nid4)) {
- u32 src_net_id = LNET_NIDNET(src_nid);
+ LNET_NID_NET(&src_nid) != LNET_NIDNET(from_nid4)) {
+ u32 src_net_id = LNET_NID_NET(&src_nid);
struct lnet_peer *gw = lpni->lpni_peer_net->lpn_peer;
struct lnet_route *route;
bool found = false;
@@ -4462,7 +4458,7 @@ void lnet_monitor_thr_stop(void)
*/
CERROR("%s, src %s: Dropping asymmetrical route %s\n",
libcfs_nid2str(from_nid4),
- libcfs_nid2str(src_nid), lnet_msgtyp2str(type));
+ libcfs_nidstr(&src_nid), lnet_msgtyp2str(type));
kfree(msg);
goto drop;
}
@@ -4486,7 +4482,7 @@ void lnet_monitor_thr_stop(void)
msg->msg_rxni = ni;
lnet_ni_addref_locked(ni, cpt);
/* Multi-Rail: Primary NID of source. */
- lnet_peer_primary_nid_locked(src_nid, &msg->msg_initiator);
+ lnet_peer_primary_nid_locked(&src_nid, &msg->msg_initiator);
/* mark the status of this lpni as UP since we received a message
* from it. The ping response reports back the ns_status which is
@@ -4718,7 +4714,7 @@ void lnet_monitor_thr_stop(void)
target.pid = target4.pid;
if (!list_empty(&the_lnet.ln_test_peers) && /* normally we don't */
- fail_peer(target4.nid, 1)) { /* shall we now? */
+ fail_peer(&target.nid, 1)) { /* shall we now? */
CERROR("Dropping PUT to %s: simulated failure\n",
libcfs_id2str(target4));
return -EIO;
@@ -4964,7 +4960,7 @@ struct lnet_msg *
target.pid = target4.pid;
if (!list_empty(&the_lnet.ln_test_peers) && /* normally we don't */
- fail_peer(target4.nid, 1)) { /* shall we now? */
+ fail_peer(&target.nid, 1)) { /* shall we now? */
CERROR("Dropping GET to %s: simulated failure\n",
libcfs_id2str(target4));
return -EIO;
diff --git a/net/lnet/lnet/peer.c b/net/lnet/lnet/peer.c
index 494b7ef..8e7f44c 100644
--- a/net/lnet/lnet/peer.c
+++ b/net/lnet/lnet/peer.c
@@ -1345,13 +1345,12 @@ struct lnet_peer_ni *
}
void
-lnet_peer_primary_nid_locked(lnet_nid_t nid, struct lnet_nid *result)
+lnet_peer_primary_nid_locked(struct lnet_nid *nid, struct lnet_nid *result)
{
- /* FIXME handle large-addr nid */
struct lnet_peer_ni *lpni;
- lnet_nid4_to_nid(nid, result);
- lpni = lnet_find_peer_ni_locked(nid);
+ *result = *nid;
+ lpni = lnet_peer_ni_find_locked(nid);
if (lpni) {
*result = lpni->lpni_peer_net->lpn_peer->lp_primary_nid;
lnet_peer_ni_decref_locked(lpni);
--
1.8.3.1
_______________________________________________
lustre-devel mailing list
lustre-devel@lists.lustre.org
http://lists.lustre.org/listinfo.cgi/lustre-devel-lustre.org
next prev parent reply other threads:[~2022-03-20 13:32 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-20 13:30 [lustre-devel] [PATCH 00/50] lustre: update to OpenSFS tree as of March 20, 2022 James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 01/50] lustre: type cleanups and remove debug statements James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 02/50] lustre: osc: Fix grant test for ARM James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 03/50] lnet: extend nids in struct lnet_msg James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 04/50] lnet: Change lnet_send() to take large-addr nids James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 05/50] lnet: use large nids in struct lnet_event James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 06/50] lnet: socklnd: prepare for new KSOCK_MSG type James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 07/50] lnet: socklnd: don't deref lnet_hdr in LNDs James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 08/50] lustre: sec: make client encryption compatible with ext4 James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 09/50] lustre: sec: allow subdir mount of encrypted dir James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 10/50] lustre: fld: repeat rpc in fld_client_rpc after EAGAIN James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 11/50] lustre: fld: don't obtain a slot for fld request James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 12/50] lustre: update version to 2.14.57 James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 13/50] lustre: llite: deadlock in ll_new_node() James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 14/50] lnet: o2iblnd: avoid static allocation for msg tx James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 15/50] lnet: separate lnet_hdr in msg from that in lnd James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 16/50] lnet: change lnet_hdr to store large nids James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 17/50] lnet: change lnet_prep_send to take net_processid James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 18/50] lnet: convert to struct lnet_process_id in lib-move James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 19/50] lnet: convert LNetGetID to return an large-addr pid James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 20/50] lnet: alter lnd_notify_peer_down() to take lnet_nid James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 21/50] lnet: socklnd: move lnet_hdr unpack into ->pro_unpack James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 22/50] lnet: socklnd: Change ksock_hello_msg to struct lnet_nid James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 23/50] lnet: socklnd: add hello message version 4 James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 24/50] lnet: Convert ping to support 16-bytes address James Simmons
2022-03-20 13:30 ` James Simmons [this message]
2022-03-20 13:30 ` [lustre-devel] [PATCH 26/50] lnet: change src_nid arg to lnet_parse() to 16byte James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 27/50] lnet: Fix NULL-deref in lnet_nidstr_r() James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 28/50] lnet: change lnet_del_route() to take lnet_nid James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 29/50] lustre: llite: Move free user pages James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 30/50] lustre: llite: Do not get/put DIO pages James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 31/50] lustre: llite: Remove unnecessary page get/put James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 32/50] lustre: llite: LL_IOC_LMV_GETSTRIPE 'default' shows inherit layout James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 33/50] lustre: hsm: update size upon completion of data version James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 34/50] lustre: llite: Delay dput in ll_dirty_page_discard_warn James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 35/50] lnet: libcfs: Use FAIL_CHECK_QUIET for fake i/o James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 36/50] lnet: Avoid peer NI recovery for local interface James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 37/50] lustre: osc: add OBD_IOC_GETATTR support for osc James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 38/50] lustre: sec: present .fscrypt in subdir mount James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 39/50] lnet: improve hash distribution across CPTs James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 40/50] lustre: osc: osc_extent_wait() deadlock James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 41/50] lustre: quota: delete unused quota ID James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 42/50] lnet: Check LNET_NID_IS_ANY in LNET_NID_NET James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 43/50] lustre: llite: clear async errors on write commit sync James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 44/50] lnet: lnet_peer_data_present() memory leak James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 45/50] lnet: Don't use pref NI for reserved portal James Simmons
2022-03-20 13:31 ` [lustre-devel] [PATCH 46/50] lnet: o2iblnd: avoid memory copy for short msg James Simmons
2022-03-20 13:31 ` [lustre-devel] [PATCH 47/50] lustre: llite: set default LMV hash type with 2.12 MDS James Simmons
2022-03-20 13:31 ` [lustre-devel] [PATCH 48/50] lnet: Stop discovery on deleted peer NI James Simmons
2022-03-20 13:31 ` [lustre-devel] [PATCH 49/50] lustre: sec: fix DIO for encrypted files James Simmons
2022-03-20 13:31 ` [lustre-devel] [PATCH 50/50] lustre: ptlrpc: Use after free of 'conn' in rhashtable retry James Simmons
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=1647783064-20688-26-git-send-email-jsimmons@infradead.org \
--to=jsimmons@infradead.org \
--cc=adilger@whamcloud.com \
--cc=green@whamcloud.com \
--cc=lustre-devel@lists.lustre.org \
--cc=neilb@suse.de \
/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: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).