Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 25 Feb 2009 13:17:46 +0000 (UTC)
From:      Robert Watson <rwatson@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org
Subject:   svn commit: r189034 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb security/audit
Message-ID:  <200902251317.n1PDHkA3097581@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rwatson
Date: Wed Feb 25 13:17:46 2009
New Revision: 189034
URL: http://svn.freebsd.org/changeset/base/189034

Log:
  Merge r184534 from head to stable/7:
  
    Allow a single read(2) system call on an audit pipe to retrieve data from
    more than one audit record at a time in order to improve efficiency.
  
    Sponsored by: Apple, Inc.

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/dev/ath/ath_hal/   (props changed)
  stable/7/sys/dev/cxgb/   (props changed)
  stable/7/sys/security/audit/audit_pipe.c

Modified: stable/7/sys/security/audit/audit_pipe.c
==============================================================================
--- stable/7/sys/security/audit/audit_pipe.c	Wed Feb 25 12:32:15 2009	(r189033)
+++ stable/7/sys/security/audit/audit_pipe.c	Wed Feb 25 13:17:46 2009	(r189034)
@@ -934,19 +934,8 @@ audit_pipe_ioctl(struct cdev *dev, u_lon
 }
 
 /*
- * Audit pipe read.  Pull one record off the queue and copy to user space.
- * On error, the record is dropped.
- *
- * Providing more sophisticated behavior, such as partial reads, is tricky
- * due to the potential for parallel I/O.  If partial read support is
- * required, it will require a per-pipe "current record being read" along
- * with an offset into that trecord which has already been read.  Threads
- * performing partial reads will need to allocate per-thread copies of the
- * data so that if another thread completes the read of the record, it can be
- * freed without adding reference count logic.  If this is added, a flag to
- * indicate that only atomic record reads are desired would be useful, as if
- * different threads are all waiting for records on the pipe, they will want
- * independent record reads, which is currently the behavior.
+ * Audit pipe read.  Read one or more partial or complete records to user
+ * memory.
  */
 static int
 audit_pipe_read(struct cdev *dev, struct uio *uio, int flag)
@@ -982,40 +971,43 @@ audit_pipe_read(struct cdev *dev, struct
 
 	/*
 	 * Copy as many remaining bytes from the current record to userspace
-	 * as we can.
+	 * as we can.  Keep processing records until we run out of records in
+	 * the queue, or until the user buffer runs out of space.
 	 *
 	 * Note: we rely on the SX lock to maintain ape's stability here.
 	 */
 	ap->ap_reads++;
-	ape = TAILQ_FIRST(&ap->ap_queue);
-	toread = MIN(ape->ape_record_len - ape->ape_record_offset,
-	    uio->uio_resid);
-	AUDIT_PIPE_UNLOCK(ap);
-	error = uiomove((char *)ape->ape_record + ape->ape_record_offset,
-	    toread, uio);
-	if (error) {
-		AUDIT_PIPE_SX_XUNLOCK(ap);
-		return (error);
-	}
+	while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL &&
+	    uio->uio_resid > 0) {
+		AUDIT_PIPE_LOCK_ASSERT(ap);
 
-	/*
-	 * If the copy succeeded, update book-keeping, and if no bytes remain
-	 * in the current record, free it.
-	 */
-	AUDIT_PIPE_LOCK(ap);
-	KASSERT(TAILQ_FIRST(&ap->ap_queue) == ape,
-	    ("audit_pipe_read: queue out of sync after uiomove"));
-	ape->ape_record_offset += toread;
-	if (ape->ape_record_offset == ape->ape_record_len) {
-		TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue);
-		ap->ap_qlen--;
-	} else
-		ape = NULL;
+		toread = MIN(ape->ape_record_len - ape->ape_record_offset,
+		    uio->uio_resid);
+		AUDIT_PIPE_UNLOCK(ap);
+		error = uiomove((char *)ape->ape_record +
+		    ape->ape_record_offset, toread, uio);
+		if (error) {
+			AUDIT_PIPE_SX_XUNLOCK(ap);
+			return (error);
+		}
+
+		/*
+		 * If the copy succeeded, update book-keeping, and if no
+		 * bytes remain in the current record, free it.
+		 */
+		AUDIT_PIPE_LOCK(ap);
+		KASSERT(TAILQ_FIRST(&ap->ap_queue) == ape,
+		    ("audit_pipe_read: queue out of sync after uiomove"));
+		ape->ape_record_offset += toread;
+		if (ape->ape_record_offset == ape->ape_record_len) {
+			TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue);
+			audit_pipe_entry_free(ape);
+			ap->ap_qlen--;
+		}
+	}
 	AUDIT_PIPE_UNLOCK(ap);
 	AUDIT_PIPE_SX_XUNLOCK(ap);
-	if (ape != NULL)
-		audit_pipe_entry_free(ape);
-	return (error);
+	return (0);
 }
 
 /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200902251317.n1PDHkA3097581>