From owner-freebsd-bugs@FreeBSD.ORG Sat Nov 19 23:40:32 2005 Return-Path: X-Original-To: freebsd-bugs@hub.freebsd.org Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id E21BE16A454 for ; Sat, 19 Nov 2005 23:40:31 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 33BAD43D45 for ; Sat, 19 Nov 2005 23:40:27 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.3/8.13.3) with ESMTP id jAJNeQR8095806 for ; Sat, 19 Nov 2005 23:40:26 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.3/8.13.1/Submit) id jAJNeQLU095805; Sat, 19 Nov 2005 23:40:26 GMT (envelope-from gnats) Date: Sat, 19 Nov 2005 23:40:26 GMT Message-Id: <200511192340.jAJNeQLU095805@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org From: Peter Jeremy Cc: Subject: Re: kern/78179: bus_dmamem_alloc() with BUS_DMA_NOWAIT can block X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Peter Jeremy List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 19 Nov 2005 23:40:34 -0000 The following reply was made to PR kern/78179; it has been noted by GNATS. From: Peter Jeremy To: Mark Tinguely Cc: bug-followup@freebsd.org Subject: Re: kern/78179: bus_dmamem_alloc() with BUS_DMA_NOWAIT can block Date: Sun, 20 Nov 2005 10:39:09 +1100 On Thu, 2005-Nov-17 16:04:14 -0600, Mark Tinguely wrote: >I took a stab at the problem that NOWAIT is not being honored in >contigmalloc() by making the vm_contig_launder_page() honor >the flag. Thank you. Of course, this doesn't help drivers like bktr(4) that use contigmalloc(M_NOWAIT) and panic() if the memory isn't available. I've gone through your changes and suspect you may have missed a few possibilities that can sleep. >*** vm/vm_contig.c.orig Thu Nov 17 15:10:10 2005 >--- vm/vm_contig.c Thu Nov 17 13:59:47 2005 >*************** >*** 95,100 **** >--- 95,105 ---- > object = m->object; > if (!VM_OBJECT_TRYLOCK(object)) > return (EAGAIN); >+ if (flags & M_NOWAIT && (m->flags & PG_BUSY || m->busy)) { >+ VM_OBJECT_UNLOCK(object); >+ printf("vm_contig_launder_page: would sleep (busy)\n"); >+ return (EWOULDBLOCK); I suspect all your EWOULDBLOCK should be EAGAIN for consistency. >+ } > if (vm_page_sleep_if_busy(m, TRUE, "vpctw0")) { > VM_OBJECT_UNLOCK(object); > vm_page_lock_queues(); >*************** >*** 104,126 **** ... >--- 109,149 ---- > if (m->dirty == 0 && m->hold_count == 0) > pmap_remove_all(m); This can sleep because it seizes a mutex for each entry. > if (m->dirty) { >+ /* Both paths use vm_pageout_flush() which forces >+ * a syncronous putpage for the kernel_object. >+ */ >+ if (flags & M_NOWAIT && object == kernel_object) { >+ VM_OBJECT_UNLOCK(object); >+ printf("vm_contig_launder_page: would sleep (kobject)\n"); >+ return (EWOULDBLOCK); >+ } > if (object->type == OBJT_VNODE) { > vm_page_unlock_queues(); > vp = object->handle; > VM_OBJECT_UNLOCK(object); > vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread); vn_lock(9) implies this can sleep unless the 2nd argument includes LK_NOWAIT. > VM_OBJECT_LOCK(object); This will sleep if something else has grabbed the object mutex. >! vm_object_page_clean(object, 0, 0, >! (flags & M_NOWAIT) ? 0 : OBJPC_SYNC); > VM_OBJECT_UNLOCK(object); > VOP_UNLOCK(vp, 0, curthread); > vm_page_lock_queues(); This will sleep if something else is holding vm_page_queue_mtx. >! if ((flags & M_NOWAIT) && m->dirty) { >! printf("vm_contig_launder_page: would sleep (dirty)\n"); >! return (EWOULDBLOCK); >! } else >! return (0); > } else if (object->type == OBJT_SWAP || > object->type == OBJT_DEFAULT) { > m_tmp = m; >! vm_pageout_flush(&m_tmp, 1, >! (flags & M_NOWAIT) ? 0 : VM_PAGER_PUT_SYNC); > VM_OBJECT_UNLOCK(object); >! if ((flags & M_NOWAIT) && m->dirty) { >! printf("vm_contig_launder_page: would sleep (dirty)\n"); >! return (EWOULDBLOCK); >! } else >! return (0); > } > } else if (m->hold_count == 0) > vm_page_cache(m); >*************** -- Peter Jeremy