From owner-svn-src-head@FreeBSD.ORG Sat Nov 1 21:16:09 2008 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9CC531065672; Sat, 1 Nov 2008 21:16:09 +0000 (UTC) (envelope-from rwatson@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 8A7A58FC0C; Sat, 1 Nov 2008 21:16:09 +0000 (UTC) (envelope-from rwatson@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id mA1LG95X019045; Sat, 1 Nov 2008 21:16:09 GMT (envelope-from rwatson@svn.freebsd.org) Received: (from rwatson@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id mA1LG91K019044; Sat, 1 Nov 2008 21:16:09 GMT (envelope-from rwatson@svn.freebsd.org) Message-Id: <200811012116.mA1LG91K019044@svn.freebsd.org> From: Robert Watson Date: Sat, 1 Nov 2008 21:16:09 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184534 - head/sys/security/audit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 01 Nov 2008 21:16:09 -0000 Author: rwatson Date: Sat Nov 1 21:16:09 2008 New Revision: 184534 URL: http://svn.freebsd.org/changeset/base/184534 Log: 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. MFC after: 2 months Sponsored by: Apple, Inc. Modified: head/sys/security/audit/audit_pipe.c Modified: head/sys/security/audit/audit_pipe.c ============================================================================== --- head/sys/security/audit/audit_pipe.c Sat Nov 1 20:54:52 2008 (r184533) +++ head/sys/security/audit/audit_pipe.c Sat Nov 1 21:16:09 2008 (r184534) @@ -930,19 +930,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) @@ -978,40 +967,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); } /*