From 7d03ff1fe9cbc4b5a3fcc5423bfa4cc11389b78b Mon Sep 17 00:00:00 2001 From: Hiren Panchasara Date: Mon, 16 Jan 2017 08:25:33 +0000 Subject: [PATCH] Add kevent EVFILT_EMPTY for notification when a client has received all data i.e. everything outstanding has been acked. Reviewed by: bz, gnn (previous version) MFC after: 3 days Sponsored by: Limelight Networks Differential Revision: https://reviews.freebsd.org/D9150 --- sys/kern/kern_event.c | 1 + sys/kern/uipc_socket.c | 25 +++++++++++++++++++++++++ sys/sys/event.h | 3 ++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index f9ee7b1103d..4473d16230b 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -344,6 +344,7 @@ static struct { { &null_filtops }, /* EVFILT_LIO */ { &user_filtops, 1 }, /* EVFILT_USER */ { &null_filtops }, /* EVFILT_SENDFILE */ + { &file_filtops, 1 }, /* EVFILT_EMPTY */ }; /* diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 23910c5bc1d..f08fc9f1a7d 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -161,6 +161,7 @@ static void filt_sowdetach(struct knote *kn); static int filt_sowrite(struct knote *kn, long hint); static int filt_solisten(struct knote *kn, long hint); static int inline hhook_run_socket(struct socket *so, void *hctx, int32_t h_id); +static int filt_soempty(struct knote *kn, long hint); fo_kqfilter_t soo_kqfilter; static struct filterops solisten_filtops = { @@ -178,6 +179,11 @@ static struct filterops sowrite_filtops = { .f_detach = filt_sowdetach, .f_event = filt_sowrite, }; +static struct filterops soempty_filtops = { + .f_isfd = 1, + .f_detach = filt_sowdetach, + .f_event = filt_soempty, +}; so_gen_t so_gencnt; /* generation count for sockets */ @@ -3083,6 +3089,10 @@ soo_kqfilter(struct file *fp, struct knote *kn) kn->kn_fop = &sowrite_filtops; sb = &so->so_snd; break; + case EVFILT_EMPTY: + kn->kn_fop = &soempty_filtops; + sb = &so->so_snd; + break; default: return (EINVAL); } @@ -3344,6 +3354,21 @@ filt_sowrite(struct knote *kn, long hint) return (kn->kn_data >= so->so_snd.sb_lowat); } +static int +filt_soempty(struct knote *kn, long hint) +{ + struct socket *so; + + so = kn->kn_fp->f_data; + SOCKBUF_LOCK_ASSERT(&so->so_snd); + kn->kn_data = sbused(&so->so_snd); + + if (kn->kn_data == 0) + return (1); + else + return (0); +} + /*ARGSUSED*/ static int filt_solisten(struct knote *kn, long hint) diff --git a/sys/sys/event.h b/sys/sys/event.h index 9ccaabad9aa..fb5b11c3293 100644 --- a/sys/sys/event.h +++ b/sys/sys/event.h @@ -43,7 +43,8 @@ #define EVFILT_LIO (-10) /* attached to lio requests */ #define EVFILT_USER (-11) /* User events */ #define EVFILT_SENDFILE (-12) /* attached to sendfile requests */ -#define EVFILT_SYSCOUNT 12 +#define EVFILT_EMPTY (-13) /* empty send socket buf */ +#define EVFILT_SYSCOUNT 13 #define EV_SET(kevp_, a, b, c, d, e, f) do { \ struct kevent *kevp = (kevp_); \