--- First major chunk of ALQ(9) rototilling (more to follow): --- --- - Add support for ALQ to be compiled and loaded as a kernel module. --- --- - Replace deprecated msleep() with mtx_sleep(). --- --- - General code and style(9) cleanup. --- --- Sponsored by: FreeBSD Foundation --- Reviewed by: jeff, rwatson, dwmalone, rpaulo --- Approved by: (mentor) --- MFC after: 2 months --- Index: kern/kern_alq.c =================================================================== --- kern/kern_alq.c (.../head/sys) (revision 204686) +++ kern/kern_alq.c (.../user/lstewart/alq_varlen_head/sys) @@ -1,7 +1,13 @@ /*- * Copyright (c) 2002, Jeffrey Roberson + * Copyright (c) 2008-2009, Lawrence Stewart + * Copyright (c) 2009-2010, The FreeBSD Foundation * All rights reserved. * + * Portions of this software were developed at the Centre for Advanced + * Internet Architectures, Swinburne University of Technology, Melbourne, + * Australia by Lawrence Stewart under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -27,8 +33,13 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_mac.h" + #include #include +#include +#include +#include #include #include #include @@ -36,12 +47,8 @@ #include #include #include +#include #include -#include -#include -#include -#include -#include #include @@ -78,7 +85,6 @@ static LIST_HEAD(, alq) ald_queues; static LIST_HEAD(, alq) ald_active; static int ald_shutingdown = 0; -struct thread *ald_thread; static struct proc *ald_proc; #define ALD_LOCK() mtx_lock(&ald_mtx) @@ -95,6 +101,7 @@ /* Internal queue functions */ static void alq_shutdown(struct alq *); +static void alq_destroy(struct alq *); static int alq_doio(struct alq *); @@ -107,14 +114,11 @@ int error; error = 0; - ALD_LOCK(); - if (ald_shutingdown) { + if (ald_shutingdown) error = EBUSY; - goto done; - } - LIST_INSERT_HEAD(&ald_queues, alq, aq_link); -done: + else + LIST_INSERT_HEAD(&ald_queues, alq, aq_link); ALD_UNLOCK(); return (error); } @@ -129,14 +133,11 @@ int error; error = 0; - ALD_LOCK(); - if (ald_shutingdown) { + if (ald_shutingdown) error = EBUSY; - goto done; - } - LIST_REMOVE(alq, aq_link); -done: + else + LIST_REMOVE(alq, aq_link); ALD_UNLOCK(); return (error); } @@ -172,17 +173,22 @@ int needwakeup; struct alq *alq; - ald_thread = FIRST_THREAD_IN_PROC(ald_proc); - EVENTHANDLER_REGISTER(shutdown_pre_sync, ald_shutdown, NULL, SHUTDOWN_PRI_FIRST); ALD_LOCK(); for (;;) { - while ((alq = LIST_FIRST(&ald_active)) == NULL) - msleep(&ald_active, &ald_mtx, PWAIT, "aldslp", 0); + while ((alq = LIST_FIRST(&ald_active)) == NULL && + !ald_shutingdown) + mtx_sleep(&ald_active, &ald_mtx, PWAIT, "aldslp", 0); + /* Don't shutdown until all active ALQs are flushed. */ + if (ald_shutingdown && alq == NULL) { + ALD_UNLOCK(); + break; + } + ALQ_LOCK(alq); ald_deactivate(alq); ALD_UNLOCK(); @@ -192,6 +198,8 @@ wakeup(alq); ALD_LOCK(); } + + kproc_exit(0); } static void @@ -200,14 +208,29 @@ struct alq *alq; ALD_LOCK(); + + /* Ensure no new queues can be created. */ ald_shutingdown = 1; + /* Shutdown all ALQs prior to terminating the ald_daemon. */ while ((alq = LIST_FIRST(&ald_queues)) != NULL) { LIST_REMOVE(alq, aq_link); ALD_UNLOCK(); alq_shutdown(alq); ALD_LOCK(); } + + /* At this point, all ALQs are flushed and shutdown. */ + + /* + * Wake ald_daemon so that it exits. It won't be able to do + * anything until we mtx_sleep because we hold the ald_mtx. + */ + wakeup(&ald_active); + + /* Wait for ald_daemon to exit. */ + mtx_sleep(ald_proc, &ald_mtx, PWAIT, "aldslp", 0); + ALD_UNLOCK(); } @@ -220,17 +243,28 @@ alq->aq_flags |= AQ_SHUTDOWN; /* Drain IO */ - while (alq->aq_flags & (AQ_FLUSHING|AQ_ACTIVE)) { + while (alq->aq_flags & AQ_ACTIVE) { alq->aq_flags |= AQ_WANTED; msleep_spin(alq, &alq->aq_mtx, "aldclose", 0); } ALQ_UNLOCK(alq); - vn_close(alq->aq_vp, FWRITE, alq->aq_cred, - curthread); + vn_close(alq->aq_vp, FWRITE, alq->aq_cred, curthread); crfree(alq->aq_cred); } +void +alq_destroy(struct alq *alq) +{ + /* Drain all pending IO. */ + alq_shutdown(alq); + + mtx_destroy(&alq->aq_mtx); + free(alq->aq_first, M_ALD); + free(alq->aq_entbuf, M_ALD); + free(alq, M_ALD); +} + /* * Flush all pending data to disk. This operation will block. */ @@ -317,9 +351,9 @@ } static struct kproc_desc ald_kp = { - "ALQ Daemon", - ald_daemon, - &ald_proc + "ALQ Daemon", + ald_daemon, + &ald_proc }; SYSINIT(aldthread, SI_SUB_KTHREAD_IDLE, SI_ORDER_ANY, kproc_start, &ald_kp); @@ -388,8 +422,11 @@ alp->ae_next = alq->aq_first; - if ((error = ald_add(alq)) != 0) + if ((error = ald_add(alq)) != 0) { + alq_destroy(alq); return (error); + } + *alqp = alq; return (0); @@ -471,8 +508,10 @@ void alq_flush(struct alq *alq) { - int needwakeup = 0; + int needwakeup; + needwakeup = 0; + ALD_LOCK(); ALQ_LOCK(alq); if (alq->aq_flags & AQ_ACTIVE) { @@ -493,20 +532,57 @@ void alq_close(struct alq *alq) { - /* - * If we're already shuting down someone else will flush and close - * the vnode. - */ - if (ald_rem(alq) != 0) - return; + /* Only flush and destroy alq if not already shutting down. */ + if (ald_rem(alq) == 0) + alq_destroy(alq); +} - /* - * Drain all pending IO. - */ - alq_shutdown(alq); +static int +alq_load_handler(module_t mod, int what, void *arg) +{ + int ret; + + ret = 0; - mtx_destroy(&alq->aq_mtx); - free(alq->aq_first, M_ALD); - free(alq->aq_entbuf, M_ALD); - free(alq, M_ALD); + switch (what) { + case MOD_LOAD: + case MOD_SHUTDOWN: + break; + + case MOD_QUIESCE: + ALD_LOCK(); + /* Only allow unload if there are no open queues. */ + if (LIST_FIRST(&ald_queues) == NULL) { + ald_shutingdown = 1; + ALD_UNLOCK(); + ald_shutdown(NULL, 0); + mtx_destroy(&ald_mtx); + } else { + ALD_UNLOCK(); + ret = EBUSY; + } + break; + + case MOD_UNLOAD: + /* If MOD_QUIESCE failed we must fail here too. */ + if (ald_shutingdown == 0) + ret = EBUSY; + break; + + default: + ret = EINVAL; + break; + } + + return (ret); } + +static moduledata_t alq_mod = +{ + "alq", + alq_load_handler, + NULL +}; + +DECLARE_MODULE(alq, alq_mod, SI_SUB_SMP, SI_ORDER_ANY); +MODULE_VERSION(alq, 1); Index: modules/Makefile =================================================================== --- modules/Makefile (.../head/sys) (revision 204686) +++ modules/Makefile (.../user/lstewart/alq_varlen_head/sys) @@ -20,6 +20,7 @@ SUBDIR= ${_3dfx} \ aio \ alc \ ale \ + alq \ ${_amd} \ ${_amdsbwd} \ ${_amdtemp} \ Index: modules/alq/Makefile =================================================================== --- modules/alq/Makefile (.../head/sys) (revision 0) +++ modules/alq/Makefile (.../user/lstewart/alq_varlen_head/sys) @@ -0,0 +1,9 @@ +# $FreeBSD$ + +.include + +.PATH: ${.CURDIR}/../../kern +KMOD= alq +SRCS= opt_mac.h vnode_if.h kern_alq.c + +.include Property changes on: modules/alq/Makefile ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:keywords + FreeBSD=%H Added: svn:eol-style + native