Add support for FIONWRITE and FIONSPACE ioctls. FIONWRITE reports
the number of bytes in the send queue, and FIONSPACE reports the number of free bytes in the send queue. These ioctls permit applications to monitor file descriptor transmission dynamics. In examining prior art, FIONWRITE exists with the semantics given here. FIONSPACE is provided so that programs may easily determine how much space is left in the send queue; they do not need to know the send queue size. The fact that a write may block even if there is enough space in the send queue for it is noted in the documentation. FIONWRITE functionality may be used to implement TIOCOUTQ for Linux emulation - Linux extended this ioctl to sockets, even though they are not ttys.
This commit is contained in:
parent
96a5d45d4c
commit
16029d56b5
|
@ -1,4 +1,4 @@
|
|||
.\" $NetBSD: ioctl.2,v 1.18 2004/05/13 10:20:58 wiz Exp $
|
||||
.\" $NetBSD: ioctl.2,v 1.19 2004/11/06 02:03:20 wrstuden Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1980, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
|
@ -89,6 +89,26 @@ These include:
|
|||
.Bl -tag -width "xxxxxx"
|
||||
.It Dv FIONREAD "int"
|
||||
Get the number of bytes that are immediately available for reading.
|
||||
.It Dv FIONWRITE "int"
|
||||
Get the number of bytes in the descriptor's send queue.
|
||||
These bytes are data which has been written to the descriptor but
|
||||
which are being held by the kernel for further processing.
|
||||
The nature of the required processing depends on the underlying device.
|
||||
For tty devices, these bytes are typically queued for delivery
|
||||
to the tty hardware.
|
||||
For TCP sockets, these bytes have not yet been acknolwedged by the
|
||||
other side of the connection.
|
||||
For files, this operation always returns zero as files do not have
|
||||
send queues.
|
||||
.It Dv FIONSPACE "int"
|
||||
Get the free space in the descriptor's send queue.
|
||||
This value is the size of the send queue minus the number of bytes
|
||||
being held in the queue.
|
||||
Note: while this value represents the number of bytes that may be
|
||||
added to the queue, other resource limitations may cause a write
|
||||
not larger than the send queue's space to be blocked.
|
||||
One such limitation would be a lack of network buffers for a write
|
||||
to a network connection.
|
||||
.It Dv FIONBIO "int"
|
||||
Set non-blocking I/O mode if the argument is non-zero.
|
||||
In non-blocking mode,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: sys_pipe.c,v 1.58 2004/07/17 20:50:08 mycroft Exp $ */
|
||||
/* $NetBSD: sys_pipe.c,v 1.59 2004/11/06 02:03:20 wrstuden Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003 The NetBSD Foundation, Inc.
|
||||
|
@ -83,7 +83,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sys_pipe.c,v 1.58 2004/07/17 20:50:08 mycroft Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: sys_pipe.c,v 1.59 2004/11/06 02:03:20 wrstuden Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -1141,6 +1141,38 @@ pipe_ioctl(fp, cmd, data, p)
|
|||
PIPE_UNLOCK(pipe);
|
||||
return (0);
|
||||
|
||||
case FIONWRITE:
|
||||
/* Look at other side */
|
||||
pipe = pipe->pipe_peer;
|
||||
PIPE_LOCK(pipe);
|
||||
#ifndef PIPE_NODIRECT
|
||||
if (pipe->pipe_state & PIPE_DIRECTW)
|
||||
*(int *)data = pipe->pipe_map.cnt;
|
||||
else
|
||||
#endif
|
||||
*(int *)data = pipe->pipe_buffer.cnt;
|
||||
PIPE_UNLOCK(pipe);
|
||||
return (0);
|
||||
|
||||
case FIONSPACE:
|
||||
/* Look at other side */
|
||||
pipe = pipe->pipe_peer;
|
||||
PIPE_LOCK(pipe);
|
||||
#ifndef PIPE_NODIRECT
|
||||
/*
|
||||
* If we're in direct-mode, we don't really have a
|
||||
* send queue, and any other write will block. Thus
|
||||
* zero seems like the best answer.
|
||||
*/
|
||||
if (pipe->pipe_state & PIPE_DIRECTW)
|
||||
*(int *)data = 0;
|
||||
else
|
||||
#endif
|
||||
*(int *)data = pipe->pipe_buffer.size -
|
||||
pipe->pipe_buffer.cnt;
|
||||
PIPE_UNLOCK(pipe);
|
||||
return (0);
|
||||
|
||||
case TIOCSPGRP:
|
||||
case FIOSETOWN:
|
||||
return fsetown(p, &pipe->pipe_pgid, cmd, data);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: sys_socket.c,v 1.40 2004/05/22 22:52:13 jonathan Exp $ */
|
||||
/* $NetBSD: sys_socket.c,v 1.41 2004/11/06 02:03:20 wrstuden Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1990, 1993
|
||||
|
@ -32,7 +32,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sys_socket.c,v 1.40 2004/05/22 22:52:13 jonathan Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: sys_socket.c,v 1.41 2004/11/06 02:03:20 wrstuden Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -116,6 +116,24 @@ soo_ioctl(fp, cmd, data, p)
|
|||
*(int *)data = so->so_rcv.sb_cc;
|
||||
return (0);
|
||||
|
||||
case FIONWRITE:
|
||||
*(int *)data = so->so_snd.sb_cc;
|
||||
return (0);
|
||||
|
||||
case FIONSPACE:
|
||||
/*
|
||||
* See the comment around sbspace()'s definition
|
||||
* in sys/socketvar.h in face of counts about maximum
|
||||
* to understand the following test. We detect overflow
|
||||
* and return zero.
|
||||
*/
|
||||
if ((so->snd.sb_hiwat < so->snd.sb_cc)
|
||||
|| (so->snd.sb_mbmax < so->snd.sb_mbcnt))
|
||||
*(int *)data = 0;
|
||||
else
|
||||
*(int *)data = sbspace(so->so_snd);
|
||||
return (0);
|
||||
|
||||
case SIOCSPGRP:
|
||||
case FIOSETOWN:
|
||||
case TIOCSPGRP:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: tty.c,v 1.169 2004/10/15 07:15:39 thorpej Exp $ */
|
||||
/* $NetBSD: tty.c,v 1.170 2004/11/06 02:03:20 wrstuden Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1990, 1991, 1993
|
||||
|
@ -37,7 +37,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: tty.c,v 1.169 2004/10/15 07:15:39 thorpej Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: tty.c,v 1.170 2004/11/06 02:03:20 wrstuden Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -880,6 +880,20 @@ ttioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
|
|||
TTY_UNLOCK(tp);
|
||||
splx(s);
|
||||
break;
|
||||
case FIONWRITE: /* get # bytes to written & unsent */
|
||||
s = spltty();
|
||||
TTY_LOCK(tp);
|
||||
*(int *)data = tp->t_outq.c_cc;
|
||||
TTY_UNLOCK(tp);
|
||||
splx(s);
|
||||
break;
|
||||
case FIONSPACE: /* get # bytes to written & unsent */
|
||||
s = spltty();
|
||||
TTY_LOCK(tp);
|
||||
*(int *)data = tp->t_outq.c_cn - tp->t_outq.c_cc;
|
||||
TTY_UNLOCK(tp);
|
||||
splx(s);
|
||||
break;
|
||||
case TIOCEXCL: /* set exclusive use of tty */
|
||||
s = spltty();
|
||||
TTY_LOCK(tp);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: vfs_vnops.c,v 1.80 2004/05/31 09:02:51 yamt Exp $ */
|
||||
/* $NetBSD: vfs_vnops.c,v 1.81 2004/11/06 02:03:20 wrstuden Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
|
@ -37,7 +37,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.80 2004/05/31 09:02:51 yamt Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.81 2004/11/06 02:03:20 wrstuden Exp $");
|
||||
|
||||
#include "fs_union.h"
|
||||
|
||||
|
@ -692,6 +692,15 @@ vn_ioctl(fp, com, data, p)
|
|||
*(int *)data = vattr.va_size - fp->f_offset;
|
||||
return (0);
|
||||
}
|
||||
if ((com == FIONWRITE) || (comm == FIONSPACE)) {
|
||||
/*
|
||||
* Files don't have send queues, so there never
|
||||
* are any bytes in them, nor is there any
|
||||
* open space in them.
|
||||
*/
|
||||
*(int *)data = 0;
|
||||
return (0);
|
||||
}
|
||||
if (com == FIOGETBMAP) {
|
||||
daddr_t *block;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: filio.h,v 1.8 2003/08/07 16:34:04 agc Exp $ */
|
||||
/* $NetBSD: filio.h,v 1.9 2004/11/06 02:03:20 wrstuden Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1990, 1993, 1994
|
||||
|
@ -51,6 +51,10 @@
|
|||
#define FIOGETOWN _IOR('f', 123, int) /* get owner */
|
||||
#define OFIOGETBMAP _IOWR('f', 122, uint32_t) /* get underlying block no. */
|
||||
#define FIOGETBMAP _IOWR('f', 122, daddr_t) /* get underlying block no. */
|
||||
#define FIONWRITE _IOR('f', 121, int) /* get # bytes outstanding
|
||||
* in send queue. */
|
||||
#define FIONSPACE _IOR('f', 120, int) /* get space in send queue. */
|
||||
|
||||
|
||||
/* Ugly symbol for compatibility with other operating systems */
|
||||
#define FIBMAP FIOGETBMAP
|
||||
|
|
Loading…
Reference in New Issue