fix locking issues uncovered by LOCKDEBUG, reorganize code a bit so that

even the initial directory notify request is sent by smbkq thread
problems found during LOCKDEBUG hunt, adresses PR kern/21067 by Martin Husemann
This commit is contained in:
jdolecek 2003-04-08 18:16:01 +00:00
parent dfc728f814
commit 3068339e18

View File

@ -1,4 +1,4 @@
/* $NetBSD: smbfs_kq.c,v 1.3 2003/04/07 12:04:15 jdolecek Exp $ */ /* $NetBSD: smbfs_kq.c,v 1.4 2003/04/08 18:16:01 jdolecek Exp $ */
/*- /*-
* Copyright (c) 2003 The NetBSD Foundation, Inc. * Copyright (c) 2003 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: smbfs_kq.c,v 1.3 2003/04/07 12:04:15 jdolecek Exp $"); __KERNEL_RCSID(0, "$NetBSD: smbfs_kq.c,v 1.4 2003/04/08 18:16:01 jdolecek Exp $");
#include <sys/param.h> #include <sys/param.h>
#include <sys/systm.h> #include <sys/systm.h>
@ -131,14 +131,13 @@ smbfs_kqpoll(void *arg)
{ {
struct kevq *ke; struct kevq *ke;
struct vattr attr; struct vattr attr;
int error; int error=0;
struct proc *p = smbkqp; struct proc *p = smbkqp;
u_quad_t osize; u_quad_t osize;
int needwake; int needwake;
simple_lock(&smbkq_lock);
for(;;) { for(;;) {
simple_lock(&smbkq_lock);
/* check all entries on poll list for changes */ /* check all entries on poll list for changes */
SLIST_FOREACH(ke, &kplist, k_link) { SLIST_FOREACH(ke, &kplist, k_link) {
/* skip if still in attrcache */ /* skip if still in attrcache */
@ -197,7 +196,6 @@ smbfs_kqpoll(void *arg)
/* Exit if there are no more kevents to watch for */ /* Exit if there are no more kevents to watch for */
if (kevs == 0) { if (kevs == 0) {
smbkqp = NULL; smbkqp = NULL;
simple_unlock(&smbkq_lock);
break; break;
} }
@ -205,8 +203,11 @@ smbfs_kqpoll(void *arg)
needwake = !SLIST_EMPTY(&kplist); needwake = !SLIST_EMPTY(&kplist);
/* wait a while before checking for changes again */ /* wait a while before checking for changes again */
error = ltsleep(smbkqp, PSOCK, "smbkqidl", if (SLIST_EMPTY(&kdnlist)) {
needwake ? (SMBFS_ATTRTIMO * hz / 2) : 0, &smbkq_lock); error = ltsleep(smbkqp, PSOCK, "smbkqidl",
needwake ? (SMBFS_ATTRTIMO * hz / 2) : 0,
&smbkq_lock);
}
if (!error) { if (!error) {
/* woken up, check if any pending notifications */ /* woken up, check if any pending notifications */
@ -219,6 +220,15 @@ smbfs_kqpoll(void *arg)
SLIST_NEXT(ke, k_link) = NULL; SLIST_NEXT(ke, k_link) = NULL;
splx(s); splx(s);
/* drop lock while processing */
simple_unlock(&smbkq_lock);
/*
* Skip fetch if not yet setup.
*/
if (__predict_false(ke->rq == NULL))
goto notifyrq;
error = smbfs_smb_nt_dirnotify_fetch(ke->rq, error = smbfs_smb_nt_dirnotify_fetch(ke->rq,
&hint); &hint);
ke->rq = NULL; /* rq deallocated by now */ ke->rq = NULL; /* rq deallocated by now */
@ -234,14 +244,19 @@ smbfs_kqpoll(void *arg)
VN_KNOTE(ke->vp, hint); VN_KNOTE(ke->vp, hint);
notifyrq:
/* reissue the notify request */ /* reissue the notify request */
(void) smbfs_smb_nt_dirnotify_setup( (void) smbfs_smb_nt_dirnotify_setup(
VTOSMB(ke->vp), VTOSMB(ke->vp),
&ke->rq, &smbkq_scred, &ke->rq, &smbkq_scred,
smbfskq_dirnotify, ke); smbfskq_dirnotify, ke);
/* reacquire the lock */
simple_lock(&smbkq_lock);
} }
} }
} }
simple_unlock(&smbkq_lock);
kthread_exit(0); kthread_exit(0);
} }
@ -450,6 +465,7 @@ smbfs_kqfilter(void *v)
FREE(ken, M_KEVENT); /* dispose, don't need */ FREE(ken, M_KEVENT); /* dispose, don't need */
} else { } else {
/* need a new one */ /* need a new one */
memset(ken, 0, sizeof(*ken));
ke = ken; ke = ken;
ke->vp = vp; ke->vp = vp;
ke->usecount = 1; ke->usecount = 1;
@ -459,16 +475,16 @@ smbfs_kqfilter(void *v)
ke->onlink = attr.va_nlink; ke->onlink = attr.va_nlink;
if (dnot) { if (dnot) {
/* If directory notify, queue request for execution */ int s;
SLIST_NEXT(ke, k_link) = NULL;
error = smbfs_smb_nt_dirnotify_setup(VTOSMB(vp), /*
&ke->rq, &smbkq_scred, smbfskq_dirnotify, ke); * Add kevent to list of 'need attend' kevnets.
if (error) { * The handler will pick it up and setup request
kevs--; * appropriately.
FREE(ke, M_KEVENT); */
return (error); s = splnet();
} SLIST_INSERT_HEAD(&kdnlist, ke, k_link);
splx(s);
dnot_num++; dnot_num++;
} else { } else {
/* add to poll list */ /* add to poll list */