Print this page
2882 implement libzfs_core
2883 changing "canmount" property to "on" should not always remount dataset
2900 "zfs snapshot" should be able to create multiple, arbitrary snapshots at once
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Chris Siden <christopher.siden@delphix.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Bill Pijewski <wdp@joyent.com>
Reviewed by: Dan Kruchinin <dan.kruchinin@gmail.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/Makefile
+++ new/usr/src/lib/Makefile
1 1 #
2 2 # CDDL HEADER START
3 3 #
4 4 # The contents of this file are subject to the terms of the
5 5 # Common Development and Distribution License (the "License").
6 6 # You may not use this file except in compliance with the License.
7 7 #
8 8 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 # or http://www.opensolaris.org/os/licensing.
10 10 # See the License for the specific language governing permissions
11 11 # and limitations under the License.
12 12 #
13 13 # When distributing Covered Code, include this CDDL HEADER in each
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 # If applicable, add the following below this CDDL HEADER, with the
16 16 # fields enclosed by brackets "[]" replaced with your own identifying
17 17 # information: Portions Copyright [yyyy] [name of copyright owner]
18 18 #
19 19 # CDDL HEADER END
20 20 #
21 21
22 22 # Copyright 2011 Nexenta Systems, Inc. All rights reserved.
23 23 # Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24 +# Copyright (c) 2012 by Delphix. All rights reserved.
24 25
25 26 include ../Makefile.master
26 27
27 28 # Note that libcurses installs commands along with its library.
28 29 # This is a minor bug which probably should be fixed.
29 30 # Note also that a few extra libraries are kept in cmd source.
30 31 #
31 32 # Certain libraries are linked with, hence depend on, other libraries.
32 33 #
33 34 # Although we have historically used .WAIT to express dependencies, it
34 35 # reduces the amount of parallelism and thus lengthens the time it
35 36 # takes to build the libraries. Thus, we now require that any new
36 37 # libraries explicitly call out their dependencies. Eventually, all
37 38 # the library dependencies will be called out explicitly. See
38 39 # "Library interdependencies" near the end of this file.
39 40 #
40 41 # Aside from explicit dependencies (and legacy .WAITs), all libraries
41 42 # are built in parallel.
42 43 #
43 44 .PARALLEL:
44 45
45 46 #
46 47 # The $(CLOSED_BUILD) additions to SUBDIRS & MSGSUBDIRS are unfortunate,
47 48 # but required due to the "dependencies" of using .WAIT to barrier the
48 49 # parallel dmake builds. once 4631488 has been fixed, they can be
49 50 # consolidated into one $(CLOSED_BUILD)SUBDIRS += (all closed libs) as
50 51 # shown in HDRSUBDIRS
51 52 #
52 53 SUBDIRS= \
53 54 common .WAIT \
54 55 ../cmd/sgs/libconv \
55 56 ../cmd/sgs/libdl .WAIT
56 57
57 58 SUBDIRS += \
58 59 libc .WAIT \
59 60 ../cmd/sgs/libelf .WAIT \
60 61 c_synonyms \
61 62 libmd \
62 63 libmd5 \
63 64 librsm \
64 65 libmp .WAIT \
65 66 libnsl \
66 67 libsecdb .WAIT \
67 68 librpcsvc \
68 69 libsocket .WAIT \
69 70 libsctp \
70 71 libsip \
71 72 libcommputil \
72 73 libresolv \
73 74 libresolv2 .WAIT \
74 75 libw .WAIT \
75 76 libintl .WAIT \
76 77 ../cmd/sgs/librtld_db \
77 78 libaio \
78 79 libast \
79 80 libdll \
80 81 libcmd \
81 82 libshell \
82 83 libsum \
83 84 librt \
84 85 libadm \
85 86 libctf \
86 87 libdtrace \
87 88 libdtrace_jni \
88 89 libcurses \
89 90 libtermcap \
90 91 libgen \
91 92 libgss \
92 93 libpam \
93 94 libuuid \
94 95 libthread \
95 96 libpthread .WAIT \
96 97 libslp \
97 98 libbsdmalloc \
98 99 libdoor \
99 100 libdevinfo \
100 101 libdladm \
101 102 libdlpi \
102 103 libeti \
103 104 libcrypt \
104 105 libdns_sd \
105 106 libefi \
106 107 libfstyp \
107 108 libwanboot \
108 109 libwanbootutil \
109 110 libcryptoutil \
110 111 libinetutil \
111 112 libipadm \
112 113 libipmp \
113 114 libiscsit \
114 115 libkmf \
115 116 libkstat \
116 117 libkvm \
117 118 liblm \
118 119 libmalloc \
119 120 libmapmalloc \
120 121 libmtmalloc \
121 122 libnls \
122 123 libnwam \
123 124 libsmbios \
124 125 libtecla \
125 126 libumem \
126 127 libnvpair .WAIT \
127 128 libexacct \
128 129 libsasl \
129 130 libldap5 \
130 131 libsldap .WAIT \
131 132 libbsm \
132 133 libsys \
133 134 libsysevent \
134 135 libnisdb \
135 136 libpool \
136 137 libpp \
137 138 libproc \
138 139 libproject \
139 140 libsendfile \
140 141 nametoaddr \
141 142 ncad_addr \
142 143 hbaapi \
143 144 smhba \
144 145 sun_fc \
145 146 sun_sas \
146 147 gss_mechs/mech_krb5 .WAIT \
147 148 libkrb5 .WAIT \
148 149 krb5 .WAIT \
149 150 libsmbfs \
150 151 libfcoe \
151 152 libsrpt \
152 153 libstmf \
153 154 libstmfproxy \
154 155 libnsctl \
155 156 libunistat \
156 157 libdscfg \
157 158 librdc \
158 159 libinstzones \
159 160 libpkg
160 161
161 162 SUBDIRS += \
162 163 passwdutil \
163 164 pam_modules \
164 165 crypt_modules \
165 166 libadt_jni \
166 167 abi \
167 168 auditd_plugins \
168 169 libvolmgt \
169 170 libdevice \
170 171 libdevid \
171 172 libdhcpsvc \
172 173 libc_db \
173 174 libndmp \
174 175 libsec \
175 176 libtnfprobe \
176 177 libtnf \
177 178 libtnfctl \
178 179 libdhcpagent \
179 180 libdhcpdu \
180 181 libdhcputil \
181 182 libxnet \
182 183 libipsecutil
183 184 $(CLOSED_BUILD)SUBDIRS += \
184 185 $(CLOSED)/lib/libike
185 186 SUBDIRS += \
186 187 nsswitch \
187 188 print \
188 189 libuutil \
189 190 libscf \
190 191 libinetsvc \
191 192 librestart \
192 193 libsched \
193 194 libelfsign \
194 195 pkcs11 .WAIT \
195 196 libpctx .WAIT \
196 197 libcpc \
197 198 watchmalloc \
198 199 extendedFILE \
199 200 madv \
200 201 mpss \
201 202 libdisasm \
202 203 libwrap \
203 204 libxcurses \
204 205 libxcurses2 \
205 206 libbrand .WAIT \
206 207 libzonecfg \
207 208 libzoneinfo \
208 209 libzonestat \
209 210 libtsnet \
210 211 libtsol \
211 212 gss_mechs/mech_spnego \
212 213 gss_mechs/mech_dummy \
213 214 gss_mechs/mech_dh \
214 215 rpcsec_gss \
215 216 libraidcfg .WAIT \
216 217 librcm .WAIT \
217 218 libcfgadm .WAIT \
218 219 libpicl .WAIT \
219 220 libpicltree .WAIT \
220 221 raidcfg_plugins \
221 222 cfgadm_plugins \
222 223 libmail \
223 224 lvm \
224 225 libsmedia \
225 226 libipp \
226 227 libdiskmgt \
↓ open down ↓ |
193 lines elided |
↑ open up ↑ |
227 228 liblgrp \
228 229 libfsmgt \
229 230 fm \
230 231 libavl \
231 232 libcmdutils \
232 233 libcontract \
233 234 ../cmd/sendmail/libmilter \
234 235 sasl_plugins \
235 236 udapl \
236 237 libzpool \
238 + libzfs_core \
237 239 libzfs \
238 - libbe \
239 - pylibbe \
240 + libbe \
241 + pylibbe \
240 242 libzfs_jni \
241 243 pyzfs \
242 244 pysolaris \
243 245 libmapid \
244 246 brand \
245 247 policykit \
246 248 hal \
247 249 libshare \
248 250 libsqlite \
249 251 libidmap \
250 252 libadutils \
251 253 libipmi \
252 254 libexacct/demo \
253 255 libvrrpadm \
254 256 libvscan \
255 257 libgrubmgmt \
256 258 smbsrv \
257 259 libilb \
258 260 scsi \
259 261 libima \
260 262 libsun_ima \
261 263 mpapi \
262 264 librstp \
263 265 libreparse \
264 266 libhotplug \
265 267 libfruutils .WAIT \
266 268 libfru \
267 269 $($(MACH)_SUBDIRS)
268 270
269 271 i386_SUBDIRS= \
270 272 libntfs \
271 273 libparted \
272 274 libfdisk
273 275
274 276 sparc_SUBDIRS= .WAIT \
275 277 efcode \
276 278 libds \
277 279 libdscp \
278 280 libprtdiag .WAIT \
279 281 libprtdiag_psr \
280 282 libpri \
281 283 librsc \
282 284 storage \
283 285 libpcp \
284 286 libtsalarm \
285 287 libv12n
286 288
287 289 FM_sparc_DEPLIBS= libpri
288 290
289 291 fm: \
290 292 libexacct \
291 293 libipmi \
292 294 libzfs \
293 295 scsi \
294 296 $(FM_$(MACH)_DEPLIBS)
295 297
296 298 #
297 299 # Create a special version of $(SUBDIRS) with no .WAIT's, for use with the
298 300 # clean and clobber targets (for more information, see those targets, below).
299 301 #
300 302 NOWAIT_SUBDIRS= $(SUBDIRS:.WAIT=)
301 303
302 304 DCSUBDIRS = \
303 305 lvm
304 306
305 307 MSGSUBDIRS= \
306 308 abi \
307 309 auditd_plugins \
308 310 brand \
309 311 cfgadm_plugins \
310 312 gss_mechs/mech_dh \
311 313 gss_mechs/mech_krb5 \
312 314 krb5 \
313 315 libast \
314 316 libbsm \
315 317 libc \
316 318 libcfgadm \
317 319 libcmd \
318 320 libcontract \
319 321 libcurses \
320 322 libdhcpsvc \
321 323 libdhcputil \
322 324 libipsecutil \
323 325 libdiskmgt \
324 326 libdladm \
325 327 libdll \
326 328 libgrubmgmt \
327 329 libgss \
328 330 libidmap \
329 331 libipmp \
330 332 libilb \
331 333 libinetutil \
332 334 libinstzones \
333 335 libipadm \
334 336 libnsl \
335 337 libnwam \
336 338 libpam \
337 339 libpicl \
338 340 libpool \
339 341 libpkg \
340 342 libpp \
341 343 libscf \
342 344 libsasl \
343 345 libldap5 \
344 346 libsecdb \
345 347 libshare \
346 348 libshell \
347 349 libsldap \
348 350 libslp \
349 351 libsmbfs \
350 352 libsmedia \
351 353 libsum \
352 354 libtsol \
353 355 libuutil \
354 356 libvrrpadm \
355 357 libvscan \
356 358 libwanboot \
357 359 libwanbootutil \
358 360 libzfs \
359 361 libzonecfg \
360 362 lvm \
361 363 madv \
362 364 mpss \
363 365 pam_modules \
364 366 pyzfs \
365 367 pysolaris \
366 368 rpcsec_gss \
367 369 libreparse
368 370 MSGSUBDIRS += \
369 371 $($(MACH)_MSGSUBDIRS)
370 372
371 373 sparc_MSGSUBDIRS= \
372 374 libprtdiag \
373 375 libprtdiag_psr
374 376
375 377 i386_MSGSUBDIRS= libfdisk
376 378
377 379 HDRSUBDIRS= \
378 380 auditd_plugins \
379 381 libast \
380 382 libbrand \
381 383 libbsm \
382 384 libc \
383 385 libcmd \
384 386 libcmdutils \
385 387 libcommputil \
386 388 libcontract \
387 389 libcpc \
388 390 libctf \
389 391 libcurses \
390 392 libtermcap \
391 393 libcryptoutil \
392 394 libdevice \
393 395 libdevid \
394 396 libdevinfo \
395 397 libdiskmgt \
396 398 libdladm \
397 399 libdll \
398 400 libdlpi \
399 401 libdhcpagent \
400 402 libdhcpsvc \
401 403 libdhcputil \
402 404 libdisasm \
403 405 libdns_sd \
404 406 libdscfg \
405 407 libdtrace \
406 408 libdtrace_jni \
407 409 libelfsign \
408 410 libeti \
409 411 libfru \
410 412 libfstyp \
411 413 libgen \
412 414 libipadm \
413 415 libipsecutil \
414 416 libinetsvc \
415 417 libinetutil \
416 418 libinstzones \
417 419 libipmi \
418 420 libipmp \
419 421 libipp \
420 422 libiscsit \
421 423 libkstat \
422 424 libkvm \
423 425 libmail \
424 426 libmd \
425 427 libmtmalloc \
426 428 libndmp \
427 429 libnvpair \
428 430 libnsctl \
429 431 libnsl \
430 432 libnwam \
431 433 libpam \
432 434 libpctx \
433 435 libpicl \
434 436 libpicltree \
435 437 libpool \
436 438 libpp \
437 439 libproc \
438 440 libraidcfg \
439 441 librcm \
440 442 librdc \
441 443 libscf \
442 444 libsip \
443 445 libsmbios \
444 446 librestart \
445 447 librpcsvc \
446 448 librsm \
447 449 librstp \
448 450 libsasl \
449 451 libsec \
450 452 libshell \
451 453 libslp \
452 454 libsmedia \
453 455 libsocket \
454 456 libsqlite \
455 457 libfcoe \
456 458 libsrpt \
457 459 libstmf \
458 460 libstmfproxy \
459 461 libsum \
460 462 libsysevent \
461 463 libtecla \
462 464 libtnf \
463 465 libtnfctl \
464 466 libtnfprobe \
465 467 libtsnet \
466 468 libtsol \
↓ open down ↓ |
217 lines elided |
↑ open up ↑ |
467 469 libvrrpadm \
468 470 libvolmgt \
469 471 libumem \
470 472 libunistat \
471 473 libuutil \
472 474 libwanboot \
473 475 libwanbootutil \
474 476 libwrap \
475 477 libxcurses2 \
476 478 libzfs \
479 + libzfs_core \
477 480 libzfs_jni \
478 481 libzoneinfo \
479 482 libzonestat \
480 483 hal \
481 484 policykit \
482 485 lvm \
483 486 pkcs11 \
484 487 passwdutil \
485 488 ../cmd/sendmail/libmilter \
486 489 fm \
487 490 udapl \
488 491 libmapid \
489 492 libkrb5 \
490 493 libsmbfs \
491 494 libshare \
492 495 libidmap \
493 496 libvscan \
494 497 libgrubmgmt \
495 498 smbsrv \
496 499 libilb \
497 500 scsi \
498 501 hbaapi \
499 502 smhba \
500 503 libima \
501 504 libsun_ima \
502 505 mpapi \
503 506 libreparse \
504 507 $($(MACH)_HDRSUBDIRS)
505 508
506 509 $(CLOSED_BUILD)HDRSUBDIRS += \
507 510 $(CLOSED)/lib/libike
508 511
509 512 i386_HDRSUBDIRS= \
510 513 libparted \
511 514 libfdisk
512 515
513 516 sparc_HDRSUBDIRS= \
514 517 libds \
515 518 libdscp \
516 519 libpri \
517 520 libv12n \
518 521 storage
519 522
520 523 all := TARGET= all
521 524 check := TARGET= check
522 525 clean := TARGET= clean
523 526 clobber := TARGET= clobber
524 527 install := TARGET= install
525 528 install_h := TARGET= install_h
526 529 lint := TARGET= lint
527 530 _dc := TARGET= _dc
528 531 _msg := TARGET= _msg
529 532
530 533 .KEEP_STATE:
531 534
532 535 #
533 536 # For the all and install targets, we clearly must respect library
534 537 # dependencies so that the libraries link correctly. However, for
535 538 # the remaining targets (check, clean, clobber, install_h, lint, _dc
536 539 # and _msg), libraries do not have any dependencies on one another
537 540 # and thus respecting dependencies just slows down the build.
538 541 # As such, for these rules, we use pattern replacement to explicitly
539 542 # avoid triggering the dependency information. Note that for clean,
540 543 # clobber and lint, we must use $(NOWAIT_SUBDIRS) rather than
541 544 # $(SUBDIRS), to prevent `.WAIT' from expanding to `.WAIT-nodepend'.
542 545 #
543 546
544 547 all: $(SUBDIRS)
545 548
546 549 install: $(SUBDIRS) .WAIT install_extra
547 550
548 551 # extra libraries kept in other source areas
549 552 install_extra:
550 553 @cd ../cmd/sgs; pwd; $(MAKE) install_lib
551 554 @pwd
552 555
553 556 clean clobber lint: $(NOWAIT_SUBDIRS:%=%-nodepend)
554 557
555 558 install_h check: $(HDRSUBDIRS:%=%-nodepend)
556 559
557 560 _msg: $(MSGSUBDIRS:%=%-nodepend) .WAIT _dc
558 561
559 562 _dc: $(DCSUBDIRS:%=%-nodepend)
560 563
561 564 #
562 565 # Library interdependencies are called out explicitly here
563 566 #
564 567 auditd_plugins: libbsm libnsl libsecdb
565 568 gss_mechs/mech_krb5: libgss libnsl libsocket libresolv pkcs11
566 569 libadt_jni: libbsm
567 570 libast: libsocket
568 571 libadutils: libldap5 libresolv libsocket libnsl
569 572 nsswitch: libadutils libidmap
570 573 libbe: libzfs
571 574 libbsm: libtsol
572 575 libcmd: libsum libast libsocket libnsl
573 576 libcmdutils: libavl
574 577 libcontract: libnvpair
575 578 libdevid: libdevinfo
576 579 libdevinfo: libnvpair libsec
577 580 libdhcpagent: libsocket libdhcputil libuuid libdlpi libcontract
578 581 libdhcpsvc: libinetutil
579 582 libdhcputil: libnsl libgen libinetutil libdlpi
580 583 libdladm: libdevinfo libinetutil libsocket libscf librcm libnvpair \
581 584 libexacct libnsl libkstat libcurses
582 585 libdll: libast
583 586 libdlpi: libinetutil libdladm
584 587 libds: libsysevent
585 588 libdscfg: libnsctl libunistat libsocket libnsl
586 589 libdtrace: libproc libgen libctf
587 590 libdtrace_jni: libuutil libdtrace
588 591 libefi: libuuid
589 592 libfstyp: libnvpair
590 593 libelfsign: libcryptoutil libkmf
591 594 libidmap: libadutils libldap5 libavl libsldap libuutil
592 595 libipadm: libnsl libinetutil libsocket libdlpi libnvpair libdhcpagent \
593 596 libdladm libsecdb
594 597 libiscsit: libc libnvpair libstmf libuuid libnsl
595 598 libkmf: libcryptoutil pkcs11
596 599 libnsl: libmd5
597 600 libmapid: libresolv
598 601 librdc: libsocket libnsl libnsctl libunistat libdscfg
599 602 libuuid: libdlpi
600 603 $(CLOSED_BUILD)libike: libipsecutil libxnet libcryptoutil
601 604 libinetutil: libsocket
602 605 libipsecutil: libtecla libsocket
603 606 libinstzones: libzonecfg libcontract
604 607 libpkg: libwanboot libscf libadm
605 608 libnwam: libscf
606 609 libsecdb: libnsl
607 610 libsasl: libgss libsocket pkcs11 libmd
608 611 sasl_plugins: pkcs11 libgss libsocket libsasl
609 612 libsctp: libsocket
610 613 libshell: libast libcmd libdll libsocket libsecdb
611 614 libsip: libmd5
612 615 libsmbfs: libcmdutils libsocket libnsl libkrb5
613 616 libsocket: libnsl
614 617 libstmfproxy: libstmf libsocket libnsl libpthread
615 618 libsum: libast
616 619 libsysevent: libsecdb
617 620 libldap5: libsasl libsocket libnsl libmd
618 621 libsldap: libldap5 libtsol libnsl libc libscf libresolv
619 622 libpool: libnvpair libexacct
620 623 libpp: libast
621 624 libzonecfg: libc libsocket libnsl libuuid libnvpair libsysevent libsec \
622 625 libbrand libpool libscf
623 626 libproc: ../cmd/sgs/librtld_db ../cmd/sgs/libelf libctf
624 627 libproject: libpool libproc libsecdb
625 628 libtermcap: libcurses
626 629 libtsnet: libnsl libtsol libsecdb
627 630 libwrap: libnsl libsocket
628 631 libwanboot: libnvpair libresolv libnsl libsocket libdevinfo libinetutil \
629 632 libdhcputil
630 633 libwanbootutil: libnsl
↓ open down ↓ |
144 lines elided |
↑ open up ↑ |
631 634 pam_modules: libproject passwdutil smbsrv
632 635 libscf: libuutil libmd libgen libsmbios libnsl
633 636 libinetsvc: libscf
634 637 librestart: libuutil libscf
635 638 ../cmd/sgs/libdl: ../cmd/sgs/libconv
636 639 ../cmd/sgs/libelf: ../cmd/sgs/libconv
637 640 pkcs11: libcryptoutil
638 641 print: libldap5
639 642 udapl/udapl_tavor: udapl/libdat
640 643 libzfs: libdevid libgen libnvpair libuutil \
641 - libadm libavl libefi libidmap libmd
644 + libadm libavl libefi libidmap libmd libzfs_core
645 +libzfs_core: libnvpair
642 646 libzfs_jni: libdiskmgt libnvpair libzfs
643 647 libzpool: libavl libumem libnvpair libcmdutils
644 648 libsec: libavl libidmap
645 649 brand: libc libsocket
646 650 libshare: libscf libzfs libuuid libfsmgt libsecdb libumem libsmbfs
647 651 libexacct/demo: libexacct libproject libsocket libnsl
648 652 libtsalarm: libpcp
649 653 smbsrv: libsocket libnsl libmd libxnet libpthread librt \
650 654 libshare libidmap pkcs11 libsqlite libcryptoutil \
651 655 libreparse libcmdutils
652 656 libv12n: libds libuuid
653 657 libvrrpadm: libsocket libdladm libscf
654 658 libvscan: libscf
655 659 libfru: libfruutils
656 660 scsi: libnvpair libfru
657 661 mpapi: libpthread libdevinfo libsysevent libnvpair
658 662 sun_fc: libdevinfo libsysevent libnvpair
659 663 libsun_ima: libdevinfo libsysevent libnsl
660 664 sun_sas: libdevinfo libsysevent libnvpair libkstat libdevid
661 665 libgrubmgmt: libdevinfo libzfs libfstyp
662 666 pylibbe: libbe libzfs
663 667 pyzfs: libnvpair libzfs
664 668 pysolaris: libsec libidmap
665 669 libreparse: libnvpair
666 670 libhotplug: libnvpair
667 671 cfgadm_plugins: libhotplug
668 672 libilb: libsocket
669 673 $(INTEL_BUILD)libdiskmgt:libfdisk
670 674
671 675 #
672 676 # The reason this rule checks for the existence of the
673 677 # Makefile is that some of the directories do not exist
674 678 # in certain situations (e.g., exportable source builds,
675 679 # OpenSolaris).
676 680 #
677 681 $(SUBDIRS): FRC
678 682 @if [ -f $@/Makefile ]; then \
679 683 cd $@; pwd; $(MAKE) $(TARGET); \
680 684 else \
681 685 true; \
682 686 fi
683 687
684 688 $(SUBDIRS:%=%-nodepend):
685 689 @if [ -f $(@:%-nodepend=%)/Makefile ]; then \
686 690 cd $(@:%-nodepend=%); pwd; $(MAKE) $(TARGET); \
687 691 else \
688 692 true; \
689 693 fi
690 694
691 695 FRC:
↓ open down ↓ |
40 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX