Browse Source

[interface] Convert all job-control interfaces to generic interfaces

Remove job-control as an interface type, and replace job-control
interfaces with generic interfaces supporting the close() method.
(Both done() and kill() are absorbed into the function of close();
kill() is merely close(-ECANCELED).)

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 16 years ago
parent
commit
a03dd97e6b

+ 30
- 39
src/core/downloader.c View File

@@ -41,7 +41,7 @@ struct downloader {
41 41
 	struct refcnt refcnt;
42 42
 
43 43
 	/** Job control interface */
44
-	struct job_interface job;
44
+	struct interface job;
45 45
 	/** Data transfer interface */
46 46
 	struct xfer_interface xfer;
47 47
 
@@ -74,13 +74,14 @@ static void downloader_free ( struct refcnt *refcnt ) {
74 74
  */
75 75
 static void downloader_finished ( struct downloader *downloader, int rc ) {
76 76
 
77
-	/* Block further incoming messages */
78
-	job_nullify ( &downloader->job );
79
-	xfer_nullify ( &downloader->xfer );
77
+	/* Register image if download was successful */
78
+	if ( rc == 0 )
79
+		rc = downloader->register_image ( downloader->image );
80 80
 
81
-	/* Free resources and close interfaces */
81
+	/* Shut down interfaces */
82
+	xfer_nullify ( &downloader->xfer );
82 83
 	xfer_close ( &downloader->xfer, rc );
83
-	job_done ( &downloader->job, rc );
84
+	intf_shutdown ( &downloader->job, rc );
84 85
 }
85 86
 
86 87
 /**
@@ -120,29 +121,14 @@ static int downloader_ensure_size ( struct downloader *downloader,
120 121
  *
121 122
  */
122 123
 
123
-/**
124
- * Handle kill() event received via job control interface
125
- *
126
- * @v job		Downloader job control interface
127
- */
128
-static void downloader_job_kill ( struct job_interface *job ) {
129
-	struct downloader *downloader =
130
-		container_of ( job, struct downloader, job );
131
-
132
-	/* Terminate download */
133
-	downloader_finished ( downloader, -ECANCELED );
134
-}
135
-
136 124
 /**
137 125
  * Report progress of download job
138 126
  *
139
- * @v job		Downloader job control interface
127
+ * @v downloader	Downloader
140 128
  * @v progress		Progress report to fill in
141 129
  */
142
-static void downloader_job_progress ( struct job_interface *job,
143
-				      struct job_progress *progress ) {
144
-	struct downloader *downloader =
145
-		container_of ( job, struct downloader, job );
130
+static void downloader_progress ( struct downloader *downloader,
131
+				  struct job_progress *progress ) {
146 132
 
147 133
 	/* This is not entirely accurate, since downloaded data may
148 134
 	 * arrive out of order (e.g. with multicast protocols), but
@@ -152,13 +138,6 @@ static void downloader_job_progress ( struct job_interface *job,
152 138
 	progress->total = downloader->image->len;
153 139
 }
154 140
 
155
-/** Downloader job control interface operations */
156
-static struct job_interface_operations downloader_job_operations = {
157
-	.done		= ignore_job_done,
158
-	.kill		= downloader_job_kill,
159
-	.progress	= downloader_job_progress,
160
-};
161
-
162 141
 /****************************************************************************
163 142
  *
164 143
  * Data transfer interface
@@ -215,10 +194,6 @@ static void downloader_xfer_close ( struct xfer_interface *xfer, int rc ) {
215 194
 	struct downloader *downloader =
216 195
 		container_of ( xfer, struct downloader, xfer );
217 196
 
218
-	/* Register image if download was successful */
219
-	if ( rc == 0 )
220
-		rc = downloader->register_image ( downloader->image );
221
-
222 197
 	/* Terminate download */
223 198
 	downloader_finished ( downloader, rc );
224 199
 }
@@ -233,6 +208,22 @@ static struct xfer_interface_operations downloader_xfer_operations = {
233 208
 	.deliver_raw	= xfer_deliver_as_iob,
234 209
 };
235 210
 
211
+/****************************************************************************
212
+ *
213
+ * Job control interface
214
+ *
215
+ */
216
+
217
+/** Downloader job control interface operations */
218
+static struct interface_operation downloader_job_op[] = {
219
+	INTF_OP ( job_progress, struct downloader *, downloader_progress ),
220
+	INTF_OP ( intf_close, struct downloader *, downloader_finished ),
221
+};
222
+
223
+/** Downloader job control interface descriptor */
224
+static struct interface_descriptor downloader_job_desc =
225
+	INTF_DESC ( struct downloader, job, downloader_job_op );
226
+
236 227
 /****************************************************************************
237 228
  *
238 229
  * Instantiator
@@ -253,7 +244,7 @@ static struct xfer_interface_operations downloader_xfer_operations = {
253 244
  * the specified image object.  If the download is successful, the
254 245
  * image registration routine @c register_image() will be called.
255 246
  */
256
-int create_downloader ( struct job_interface *job, struct image *image,
247
+int create_downloader ( struct interface *job, struct image *image,
257 248
 			int ( * register_image ) ( struct image *image ),
258 249
 			int type, ... ) {
259 250
 	struct downloader *downloader;
@@ -265,8 +256,8 @@ int create_downloader ( struct job_interface *job, struct image *image,
265 256
 	if ( ! downloader )
266 257
 		return -ENOMEM;
267 258
 	ref_init ( &downloader->refcnt, downloader_free );
268
-	job_init ( &downloader->job, &downloader_job_operations,
269
-		   &downloader->refcnt );
259
+	intf_init ( &downloader->job, &downloader_job_desc,
260
+		    &downloader->refcnt );
270 261
 	xfer_init ( &downloader->xfer, &downloader_xfer_operations,
271 262
 		    &downloader->refcnt );
272 263
 	downloader->image = image_get ( image );
@@ -278,7 +269,7 @@ int create_downloader ( struct job_interface *job, struct image *image,
278 269
 		goto err;
279 270
 
280 271
 	/* Attach parent interface, mortalise self, and return */
281
-	job_plug_plug ( &downloader->job, job );
272
+	intf_plug_plug ( &downloader->job, job );
282 273
 	ref_put ( &downloader->refcnt );
283 274
 	va_end ( args );
284 275
 	return 0;

+ 21
- 64
src/core/job.c View File

@@ -28,70 +28,27 @@ FILE_LICENCE ( GPL2_OR_LATER );
28 28
  *
29 29
  */
30 30
 
31
-void job_done ( struct job_interface *job, int rc ) {
32
-	struct job_interface *dest = job_get_dest ( job );
33
-
34
-	job_unplug ( job );
35
-	dest->op->done ( dest, rc );
36
-	job_put ( dest );
37
-}
38
-
39
-void job_kill ( struct job_interface *job ) {
40
-	struct job_interface *dest = job_get_dest ( job );
41
-
42
-	job_unplug ( job );
43
-	dest->op->kill ( dest );
44
-	job_put ( dest );
45
-}
46
-
47
-void job_progress ( struct job_interface *job,
48
-		    struct job_progress *progress ) {
49
-	struct job_interface *dest = job_get_dest ( job );
50
-
51
-	dest->op->progress ( dest, progress );
52
-	job_put ( dest );
53
-}
54
-
55
-/****************************************************************************
56
- *
57
- * Helper methods
58
- *
59
- * These functions are designed to be used as methods in the
60
- * job_interface_operations table.
61
- *
62
- */
63
-
64
-void ignore_job_done ( struct job_interface *job __unused, int rc __unused ) {
65
-	/* Nothing to do */
66
-}
67
-
68
-void ignore_job_kill ( struct job_interface *job __unused ) {
69
-	/* Nothing to do */
70
-}
71
-
72
-void ignore_job_progress ( struct job_interface *job __unused,
73
-			   struct job_progress *progress ) {
74
-	memset ( progress, 0, sizeof ( *progress ) );
75
-}
76
-
77
-/** Null job control interface operations */
78
-struct job_interface_operations null_job_ops = {
79
-	.done		= ignore_job_done,
80
-	.kill		= ignore_job_kill,
81
-	.progress	= ignore_job_progress,
82
-};
83
-
84 31
 /**
85
- * Null job control interface
32
+ * Get job progress
86 33
  *
87
- * This is the interface to which job control interfaces are connected
88
- * when unplugged.  It will never generate messages, and will silently
89
- * absorb all received messages.
34
+ * @v intf		Object interface
35
+ * @v progress		Progress data to fill in
90 36
  */
91
-struct job_interface null_job = {
92
-	.intf = {
93
-		.dest = &null_job.intf,
94
-		.refcnt = NULL,
95
-	},
96
-	.op = &null_job_ops,
97
-};
37
+void job_progress ( struct interface *intf, struct job_progress *progress ) {
38
+	struct interface *dest;
39
+	job_progress_TYPE ( void * ) *op =
40
+		intf_get_dest_op ( intf, job_progress, &dest );
41
+	void *object = intf_object ( dest );
42
+
43
+	DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " job_progress\n",
44
+	       INTF_INTF_DBG ( intf, dest ) );
45
+
46
+	if ( op ) {
47
+		op ( object, progress );
48
+	} else {
49
+		/* Default is to mark progress as zero */
50
+		memset ( progress, 0, sizeof ( *progress ) );
51
+	}
52
+
53
+	intf_put ( dest );
54
+}

+ 10
- 19
src/core/monojob.c View File

@@ -36,25 +36,19 @@ FILE_LICENCE ( GPL2_OR_LATER );
36 36
 
37 37
 static int monojob_rc;
38 38
 
39
-static void monojob_done ( struct job_interface *job __unused, int rc ) {
39
+static void monojob_close ( struct interface *intf, int rc ) {
40 40
 	monojob_rc = rc;
41
+	intf_restart ( intf, rc );
41 42
 }
42 43
 
43
-/** Single foreground job operations */
44
-static struct job_interface_operations monojob_operations = {
45
-	.done		= monojob_done,
46
-	.kill		= ignore_job_kill,
47
-	.progress	= ignore_job_progress,
44
+static struct interface_operation monojob_intf_op[] = {
45
+	INTF_OP ( intf_close, struct interface *, monojob_close ),
48 46
 };
49 47
 
50
-/** Single foreground job */
51
-struct job_interface monojob = {
52
-	.intf = {
53
-		.dest = &null_job.intf,
54
-		.refcnt = NULL,
55
-	},
56
-	.op = &monojob_operations,
57
-};
48
+static struct interface_descriptor monojob_intf_desc =
49
+	INTF_DESC_PURE ( monojob_intf_op );
50
+
51
+struct interface monojob = INTF_INIT ( monojob_intf_desc );
58 52
 
59 53
 /**
60 54
  * Wait for single foreground job to complete
@@ -77,9 +71,8 @@ int monojob_wait ( const char *string ) {
77 71
 			key = getchar();
78 72
 			switch ( key ) {
79 73
 			case CTRL_C:
80
-				job_kill ( &monojob );
81
-				rc = -ECANCELED;
82
-				goto done;
74
+				monojob_close ( &monojob, -ECANCELED );
75
+				break;
83 76
 			default:
84 77
 				break;
85 78
 			}
@@ -92,8 +85,6 @@ int monojob_wait ( const char *string ) {
92 85
 	}
93 86
 	rc = monojob_rc;
94 87
 
95
-done:
96
-	job_done ( &monojob, rc );
97 88
 	if ( rc ) {
98 89
 		printf ( " %s\n", strerror ( rc ) );
99 90
 	} else {

+ 3
- 3
src/include/ipxe/dhcp.h View File

@@ -18,7 +18,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
18 18
 #include <ipxe/netdevice.h>
19 19
 #include <ipxe/uaccess.h>
20 20
 
21
-struct job_interface;
21
+struct interface;
22 22
 struct dhcp_options;
23 23
 struct dhcp_packet;
24 24
 
@@ -622,8 +622,8 @@ extern int dhcp_create_request ( struct dhcp_packet *dhcppkt,
622 622
 				 struct net_device *netdev,
623 623
 				 unsigned int msgtype, struct in_addr ciaddr,
624 624
 				 void *data, size_t max_len );
625
-extern int start_dhcp ( struct job_interface *job, struct net_device *netdev );
626
-extern int start_pxebs ( struct job_interface *job, struct net_device *netdev,
625
+extern int start_dhcp ( struct interface *job, struct net_device *netdev );
626
+extern int start_pxebs ( struct interface *job, struct net_device *netdev,
627 627
 			 unsigned int pxe_type );
628 628
 
629 629
 /* In environments that can provide cached DHCP packets, this function

+ 2
- 2
src/include/ipxe/downloader.h View File

@@ -9,10 +9,10 @@
9 9
 
10 10
 FILE_LICENCE ( GPL2_OR_LATER );
11 11
 
12
-struct job_interface;
12
+struct interface;
13 13
 struct image;
14 14
 
15
-extern int create_downloader ( struct job_interface *job, struct image *image,
15
+extern int create_downloader ( struct interface *job, struct image *image,
16 16
 			       int ( * register_image ) ( struct image *image ),
17 17
 			       int type, ... );
18 18
 

+ 3
- 134
src/include/ipxe/job.h View File

@@ -9,7 +9,6 @@
9 9
 
10 10
 FILE_LICENCE ( GPL2_OR_LATER );
11 11
 
12
-#include <stddef.h>
13 12
 #include <ipxe/interface.h>
14 13
 
15 14
 /** Job progress */
@@ -31,139 +30,9 @@ struct job_progress {
31 30
 	unsigned long total;
32 31
 };
33 32
 
34
-struct job_interface;
35
-
36
-/** Job control interface operations */
37
-struct job_interface_operations {
38
-	/** Job completed
39
-	 *
40
-	 * @v job		Job control interface
41
-	 * @v rc		Overall job status code
42
-	 */
43
-	void ( * done ) ( struct job_interface *job, int rc );
44
-	/** Abort job
45
-	 *
46
-	 * @v job		Job control interface
47
-	 */
48
-	void ( * kill ) ( struct job_interface *job );
49
-	/** Get job progress
50
-	 *
51
-	 * @v job		Job control interface
52
-	 * @v progress		Progress data to fill in
53
-	 */
54
-	void ( * progress ) ( struct job_interface *job,
55
-			      struct job_progress *progress );
56
-};
57
-
58
-/** A job control interface */
59
-struct job_interface {
60
-	/** Generic object communication interface */
61
-	struct interface intf;
62
-	/** Operations for received messages */
63
-	struct job_interface_operations *op;
64
-};
65
-
66
-extern struct job_interface null_job;
67
-extern struct job_interface_operations null_job_ops;
68
-
69
-extern void job_done ( struct job_interface *job, int rc );
70
-extern void job_kill ( struct job_interface *job );
71
-extern void job_progress ( struct job_interface *job,
33
+extern void job_progress ( struct interface *intf,
72 34
 			   struct job_progress *progress );
73
-
74
-extern void ignore_job_done ( struct job_interface *job, int rc );
75
-extern void ignore_job_kill ( struct job_interface *job );
76
-extern void ignore_job_progress ( struct job_interface *job,
77
-				  struct job_progress *progress );
78
-
79
-/**
80
- * Initialise a job control interface
81
- *
82
- * @v job		Job control interface
83
- * @v op		Job control interface operations
84
- * @v refcnt		Containing object reference counter, or NULL
85
- */
86
-static inline void job_init ( struct job_interface *job,
87
-			      struct job_interface_operations *op,
88
-			      struct refcnt *refcnt ) {
89
-	job->intf.dest = &null_job.intf;
90
-	job->intf.refcnt = refcnt;
91
-	job->op = op;
92
-}
93
-
94
-/**
95
- * Get job control interface from generic object communication interface
96
- *
97
- * @v intf		Generic object communication interface
98
- * @ret job		Job control interface
99
- */
100
-static inline __attribute__ (( always_inline )) struct job_interface *
101
-intf_to_job ( struct interface *intf ) {
102
-	return container_of ( intf, struct job_interface, intf );
103
-}
104
-
105
-/**
106
- * Get reference to destination job control interface
107
- *
108
- * @v job		Job control interface
109
- * @ret dest		Destination interface
110
- */
111
-static inline __attribute__ (( always_inline )) struct job_interface *
112
-job_get_dest ( struct job_interface *job ) {
113
-	return intf_to_job ( intf_get ( job->intf.dest ) );
114
-}
115
-
116
-/**
117
- * Drop reference to job control interface
118
- *
119
- * @v job		Job control interface
120
- */
121
-static inline __attribute__ (( always_inline )) void
122
-job_put ( struct job_interface *job ) {
123
-	intf_put ( &job->intf );
124
-}
125
-
126
-/**
127
- * Plug a job control interface into a new destination interface
128
- *
129
- * @v job		Job control interface
130
- * @v dest		New destination interface
131
- */
132
-static inline void job_plug ( struct job_interface *job,
133
-			       struct job_interface *dest ) {
134
-	intf_plug ( &job->intf, &dest->intf );
135
-}
136
-
137
-/**
138
- * Plug two job control interfaces together
139
- *
140
- * @v a			Job control interface A
141
- * @v b			Job control interface B
142
- */
143
-static inline void job_plug_plug ( struct job_interface *a,
144
-				    struct job_interface *b ) {
145
-	intf_plug_plug ( &a->intf, &b->intf );
146
-}
147
-
148
-/**
149
- * Unplug a job control interface
150
- *
151
- * @v job		Job control interface
152
- */
153
-static inline void job_unplug ( struct job_interface *job ) {
154
-	intf_plug ( &job->intf, &null_job.intf );
155
-}
156
-
157
-/**
158
- * Stop using a job control interface
159
- *
160
- * @v job		Job control interface
161
- *
162
- * After calling this method, no further messages will be received via
163
- * the interface.
164
- */
165
-static inline void job_nullify ( struct job_interface *job ) {
166
-	job->op = &null_job_ops;
167
-};
35
+#define job_progress_TYPE( object_type ) \
36
+	typeof ( void ( object_type, struct job_progress *progress ) )
168 37
 
169 38
 #endif /* _IPXE_JOB_H */

+ 3
- 2
src/include/ipxe/monojob.h View File

@@ -9,9 +9,10 @@
9 9
 
10 10
 FILE_LICENCE ( GPL2_OR_LATER );
11 11
 
12
-struct job_interface;
12
+struct interface;
13
+
14
+extern struct interface monojob;
13 15
 
14
-extern struct job_interface monojob;
15 16
 extern int monojob_wait ( const char *string );
16 17
 
17 18
 #endif /* _IPXE_MONOJOB_H */

+ 16
- 30
src/net/udp/dhcp.c View File

@@ -238,7 +238,7 @@ struct dhcp_session {
238 238
 	/** Reference counter */
239 239
 	struct refcnt refcnt;
240 240
 	/** Job control interface */
241
-	struct job_interface job;
241
+	struct interface job;
242 242
 	/** Data transfer interface */
243 243
 	struct xfer_interface xfer;
244 244
 
@@ -294,16 +294,13 @@ static void dhcp_free ( struct refcnt *refcnt ) {
294 294
  */
295 295
 static void dhcp_finished ( struct dhcp_session *dhcp, int rc ) {
296 296
 
297
-	/* Block futher incoming messages */
298
-	job_nullify ( &dhcp->job );
299
-	xfer_nullify ( &dhcp->xfer );
300
-
301 297
 	/* Stop retry timer */
302 298
 	stop_timer ( &dhcp->timer );
303 299
 
304
-	/* Free resources and close interfaces */
300
+	/* Shut down interfaces */
301
+	xfer_nullify ( &dhcp->xfer );
305 302
 	xfer_close ( &dhcp->xfer, rc );
306
-	job_done ( &dhcp->job, rc );
303
+	intf_shutdown ( &dhcp->job, rc );
307 304
 }
308 305
 
309 306
 /**
@@ -1366,26 +1363,15 @@ static void dhcp_timer_expired ( struct retry_timer *timer, int fail ) {
1366 1363
  *
1367 1364
  */
1368 1365
 
1369
-/**
1370
- * Handle kill() event received via job control interface
1371
- *
1372
- * @v job		DHCP job control interface
1373
- */
1374
-static void dhcp_job_kill ( struct job_interface *job ) {
1375
-	struct dhcp_session *dhcp =
1376
-		container_of ( job, struct dhcp_session, job );
1377
-
1378
-	/* Terminate DHCP session */
1379
-	dhcp_finished ( dhcp, -ECANCELED );
1380
-}
1381
-
1382 1366
 /** DHCP job control interface operations */
1383
-static struct job_interface_operations dhcp_job_operations = {
1384
-	.done		= ignore_job_done,
1385
-	.kill		= dhcp_job_kill,
1386
-	.progress	= ignore_job_progress,
1367
+static struct interface_operation dhcp_job_op[] = {
1368
+	INTF_OP ( intf_close, struct dhcp_session *, dhcp_finished ),
1387 1369
 };
1388 1370
 
1371
+/** DHCP job control interface descriptor */
1372
+static struct interface_descriptor dhcp_job_desc =
1373
+	INTF_DESC ( struct dhcp_session, job, dhcp_job_op );
1374
+
1389 1375
 /****************************************************************************
1390 1376
  *
1391 1377
  * Instantiators
@@ -1424,7 +1410,7 @@ __weak void get_cached_dhcpack ( void ) {}
1424 1410
  * started; a positive return value indicates the success condition of
1425 1411
  * having fetched the appropriate data from cached information.
1426 1412
  */
1427
-int start_dhcp ( struct job_interface *job, struct net_device *netdev ) {
1413
+int start_dhcp ( struct interface *job, struct net_device *netdev ) {
1428 1414
 	struct dhcp_session *dhcp;
1429 1415
 	int rc;
1430 1416
 
@@ -1440,7 +1426,7 @@ int start_dhcp ( struct job_interface *job, struct net_device *netdev ) {
1440 1426
 	if ( ! dhcp )
1441 1427
 		return -ENOMEM;
1442 1428
 	ref_init ( &dhcp->refcnt, dhcp_free );
1443
-	job_init ( &dhcp->job, &dhcp_job_operations, &dhcp->refcnt );
1429
+	intf_init ( &dhcp->job, &dhcp_job_desc, &dhcp->refcnt );
1444 1430
 	xfer_init ( &dhcp->xfer, &dhcp_xfer_operations, &dhcp->refcnt );
1445 1431
 	timer_init ( &dhcp->timer, dhcp_timer_expired );
1446 1432
 	dhcp->netdev = netdev_get ( netdev );
@@ -1456,7 +1442,7 @@ int start_dhcp ( struct job_interface *job, struct net_device *netdev ) {
1456 1442
 	dhcp_set_state ( dhcp, &dhcp_state_discover );
1457 1443
 
1458 1444
 	/* Attach parent interface, mortalise self, and return */
1459
-	job_plug_plug ( &dhcp->job, job );
1445
+	intf_plug_plug ( &dhcp->job, job );
1460 1446
 	ref_put ( &dhcp->refcnt );
1461 1447
 	return 0;
1462 1448
 
@@ -1517,7 +1503,7 @@ static void pxebs_list ( struct dhcp_session *dhcp, void *raw,
1517 1503
  * If successful, the Boot Server ACK will be registered as an option
1518 1504
  * source.
1519 1505
  */
1520
-int start_pxebs ( struct job_interface *job, struct net_device *netdev,
1506
+int start_pxebs ( struct interface *job, struct net_device *netdev,
1521 1507
 		  unsigned int pxe_type ) {
1522 1508
 	struct setting pxe_discovery_control_setting =
1523 1509
 		{ .tag = DHCP_PXE_DISCOVERY_CONTROL };
@@ -1543,7 +1529,7 @@ int start_pxebs ( struct job_interface *job, struct net_device *netdev,
1543 1529
 	if ( ! dhcp )
1544 1530
 		return -ENOMEM;
1545 1531
 	ref_init ( &dhcp->refcnt, dhcp_free );
1546
-	job_init ( &dhcp->job, &dhcp_job_operations, &dhcp->refcnt );
1532
+	intf_init ( &dhcp->job, &dhcp_job_desc, &dhcp->refcnt );
1547 1533
 	xfer_init ( &dhcp->xfer, &dhcp_xfer_operations, &dhcp->refcnt );
1548 1534
 	timer_init ( &dhcp->timer, dhcp_timer_expired );
1549 1535
 	dhcp->netdev = netdev_get ( netdev );
@@ -1602,7 +1588,7 @@ int start_pxebs ( struct job_interface *job, struct net_device *netdev,
1602 1588
 	dhcp_set_state ( dhcp, &dhcp_state_pxebs );
1603 1589
 
1604 1590
 	/* Attach parent interface, mortalise self, and return */
1605
-	job_plug_plug ( &dhcp->job, job );
1591
+	intf_plug_plug ( &dhcp->job, job );
1606 1592
 	ref_put ( &dhcp->refcnt );
1607 1593
 	return 0;
1608 1594
 

Loading…
Cancel
Save