diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/quiesce.c | 53 | ||||
-rw-r--r-- | src/core/sanboot.c | 15 |
2 files changed, 68 insertions, 0 deletions
diff --git a/src/core/quiesce.c b/src/core/quiesce.c new file mode 100644 index 00000000..5d2a919d --- /dev/null +++ b/src/core/quiesce.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2017 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +/** + * @file + * + * Quiesce system + * + */ + +#include <ipxe/quiesce.h> + +/** Quiesce system */ +void quiesce ( void ) { + struct quiescer *quiescer; + + /* Call all quiescers */ + for_each_table_entry ( quiescer, QUIESCERS ) { + quiescer->quiesce(); + } +} + +/** Unquiesce system */ +void unquiesce ( void ) { + struct quiescer *quiescer; + + /* Call all quiescers */ + for_each_table_entry ( quiescer, QUIESCERS ) { + quiescer->unquiesce(); + } +} diff --git a/src/core/sanboot.c b/src/core/sanboot.c index 1fd63490..cabc4843 100644 --- a/src/core/sanboot.c +++ b/src/core/sanboot.c @@ -41,6 +41,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <ipxe/iso9660.h> #include <ipxe/dhcp.h> #include <ipxe/settings.h> +#include <ipxe/quiesce.h> #include <ipxe/sanboot.h> /** @@ -365,6 +366,9 @@ int sandev_reopen ( struct san_device *sandev ) { struct san_path *sanpath; int rc; + /* Unquiesce system */ + unquiesce(); + /* Close any outstanding command and restart interfaces */ sandev_restart ( sandev, -ECONNRESET ); assert ( sandev->active == NULL ); @@ -503,6 +507,9 @@ sandev_command ( struct san_device *sandev, /* Sanity check */ assert ( ! timer_running ( &sandev->timer ) ); + /* Unquiesce system */ + unquiesce(); + /* (Re)try command */ do { @@ -654,6 +661,14 @@ int sandev_write ( struct san_device *sandev, uint64_t lba, if ( ( rc = sandev_rw ( sandev, lba, count, buffer, block_write ) ) != 0 ) return rc; + /* Quiesce system. This is a heuristic designed to ensure + * that the system is quiesced before Windows starts up, since + * a Windows SAN boot will typically write a status flag to + * the disk as its last action before transferring control to + * the native drivers. + */ + quiesce(); + return 0; } |