ソースを参照

Quick hack to get AoE back in to the tree, on a par with the current

iSCSI hack.
tags/v0.9.3
Michael Brown 17年前
コミット
43013da9bf
8個のファイルの変更187行の追加181行の削除
  1. 0
    55
      src/drivers/ata/aoedev.c
  2. 8
    17
      src/include/gpxe/aoe.h
  3. 3
    0
      src/include/gpxe/ata.h
  4. 6
    0
      src/include/usr/aoeboot.h
  5. 96
    34
      src/net/aoe.c
  6. 0
    71
      src/tests/aoeboot.c
  7. 67
    0
      src/usr/aoeboot.c
  8. 7
    4
      src/usr/autoboot.c

+ 0
- 55
src/drivers/ata/aoedev.c ファイルの表示

@@ -1,55 +0,0 @@
1
-/*
2
- * Copyright (C) 2006 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., 675 Mass Ave, Cambridge, MA 02139, USA.
17
- */
18
-
19
-#include <stddef.h>
20
-#include <gpxe/async.h>
21
-#include <gpxe/aoe.h>
22
-
23
-/** @file
24
- *
25
- * AoE ATA device
26
- *
27
- */
28
-
29
-/**
30
- * Issue ATA command via AoE device
31
- *
32
- * @v ata		ATA device
33
- * @v command		ATA command
34
- * @ret rc		Return status code
35
- */
36
-static int aoe_command ( struct ata_device *ata,
37
-			 struct ata_command *command ) {
38
-	struct aoe_device *aoedev
39
-		= container_of ( ata, struct aoe_device, ata );
40
-	struct async async;
41
-
42
-	return async_block ( &async, aoe_issue ( &aoedev->aoe, command,
43
-						 &async ) );
44
-}
45
-
46
-/**
47
- * Initialise AoE device
48
- *
49
- * @v aoedev		AoE device
50
- */
51
-int init_aoedev ( struct aoe_device *aoedev ) {
52
-	aoedev->ata.command = aoe_command;
53
-	aoe_open ( &aoedev->aoe );
54
-	return init_atadev ( &aoedev->ata );
55
-}

+ 8
- 17
src/include/gpxe/aoe.h ファイルの表示

