Skip site navigation (1)Skip section navigation (2)
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>