From 3068339e18f0d88a29207722f3061060fa0079a7 Mon Sep 17 00:00:00 2001 From: jdolecek Date: Tue, 8 Apr 2003 18:16:01 +0000 Subject: [PATCH] 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 --- sys/fs/smbfs/smbfs_kq.c | 50 +++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/sys/fs/smbfs/smbfs_kq.c b/sys/fs/smbfs/smbfs_kq.c index 25f9b6da4cd9..3a6ed20d4cf7 100644 --- a/sys/fs/smbfs/smbfs_kq.c +++ b/sys/fs/smbfs/smbfs_kq.c @@ -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. @@ -37,7 +37,7 @@ */ #include -__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 #include @@ -131,14 +131,13 @@ smbfs_kqpoll(void *arg) { struct kevq *ke; struct vattr attr; - int error; + int error=0; struct proc *p = smbkqp; u_quad_t osize; int needwake; + simple_lock(&smbkq_lock); for(;;) { - simple_lock(&smbkq_lock); - /* check all entries on poll list for changes */ SLIST_FOREACH(ke, &kplist, k_link) { /* skip if still in attrcache */ @@ -197,7 +196,6 @@ smbfs_kqpoll(void *arg) /* Exit if there are no more kevents to watch for */ if (kevs == 0) { smbkqp = NULL; - simple_unlock(&smbkq_lock); break; } @@ -205,8 +203,11 @@ smbfs_kqpoll(void *arg) needwake = !SLIST_EMPTY(&kplist); /* wait a while before checking for changes again */ - error = ltsleep(smbkqp, PSOCK, "smbkqidl", - needwake ? (SMBFS_ATTRTIMO * hz / 2) : 0, &smbkq_lock); + if (SLIST_EMPTY(&kdnlist)) { + error = ltsleep(smbkqp, PSOCK, "smbkqidl", + needwake ? (SMBFS_ATTRTIMO * hz / 2) : 0, + &smbkq_lock); + } if (!error) { /* woken up, check if any pending notifications */ @@ -219,6 +220,15 @@ smbfs_kqpoll(void *arg) SLIST_NEXT(ke, k_link) = NULL; 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, &hint); ke->rq = NULL; /* rq deallocated by now */ @@ -234,14 +244,19 @@ smbfs_kqpoll(void *arg) VN_KNOTE(ke->vp, hint); + notifyrq: /* reissue the notify request */ (void) smbfs_smb_nt_dirnotify_setup( VTOSMB(ke->vp), &ke->rq, &smbkq_scred, smbfskq_dirnotify, ke); + + /* reacquire the lock */ + simple_lock(&smbkq_lock); } } } + simple_unlock(&smbkq_lock); kthread_exit(0); } @@ -450,6 +465,7 @@ smbfs_kqfilter(void *v) FREE(ken, M_KEVENT); /* dispose, don't need */ } else { /* need a new one */ + memset(ken, 0, sizeof(*ken)); ke = ken; ke->vp = vp; ke->usecount = 1; @@ -459,16 +475,16 @@ smbfs_kqfilter(void *v) ke->onlink = attr.va_nlink; if (dnot) { - /* If directory notify, queue request for execution */ - SLIST_NEXT(ke, k_link) = NULL; + int s; - error = smbfs_smb_nt_dirnotify_setup(VTOSMB(vp), - &ke->rq, &smbkq_scred, smbfskq_dirnotify, ke); - if (error) { - kevs--; - FREE(ke, M_KEVENT); - return (error); - } + /* + * Add kevent to list of 'need attend' kevnets. + * The handler will pick it up and setup request + * appropriately. + */ + s = splnet(); + SLIST_INSERT_HEAD(&kdnlist, ke, k_link); + splx(s); dnot_num++; } else { /* add to poll list */