@@ -81,6 +81,9 @@ struct aoehdr {
81 81
 
82 82
 /** An AoE session */
83 83
 struct aoe_session {
84
+	/** Reference counter */
85
+	struct refcnt refcnt;
86
+
84 87
 	/** List of all AoE sessions */
85 88
 	struct list_head list;
86 89
 
@@ -103,8 +106,8 @@ struct aoe_session {
103 106
 	unsigned int status;
104 107
 	/** Byte offset within command's data buffer */
105 108
 	unsigned int command_offset;
106
-	/** Asynchronous operation for this command */
107
-	struct async async;
109
+	/** Return status code for command */
110
+	int rc;
108 111
 
109 112
 	/** Retransmission timer */
110 113
 	struct retry_timer timer;
@@ -116,20 +119,8 @@ struct aoe_session {
116 119
 /** Maximum number of sectors per packet */
117 120
 #define AOE_MAX_COUNT 2
118 121
 
119
-extern void aoe_open ( struct aoe_session *aoe );
120
-extern void aoe_close ( struct aoe_session *aoe );
121
-extern int aoe_issue ( struct aoe_session *aoe,
122
-		       struct ata_command *command,
123
-		       struct async *parent );
124
-
125
-/** An AoE device */
126
-struct aoe_device {
127
-	/** ATA device interface */
128
-	struct ata_device ata;
129
-	/** AoE protocol instance */
130
-	struct aoe_session aoe;
131
-};
132
-
133
-extern int init_aoedev ( struct aoe_device *aoedev );
122
+extern void aoe_detach ( struct ata_device *ata );
123
+extern int aoe_attach ( struct ata_device *ata, struct net_device *netdev,
124
+			const char *root_path );
134 125
 
135 126
 #endif /* _GPXE_AOE_H */

+ 3
- 0
src/include/gpxe/ata.h ファイルの表示

@@ -4,6 +4,7 @@
4 4
 #include <stdint.h>
5 5
 #include <gpxe/blockdev.h>
6 6
 #include <gpxe/uaccess.h>
7
+#include <gpxe/refcnt.h>
7 8
 
8 9
 /** @file
9 10
  *
@@ -195,6 +196,8 @@ struct ata_device {
195 196
 	 */
196 197
 	int ( * command ) ( struct ata_device *ata,
197 198
 			    struct ata_command *command );
199
+	/** Backing device */
200
+	struct refcnt *backend;
198 201
 };
199 202
 
200 203
 extern int init_atadev ( struct ata_device *ata );

+ 6
- 0
src/include/usr/aoeboot.h ファイルの表示

@@ -0,0 +1,6 @@
1
+#ifndef _USR_AOEBOOT_H
2
+#define _USR_AOEBOOT_H
3
+
4
+extern int aoeboot ( const char *root_path );
5
+
6
+#endif /* _USR_AOEBOOT_H */

+ 96
- 34
src/net/aoe.c ファイルの表示

@@ -19,6 +19,7 @@
19 19
 #include <stddef.h>
20 20
 #include <string.h>
21 21
 #include <stdio.h>
22
+#include <stdlib.h>
22 23
 #include <errno.h>
23 24
 #include <assert.h>
24 25
 #include <byteswap.h>
@@ -29,7 +30,7 @@
29 30
 #include <gpxe/uaccess.h>
30 31
 #include <gpxe/ata.h>
31 32
 #include <gpxe/netdevice.h>
32
-#include <gpxe/async.h>
33
+#include <gpxe/process.h>
33 34
 #include <gpxe/aoe.h>
34 35
 
35 36
 /** @file
@@ -43,6 +44,14 @@ struct net_protocol aoe_protocol;
43 44
 /** List of all AoE sessions */
44 45
 static LIST_HEAD ( aoe_sessions );
45 46
 
47
+static void aoe_free ( struct refcnt *refcnt ) {
48
+	struct aoe_session *aoe =
49
+		container_of ( refcnt, struct aoe_session, refcnt );
50
+
51
+	netdev_put ( aoe->netdev );
52
+	free ( aoe );
53
+}
54
+
46 55
 /**
47 56
  * Mark current AoE command complete
48 57
  *
@@ -55,8 +64,8 @@ static void aoe_done ( struct aoe_session *aoe, int rc ) {
55 64
 	aoe->command->cb.cmd_stat = aoe->status;
56 65
 	aoe->command = NULL;
57 66
 
58
-	/* Mark async operation as complete */
59
-	async_done ( &aoe->async, rc );
67
+	/* Mark operation as complete */
68
+	aoe->rc = rc;
60 69
 }
61 70
 
62 71
 /**
@@ -265,46 +274,99 @@ struct net_protocol aoe_protocol __net_protocol = {
265 274
 	.rx = aoe_rx,
266 275
 };
267 276
 
268
-/**
269
- * Open AoE session
270
- *
271
- * @v aoe		AoE session
272
- */
273
-void aoe_open ( struct aoe_session *aoe ) {
274
-	memcpy ( aoe->target, ethernet_protocol.ll_broadcast,
275
-		 sizeof ( aoe->target ) );
276
-	aoe->tag = AOE_TAG_MAGIC;
277
-	aoe->timer.expired = aoe_timer_expired;
278
-	list_add ( &aoe->list, &aoe_sessions );
279
-}
280
-
281
-/**
282
- * Close AoE session
283
- *
284
- * @v aoe		AoE session
285
- */
286
-void aoe_close ( struct aoe_session *aoe ) {
287
-	list_del ( &aoe->list );
288
-}
289
-
290 277
 /**
291 278
  * Issue ATA command via an open AoE session
292 279
  *
293
- * @v aoe		AoE session
280
+ * @v ata		ATA device
294 281
  * @v command		ATA command
295
- * @v parent		Parent asynchronous operation
296 282
  * @ret rc		Return status code
297
- *
298
- * Only one command may be issued concurrently per session.  This call
299
- * is non-blocking; use async_wait() to wait for the command to
300
- * complete.
301 283
  */
302
-int aoe_issue ( struct aoe_session *aoe, struct ata_command *command,
303
-		struct async *parent ) {
284
+static int aoe_command ( struct ata_device *ata,
285
+			 struct ata_command *command ) {
286
+	struct aoe_session *aoe =
287
+		container_of ( ata->backend, struct aoe_session, refcnt );
288
+	int rc;
289
+
304 290
 	aoe->command = command;
305 291
 	aoe->status = 0;
306 292
 	aoe->command_offset = 0;
307 293
 	aoe_send_command ( aoe );
308
-	async_init ( &aoe->async, &default_async_operations, parent );
294
+
295
+	aoe->rc = -EINPROGRESS;
296
+	while ( aoe->rc == -EINPROGRESS )
297
+		step();
298
+	rc = aoe->rc;
299
+
300
+	return rc;
301
+}
302
+
303
+static int aoe_detached_command ( struct ata_device *ata __unused,
304
+				  struct ata_command *command __unused ) {
305
+	return -ENODEV;
306
+}
307
+
308
+void aoe_detach ( struct ata_device *ata ) {
309
+	struct aoe_session *aoe =
310
+		container_of ( ata->backend, struct aoe_session, refcnt );
311
+
312
+	stop_timer ( &aoe->timer );
313
+	ata->command = aoe_detached_command;
314
+	list_del ( &aoe->list );
315
+	ref_put ( ata->backend );
316
+	ata->backend = NULL;
317
+}
318
+
319
+static int aoe_parse_root_path ( struct aoe_session *aoe,
320
+				 const char *root_path ) {
321
+	char *ptr;
322
+
323
+	if ( strncmp ( root_path, "aoe:", 4 ) != 0 )
324
+		return -EINVAL;
325
+	ptr = ( ( char * ) root_path + 4 );
326
+
327
+	if ( *ptr++ != 'e' )
328
+		return -EINVAL;
329
+
330
+	aoe->major = strtoul ( ptr, &ptr, 10 );
331
+	if ( *ptr++ != '.' )
332
+		return -EINVAL;
333
+
334
+	aoe->minor = strtoul ( ptr, &ptr, 10 );
335
+	if ( *ptr )
336
+		return -EINVAL;
337
+
309 338
 	return 0;
310 339
 }
340
+
341
+int aoe_attach ( struct ata_device *ata, struct net_device *netdev,
342
+		 const char *root_path ) {
343
+	struct aoe_session *aoe;
344
+	int rc;
345
+
346
+	/* Allocate and initialise structure */
347
+	aoe = zalloc ( sizeof ( *aoe ) );
348
+	if ( ! aoe )
349
+		return -ENOMEM;
350
+	aoe->refcnt.free = aoe_free;
351
+	aoe->netdev = netdev_get ( netdev );
352
+	memcpy ( aoe->target, ethernet_protocol.ll_broadcast,
353
+		 sizeof ( aoe->target ) );
354
+	aoe->tag = AOE_TAG_MAGIC;
355
+	aoe->timer.expired = aoe_timer_expired;
356
+
357
+	/* Parse root path */
358
+	if ( ( rc = aoe_parse_root_path ( aoe, root_path ) ) != 0 )
359
+		goto err;
360
+
361
+	/* Attach parent interface, transfer reference to connection
362
+	 * list, and return
363
+	 */
364
+	ata->backend = ref_get ( &aoe->refcnt );
365
+	ata->command = aoe_command;
366
+	list_add ( &aoe->list, &aoe_sessions );
367
+	return 0;
368
+
369
+ err:
370
+	ref_put ( &aoe->refcnt );
371
+	return rc;
372
+}

+ 0
- 71
src/tests/aoeboot.c ファイルの表示

@@ -1,71 +0,0 @@
1
-#include <stdint.h>
2
-#include <stdlib.h>
3
-#include <stdio.h>
4
-#include <errno.h>
5
-#include <console.h>
6
-#include <gpxe/netdevice.h>
7
-#include <gpxe/aoe.h>
8
-#include <int13.h>
9
-
10
-static struct aoe_device test_aoedev = {
11
-	.aoe = {
12
-		.major = 0,
13
-		.minor = 0,
14
-	},
15
-};
16
-
17
-static int aoe_parse ( const char *aoename, struct aoe_session *aoe ) {
18
-	char *ptr = ( ( char * ) aoename );
19
-
20
-	if ( *ptr++ != 'e' )
21
-		return -EINVAL;
22
-
23
-	aoe->major = strtoul ( ptr, &ptr, 10 );
24
-	if ( *ptr++ != '.' )
25
-		return -EINVAL;
26
-
27
-	aoe->minor = strtoul ( ptr, &ptr, 10 );
28
-	if ( *ptr )
29
-		return -EINVAL;
30
-
31
-	return 0;
32
-}
33
-
34
-int test_aoeboot ( struct net_device *netdev, const char *aoename,
35
-		   unsigned int drivenum ) {
36
-	struct int13_drive drive;
37
-	int rc;
38
-
39
-	printf ( "Attempting to boot from AoE device %s via %s\n",
40
-		 aoename, netdev->name );
41
-
42
-	if ( ( rc = aoe_parse ( aoename, &test_aoedev.aoe ) ) != 0 ) {
43
-		printf ( "Invalid AoE device name \"%s\"\n", aoename );
44
-		return rc;
45
-	}
46
-
47
-	printf ( "Initialising AoE device e%d.%d\n",
48
-		 test_aoedev.aoe.major, test_aoedev.aoe.minor );
49
-	test_aoedev.aoe.netdev = netdev;
50
-	if ( ( rc = init_aoedev ( &test_aoedev ) ) != 0 ) {
51
-		printf ( "Could not reach AoE device e%d.%d\n",
52
-			 test_aoedev.aoe.major, test_aoedev.aoe.minor );
53
-		return rc;
54
-	}
55
-
56
-	memset ( &drive, 0, sizeof ( drive ) );
57
-	drive.drive = drivenum;
58
-	drive.blockdev = &test_aoedev.ata.blockdev;
59
-	register_int13_drive ( &drive );
60
-	printf ( "Registered AoE device e%d.%d as BIOS drive %#02x\n",
61
-		 test_aoedev.aoe.major, test_aoedev.aoe.minor, drive.drive );
62
-
63
-	printf ( "Booting from BIOS drive %#02x\n", drive.drive );
64
-	rc = int13_boot ( drive.drive );
65
-	printf ( "Boot failed\n" );
66
-
67
-	printf ( "Unregistering BIOS drive %#02x\n", drive.drive );
68
-	unregister_int13_drive ( &drive );
69
-
70
-	return rc;
71
-}

+ 67
- 0
src/usr/aoeboot.c ファイルの表示

@@ -0,0 +1,67 @@
1
+#include <stdint.h>
2
+#include <string.h>
3
+#include <stdio.h>
4
+#include <gpxe/aoe.h>
5
+#include <gpxe/ata.h>
6
+#include <gpxe/netdevice.h>
7
+#include <gpxe/dhcp.h>
8
+#include <int13.h>
9
+#include <usr/aoeboot.h>
10
+
11
+/**
12
+ * Guess boot network device
13
+ *
14
+ * @ret netdev		Boot network device
15
+ */
16
+static struct net_device * guess_boot_netdev ( void ) {
17
+	struct net_device *boot_netdev;
18
+
19
+	/* Just use the first network device */
20
+	for_each_netdev ( boot_netdev ) {
21
+		return boot_netdev;
22
+	}
23
+
24
+	return NULL;
25
+}
26
+
27
+int aoeboot ( const char *root_path ) {
28
+	struct ata_device ata;
29
+	struct int13_drive drive;
30
+	int rc;
31
+
32
+	memset ( &ata, 0, sizeof ( ata ) );
33
+	memset ( &drive, 0, sizeof ( drive ) );
34
+
35
+	printf ( "AoE booting from %s\n", root_path );
36
+
37
+	/* FIXME: ugly, ugly hack */
38
+	struct net_device *netdev = guess_boot_netdev();
39
+
40
+	if ( ( rc = aoe_attach ( &ata, netdev, root_path ) ) != 0 ) {
41
+		printf ( "Could not attach AoE device: %s\n",
42
+			 strerror ( rc ) );
43
+		goto error_attach;
44
+	}
45
+	if ( ( rc = init_atadev ( &ata ) ) != 0 ) {
46
+		printf ( "Could not initialise AoE device: %s\n",
47
+			 strerror ( rc ) );
48
+		goto error_init;
49
+	}
50
+
51
+	drive.drive = find_global_dhcp_num_option ( DHCP_EB_BIOS_DRIVE );
52
+	drive.blockdev = &ata.blockdev;
53
+
54
+	register_int13_drive ( &drive );
55
+	printf ( "Registered as BIOS drive %#02x\n", drive.drive );
56
+	printf ( "Booting from BIOS drive %#02x\n", drive.drive );
57
+	rc = int13_boot ( drive.drive );
58
+	printf ( "Boot failed\n" );
59
+
60
+	printf ( "Unregistering BIOS drive %#02x\n", drive.drive );
61
+	unregister_int13_drive ( &drive );
62
+
63
+ error_init:
64
+	aoe_detach ( &ata );
65
+ error_attach:
66
+	return rc;
67
+}

+ 7
- 4
src/usr/autoboot.c ファイルの表示

@@ -27,6 +27,7 @@
27 27
 #include <usr/dhcpmgmt.h>
28 28
 #include <usr/imgmgmt.h>
29 29
 #include <usr/iscsiboot.h>
30
+#include <usr/aoeboot.h>
30 31
 #include <usr/autoboot.h>
31 32
 
32 33
 /** @file
@@ -88,13 +89,15 @@ static int boot_filename ( const char *filename ) {
88 89
  * @ret rc		Return status code
89 90
  */
90 91
 static int boot_root_path ( const char *root_path ) {
91
-	int rc;
92 92
 
93 93
 	/* Quick hack */
94
-	if ( ( rc = iscsiboot ( root_path ) ) != 0 )
95
-		return rc;
94
+	if ( strncmp ( root_path, "iscsi:", 6 ) == 0 ) {
95
+		return iscsiboot ( root_path );
96
+	} else if ( strncmp ( root_path, "aoe:", 4 ) == 0 ) {
97
+		return aoeboot ( root_path );
98
+	}
96 99
 
97
-	return 0;
100
+	return -ENOTSUP;
98 101
 }
99 102
 
100 103
 /**

読み込み中…
キャンセル
保存