FreeBSD/sys/fs/nfsclient/nfs_clnfsiod.c
/*
 * Asynchronous I/O daemons for client nfs.
 * They do read-ahead and write-behind operations on the block I/O cache.
 * Returns if we hit the timeout defined by the iodmaxidle sysctl.
 */
Asynchronous I/O daemons for client nfs.
They do read-ahead and write-behind operations on the block I/O cache.
Returns if we hit the timeout defined by the iodmaxidle sysctl.
Asynchronous I / O daemons for client nfs . They do read - ahead and write - behind operations on the block I / O cache . Returns if we hit the timeout defined by the iodmaxidle sysctl .
static void
nfssvc_iod(void *instance)
{
	struct buf *bp;
	struct nfsmount *nmp;
	int myiod, timo;
	int error = 0;
	mtx_lock(&ncl_iod_mutex);
	myiod = (int *)instance - nfs_asyncdaemon;
	for (;;) {
	    while (((nmp = ncl_iodmount[myiod]) == NULL)
		   || !TAILQ_FIRST(&nmp->nm_bufq)) {
		if (myiod >= ncl_iodmax)
			goto finish;
		if (nmp)
			nmp->nm_bufqiods--;
		if (ncl_iodwant[myiod] == NFSIOD_NOT_AVAILABLE)
			ncl_iodwant[myiod] = NFSIOD_AVAILABLE;
		ncl_iodmount[myiod] = NULL;
		timo = (myiod < nfs_iodmin) ? 0 : nfs_iodmaxidle * hz;
		error = msleep(&ncl_iodwant[myiod], &ncl_iod_mutex, PWAIT | PCATCH,
		    "-", timo);
		if (error) {
			nmp = ncl_iodmount[myiod];
			if (nmp && TAILQ_FIRST(&nmp->nm_bufq))
				error = 0;
			break;
		}
	    }
	    if (error)
		    break;
	    while ((bp = TAILQ_FIRST(&nmp->nm_bufq)) != NULL) {
		TAILQ_REMOVE(&nmp->nm_bufq, bp, b_freelist);
		nmp->nm_bufqlen--;
		if (nmp->nm_bufqwant && nmp->nm_bufqlen <= ncl_numasync) {
		    nmp->nm_bufqwant = 0;
		    wakeup(&nmp->nm_bufq);
		}
		mtx_unlock(&ncl_iod_mutex);
		if (bp->b_flags & B_DIRECT) {
			KASSERT((bp->b_iocmd == BIO_WRITE), ("nfscvs_iod: BIO_WRITE not set"));
			(void)ncl_doio_directwrite(bp);
		} else {
			if (bp->b_iocmd == BIO_READ)
				(void) ncl_doio(bp->b_vp, bp, bp->b_rcred,
				    NULL, 0);
			else
				(void) ncl_doio(bp->b_vp, bp, bp->b_wcred,
				    NULL, 0);
		}
		mtx_lock(&ncl_iod_mutex);
		nmp = ncl_iodmount[myiod];
		if (nmp == NULL)
			break;
		if (nfs_defect && nmp->nm_bufqiods > 1) {
		    NFS_DPF(ASYNCIO,
			    ("nfssvc_iod: iod %d defecting from mount %p\n",
			     myiod, nmp));
		    ncl_iodmount[myiod] = NULL;
		    nmp->nm_bufqiods--;
		    break;
		}
	    }
	}
finish:
	nfs_asyncdaemon[myiod] = 0;
	if (nmp)
	    nmp->nm_bufqiods--;
	ncl_iodwant[myiod] = NFSIOD_NOT_AVAILABLE;
	ncl_iodmount[myiod] = NULL;
	if (--ncl_numasync == 0)
		wakeup(&ncl_numasync);
	mtx_unlock(&ncl_iod_mutex);
	if ((error == 0) || (error == EWOULDBLOCK))
		kproc_exit(0);
	kproc_exit(1);
}
static void nfssvc_iod ( void * instance ) { struct buf * bp ; struct nfsmount * nmp ; int myiod , timo ; int error = 0 ; mtx_lock ( & ncl_iod_mutex ) ; myiod = ( int * ) instance - nfs_asyncdaemon ; for ( ; ; ) { while ( ( ( nmp = ncl_iodmount [ myiod ] ) == NULL ) || ! TAILQ_FIRST ( & nmp -> nm_bufq ) ) { if ( myiod >= ncl_iodmax ) goto finish ; if ( nmp ) nmp -> nm_bufqiods -- ; if ( ncl_iodwant [ myiod ] == NFSIOD_NOT_AVAILABLE ) ncl_iodwant [ myiod ] = NFSIOD_AVAILABLE ; ncl_iodmount [ myiod ] = NULL ; timo = ( myiod < nfs_iodmin ) ? 0 : nfs_iodmaxidle * hz ; error = msleep ( & ncl_iodwant [ myiod ] , & ncl_iod_mutex , PWAIT | PCATCH , " " , timo ) ; if ( error ) { nmp = ncl_iodmount [ myiod ] ; if ( nmp && TAILQ_FIRST ( & nmp -> nm_bufq ) ) error = 0 ; break ; } } if ( error ) break ; while ( ( bp = TAILQ_FIRST ( & nmp -> nm_bufq ) ) != NULL ) { TAILQ_REMOVE ( & nmp -> nm_bufq , bp , b_freelist ) ; nmp -> nm_bufqlen -- ; if ( nmp -> nm_bufqwant && nmp -> nm_bufqlen <= ncl_numasync ) { nmp -> nm_bufqwant = 0 ; wakeup ( & nmp -> nm_bufq ) ; } mtx_unlock ( & ncl_iod_mutex ) ; if ( bp -> b_flags & B_DIRECT ) { KASSERT ( ( bp -> b_iocmd == BIO_WRITE ) , ( " " ) ) ; ( void ) ncl_doio_directwrite ( bp ) ; } else { if ( bp -> b_iocmd == BIO_READ ) ( void ) ncl_doio ( bp -> b_vp , bp , bp -> b_rcred , NULL , 0 ) ; else ( void ) ncl_doio ( bp -> b_vp , bp , bp -> b_wcred , NULL , 0 ) ; } mtx_lock ( & ncl_iod_mutex ) ; nmp = ncl_iodmount [ myiod ] ; if ( nmp == NULL ) break ; if ( nfs_defect && nmp -> nm_bufqiods > 1 ) { NFS_DPF ( ASYNCIO , ( " \n " , myiod , nmp ) ) ; ncl_iodmount [ myiod ] = NULL ; nmp -> nm_bufqiods -- ; break ; } } } finish : nfs_asyncdaemon [ myiod ] = 0 ; if ( nmp ) nmp -> nm_bufqiods -- ; ncl_iodwant [ myiod ] = NFSIOD_NOT_AVAILABLE ; ncl_iodmount [ myiod ] = NULL ; if ( -- ncl_numasync == 0 ) wakeup ( & ncl_numasync ) ; mtx_unlock ( & ncl_iod_mutex ) ; if ( ( error == 0 ) || ( error == EWOULDBLOCK ) ) kproc_exit ( 0 ) ; kproc_exit ( 1 ) ; }
Asynchronous I/O daemons for client nfs.
Asynchronous I / O daemons for client nfs .
/*
	 * Main loop
	 */ /*
		 * Always keep at least nfs_iodmin kthreads.
		 */ /*
			 * Rechecking the nm_bufq closes a rare race where the 
			 * nfsiod is woken up at the exact time the idle timeout
			 * fires
			 */ /* Take one off the front of the list */ /*
		 * Make sure the nmp hasn't been dismounted as soon as
		 * ncl_doio() completes for the last buffer.
		 */ /*
		 * If there are more than one iod on this mount, then defect
		 * so that the iods can be shared out fairly between the mounts
		 */ /* Someone may be waiting for the last nfsiod to terminate. */ /* Abnormal termination */