Date: Fri, 2 Oct 2009 20:15:48 +0000 (UTC) From: Kip Macy <kmacy@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r197718 - in user/kmacy/releng_8_fcs/sys: kern sys Message-ID: <200910022015.n92KFm0m012048@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200910022015.n92KFm0m012048>