diff options
author | adrian <adrian@FreeBSD.org> | 2014-01-17 05:26:55 +0000 |
---|---|---|
committer | adrian <adrian@FreeBSD.org> | 2014-01-17 05:26:55 +0000 |
commit | c46f73c7ae08f8eec4084f731b5c3c4c0fa42b19 (patch) | |
tree | 2ee74af347fde330acc3a30d52e45c03ba9e066e /sys/compat | |
parent | 9d7a5637e20993a9c0cc3fb858a18d0f8b49b310 (diff) | |
download | FreeBSD-src-c46f73c7ae08f8eec4084f731b5c3c4c0fa42b19.zip FreeBSD-src-c46f73c7ae08f8eec4084f731b5c3c4c0fa42b19.tar.gz |
Implement a kqueue notification path for sendfile.
This fires off a kqueue note (of type sendfile) to the configured kqfd
when the sendfile transaction has completed and the relevant memory
backing the transaction is no longer in use by this transaction.
This is analogous to SF_SYNC waiting for the mbufs to complete -
except now you don't have to wait.
Both SF_SYNC and SF_KQUEUE should work together, even if it
doesn't necessarily make any practical sense.
This is designed for use by applications which use backing cache/store
files (eg Varnish) or POSIX shared memory (not sure anything is using
it yet!) to know when a region of memory is free for re-use. Note
it doesn't mark the region as free overall - only free from this
transaction. The application developer still needs to track which
ranges are in the process of being recycled and wait until all
pending transactions are completed.
TODO:
* documentation, as always
Sponsored by: Netflix, Inc.
Diffstat (limited to 'sys/compat')
-rw-r--r-- | sys/compat/freebsd32/freebsd32_misc.c | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index c8681c6..719a057 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -1644,18 +1644,28 @@ struct sf_hdtr32 { int trl_cnt; }; +struct sf_hdtr_kq32 { + int kq_fd; + uint32_t kq_flags; + uint32_t kq_udata; /* 32-bit void ptr */ + uint32_t kq_ident; /* 32-bit uintptr_t */ +}; + static int freebsd32_do_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap, int compat) { struct sf_hdtr32 hdtr32; struct sf_hdtr hdtr; + struct sf_hdtr_kq32 hdtr_kq32; + struct sf_hdtr_kq hdtr_kq; struct uio *hdr_uio, *trl_uio; struct iovec32 *iov32; off_t offset; int error; off_t sbytes; struct sendfile_sync *sfs; + int do_kqueue = 0; offset = PAIR32TO64(off_t, uap->offset); if (offset < 0) @@ -1687,10 +1697,32 @@ freebsd32_do_sendfile(struct thread *td, if (error) goto out; } + + /* + * If SF_KQUEUE is set, then we need to also copy in + * the kqueue data after the normal hdtr set and set do_kqueue=1. + */ + if (uap->flags & SF_KQUEUE) { + error = copyin(((char *) uap->hdtr) + sizeof(hdtr32), + &hdtr_kq32, + sizeof(hdtr_kq32)); + if (error != 0) + goto out; + + /* 32->64 bit fields */ + CP(hdtr_kq32, hdtr_kq, kq_fd); + CP(hdtr_kq32, hdtr_kq, kq_flags); + PTRIN_CP(hdtr_kq32, hdtr_kq, kq_udata); + CP(hdtr_kq32, hdtr_kq, kq_ident); + do_kqueue = 1; + } } + + /* Call sendfile */ + /* XXX stack depth! */ error = _do_sendfile(td, uap->fd, uap->s, uap->flags, compat, - offset, uap->nbytes, &sbytes, hdr_uio, trl_uio); + offset, uap->nbytes, &sbytes, hdr_uio, trl_uio, &hdtr_kq); if (uap->sbytes != NULL) copyout(&sbytes, uap->sbytes, sizeof(off_t)); |