mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-15 10:17:20 +00:00
buf.h:
Change the definition of a buffer queue so that bufqdisksort can properly deal with bordered writes. Add inline functions for accessing buffer queues. This should be considered an opaque data structure by clients. callout.h: New callout implementation. device.h: Add support for CAM interrupts. disk.h: disklabel.h: tqdisksort->bufqdisksort kernel.h: Add new configuration entries for configuration hooks and calling cpu_rootconf and cpu_dumpconf. param.h: Add a priority for sleeping waiting on config hooks. proc.h: Update for new callout implementation. queue.h: Add TAILQ_HEAD_INITIALIZER from NetBSD. systm.h: Add prototypes for cpu_root/dumpconf, splcam, splsoftcam, etc..
This commit is contained in:
parent
e74a2bdcb0
commit
5957b26149
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=29683
@ -36,7 +36,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)buf.h 8.9 (Berkeley) 3/30/95
|
||||
* $Id: buf.h,v 1.40 1997/09/07 16:56:34 bde Exp $
|
||||
* $Id: buf.h,v 1.41 1997/09/16 11:44:02 bde Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SYS_BUF_H_
|
||||
@ -58,8 +58,6 @@ struct iodone_chain {
|
||||
} ic_args[5];
|
||||
};
|
||||
|
||||
typedef TAILQ_HEAD(buf_queue_head, buf) buf_queue_head, *buf_queue_head_t;
|
||||
|
||||
/*
|
||||
* The buffer header describes an I/O operation in the kernel.
|
||||
*/
|
||||
@ -149,6 +147,72 @@ struct buf {
|
||||
#define B_CLUSTER 0x40000000 /* pagein op, so swap() can count it */
|
||||
#define B_BOUNCE 0x80000000 /* bounce buffer flag */
|
||||
|
||||
typedef struct buf_queue_head {
|
||||
TAILQ_HEAD(, buf) queue;
|
||||
struct buf *insert_point;
|
||||
struct buf *switch_point;
|
||||
} buf_queue_head, *buf_queue_head_t;
|
||||
|
||||
static __inline void bufq_init __P((buf_queue_head *head));
|
||||
|
||||
static __inline void bufq_insert_tail __P((buf_queue_head *head,
|
||||
struct buf *bp));
|
||||
|
||||
static __inline void bufq_remove __P((buf_queue_head *head,
|
||||
struct buf *bp));
|
||||
|
||||
static __inline struct buf *bufq_first __P((buf_queue_head *head));
|
||||
|
||||
static __inline void
|
||||
bufq_init(buf_queue_head *head)
|
||||
{
|
||||
TAILQ_INIT(&head->queue);
|
||||
head->insert_point = NULL;
|
||||
head->switch_point = NULL;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
bufq_insert_tail(buf_queue_head *head, struct buf *bp)
|
||||
{
|
||||
if ((bp->b_flags & B_ORDERED) != 0) {
|
||||
head->insert_point = bp;
|
||||
head->switch_point = NULL;
|
||||
}
|
||||
TAILQ_INSERT_TAIL(&head->queue, bp, b_act);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
bufq_remove(buf_queue_head *head, struct buf *bp)
|
||||
{
|
||||
if (bp == TAILQ_FIRST(&head->queue)) {
|
||||
if (bp == head->insert_point)
|
||||
head->insert_point = NULL;
|
||||
if (TAILQ_NEXT(bp, b_act) == head->switch_point)
|
||||
head->switch_point = NULL;
|
||||
} else {
|
||||
if (bp == head->insert_point) {
|
||||
/*
|
||||
* Not 100% correct (we really want the
|
||||
* previous bp), but it will ensure queue
|
||||
* ordering and is less expensive than
|
||||
* using a CIRCLEQ.
|
||||
*/
|
||||
head->insert_point == TAILQ_NEXT(bp, b_act);
|
||||
}
|
||||
if (bp == head->switch_point) {
|
||||
head->switch_point == TAILQ_NEXT(bp, b_act);
|
||||
}
|
||||
}
|
||||
TAILQ_REMOVE(&head->queue, bp, b_act);
|
||||
}
|
||||
|
||||
static __inline struct buf *
|
||||
bufq_first(buf_queue_head *head)
|
||||
{
|
||||
return (TAILQ_FIRST(&head->queue));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* number of buffer hash entries
|
||||
*/
|
||||
|
@ -36,7 +36,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)buf.h 8.9 (Berkeley) 3/30/95
|
||||
* $Id: buf.h,v 1.40 1997/09/07 16:56:34 bde Exp $
|
||||
* $Id: buf.h,v 1.41 1997/09/16 11:44:02 bde Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SYS_BUF_H_
|
||||
@ -58,8 +58,6 @@ struct iodone_chain {
|
||||
} ic_args[5];
|
||||
};
|
||||
|
||||
typedef TAILQ_HEAD(buf_queue_head, buf) buf_queue_head, *buf_queue_head_t;
|
||||
|
||||
/*
|
||||
* The buffer header describes an I/O operation in the kernel.
|
||||
*/
|
||||
@ -149,6 +147,72 @@ struct buf {
|
||||
#define B_CLUSTER 0x40000000 /* pagein op, so swap() can count it */
|
||||
#define B_BOUNCE 0x80000000 /* bounce buffer flag */
|
||||
|
||||
typedef struct buf_queue_head {
|
||||
TAILQ_HEAD(, buf) queue;
|
||||
struct buf *insert_point;
|
||||
struct buf *switch_point;
|
||||
} buf_queue_head, *buf_queue_head_t;
|
||||
|
||||
static __inline void bufq_init __P((buf_queue_head *head));
|
||||
|
||||
static __inline void bufq_insert_tail __P((buf_queue_head *head,
|
||||
struct buf *bp));
|
||||
|
||||
static __inline void bufq_remove __P((buf_queue_head *head,
|
||||
struct buf *bp));
|
||||
|
||||
static __inline struct buf *bufq_first __P((buf_queue_head *head));
|
||||
|
||||
static __inline void
|
||||
bufq_init(buf_queue_head *head)
|
||||
{
|
||||
TAILQ_INIT(&head->queue);
|
||||
head->insert_point = NULL;
|
||||
head->switch_point = NULL;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
bufq_insert_tail(buf_queue_head *head, struct buf *bp)
|
||||
{
|
||||
if ((bp->b_flags & B_ORDERED) != 0) {
|
||||
head->insert_point = bp;
|
||||
head->switch_point = NULL;
|
||||
}
|
||||
TAILQ_INSERT_TAIL(&head->queue, bp, b_act);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
bufq_remove(buf_queue_head *head, struct buf *bp)
|
||||
{
|
||||
if (bp == TAILQ_FIRST(&head->queue)) {
|
||||
if (bp == head->insert_point)
|
||||
head->insert_point = NULL;
|
||||
if (TAILQ_NEXT(bp, b_act) == head->switch_point)
|
||||
head->switch_point = NULL;
|
||||
} else {
|
||||
if (bp == head->insert_point) {
|
||||
/*
|
||||
* Not 100% correct (we really want the
|
||||
* previous bp), but it will ensure queue
|
||||
* ordering and is less expensive than
|
||||
* using a CIRCLEQ.
|
||||
*/
|
||||
head->insert_point == TAILQ_NEXT(bp, b_act);
|
||||
}
|
||||
if (bp == head->switch_point) {
|
||||
head->switch_point == TAILQ_NEXT(bp, b_act);
|
||||
}
|
||||
}
|
||||
TAILQ_REMOVE(&head->queue, bp, b_act);
|
||||
}
|
||||
|
||||
static __inline struct buf *
|
||||
bufq_first(buf_queue_head *head)
|
||||
{
|
||||
return (TAILQ_FIRST(&head->queue));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* number of buffer hash entries
|
||||
*/
|
||||
|
@ -36,22 +36,38 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)callout.h 8.2 (Berkeley) 1/21/94
|
||||
* $Id: callout.h,v 1.6 1997/02/22 09:44:50 peter Exp $
|
||||
* $Id: callout.h,v 1.7 1997/09/07 05:26:57 bde Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SYS_CALLOUT_H_
|
||||
#define _SYS_CALLOUT_H_
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
SLIST_HEAD(callout_list, callout);
|
||||
TAILQ_HEAD(callout_tailq, callout);
|
||||
|
||||
struct callout {
|
||||
struct callout *c_next; /* next callout in queue */
|
||||
union {
|
||||
SLIST_ENTRY(callout) sle;
|
||||
TAILQ_ENTRY(callout) tqe;
|
||||
} c_links;
|
||||
struct callout_tailq *c_bucket;
|
||||
void *c_arg; /* function argument */
|
||||
void (*c_func) __P((void *)); /* function to call */
|
||||
int c_time; /* ticks to the event */
|
||||
};
|
||||
|
||||
#ifdef KERNEL
|
||||
extern struct callout *callfree, *callout;
|
||||
extern int ncallout;
|
||||
#endif
|
||||
struct callout_handle {
|
||||
struct callout *callout;
|
||||
};
|
||||
|
||||
#endif
|
||||
#ifdef KERNEL
|
||||
extern struct callout_list callfree;
|
||||
extern struct callout *callout;
|
||||
extern int ncallout;
|
||||
extern struct callout_tailq *callwheel;
|
||||
extern int callwheelsize, callwheelbits, callwheelmask;
|
||||
#endif /* KERNEL */
|
||||
|
||||
#endif /* _SYS_CALLOUT_H_ */
|
||||
|
@ -40,12 +40,14 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)device.h 8.2 (Berkeley) 2/17/94
|
||||
* $Id$
|
||||
* $Id: device.h,v 1.6 1997/02/22 09:45:00 peter Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SYS_DEVICE_H_
|
||||
#define _SYS_DEVICE_H_
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
/*
|
||||
* Minimal device structures.
|
||||
* Note that all ``system'' device types are listed here.
|
||||
@ -114,6 +116,12 @@ struct cfdriver {
|
||||
int cd_ndevs; /* size of cd_devs array */
|
||||
};
|
||||
|
||||
struct intr_config_hook {
|
||||
TAILQ_ENTRY(intr_config_hook) ich_links;
|
||||
void (*ich_func) __P((void *arg));
|
||||
void *ich_arg;
|
||||
};
|
||||
|
||||
/*
|
||||
* Configuration printing functions, and their return codes. The second
|
||||
* argument is NULL if the device was configured; otherwise it is the name
|
||||
@ -142,4 +150,7 @@ int config_found __P((struct device *, void *, cfprint_t));
|
||||
int config_rootfound __P((char *, void *));
|
||||
void config_attach __P((struct device *, struct cfdata *, void *, cfprint_t));
|
||||
void evcnt_attach __P((struct device *, const char *, struct evcnt *));
|
||||
int config_intrhook_establish __P((struct intr_config_hook *hook));
|
||||
void config_intrhook_disestablish __P((struct intr_config_hook *hook));
|
||||
|
||||
#endif /* !_SYS_DEVICE_H_ */
|
||||
|
@ -41,7 +41,7 @@
|
||||
*
|
||||
* @(#)disk.h 8.1 (Berkeley) 6/2/93
|
||||
*
|
||||
* $Id$
|
||||
* $Id: disk.h,v 1.7 1997/02/22 09:45:04 peter Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SYS_DISK_H_
|
||||
@ -107,7 +107,7 @@ struct disksort_stats {
|
||||
#endif
|
||||
|
||||
#ifdef KERNEL
|
||||
void tqdisksort __P((struct buf_queue_head *, struct buf *));
|
||||
void bufqdisksort __P((struct buf_queue_head *, struct buf *));
|
||||
char *readdisklabel __P((struct dkdevice *, int));
|
||||
int setdisklabel __P((struct dkdevice *, struct disklabel *));
|
||||
int writedisklabel __P((struct dkdevice *, int));
|
||||
|
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)disklabel.h 8.2 (Berkeley) 7/10/94
|
||||
* $Id$
|
||||
* $Id: disklabel.h,v 1.27 1997/02/22 09:45:05 peter Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SYS_DISKLABEL_H_
|
||||
@ -432,7 +432,7 @@ void disksort __P((struct buf *ap, struct buf *bp));
|
||||
u_int dkcksum __P((struct disklabel *lp));
|
||||
char *readdisklabel __P((dev_t dev, void (*strat)(struct buf *bp),
|
||||
struct disklabel *lp));
|
||||
void tqdisksort __P((struct buf_queue_head *ap, struct buf *bp));
|
||||
void bufqdisksort __P((struct buf_queue_head *ap, struct buf *bp));
|
||||
int setdisklabel __P((struct disklabel *olp, struct disklabel *nlp,
|
||||
u_long openmask));
|
||||
int writedisklabel __P((dev_t dev, void (*strat)(struct buf *bp),
|
||||
|
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)disklabel.h 8.2 (Berkeley) 7/10/94
|
||||
* $Id$
|
||||
* $Id: disklabel.h,v 1.27 1997/02/22 09:45:05 peter Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SYS_DISKLABEL_H_
|
||||
@ -432,7 +432,7 @@ void disksort __P((struct buf *ap, struct buf *bp));
|
||||
u_int dkcksum __P((struct disklabel *lp));
|
||||
char *readdisklabel __P((dev_t dev, void (*strat)(struct buf *bp),
|
||||
struct disklabel *lp));
|
||||
void tqdisksort __P((struct buf_queue_head *ap, struct buf *bp));
|
||||
void bufqdisksort __P((struct buf_queue_head *ap, struct buf *bp));
|
||||
int setdisklabel __P((struct disklabel *olp, struct disklabel *nlp,
|
||||
u_long openmask));
|
||||
int writedisklabel __P((dev_t dev, void (*strat)(struct buf *bp),
|
||||
|
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)disklabel.h 8.2 (Berkeley) 7/10/94
|
||||
* $Id$
|
||||
* $Id: disklabel.h,v 1.27 1997/02/22 09:45:05 peter Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SYS_DISKLABEL_H_
|
||||
@ -432,7 +432,7 @@ void disksort __P((struct buf *ap, struct buf *bp));
|
||||
u_int dkcksum __P((struct disklabel *lp));
|
||||
char *readdisklabel __P((dev_t dev, void (*strat)(struct buf *bp),
|
||||
struct disklabel *lp));
|
||||
void tqdisksort __P((struct buf_queue_head *ap, struct buf *bp));
|
||||
void bufqdisksort __P((struct buf_queue_head *ap, struct buf *bp));
|
||||
int setdisklabel __P((struct disklabel *olp, struct disklabel *nlp,
|
||||
u_long openmask));
|
||||
int writedisklabel __P((dev_t dev, void (*strat)(struct buf *bp),
|
||||
|
@ -39,7 +39,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)kernel.h 8.3 (Berkeley) 1/21/94
|
||||
* $Id: kernel.h,v 1.32 1997/06/22 16:04:20 peter Exp $
|
||||
* $Id: kernel.h,v 1.33 1997/06/24 18:21:08 jhay Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SYS_KERNEL_H_
|
||||
@ -163,7 +163,10 @@ enum sysinit_sub_id {
|
||||
SI_SUB_PROTO_END = 0x8fffffff, /* XXX: set splx (kludge)*/
|
||||
SI_SUB_KPROF = 0x90000000, /* kernel profiling*/
|
||||
SI_SUB_KICK_SCHEDULER = 0xa0000000, /* start the timeout events*/
|
||||
SI_SUB_ROOT = 0xb0000000, /* root mount*/
|
||||
SI_SUB_INT_CONFIG_HOOKS = 0xa8000000, /* Interrupts enabled config */
|
||||
SI_SUB_ROOT_CONF = 0xb0000000, /* Find root devices */
|
||||
SI_SUB_DUMP_CONF = 0xb2000000, /* Find dump devices */
|
||||
SI_SUB_MOUNT_ROOT = 0xb4000000, /* root mount*/
|
||||
SI_SUB_ROOT_FDTAB = 0xb8000000, /* root vnode in fd table...*/
|
||||
SI_SUB_SWAP = 0xc0000000, /* swap*/
|
||||
SI_SUB_INTRINSIC_POST = 0xd0000000, /* proc 0 cleanup*/
|
||||
|
@ -36,7 +36,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)param.h 8.3 (Berkeley) 4/4/95
|
||||
* $Id: param.h,v 1.25 1997/03/03 08:34:08 ache Exp $
|
||||
* $Id: param.h,v 1.26 1997/03/03 09:51:10 ache Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SYS_PARAM_H_
|
||||
@ -106,6 +106,7 @@
|
||||
#define PZERO 22 /* No longer magic, shouldn't be here. XXX */
|
||||
#define PSOCK 24
|
||||
#define PWAIT 32
|
||||
#define PCONFIG 32
|
||||
#define PLOCK 36
|
||||
#define PPAUSE 40
|
||||
#define PUSER 50
|
||||
|
@ -36,13 +36,14 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)proc.h 8.15 (Berkeley) 5/19/95
|
||||
* $Id: proc.h,v 1.42 1997/07/06 02:40:36 dyson Exp $
|
||||
* $Id: proc.h,v 1.43 1997/09/13 19:42:27 joerg Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SYS_PROC_H_
|
||||
#define _SYS_PROC_H_
|
||||
|
||||
#include <machine/proc.h> /* Machine-dependent proc substruct. */
|
||||
#include <sys/callout.h> /* For struct callout_handle. */
|
||||
#include <sys/rtprio.h> /* For struct rtprio. */
|
||||
#include <sys/select.h> /* For struct selinfo. */
|
||||
#include <sys/time.h> /* For structs itimerval, timeval. */
|
||||
@ -108,6 +109,10 @@ struct proc {
|
||||
LIST_ENTRY(proc) p_sibling; /* List of sibling processes. */
|
||||
LIST_HEAD(, proc) p_children; /* Pointer to list of children. */
|
||||
|
||||
struct callout_handle p_ithandle; /*
|
||||
* Callout handle for scheduling
|
||||
* p_realtimer.
|
||||
*/
|
||||
/* The following fields are all zeroed upon creation in fork. */
|
||||
#define p_startzero p_oppid
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)queue.h 8.5 (Berkeley) 8/20/94
|
||||
* $Id: queue.h,v 1.16 1997/05/07 14:38:11 dfr Exp $
|
||||
* $Id: queue.h,v 1.17 1997/08/25 20:21:54 phk Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SYS_QUEUE_H_
|
||||
@ -298,6 +298,9 @@ struct name { \
|
||||
struct type **tqh_last; /* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define TAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).tqh_first }
|
||||
|
||||
#define TAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *tqe_next; /* next element */ \
|
||||
|
@ -36,13 +36,14 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)systm.h 8.7 (Berkeley) 3/29/95
|
||||
* $Id: systm.h,v 1.58 1997/09/07 16:20:55 bde Exp $
|
||||
* $Id: systm.h,v 1.59 1997/09/16 14:19:46 bde Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SYS_SYSTM_H_
|
||||
#define _SYS_SYSTM_H_
|
||||
|
||||
#include <machine/cpufunc.h>
|
||||
#include <sys/callout.h>
|
||||
|
||||
extern int securelevel; /* system security level (see init(8)) */
|
||||
|
||||
@ -87,6 +88,8 @@ void *phashinit __P((int count, int type, u_long *nentries));
|
||||
void panic __P((const char *, ...)) __dead2;
|
||||
void boot __P((int)) __dead2;
|
||||
void cpu_boot __P((int));
|
||||
void cpu_rootconf __P((void));
|
||||
void cpu_dumpconf __P((void));
|
||||
void tablefull __P((const char *));
|
||||
int addlog __P((const char *, ...));
|
||||
int kvprintf __P((char const *, void (*)(int, void*), void *, int,
|
||||
@ -157,18 +160,25 @@ void startrtclock __P((void));
|
||||
|
||||
/* Timeouts */
|
||||
typedef void timeout_t __P((void *)); /* timeout function type */
|
||||
#define CALLOUT_HANDLE_INITIALIZER(handle) \
|
||||
{ NULL }
|
||||
|
||||
void timeout __P((timeout_t *, void *, int));
|
||||
void untimeout __P((timeout_t *, void *));
|
||||
void callout_handle_init __P((struct callout_handle *));
|
||||
struct callout_handle timeout __P((timeout_t *, void *, int));
|
||||
void untimeout __P((timeout_t *, void *, struct callout_handle));
|
||||
|
||||
/* Interrupt management */
|
||||
void setdelayed(void);
|
||||
void setsoftast(void);
|
||||
void setsoftclock(void);
|
||||
void setsoftnet(void);
|
||||
void setsoftcambio(void);
|
||||
void setsoftcamnet(void);
|
||||
void setsofttty(void);
|
||||
void schedsoftnet(void);
|
||||
void schedsofttty(void);
|
||||
void schedsoftcamnet(void);
|
||||
void schedsoftcambio(void);
|
||||
void spl0(void);
|
||||
intrmask_t softclockpending(void);
|
||||
intrmask_t splbio(void);
|
||||
@ -179,6 +189,10 @@ intrmask_t splnet(void);
|
||||
#ifdef SMP
|
||||
intrmask_t splq(intrmask_t mask);
|
||||
#endif
|
||||
intrmask_t splcam(void);
|
||||
intrmask_t splsoftcam(void);
|
||||
intrmask_t splsoftcambio(void);
|
||||
intrmask_t splsoftcamnet(void);
|
||||
intrmask_t splsoftclock(void);
|
||||
intrmask_t splsofttty(void);
|
||||
intrmask_t splstatclock(void);
|
||||
@ -194,6 +208,7 @@ void splz(void);
|
||||
* implicitly causes these to be defined when it #included <machine/spl.h>
|
||||
*/
|
||||
extern intrmask_t bio_imask; /* group of interrupts masked with splbio() */
|
||||
extern intrmask_t cam_imask; /* group of interrupts masked with splcam() */
|
||||
extern intrmask_t net_imask; /* group of interrupts masked with splimp() */
|
||||
extern intrmask_t stat_imask; /* interrupts masked with splstatclock() */
|
||||
extern intrmask_t tty_imask; /* group of interrupts masked with spltty() */
|
||||
|
Loading…
Reference in New Issue
Block a user