svn commit: r197718 - in user/kmacy/releng_8_fcs/sys: kern sys
Kip Macy
kmacy at FreeBSD.org
Fri Oct 2 20:15:48 UTC 2009
Author: kmacy
Date: Fri Oct 2 20:15:47 2009
New Revision: 197718
URL: http://svn.freebsd.org/changeset/base/197718
Log:
Add background sendfile for asynchrounous completion of non-blocking requests.
Disable by default.
Modified:
user/kmacy/releng_8_fcs/sys/kern/uipc_sockbuf.c
user/kmacy/releng_8_fcs/sys/kern/uipc_socket.c
user/kmacy/releng_8_fcs/sys/kern/uipc_syscalls.c
user/kmacy/releng_8_fcs/sys/sys/file.h
user/kmacy/releng_8_fcs/sys/sys/sockbuf.h
user/kmacy/releng_8_fcs/sys/sys/socket.h
user/kmacy/releng_8_fcs/sys/sys/socketvar.h
user/kmacy/releng_8_fcs/sys/sys/sockstate.h
user/kmacy/releng_8_fcs/sys/sys/syscallsubr.h
Modified: user/kmacy/releng_8_fcs/sys/kern/uipc_sockbuf.c
==============================================================================
--- user/kmacy/releng_8_fcs/sys/kern/uipc_sockbuf.c Fri Oct 2 19:51:03 2009 (r197717)
+++ user/kmacy/releng_8_fcs/sys/kern/uipc_sockbuf.c Fri Oct 2 20:15:47 2009 (r197718)
@@ -133,7 +133,7 @@ sbwait(struct sockbuf *sb)
}
int
-sblock(struct sockbuf *sb, int flags)
+_sblock(struct sockbuf *sb, int flags, const char *file, int line)
{
KASSERT((flags & SBL_VALID) == flags,
@@ -142,12 +142,12 @@ sblock(struct sockbuf *sb, int flags)
if (flags & SBL_WAIT) {
if ((sb->sb_flags & SB_NOINTR) ||
(flags & SBL_NOINTR)) {
- sx_xlock(&sb->sb_sx);
+ _sx_xlock(&sb->sb_sx, 0, file, line);
return (0);
}
- return (sx_xlock_sig(&sb->sb_sx));
+ return (_sx_xlock(&sb->sb_sx, SX_INTERRUPTIBLE, file, line));
} else {
- if (sx_try_xlock(&sb->sb_sx) == 0)
+ if (_sx_try_xlock(&sb->sb_sx, file, line) == 0)
return (EWOULDBLOCK);
return (0);
}
@@ -178,7 +178,10 @@ sowakeup(struct socket *so, struct sockb
int ret;
SOCKBUF_LOCK_ASSERT(sb);
-
+ if (sb->sb_flags & SB_SENDING) {
+ SOCKBUF_UNLOCK(sb);
+ return;
+ }
selwakeuppri(&sb->sb_sel, PSOCK);
if (!SEL_WAITING(&sb->sb_sel))
sb->sb_flags &= ~SB_SEL;
@@ -906,6 +909,8 @@ sbdrop_locked(struct sockbuf *sb, int le
SOCKBUF_LOCK_ASSERT(sb);
sbdrop_internal(sb, len);
+ if (sb->sb_flags & SB_SENDING)
+ sosendingwakeup(sb);
}
void
Modified: user/kmacy/releng_8_fcs/sys/kern/uipc_socket.c
==============================================================================
--- user/kmacy/releng_8_fcs/sys/kern/uipc_socket.c Fri Oct 2 19:51:03 2009 (r197717)
+++ user/kmacy/releng_8_fcs/sys/kern/uipc_socket.c Fri Oct 2 20:15:47 2009 (r197718)
@@ -124,10 +124,15 @@ __FBSDID("$FreeBSD$");
#include <sys/resourcevar.h>
#include <net/route.h>
#include <sys/signalvar.h>
+#include <sys/smp.h>
#include <sys/stat.h>
#include <sys/sx.h>
+#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
+#include <sys/sysproto.h>
+#include <sys/taskqueue.h>
#include <sys/uio.h>
+#include <sys/vnode.h>
#include <sys/jail.h>
#include <net/vnet.h>
@@ -3329,6 +3334,345 @@ soisdisconnected(struct socket *so)
wakeup(&so->so_timeo);
}
+struct socketref {
+ struct proc *sr_proc;
+ struct ucred *sr_ucred;
+ struct file *sr_sock_fp;
+ struct file *sr_fp;
+ struct socket *sr_so;
+ struct sendfile_args sr_uap;
+ struct uio sr_hdr_uio;
+ struct uio sr_trl_uio;
+ short sr_compat;
+ int sr_magic;
+ off_t sr_vnp_size;
+ struct task sr_task;
+ TAILQ_ENTRY(socketref) entry;
+
+};
+TAILQ_HEAD(srq, socketref);
+
+struct srq *sendfile_bg_queue;
+struct mtx sendfile_bg_lock;
+struct callout *sendfile_callout;
+struct taskqueue *sendfile_tq;
+extern int getsock(struct filedesc *fdp, int fd,
+ struct file **fpp, u_int *fflagp);
+static void sendfile_task_func(void *context, int pending __unused);
+static int srsendingwakeup(struct socketref *sr);
+
+MALLOC_DEFINE(M_SOCKREF, "sockref", "socket reference memory");
+
+#define SOCKBUF_LOCK_COND(sb, lockflag) do { \
+ if ((lockflag)) \
+ SOCKBUF_LOCK((sb)); \
+} while (0)
+
+#define SOCKBUF_UNLOCK_COND(sb, lockflag) do { \
+ if ((lockflag)) \
+ SOCKBUF_UNLOCK((sb)); \
+} while (0)
+
+
+static void
+socketref_free(struct socketref *sr)
+{
+ struct file *fp = sr->sr_fp;
+ struct file *sock_fp = sr->sr_sock_fp;
+ struct proc *p = sr->sr_proc;
+ struct ucred *cred = sr->sr_ucred;
+
+ if (cred != NULL)
+ crfree(cred);
+ vrele(fp->f_vnode);
+ fdrop(fp, NULL);
+ fdrop(sock_fp, NULL);
+ PRELE(p);
+#ifdef INVARIANTS
+ bzero(sr, sizeof(*sr));
+#endif
+ free(sr, M_SOCKREF);
+}
+
+void
+soissending(struct socket *so, struct thread *td,
+ struct sendfile_args *uap, struct uio *hdr_uio,
+ struct uio *trl_uio, int compat, off_t sbytes,
+ off_t vnp_size)
+{
+ struct socketref *ref;
+ int error;
+ struct socket *refso;
+ struct vnode *vp;
+
+ SOCKBUF_LOCK_ASSERT(&so->so_snd);
+ ref = malloc(sizeof(struct socketref),
+ M_SOCKREF, M_NOWAIT|M_ZERO);
+ if (ref == NULL)
+ return;
+ /*
+ * Obtain reference to socket :-/
+ * drop when done sending
+ */
+ so->so_snd.sb_flags |= SB_SENDING;
+ PROC_LOCK(td->td_proc);
+ td->td_proc->p_lock++;
+ PROC_UNLOCK(td->td_proc);
+
+ ref->sr_proc = td->td_proc;
+
+ if ((error = getsock(td->td_proc->p_fd, uap->s, &ref->sr_sock_fp,
+ NULL)) != 0) {
+ goto error;
+ }
+ if (ref->sr_sock_fp->f_type != DTYPE_SOCKET) {
+ printf("socket descriptor s=%d is not socket", uap->s);
+ goto error;
+ }
+
+ refso = ref->sr_sock_fp->f_data;
+ if (refso != so) {
+ printf("socket mismatch between refso: %p so: %p\n",
+ refso, so);
+ goto error_sock_fp;
+ }
+ ref->sr_so = refso;
+
+ if ((error = fget(td, uap->fd, &ref->sr_fp)) != 0) {
+ goto error_sock_fp;
+ } else if (ref->sr_fp->f_vnode != NULL) {
+ vp = ref->sr_fp->f_vnode;
+ vref(vp);
+ } else {
+ goto error_fp;
+ }
+
+ bcopy(uap, &ref->sr_uap, sizeof(*uap));
+ ref->sr_uap.sbytes = NULL;
+ ref->sr_sock_fp->f_sfbytes = 0;
+ CTR4(KTR_SPARE1, "sock %p off %ld sbytes %ld total_sbytes %ld",
+ so, ref->sr_uap.offset, sbytes, ref->sr_fp->f_sfbytes);
+ ref->sr_uap.offset += sbytes;
+ if (uap->nbytes)
+ ref->sr_uap.nbytes -= sbytes;
+ /*
+ * XXX
+ * We have to malloc memory for the uio data
+ */
+ if (hdr_uio != NULL)
+ bcopy(hdr_uio, &ref->sr_hdr_uio,
+ sizeof(*hdr_uio));
+ if (trl_uio != NULL)
+ bcopy(trl_uio, &ref->sr_trl_uio,
+ sizeof(*trl_uio));
+ ref->sr_compat = compat;
+ ref->sr_magic = 0xCAFEBABE;
+ ref->sr_vnp_size = vnp_size;
+ TASK_INIT(&ref->sr_task, 0, sendfile_task_func, ref);
+
+ CTR3(KTR_SPARE2, "enqueueing socket %p sock_fp %p s %d", so, ref->sr_sock_fp, uap->s);
+ mtx_lock(&sendfile_bg_lock);
+ TAILQ_INSERT_TAIL(sendfile_bg_queue, ref, entry);
+ mtx_unlock(&sendfile_bg_lock);
+ return;
+error_fp:
+ fdrop(ref->sr_fp, td);
+error_sock_fp:
+ fdrop(ref->sr_sock_fp, td);
+error:
+ free(ref, M_DEVBUF);
+}
+
+static void
+sendfile_task_func(void *context, int pending __unused)
+{
+ struct socketref *sr;
+ struct socket *so;
+ struct sockbuf *sb;
+ struct file *sock_fp, *fp;
+ int error = EAGAIN;
+ struct uio *hdr_uio = NULL, *trl_uio = NULL;
+ off_t sbytes = 0;
+
+ sr = context;
+ CTR0(KTR_SPARE2, "task_func running");
+ if (sr->sr_magic != 0xCAFEBABE) {
+ printf("bad magic! 0x%x\n", sr->sr_magic);
+ /* XXX memory leak */
+ return;
+ }
+
+ sock_fp = sr->sr_sock_fp;
+ fp = sr->sr_fp;
+ CTR2(KTR_SPARE2, "processing sr %p sock_fp %p", sr, sock_fp);
+ if (sock_fp->f_type != DTYPE_SOCKET)
+ goto done;
+
+ so = sock_fp->f_data;
+ CTR1(KTR_SPARE2, "task processing socket %p", so);
+
+ if ((so->so_state & SS_ISCONNECTED) == 0)
+ goto done;
+
+ if (sr->sr_ucred == NULL &&
+ (sr->sr_ucred = crdup(sr->sr_proc->p_ucred)) == NULL)
+ goto done;
+
+ sb = &so->so_snd;
+ SOCKBUF_UNLOCK_ASSERT(sb);
+ SOCKBUF_LOCK(sb);
+ sb->sb_flags &= ~SB_SENDING;
+ if (sb->sb_state & SBS_CANTSENDMORE) {
+ CTR1(KTR_SPARE2, "SBS_CANTSENDMORE - socket %p", so);
+ sowwakeup_locked(so);
+ goto done;
+ } else if (sowriteable(so)) {
+ sb->sb_flags |= SB_SENDING;
+ SOCKBUF_UNLOCK(sb);
+ if (sr->sr_hdr_uio.uio_td != NULL)
+ hdr_uio = &sr->sr_hdr_uio;
+ if (sr->sr_trl_uio.uio_td != NULL)
+ trl_uio = &sr->sr_trl_uio;
+
+ sr->sr_uap.sbytes = &sbytes;
+ sr->sr_uap.flags |= SF_TASKQ;
+ CTR1(KTR_SPARE2, "task sending on socket %p", so);
+
+ error = kern_sendfile(curthread, &sr->sr_uap,
+ hdr_uio, trl_uio,
+ sr->sr_compat, fp, so, sr->sr_ucred);
+ CTR4(KTR_SPARE1, "sock %p off %ld sbytes %ld total_sbytes %ld",
+ so, sr->sr_uap.offset, sbytes, fp->f_sfbytes);
+ atomic_add_long(&fp->f_sfbytes, sbytes);
+ sr->sr_uap.offset += sbytes;
+ if (sr->sr_uap.nbytes)
+ sr->sr_uap.nbytes -= sbytes;
+ if (error == EAGAIN &&
+ (sr->sr_uap.offset + sbytes == sr->sr_vnp_size)) {
+ CTR0(KTR_SPARE1, "EAGAIN on full send");
+ error = 0;
+ }
+ SOCKBUF_LOCK(sb);
+ }
+#ifdef KTR
+ else
+ CTR2(KTR_SPARE1, "sock %p off %ld - not writeable in task_func",
+ so, sr->sr_uap.offset);
+#endif
+ if (error == EAGAIN && srsendingwakeup(sr) != ENOTCONN) {
+ SOCKBUF_UNLOCK(sb);
+ return;
+ }
+#ifdef KTR
+ if (error && error != EAGAIN && error != EPIPE)
+ CTR1(KTR_SPARE1, "error %d", error);
+#endif
+
+ sb->sb_flags &= ~SB_SENDING;
+ sowwakeup_locked(so);
+done:
+ SOCKBUF_UNLOCK_ASSERT(sb);
+ socketref_free(sr);
+}
+
+static int
+srsendingwakeup(struct socketref *sr)
+{
+ struct socket *so;
+ struct file *fp;
+ struct sockbuf *sb;
+
+ if (sr->sr_magic != 0xCAFEBABE) {
+ printf("bad magic! sr: %p magic : 0x%x in %s\n",
+ sr, sr->sr_magic, __FUNCTION__);
+ /*
+ * XXX leak - should be assert perhaps
+ *
+ */
+ return (0);
+ }
+
+ fp = sr->sr_sock_fp;
+ CTR2(KTR_SPARE2, "processing s %d sock_fp %p", sr->sr_uap.s, fp);
+ if (fp->f_type != DTYPE_SOCKET) {
+ CTR1(KTR_SPARE1, "not socket - type %d", fp->f_type);
+ goto error;
+ }
+ so = fp->f_data;
+ if ((so->so_state & SS_ISCONNECTED) == 0) {
+ CTR1(KTR_SPARE1, "not connected %p", so);
+ goto error;
+ }
+
+ CTR1(KTR_SPARE2, "processing socket %p", so);
+ sb = &so->so_snd;
+ SOCKBUF_LOCK_ASSERT(sb);
+ sb->sb_flags &= ~SB_SENDING;
+ if (sb->sb_state & SBS_CANTSENDMORE) {
+ CTR1(KTR_SPARE1, "SBS_CANTSENDMORE %p", so);
+ } else if (sowriteable(so)) {
+ CTR2(KTR_SPARE2, "enqueue socket to task %p sr %p", so, sr);
+ sb->sb_flags |= SB_SENDING;
+ taskqueue_enqueue(sendfile_tq, &sr->sr_task);
+ } else {
+ CTR2(KTR_SPARE1, "sock %p off %ld - not writeable in srsendingwakeup",
+ so, sr->sr_uap.offset);
+ sb->sb_flags |= SB_SENDING;
+ mtx_lock(&sendfile_bg_lock);
+ TAILQ_INSERT_TAIL(sendfile_bg_queue, sr, entry);
+ mtx_unlock(&sendfile_bg_lock);
+ }
+ return (0);
+error:
+ return (ENOTCONN);
+}
+
+void
+sosendingwakeup(struct sockbuf *sb)
+{
+ struct socketref *sr = NULL;
+
+ SOCKBUF_LOCK_ASSERT(sb);
+ mtx_lock(&sendfile_bg_lock);
+ if (!TAILQ_EMPTY(sendfile_bg_queue)) {
+ TAILQ_FOREACH(sr, sendfile_bg_queue, entry) {
+ if (sb == &sr->sr_so->so_snd) {
+ sb->sb_flags &= ~SB_SENDING;
+ TAILQ_REMOVE(sendfile_bg_queue, sr, entry);
+ break;
+ }
+ }
+
+ }
+ mtx_unlock(&sendfile_bg_lock);
+
+ /*
+ * Buffer in flight
+ */
+ if (sr != NULL && srsendingwakeup(sr) == ENOTCONN) {
+ CTR2(KTR_SPARE2, "freeing expired socket %p ref %p",
+ sr->sr_so, sr);
+ socketref_free(sr);
+ }
+}
+
+static void
+init_bgsend(void *unused __unused)
+{
+
+ sendfile_tq = taskqueue_create("sendfile background taskq", M_NOWAIT,
+ taskqueue_thread_enqueue, &sendfile_tq);
+ taskqueue_start_threads(&sendfile_tq, mp_ncpus, PI_SOFT,
+ "sendfile background taskq");
+
+ mtx_init(&sendfile_bg_lock, "sendfile bg", NULL, MTX_DEF);
+ sendfile_bg_queue = malloc(sizeof(struct srq),
+ M_DEVBUF, M_NOWAIT);
+ TAILQ_INIT(sendfile_bg_queue);
+}
+
+SYSINIT(init_bgsend, SI_SUB_SMP, SI_ORDER_ANY, init_bgsend, NULL);
+
/*
* Make a copy of a sockaddr in a malloced buffer of type M_SONAME.
*/
Modified: user/kmacy/releng_8_fcs/sys/kern/uipc_syscalls.c
==============================================================================
--- user/kmacy/releng_8_fcs/sys/kern/uipc_syscalls.c Fri Oct 2 19:51:03 2009 (r197717)
+++ user/kmacy/releng_8_fcs/sys/kern/uipc_syscalls.c Fri Oct 2 20:15:47 2009 (r197718)
@@ -112,6 +112,14 @@ SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufsp
SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufsused, CTLFLAG_RD, &nsfbufsused, 0,
"Number of sendfile(2) sf_bufs in use");
+
+/* XXX move to header */
+int getsock(struct filedesc *fdp, int fd, struct file **fpp, u_int *fflagp);
+
+static int bg_sendfile_enable = 0;
+SYSCTL_INT(_kern_ipc, OID_AUTO, bg_sendfile_enable, CTLFLAG_RW,
+ &bg_sendfile_enable, 0, "Enable background sendfile");
+
/*
* Convert a user file descriptor to a kernel file entry. A reference on the
* file entry is held upon returning. This is lighter weight than
@@ -120,7 +128,7 @@ SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufsu
* associated with the additional reference count. If requested, return the
* open file flags.
*/
-static int
+int
getsock(struct filedesc *fdp, int fd, struct file **fpp, u_int *fflagp)
{
struct file *fp;
@@ -1774,7 +1782,8 @@ do_sendfile(struct thread *td, struct se
}
}
- error = kern_sendfile(td, uap, hdr_uio, trl_uio, compat);
+ error = kern_sendfile(td, uap, hdr_uio, trl_uio, compat,
+ NULL, NULL, NULL);
out:
if (hdr_uio)
free(hdr_uio, M_IOV);
@@ -1803,20 +1812,27 @@ freebsd4_sendfile(struct thread *td, str
int
kern_sendfile(struct thread *td, struct sendfile_args *uap,
- struct uio *hdr_uio, struct uio *trl_uio, int compat)
+ struct uio *hdr_uio, struct uio *trl_uio, int compat,
+ struct file *bgfp, struct socket *bgso, struct ucred *bgcred)
{
- struct file *sock_fp;
- struct vnode *vp;
+ struct file *sock_fp, *fp = NULL;
+ struct vnode *vp = NULL;
struct vm_object *obj = NULL;
struct socket *so = NULL;
struct mbuf *m = NULL;
struct sf_buf *sf;
struct vm_page *pg;
- off_t off, xfsize, fsbytes = 0, sbytes = 0, rem = 0;
+ struct ucred *cred;
+ off_t off, xfsize, fsbytes = 0, sbytes = 0, rem = 0, vnp_size = 0;
int error, hdrlen = 0, mnw = 0;
int vfslocked;
struct sendfile_sync *sfs = NULL;
+ if (bgcred != NULL)
+ cred = bgcred;
+ else
+ cred = td->td_ucred;
+
/*
* The file descriptor must be a regular file and have a
* backing VM object.
@@ -1824,8 +1840,23 @@ kern_sendfile(struct thread *td, struct
* we send only the header/trailer and no payload data.
*/
AUDIT_ARG_FD(uap->fd);
- if ((error = fgetvp_read(td, uap->fd, &vp)) != 0)
- goto out;
+ if ((uap->flags & SF_TASKQ) == 0) {
+ if ((error = fget_read(td, uap->fd, &fp)) != 0)
+ goto out;
+ else {
+ if (fp->f_vnode == NULL) {
+ fdrop(fp, td);
+ error = EINVAL;
+ goto out;
+ } else {
+ vp = fp->f_vnode;
+ vref(vp);
+ }
+ }
+ } else {
+ vp = bgfp->f_vnode;
+ }
+
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
vn_lock(vp, LK_SHARED | LK_RETRY);
if (vp->v_type == VREG) {
@@ -1858,22 +1889,39 @@ kern_sendfile(struct thread *td, struct
goto out;
}
- /*
- * The socket must be a stream socket and connected.
- * Remember if it a blocking or non-blocking socket.
- */
- if ((error = getsock(td->td_proc->p_fd, uap->s, &sock_fp,
- NULL)) != 0)
- goto out;
- so = sock_fp->f_data;
- if (so->so_type != SOCK_STREAM) {
- error = EINVAL;
- goto out;
+ if ((uap->flags & SF_TASKQ) == 0) {
+ /*
+ * The socket must be a stream socket and connected.
+ * Remember if it a blocking or non-blocking socket.
+ */
+ if ((error = getsock(td->td_proc->p_fd, uap->s, &sock_fp,
+ NULL)) != 0)
+ goto out;
+ so = sock_fp->f_data;
+ if (so->so_type != SOCK_STREAM) {
+ error = EINVAL;
+ goto out;
+ }
+ if ((so->so_state & SS_ISCONNECTED) == 0) {
+ error = ENOTCONN;
+ goto out;
+ }
+ } else {
+ so = bgso;
}
- if ((so->so_state & SS_ISCONNECTED) == 0) {
- error = ENOTCONN;
+
+ if ((uap->flags & SF_TASKQ) == 0 &&
+ sock_fp->f_sfbytes != 0) {
+ SOCKBUF_UNLOCK(&so->so_snd);
+ if (uap->sbytes != NULL) {
+ copyout(&sbytes, uap->sbytes, sizeof(off_t));
+ sock_fp->f_sfbytes = 0;
+ }
+ error = 0;
goto out;
}
+
+
/*
* Do not wait on memory allocations but return ENOMEM for
* caller to retry later.
@@ -1890,7 +1938,7 @@ kern_sendfile(struct thread *td, struct
}
#ifdef MAC
- error = mac_socket_check_send(td->td_ucred, so);
+ error = mac_socket_check_send(cred, so);
if (error)
goto out;
#endif
@@ -1980,6 +2028,9 @@ retry_space:
(space <= 0 ||
space < so->so_snd.sb_lowat)) {
if (so->so_state & SS_NBIO) {
+ if (bg_sendfile_enable &&
+ (so->so_snd.sb_flags & SB_SENDING) == 0)
+ soissending(so, td, uap, hdr_uio, trl_uio, compat, sbytes, vnp_size);
SOCKBUF_UNLOCK(&so->so_snd);
error = EAGAIN;
goto done;
@@ -2041,6 +2092,7 @@ retry_space:
done = 1; /* all data sent */
break;
}
+ vnp_size = obj->un_pager.vnp.vnp_size;
/*
* Don't overflow the send buffer.
* Stop here and send out what we've
@@ -2098,7 +2150,7 @@ retry_space:
error = vn_rdwr(UIO_READ, vp, NULL, MAXBSIZE,
trunc_page(off), UIO_NOCOPY, IO_NODELOCKED |
IO_VMIO | ((MAXBSIZE / bsize) << IO_SEQSHIFT),
- td->td_ucred, NOCRED, &resid, td);
+ cred, NOCRED, &resid, td);
VOP_UNLOCK(vp, 0);
VFS_UNLOCK_GIANT(vfslocked);
VM_OBJECT_LOCK(obj);
@@ -2245,17 +2297,24 @@ out:
td->td_retval[0] = 0;
}
if (uap->sbytes != NULL) {
- copyout(&sbytes, uap->sbytes, sizeof(off_t));
+ if ((uap->flags & SF_TASKQ) == 0)
+ copyout(&sbytes, uap->sbytes, sizeof(off_t));
+ else
+ *(uap->sbytes) = sbytes;
}
if (obj != NULL)
vm_object_deallocate(obj);
- if (vp != NULL) {
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
- vrele(vp);
- VFS_UNLOCK_GIANT(vfslocked);
+ if ((uap->flags & SF_TASKQ) == 0) {
+ if (vp != NULL) {
+ vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+ vrele(vp);
+ VFS_UNLOCK_GIANT(vfslocked);
+ }
+ if (so)
+ fdrop(sock_fp, td);
+ if (fp)
+ fdrop(fp, td);
}
- if (so)
- fdrop(sock_fp, td);
if (m)
m_freem(m);
Modified: user/kmacy/releng_8_fcs/sys/sys/file.h
==============================================================================
--- user/kmacy/releng_8_fcs/sys/sys/file.h Fri Oct 2 19:51:03 2009 (r197717)
+++ user/kmacy/releng_8_fcs/sys/sys/file.h Fri Oct 2 20:15:47 2009 (r197718)
@@ -132,6 +132,7 @@ struct file {
* DFLAG_SEEKABLE specific fields
*/
off_t f_offset;
+ off_t f_sfbytes;
/*
* Mandatory Access control information.
*/
Modified: user/kmacy/releng_8_fcs/sys/sys/sockbuf.h
==============================================================================
--- user/kmacy/releng_8_fcs/sys/sys/sockbuf.h Fri Oct 2 19:51:03 2009 (r197717)
+++ user/kmacy/releng_8_fcs/sys/sys/sockbuf.h Fri Oct 2 20:15:47 2009 (r197718)
@@ -52,6 +52,7 @@
#define SB_NOCOALESCE 0x200 /* don't coalesce new data into existing mbufs */
#define SB_IN_TOE 0x400 /* socket buffer is in the middle of an operation */
#define SB_AUTOSIZE 0x800 /* automatically size socket buffer */
+#define SB_SENDING 0x1000 /* socket is owned by sendfile thread */
#define SBS_CANTSENDMORE 0x0010 /* can't send more data to peer */
#define SBS_CANTRCVMORE 0x0020 /* can't receive more data from peer */
@@ -155,9 +156,12 @@ struct mbuf *
sbsndptr(struct sockbuf *sb, u_int off, u_int len, u_int *moff);
void sbtoxsockbuf(struct sockbuf *sb, struct xsockbuf *xsb);
int sbwait(struct sockbuf *sb);
-int sblock(struct sockbuf *sb, int flags);
+int _sblock(struct sockbuf *sb, int flags, const char *file, int line);
void sbunlock(struct sockbuf *sb);
+#define sblock(sb, flags) \
+ _sblock((sb), (flags), __FILE__, __LINE__)
+
/*
* How much space is there in a socket buffer (so->so_snd or so->so_rcv)?
* This is problematical if the fields are unsigned, as the space might
Modified: user/kmacy/releng_8_fcs/sys/sys/socket.h
==============================================================================
--- user/kmacy/releng_8_fcs/sys/sys/socket.h Fri Oct 2 19:51:03 2009 (r197717)
+++ user/kmacy/releng_8_fcs/sys/sys/socket.h Fri Oct 2 20:15:47 2009 (r197718)
@@ -617,6 +617,7 @@ struct sf_hdtr {
#define SF_NODISKIO 0x00000001
#define SF_MNOWAIT 0x00000002
#define SF_SYNC 0x00000004
+#define SF_TASKQ 0x00000008
#endif
#ifndef _KERNEL
Modified: user/kmacy/releng_8_fcs/sys/sys/socketvar.h
==============================================================================
--- user/kmacy/releng_8_fcs/sys/sys/socketvar.h Fri Oct 2 19:51:03 2009 (r197717)
+++ user/kmacy/releng_8_fcs/sys/sys/socketvar.h Fri Oct 2 20:15:47 2009 (r197718)
@@ -206,7 +206,8 @@ struct xsocket {
/* can we write something to so? */
#define sowriteable(so) \
((sbspace(&(so)->so_snd) >= (so)->so_snd.sb_lowat && \
- (((so)->so_state&SS_ISCONNECTED) || \
+ !((so)->so_snd.sb_flags & SB_SENDING) && \
+ (((so)->so_state&SS_ISCONNECTED) || \
((so)->so_proto->pr_flags&PR_CONNREQUIRED)==0)) || \
((so)->so_snd.sb_state & SBS_CANTSENDMORE) || \
(so)->so_error)
Modified: user/kmacy/releng_8_fcs/sys/sys/sockstate.h
==============================================================================
--- user/kmacy/releng_8_fcs/sys/sys/sockstate.h Fri Oct 2 19:51:03 2009 (r197717)
+++ user/kmacy/releng_8_fcs/sys/sys/sockstate.h Fri Oct 2 20:15:47 2009 (r197718)
@@ -71,11 +71,18 @@
#define SBS_RCVATMARK 0x0040 /* at mark on input */
struct socket;
+struct sendfile_args;
+struct uio;
void soisconnected(struct socket *so);
void soisconnecting(struct socket *so);
void soisdisconnected(struct socket *so);
void soisdisconnecting(struct socket *so);
+void soissending(struct socket *so,
+ struct thread *td, struct sendfile_args *uap,
+ struct uio *hdr_uio, struct uio *trl_uio,
+ int compat, off_t sbytes, off_t vnp_size);
+void sosendingwakeup(struct sockbuf *sb);
void socantrcvmore(struct socket *so);
void socantrcvmore_locked(struct socket *so);
void socantsendmore(struct socket *so);
Modified: user/kmacy/releng_8_fcs/sys/sys/syscallsubr.h
==============================================================================
--- user/kmacy/releng_8_fcs/sys/sys/syscallsubr.h Fri Oct 2 19:51:03 2009 (r197717)
+++ user/kmacy/releng_8_fcs/sys/sys/syscallsubr.h Fri Oct 2 20:15:47 2009 (r197718)
@@ -172,7 +172,8 @@ int kern_semctl(struct thread *td, int s
int kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou,
fd_set *fd_ex, struct timeval *tvp, int abi_nfdbits);
int kern_sendfile(struct thread *td, struct sendfile_args *uap,
- struct uio *hdr_uio, struct uio *trl_uio, int compat);
+ struct uio *hdr_uio, struct uio *trl_uio, int compat,
+ struct file *bgfp, struct socket *bgso, struct ucred *bgcred);
int kern_sendit(struct thread *td, int s, struct msghdr *mp, int flags,
struct mbuf *control, enum uio_seg segflg);
int kern_setgroups(struct thread *td, u_int ngrp, gid_t *groups);
More information about the svn-src-user
mailing list