Date: Wed, 23 Mar 2016 16:59:25 -0700 From: Gleb Smirnoff <glebius@FreeBSD.org> To: Vitalij Satanivskij <satan@ukr.net> Cc: current@freebsd.org Subject: Re: CURRENT r296381 panic in vn_sendfile (/usr/src/sys/kern/kern_sendfile.c:833) Message-ID: <20160323235925.GT2616@FreeBSD.org> In-Reply-To: <20160323181131.GN2616@FreeBSD.org> References: <20160304124053.GA25071@hell.ukr.net> <20160323181131.GN2616@FreeBSD.org>
next in thread | previous in thread | raw e-mail | index | archive | help
--O5XBE6gyVG5Rl6Rj
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Vitalij,
although the first patch should fixup the panic, can you please
instead run this one. And if it is possible, can you please
monitor this sysctl:
sysctl kern.ipc.sf_long_headers
--
Totus tuus, Glebius.
--O5XBE6gyVG5Rl6Rj
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment; filename="sendfile.diff"
Index: sys/kern/kern_descrip.c
===================================================================
--- sys/kern/kern_descrip.c (revision 297217)
+++ sys/kern/kern_descrip.c (working copy)
@@ -3958,7 +3958,7 @@ badfo_chown(struct file *fp, uid_t uid, gid_t gid,
static int
badfo_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
struct uio *trl_uio, off_t offset, size_t nbytes, off_t *sent, int flags,
- int kflags, struct thread *td)
+ struct thread *td)
{
return (EBADF);
@@ -4044,7 +4044,7 @@ invfo_chown(struct file *fp, uid_t uid, gid_t gid,
int
invfo_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
struct uio *trl_uio, off_t offset, size_t nbytes, off_t *sent, int flags,
- int kflags, struct thread *td)
+ struct thread *td)
{
return (EINVAL);
Index: sys/kern/kern_sendfile.c
===================================================================
--- sys/kern/kern_sendfile.c (revision 297217)
+++ sys/kern/kern_sendfile.c (working copy)
@@ -95,6 +95,7 @@ struct sendfile_sync {
};
counter_u64_t sfstat[sizeof(struct sfstat) / sizeof(uint64_t)];
+static counter_u64_t sf_long_headers; /* QQQGL */
static void
sfstat_init(const void *unused)
@@ -102,6 +103,7 @@ sfstat_init(const void *unused)
COUNTER_ARRAY_ALLOC(sfstat, sizeof(struct sfstat) / sizeof(uint64_t),
M_WAITOK);
+ sf_long_headers = counter_u64_alloc(M_WAITOK); /* QQQGL */
}
SYSINIT(sfstat, SI_SUB_MBUF, SI_ORDER_FIRST, sfstat_init, NULL);
@@ -117,6 +119,8 @@ sfstat_sysctl(SYSCTL_HANDLER_ARGS)
}
SYSCTL_PROC(_kern_ipc, OID_AUTO, sfstat, CTLTYPE_OPAQUE | CTLFLAG_RW,
NULL, 0, sfstat_sysctl, "I", "sendfile statistics");
+SYSCTL_COUNTER_U64(_kern_ipc, OID_AUTO, sf_long_headers, CTLFLAG_RW,
+ &sf_long_headers, "times headers did not fit into socket buffer");
/*
* Detach mapped page and release resources back to the system. Called
@@ -516,7 +520,7 @@ sendfile_getsock(struct thread *td, int s, struct
int
vn_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
struct uio *trl_uio, off_t offset, size_t nbytes, off_t *sent, int flags,
- int kflags, struct thread *td)
+ struct thread *td)
{
struct file *sock_fp;
struct vnode *vp;
@@ -534,7 +538,7 @@ vn_sendfile(struct file *fp, int sockfd, struct ui
so = NULL;
m = mh = NULL;
sfs = NULL;
- sbytes = 0;
+ hdrlen = sbytes = 0;
softerr = 0;
error = sendfile_getobj(td, fp, &obj, &vp, &shmfd, &obj_size, &bsize);
@@ -560,26 +564,6 @@ vn_sendfile(struct file *fp, int sockfd, struct ui
cv_init(&sfs->cv, "sendfile");
}
- /* If headers are specified copy them into mbufs. */
- if (hdr_uio != NULL && hdr_uio->uio_resid > 0) {
- hdr_uio->uio_td = td;
- hdr_uio->uio_rw = UIO_WRITE;
- /*
- * In FBSD < 5.0 the nbytes to send also included
- * the header. If compat is specified subtract the
- * header size from nbytes.
- */
- if (kflags & SFK_COMPAT) {
- if (nbytes > hdr_uio->uio_resid)
- nbytes -= hdr_uio->uio_resid;
- else
- nbytes = 0;
- }
- mh = m_uiotombuf(hdr_uio, M_WAITOK, 0, 0, 0);
- hdrlen = m_length(mh, &mhtail);
- } else
- hdrlen = 0;
-
rem = nbytes ? omin(nbytes, obj_size - offset) : obj_size - offset;
/*
@@ -668,11 +652,23 @@ retry_space:
SOCKBUF_UNLOCK(&so->so_snd);
/*
- * Reduce space in the socket buffer by the size of
- * the header mbuf chain.
- * hdrlen is set to 0 after the first loop.
+ * At the beginning of the first loop check if any headers
+ * are specified and copy them into mbufs. Reduce space in
+ * the socket buffer by the size of the header mbuf chain.
+ * Clear hdr_uio here and hdrlen at the end of the first loop.
*/
- space -= hdrlen;
+ if (hdr_uio != NULL) {
+ hdr_uio->uio_td = td;
+ hdr_uio->uio_rw = UIO_WRITE;
+ /* QQQGL remove counter */
+ if (space < hdr_uio->uio_resid)
+ counter_u64_add(sf_long_headers, 1);
+ hdr_uio->uio_resid = min(hdr_uio->uio_resid, space);
+ mh = m_uiotombuf(hdr_uio, M_WAITOK, 0, 0, 0);
+ hdrlen = m_length(mh, &mhtail);
+ space -= hdrlen;
+ hdr_uio = NULL;
+ }
if (vp != NULL) {
error = vn_lock(vp, LK_SHARED);
@@ -944,6 +940,17 @@ sendfile(struct thread *td, struct sendfile_args *
&hdr_uio);
if (error != 0)
goto out;
+ /*
+ * In FBSD < 5.0 the nbytes to send also included
+ * the header. If compat is specified subtract the
+ * header size from nbytes.
+ */
+ if (compat) {
+ if (uap->nbytes > hdr_uio->uio_resid)
+ uap->nbytes -= hdr_uio->uio_resid;
+ else
+ uap->nbytes = 0;
+ }
}
if (hdtr.trailers != NULL) {
error = copyinuio(hdtr.trailers, hdtr.trl_cnt,
@@ -965,7 +972,7 @@ sendfile(struct thread *td, struct sendfile_args *
}
error = fo_sendfile(fp, uap->s, hdr_uio, trl_uio, uap->offset,
- uap->nbytes, &sbytes, uap->flags, compat ? SFK_COMPAT : 0, td);
+ uap->nbytes, &sbytes, uap->flags, td);
fdrop(fp, td);
if (uap->sbytes != NULL)
Index: sys/sys/file.h
===================================================================
--- sys/sys/file.h (revision 297217)
+++ sys/sys/file.h (working copy)
@@ -112,7 +112,7 @@ typedef int fo_chown_t(struct file *fp, uid_t uid,
struct ucred *active_cred, struct thread *td);
typedef int fo_sendfile_t(struct file *fp, int sockfd, struct uio *hdr_uio,
struct uio *trl_uio, off_t offset, size_t nbytes,
- off_t *sent, int flags, int kflags, struct thread *td);
+ off_t *sent, int flags, struct thread *td);
typedef int fo_seek_t(struct file *fp, off_t offset, int whence,
struct thread *td);
typedef int fo_fill_kinfo_t(struct file *fp, struct kinfo_file *kif,
@@ -376,11 +376,11 @@ fo_chown(struct file *fp, uid_t uid, gid_t gid, st
static __inline int
fo_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
struct uio *trl_uio, off_t offset, size_t nbytes, off_t *sent, int flags,
- int kflags, struct thread *td)
+ struct thread *td)
{
return ((*fp->f_ops->fo_sendfile)(fp, sockfd, hdr_uio, trl_uio, offset,
- nbytes, sent, flags, kflags, td));
+ nbytes, sent, flags, td));
}
static __inline int
Index: sys/sys/socket.h
===================================================================
--- sys/sys/socket.h (revision 297217)
+++ sys/sys/socket.h (working copy)
@@ -594,7 +594,6 @@ struct sf_hdtr {
#define SF_FLAGS(rh, flags) (((rh) << 16) | (flags))
#ifdef _KERNEL
-#define SFK_COMPAT 0x00000001
#define SF_READAHEAD(flags) ((flags) >> 16)
#endif /* _KERNEL */
--O5XBE6gyVG5Rl6Rj--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20160323235925.GT2616>
