Browse Source

[block] Provide abstraction to allow system to be quiesced

When performing a SAN boot via INT 13, there is no way for the
operating system to indicate that it has finished using the INT 13 SAN
device.  We therefore have no opportunity to clean up state before the
loaded operating system's native drivers take over.  This can cause
problems when booting Windows, which tends not to be forgiving of
unexpected system state.

Windows will typically write a flag to the SAN device as the last
action before transferring control to the native drivers.  We can use
this as a heuristic to bring the system to a quiescent state (without
performing a full shutdown); this provides us an opportunity to
temporarily clean up state that could otherwise prevent a successful
Windows boot.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 7 years ago
parent
commit
648657b776
3 changed files with 99 additions and 0 deletions
  1. 53
    0
      src/core/quiesce.c
  2. 15
    0
      src/core/sanboot.c
  3. 31
    0
      src/include/ipxe/quiesce.h

+ 53
- 0
src/core/quiesce.c View File

1
+/*
2
+ * Copyright (C) 2017 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
18
+ *
19
+ * You can also choose to distribute this program under the terms of
20
+ * the Unmodified Binary Distribution Licence (as given in the file
21
+ * COPYING.UBDL), provided that you have satisfied its requirements.
22
+ */
23
+
24
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
+
26
+/**
27
+ * @file
28
+ *
29
+ * Quiesce system
30
+ *
31
+ */
32
+
33
+#include <ipxe/quiesce.h>
34
+
35
+/** Quiesce system */
36
+void quiesce ( void ) {
37
+	struct quiescer *quiescer;
38
+
39
+	/* Call all quiescers */
40
+	for_each_table_entry ( quiescer, QUIESCERS ) {
41
+		quiescer->quiesce();
42
+	}
43
+}
44
+
45
+/** Unquiesce system */
46
+void unquiesce ( void ) {
47
+	struct quiescer *quiescer;
48
+
49
+	/* Call all quiescers */
50
+	for_each_table_entry ( quiescer, QUIESCERS ) {
51
+		quiescer->unquiesce();
52
+	}
53
+}

+ 15
- 0
src/core/sanboot.c View File

41
 #include <ipxe/iso9660.h>
41
 #include <ipxe/iso9660.h>
42
 #include <ipxe/dhcp.h>
42
 #include <ipxe/dhcp.h>
43
 #include <ipxe/settings.h>
43
 #include <ipxe/settings.h>
44
+#include <ipxe/quiesce.h>
44
 #include <ipxe/sanboot.h>
45
 #include <ipxe/sanboot.h>
45
 
46
 
46
 /**
47
 /**
365
 	struct san_path *sanpath;
366
 	struct san_path *sanpath;
366
 	int rc;
367
 	int rc;
367
 
368
 
369
+	/* Unquiesce system */
370
+	unquiesce();
371
+
368
 	/* Close any outstanding command and restart interfaces */
372
 	/* Close any outstanding command and restart interfaces */
369
 	sandev_restart ( sandev, -ECONNRESET );
373
 	sandev_restart ( sandev, -ECONNRESET );
370
 	assert ( sandev->active == NULL );
374
 	assert ( sandev->active == NULL );
503
 	/* Sanity check */
507
 	/* Sanity check */
504
 	assert ( ! timer_running ( &sandev->timer ) );
508
 	assert ( ! timer_running ( &sandev->timer ) );
505
 
509
 
510
+	/* Unquiesce system */
511
+	unquiesce();
512
+
506
 	/* (Re)try command */
513
 	/* (Re)try command */
507
 	do {
514
 	do {
508
 
515
 
654
 	if ( ( rc = sandev_rw ( sandev, lba, count, buffer, block_write ) ) != 0 )
661
 	if ( ( rc = sandev_rw ( sandev, lba, count, buffer, block_write ) ) != 0 )
655
 		return rc;
662
 		return rc;
656
 
663
 
664
+	/* Quiesce system.  This is a heuristic designed to ensure
665
+	 * that the system is quiesced before Windows starts up, since
666
+	 * a Windows SAN boot will typically write a status flag to
667
+	 * the disk as its last action before transferring control to
668
+	 * the native drivers.
669
+	 */
670
+	quiesce();
671
+
657
 	return 0;
672
 	return 0;
658
 }
673
 }
659
 
674
 

+ 31
- 0
src/include/ipxe/quiesce.h View File

1
+#ifndef _IPXE_QUIESCE_H
2
+#define _IPXE_QUIESCE_H
3
+
4
+/** @file
5
+ *
6
+ * Quiesce system
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11
+
12
+#include <ipxe/tables.h>
13
+
14
+/** A quiescer */
15
+struct quiescer {
16
+	/** Quiesce system */
17
+	void ( * quiesce ) ( void );
18
+	/** Unquiesce system */
19
+	void ( * unquiesce ) ( void );
20
+};
21
+
22
+/** Quiescer table */
23
+#define QUIESCERS __table ( struct quiescer, "quiescers" )
24
+
25
+/** Declare a quiescer */
26
+#define __quiescer __table_entry ( QUIESCERS, 01 )
27
+
28
+extern void quiesce ( void );
29
+extern void unquiesce ( void );
30
+
31
+#endif /* _IPXE_QUIESCE_H */

Loading…
Cancel
Save