soreceive_generic(), and sopoll_generic(). Add new functions sosend(),
soreceive(), and sopoll(), which are wrappers for pru_sosend, pru_soreceive, and pru_sopoll, and are now used univerally by socket consumers rather than either directly invoking the old so*() functions or directly invoking the protocol switch method (about an even split prior to this commit). This completes an architectural change that was begun in 1996 to permit protocols to provide substitute implementations, as now used by UDP. Consumers now uniformly invoke sosend(), soreceive(), and sopoll() to perform these operations on sockets -- in particular, distributed file systems and socket system calls. Architectural head nod: sam, gnn, wollman
This commit is contained in:
parent
8eb98847ea
commit
b0668f7151
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=160619
@ -88,7 +88,7 @@ soo_read(fp, uio, active_cred, flags, td)
|
||||
return (error);
|
||||
}
|
||||
#endif
|
||||
error = so->so_proto->pr_usrreqs->pru_soreceive(so, 0, uio, 0, 0, 0);
|
||||
error = soreceive(so, 0, uio, 0, 0, 0);
|
||||
NET_UNLOCK_GIANT();
|
||||
return (error);
|
||||
}
|
||||
@ -115,8 +115,7 @@ soo_write(fp, uio, active_cred, flags, td)
|
||||
return (error);
|
||||
}
|
||||
#endif
|
||||
error = so->so_proto->pr_usrreqs->pru_sosend(so, 0, uio, 0, 0, 0,
|
||||
uio->uio_td);
|
||||
error = sosend(so, 0, uio, 0, 0, 0, uio->uio_td);
|
||||
if (error == EPIPE && (so->so_options & SO_NOSIGPIPE) == 0) {
|
||||
PROC_LOCK(uio->uio_td->td_proc);
|
||||
psignal(uio->uio_td->td_proc, SIGPIPE);
|
||||
@ -243,8 +242,7 @@ soo_poll(fp, events, active_cred, td)
|
||||
return (error);
|
||||
}
|
||||
#endif
|
||||
error = (so->so_proto->pr_usrreqs->pru_sopoll)
|
||||
(so, events, fp->f_cred, td);
|
||||
error = sopoll(so, events, fp->f_cred, td);
|
||||
NET_UNLOCK_GIANT();
|
||||
|
||||
return (error);
|
||||
|
@ -119,9 +119,9 @@ protosw_init(struct protosw *pr)
|
||||
DEFAULT(pu->pru_rcvd, pru_rcvd_notsupp);
|
||||
DEFAULT(pu->pru_rcvoob, pru_rcvoob_notsupp);
|
||||
DEFAULT(pu->pru_sense, pru_sense_null);
|
||||
DEFAULT(pu->pru_sosend, sosend);
|
||||
DEFAULT(pu->pru_soreceive, soreceive);
|
||||
DEFAULT(pu->pru_sopoll, sopoll);
|
||||
DEFAULT(pu->pru_sosend, sosend_generic);
|
||||
DEFAULT(pu->pru_soreceive, soreceive_generic);
|
||||
DEFAULT(pu->pru_sopoll, sopoll_generic);
|
||||
#undef DEFAULT
|
||||
if (pr->pr_init)
|
||||
(*pr->pr_init)();
|
||||
|
@ -1093,7 +1093,7 @@ sosend_dgram(so, addr, uio, top, control, flags, td)
|
||||
*/
|
||||
#define snderr(errno) { error = (errno); goto release; }
|
||||
int
|
||||
sosend(so, addr, uio, top, control, flags, td)
|
||||
sosend_generic(so, addr, uio, top, control, flags, td)
|
||||
struct socket *so;
|
||||
struct sockaddr *addr;
|
||||
struct uio *uio;
|
||||
@ -1256,6 +1256,25 @@ sosend(so, addr, uio, top, control, flags, td)
|
||||
}
|
||||
#undef snderr
|
||||
|
||||
int
|
||||
sosend(so, addr, uio, top, control, flags, td)
|
||||
struct socket *so;
|
||||
struct sockaddr *addr;
|
||||
struct uio *uio;
|
||||
struct mbuf *top;
|
||||
struct mbuf *control;
|
||||
int flags;
|
||||
struct thread *td;
|
||||
{
|
||||
|
||||
/* XXXRW: Temporary debugging. */
|
||||
KASSERT(so->so_proto->pr_usrreqs->pru_sosend != sosend,
|
||||
("sosend: protocol calls sosend"));
|
||||
|
||||
return (so->so_proto->pr_usrreqs->pru_sosend(so, addr, uio, top,
|
||||
control, flags, td));
|
||||
}
|
||||
|
||||
/*
|
||||
* The part of soreceive() that implements reading non-inline out-of-band
|
||||
* data from a socket. For more complete comments, see soreceive(), from
|
||||
@ -1361,7 +1380,7 @@ sockbuf_pushsync(struct sockbuf *sb, struct mbuf *nextrecord)
|
||||
* the count in uio_resid.
|
||||
*/
|
||||
int
|
||||
soreceive(so, psa, uio, mp0, controlp, flagsp)
|
||||
soreceive_generic(so, psa, uio, mp0, controlp, flagsp)
|
||||
struct socket *so;
|
||||
struct sockaddr **psa;
|
||||
struct uio *uio;
|
||||
@ -1801,6 +1820,24 @@ soreceive(so, psa, uio, mp0, controlp, flagsp)
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
soreceive(so, psa, uio, mp0, controlp, flagsp)
|
||||
struct socket *so;
|
||||
struct sockaddr **psa;
|
||||
struct uio *uio;
|
||||
struct mbuf **mp0;
|
||||
struct mbuf **controlp;
|
||||
int *flagsp;
|
||||
{
|
||||
|
||||
/* XXXRW: Temporary debugging. */
|
||||
KASSERT(so->so_proto->pr_usrreqs->pru_soreceive != soreceive,
|
||||
("soreceive: protocol calls soreceive"));
|
||||
|
||||
return (so->so_proto->pr_usrreqs->pru_soreceive(so, psa, uio, mp0,
|
||||
controlp, flagsp));
|
||||
}
|
||||
|
||||
int
|
||||
soshutdown(so, how)
|
||||
struct socket *so;
|
||||
@ -2411,6 +2448,19 @@ int
|
||||
sopoll(struct socket *so, int events, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
/* XXXRW: Temporary debugging. */
|
||||
KASSERT(so->so_proto->pr_usrreqs->pru_sopoll != sopoll,
|
||||
("sopoll: protocol calls sopoll"));
|
||||
|
||||
return (so->so_proto->pr_usrreqs->pru_sopoll(so, events, active_cred,
|
||||
td));
|
||||
}
|
||||
|
||||
int
|
||||
sopoll_generic(struct socket *so, int events, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
int revents = 0;
|
||||
|
||||
SOCKBUF_LOCK(&so->so_snd);
|
||||
|
@ -803,8 +803,7 @@ kern_sendit(td, s, mp, flags, control, segflg)
|
||||
ktruio = cloneuio(&auio);
|
||||
#endif
|
||||
len = auio.uio_resid;
|
||||
error = so->so_proto->pr_usrreqs->pru_sosend(so, mp->msg_name, &auio,
|
||||
0, control, flags, td);
|
||||
error = sosend(so, mp->msg_name, &auio, 0, control, flags, td);
|
||||
if (error) {
|
||||
if (auio.uio_resid != len && (error == ERESTART ||
|
||||
error == EINTR || error == EWOULDBLOCK))
|
||||
@ -1020,8 +1019,7 @@ kern_recvit(td, s, mp, fromseg, controlp)
|
||||
ktruio = cloneuio(&auio);
|
||||
#endif
|
||||
len = auio.uio_resid;
|
||||
error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio,
|
||||
(struct mbuf **)0,
|
||||
error = soreceive(so, &fromsa, &auio, (struct mbuf **)0,
|
||||
(mp->msg_control || controlp) ? &control : (struct mbuf **)0,
|
||||
&mp->msg_flags);
|
||||
if (error) {
|
||||
|
@ -786,9 +786,9 @@ struct pr_usrreqs uipc_usrreqs = {
|
||||
.pru_sense = uipc_sense,
|
||||
.pru_shutdown = uipc_shutdown,
|
||||
.pru_sockaddr = uipc_sockaddr,
|
||||
.pru_sosend = sosend,
|
||||
.pru_soreceive = soreceive,
|
||||
.pru_sopoll = sopoll,
|
||||
.pru_sosend = sosend_generic,
|
||||
.pru_soreceive = soreceive_generic,
|
||||
.pru_sopoll = sopoll_generic,
|
||||
.pru_close = uipc_close,
|
||||
};
|
||||
|
||||
|
@ -1558,8 +1558,8 @@ ng_btsocket_rfcomm_session_receive(ng_btsocket_rfcomm_session_p s)
|
||||
flags = MSG_DONTWAIT;
|
||||
|
||||
m = NULL;
|
||||
error = (*s->l2so->so_proto->pr_usrreqs->pru_soreceive)(s->l2so,
|
||||
NULL, &uio, &m, (struct mbuf **) NULL, &flags);
|
||||
error = soreceive(s->l2so, NULL, &uio, &m,
|
||||
(struct mbuf **) NULL, &flags);
|
||||
if (error != 0) {
|
||||
if (error == EWOULDBLOCK)
|
||||
return (0); /* XXX can happen? */
|
||||
@ -1610,9 +1610,8 @@ ng_btsocket_rfcomm_session_send(ng_btsocket_rfcomm_session_p s)
|
||||
return (0); /* we are done */
|
||||
|
||||
/* Call send function on the L2CAP socket */
|
||||
error = (*s->l2so->so_proto->pr_usrreqs->pru_sosend)
|
||||
(s->l2so, NULL, NULL, m, NULL, 0,
|
||||
curthread /* XXX */);
|
||||
error = sosend(s->l2so, NULL, NULL, m, NULL, 0,
|
||||
curthread /* XXX */);
|
||||
if (error != 0) {
|
||||
NG_BTSOCKET_RFCOMM_ERR(
|
||||
"%s: Could not send data to L2CAP socket, error=%d\n", __func__, error);
|
||||
|
@ -920,7 +920,7 @@ ng_ksocket_rcvdata(hook_p hook, item_p item)
|
||||
sa = &stag->sa;
|
||||
|
||||
/* Send packet */
|
||||
error = (*so->so_proto->pr_usrreqs->pru_sosend)(so, sa, 0, m, 0, 0, td);
|
||||
error = sosend(so, sa, 0, m, 0, 0, td);
|
||||
|
||||
return (error);
|
||||
}
|
||||
@ -1101,9 +1101,8 @@ ng_ksocket_incoming2(node_p node, hook_p hook, void *arg1, int waitflag)
|
||||
struct mbuf *n;
|
||||
|
||||
/* Try to get next packet from socket */
|
||||
if ((error = (*so->so_proto->pr_usrreqs->pru_soreceive)
|
||||
(so, (so->so_state & SS_ISCONNECTED) ? NULL : &sa,
|
||||
&auio, &m, (struct mbuf **)0, &flags)) != 0)
|
||||
if ((error = soreceive(so, (so->so_state & SS_ISCONNECTED) ?
|
||||
NULL : &sa, &auio, &m, (struct mbuf **)0, &flags)) != 0)
|
||||
break;
|
||||
|
||||
/* See if we got anything */
|
||||
|
@ -139,10 +139,9 @@ int ncp_sock_recv(struct socket *so, struct mbuf **mp, int *rlen)
|
||||
auio.uio_td = td;
|
||||
flags = MSG_DONTWAIT;
|
||||
|
||||
/* error = so->so_proto->pr_usrreqs->pru_soreceive(so, 0, &auio,
|
||||
(struct mbuf **)0, (struct mbuf **)0, &flags);*/
|
||||
error = so->so_proto->pr_usrreqs->pru_soreceive(so, 0, &auio,
|
||||
mp, (struct mbuf **)0, &flags);
|
||||
/* error = soreceive(so, 0, &auio, (struct mbuf **)0, (struct mbuf **)0,
|
||||
&flags);*/
|
||||
error = soreceive(so, 0, &auio, mp, (struct mbuf **)0, &flags);
|
||||
*rlen = len - auio.uio_resid;
|
||||
/* if (!error) {
|
||||
*rlen=iov.iov_len;
|
||||
@ -168,7 +167,7 @@ ncp_sock_send(struct socket *so, struct mbuf *top, struct ncp_rq *rqp)
|
||||
for (;;) {
|
||||
m = m_copym(top, 0, M_COPYALL, M_TRYWAIT);
|
||||
/* NCPDDEBUG(m);*/
|
||||
error = so->so_proto->pr_usrreqs->pru_sosend(so, to, 0, m, 0, flags, td);
|
||||
error = sosend(so, to, 0, m, 0, flags, td);
|
||||
if (error == 0 || error == EINTR || error == ENETDOWN)
|
||||
break;
|
||||
if (rqp->rexmit == 0) break;
|
||||
@ -189,7 +188,7 @@ ncp_poll(struct socket *so, int events)
|
||||
struct thread *td = curthread;
|
||||
struct ucred *cred = NULL;
|
||||
|
||||
return so->so_proto->pr_usrreqs->pru_sopoll(so, events, cred, td);
|
||||
return (sopoll(so, events, cred, td));
|
||||
}
|
||||
|
||||
int
|
||||
@ -443,8 +442,8 @@ ncp_watchdog(struct ncp_conn *conn) {
|
||||
auio.uio_resid = len = 1000000;
|
||||
auio.uio_td = curthread;
|
||||
flags = MSG_DONTWAIT;
|
||||
error = so->so_proto->pr_usrreqs->pru_soreceive(so,
|
||||
(struct sockaddr**)&sa, &auio, &m, (struct mbuf**)0, &flags);
|
||||
error = soreceive(so, (struct sockaddr**)&sa, &auio, &m,
|
||||
(struct mbuf**)0, &flags);
|
||||
if (error) break;
|
||||
len -= auio.uio_resid;
|
||||
NCPSDEBUG("got watch dog %d\n",len);
|
||||
@ -452,7 +451,7 @@ ncp_watchdog(struct ncp_conn *conn) {
|
||||
buf = mtod(m, char*);
|
||||
if (buf[1] != '?') break;
|
||||
buf[1] = 'Y';
|
||||
error = so->so_proto->pr_usrreqs->pru_sosend(so, (struct sockaddr*)sa, 0, m, 0, 0, curthread);
|
||||
error = sosend(so, (struct sockaddr*)sa, 0, m, 0, 0, curthread);
|
||||
NCPSDEBUG("send watch dog %d\n",error);
|
||||
break;
|
||||
}
|
||||
|
@ -75,8 +75,7 @@ SYSCTL_DECL(_net_smb);
|
||||
SYSCTL_INT(_net_smb, OID_AUTO, tcpsndbuf, CTLFLAG_RW, &smb_tcpsndbuf, 0, "");
|
||||
SYSCTL_INT(_net_smb, OID_AUTO, tcprcvbuf, CTLFLAG_RW, &smb_tcprcvbuf, 0, "");
|
||||
|
||||
#define nb_sosend(so,m,flags,td) (so)->so_proto->pr_usrreqs->pru_sosend( \
|
||||
so, NULL, 0, m, 0, flags, td)
|
||||
#define nb_sosend(so,m,flags,td) sosend(so, NULL, 0, m, 0, flags, td)
|
||||
|
||||
static int nbssn_recv(struct nbpcb *nbp, struct mbuf **mpp, int *lenp,
|
||||
u_int8_t *rpcodep, struct thread *td);
|
||||
@ -98,8 +97,7 @@ nb_setsockopt_int(struct socket *so, int level, int name, int val)
|
||||
static __inline int
|
||||
nb_poll(struct nbpcb *nbp, int events, struct thread *td)
|
||||
{
|
||||
return nbp->nbp_tso->so_proto->pr_usrreqs->pru_sopoll(nbp->nbp_tso,
|
||||
events, NULL, td);
|
||||
return sopoll(nbp->nbp_tso, events, NULL, td);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -377,8 +375,7 @@ nbssn_recvhdr(struct nbpcb *nbp, int *lenp,
|
||||
auio.uio_offset = 0;
|
||||
auio.uio_resid = sizeof(len);
|
||||
auio.uio_td = td;
|
||||
error = so->so_proto->pr_usrreqs->pru_soreceive
|
||||
(so, (struct sockaddr **)NULL, &auio,
|
||||
error = soreceive(so, (struct sockaddr **)NULL, &auio,
|
||||
(struct mbuf **)NULL, (struct mbuf **)NULL, &flags);
|
||||
if (error)
|
||||
return error;
|
||||
@ -461,8 +458,7 @@ nbssn_recv(struct nbpcb *nbp, struct mbuf **mpp, int *lenp,
|
||||
*/
|
||||
do {
|
||||
rcvflg = MSG_WAITALL;
|
||||
error = so->so_proto->pr_usrreqs->pru_soreceive
|
||||
(so, (struct sockaddr **)NULL,
|
||||
error = soreceive(so, (struct sockaddr **)NULL,
|
||||
&auio, &tm, (struct mbuf **)NULL, &rcvflg);
|
||||
} while (error == EWOULDBLOCK || error == EINTR ||
|
||||
error == ERESTART);
|
||||
|
@ -606,8 +606,7 @@ nfs_send(struct socket *so, struct sockaddr *nam, struct mbuf *top,
|
||||
else
|
||||
flags = 0;
|
||||
|
||||
error = so->so_proto->pr_usrreqs->pru_sosend(so, sendnam, 0, top, 0,
|
||||
flags, curthread /*XXX*/);
|
||||
error = sosend(so, sendnam, 0, top, 0, flags, curthread /*XXX*/);
|
||||
if (error == ENOBUFS && so->so_type == SOCK_DGRAM) {
|
||||
error = 0;
|
||||
mtx_lock(&rep->r_mtx);
|
||||
@ -946,9 +945,8 @@ nfs_clnt_tcp_soupcall(struct socket *so, void *arg, int waitflag)
|
||||
auio.uio_iovcnt = 0;
|
||||
mp = NULL;
|
||||
rcvflg = (MSG_DONTWAIT | MSG_SOCALLBCK);
|
||||
error = so->so_proto->pr_usrreqs->pru_soreceive
|
||||
(so, (struct sockaddr **)0,
|
||||
&auio, &mp, (struct mbuf **)0, &rcvflg);
|
||||
error = soreceive(so, (struct sockaddr **)0, &auio,
|
||||
&mp, (struct mbuf **)0, &rcvflg);
|
||||
/*
|
||||
* We've already tested that the socket is readable. 2 cases
|
||||
* here, we either read 0 bytes (client closed connection),
|
||||
@ -1016,9 +1014,8 @@ nfs_clnt_tcp_soupcall(struct socket *so, void *arg, int waitflag)
|
||||
auio.uio_iovcnt = 0;
|
||||
mp = NULL;
|
||||
rcvflg = (MSG_DONTWAIT | MSG_SOCALLBCK);
|
||||
error = so->so_proto->pr_usrreqs->pru_soreceive
|
||||
(so, (struct sockaddr **)0,
|
||||
&auio, &mp, (struct mbuf **)0, &rcvflg);
|
||||
error = soreceive(so, (struct sockaddr **)0, &auio,
|
||||
&mp, (struct mbuf **)0, &rcvflg);
|
||||
if (error || auio.uio_resid > 0) {
|
||||
if (error && error != ECONNRESET) {
|
||||
log(LOG_ERR,
|
||||
@ -1058,9 +1055,7 @@ nfs_clnt_udp_soupcall(struct socket *so, void *arg, int waitflag)
|
||||
auio.uio_resid = 1000000000;
|
||||
do {
|
||||
mp = control = NULL;
|
||||
error = so->so_proto->pr_usrreqs->pru_soreceive(so,
|
||||
NULL, &auio, &mp,
|
||||
&control, &rcvflag);
|
||||
error = soreceive(so, NULL, &auio, &mp, &control, &rcvflag);
|
||||
if (control)
|
||||
m_freem(control);
|
||||
if (mp)
|
||||
|
@ -466,8 +466,7 @@ nfsrv_rcv(struct socket *so, void *arg, int waitflag)
|
||||
auio.uio_resid = 1000000000;
|
||||
flags = MSG_DONTWAIT;
|
||||
NFSD_UNLOCK();
|
||||
error = so->so_proto->pr_usrreqs->pru_soreceive
|
||||
(so, &nam, &auio, &mp, NULL, &flags);
|
||||
error = soreceive(so, &nam, &auio, &mp, NULL, &flags);
|
||||
NFSD_LOCK();
|
||||
if (error || mp == NULL) {
|
||||
if (error == EWOULDBLOCK)
|
||||
@ -503,8 +502,7 @@ nfsrv_rcv(struct socket *so, void *arg, int waitflag)
|
||||
auio.uio_resid = 1000000000;
|
||||
flags = MSG_DONTWAIT;
|
||||
NFSD_UNLOCK();
|
||||
error = so->so_proto->pr_usrreqs->pru_soreceive
|
||||
(so, &nam, &auio, &mp, NULL, &flags);
|
||||
error = soreceive(so, &nam, &auio, &mp, NULL, &flags);
|
||||
if (mp) {
|
||||
struct nfsrv_rec *rec;
|
||||
rec = malloc(sizeof(struct nfsrv_rec),
|
||||
@ -785,8 +783,7 @@ nfsrv_send(struct socket *so, struct sockaddr *nam, struct mbuf *top)
|
||||
else
|
||||
flags = 0;
|
||||
|
||||
error = so->so_proto->pr_usrreqs->pru_sosend(so, sendnam, 0, top, 0,
|
||||
flags, curthread/*XXX*/);
|
||||
error = sosend(so, sendnam, 0, top, 0, flags, curthread/*XXX*/);
|
||||
if (error == ENOBUFS && so->so_type == SOCK_DGRAM)
|
||||
error = 0;
|
||||
|
||||
|
@ -228,15 +228,6 @@ struct pr_usrreqs {
|
||||
int (*pru_sense)(struct socket *so, struct stat *sb);
|
||||
int (*pru_shutdown)(struct socket *so);
|
||||
int (*pru_sockaddr)(struct socket *so, struct sockaddr **nam);
|
||||
|
||||
/*
|
||||
* These four added later, so they are out of order. They are used
|
||||
* for shortcutting (fast path input/output) in some protocols.
|
||||
* XXX - that's a lie, they are not implemented yet
|
||||
* Rather than calling sosend() etc. directly, calls are made
|
||||
* through these entry points. For protocols which still use
|
||||
* the generic code, these just point to those routines.
|
||||
*/
|
||||
int (*pru_sosend)(struct socket *so, struct sockaddr *addr,
|
||||
struct uio *uio, struct mbuf *top, struct mbuf *control,
|
||||
int flags, struct thread *td);
|
||||
|
@ -530,8 +530,13 @@ int soopt_mcopyout(struct sockopt *sopt, struct mbuf *m);
|
||||
|
||||
int sopoll(struct socket *so, int events, struct ucred *active_cred,
|
||||
struct thread *td);
|
||||
int sopoll_generic(struct socket *so, int events,
|
||||
struct ucred *active_cred, struct thread *td);
|
||||
int soreceive(struct socket *so, struct sockaddr **paddr, struct uio *uio,
|
||||
struct mbuf **mp0, struct mbuf **controlp, int *flagsp);
|
||||
int soreceive_generic(struct socket *so, struct sockaddr **paddr,
|
||||
struct uio *uio, struct mbuf **mp0, struct mbuf **controlp,
|
||||
int *flagsp);
|
||||
int soreserve(struct socket *so, u_long sndcc, u_long rcvcc);
|
||||
void sorflush(struct socket *so);
|
||||
int sosend(struct socket *so, struct sockaddr *addr, struct uio *uio,
|
||||
@ -540,6 +545,9 @@ int sosend(struct socket *so, struct sockaddr *addr, struct uio *uio,
|
||||
int sosend_dgram(struct socket *so, struct sockaddr *addr,
|
||||
struct uio *uio, struct mbuf *top, struct mbuf *control,
|
||||
int flags, struct thread *td);
|
||||
int sosend_generic(struct socket *so, struct sockaddr *addr,
|
||||
struct uio *uio, struct mbuf *top, struct mbuf *control,
|
||||
int flags, struct thread *td);
|
||||
int sosetopt(struct socket *so, struct sockopt *sopt);
|
||||
int soshutdown(struct socket *so, int how);
|
||||
void sotoxsocket(struct socket *so, struct xsocket *xso);
|
||||
|
Loading…
Reference in New Issue
Block a user