4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or https://opensource.org/licenses/CDDL-1.0.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 #include <sys/zfs_context.h>
24 #include <sys/spa_impl.h>
28 #include <sys/vdev_os.h>
29 #include <sys/vdev_impl.h>
30 #include <sys/uberblock_impl.h>
31 #include <sys/metaslab.h>
32 #include <sys/metaslab_impl.h>
34 #include <sys/dsl_scan.h>
36 #include <sys/fs/zfs.h>
39 vdev_label_write_pad2(vdev_t
*vd
, const char *buf
, size_t size
)
41 spa_t
*spa
= vd
->vdev_spa
;
44 int flags
= ZIO_FLAG_CONFIG_WRITER
| ZIO_FLAG_CANFAIL
;
47 if (size
> VDEV_PAD_SIZE
)
50 if (!vd
->vdev_ops
->vdev_op_leaf
)
55 ASSERT3U(spa_config_held(spa
, SCL_ALL
, RW_WRITER
), ==, SCL_ALL
);
57 pad2
= abd_alloc_for_io(VDEV_PAD_SIZE
, B_TRUE
);
58 abd_copy_from_buf(pad2
, buf
, size
);
59 abd_zero_off(pad2
, size
, VDEV_PAD_SIZE
- size
);
62 zio
= zio_root(spa
, NULL
, NULL
, flags
);
63 vdev_label_write(zio
, vd
, 0, pad2
,
64 offsetof(vdev_label_t
, vl_be
),
65 VDEV_PAD_SIZE
, NULL
, NULL
, flags
);
66 error
= zio_wait(zio
);
67 if (error
!= 0 && !(flags
& ZIO_FLAG_TRYHARD
)) {
68 flags
|= ZIO_FLAG_TRYHARD
;
77 vdev_child_done(zio_t
*zio
)
79 zio_t
*pio
= zio
->io_private
;
81 mutex_enter(&pio
->io_lock
);
82 pio
->io_error
= zio_worst_error(pio
->io_error
, zio
->io_error
);
83 mutex_exit(&pio
->io_lock
);
87 * Check if the reserved boot area is in-use.
89 * When booting FreeBSD with an MBR partition with ZFS, the zfsboot file
90 * (which understands the ZFS file system) is written to the ZFS BOOT
91 * reserve area (at offset 512K). We check for that here before attaching
92 * a disk to raidz which would then corrupt this boot data.
95 vdev_check_boot_reserve(spa_t
*spa
, vdev_t
*childvd
)
97 ASSERT(childvd
->vdev_ops
->vdev_op_leaf
);
99 size_t size
= SPA_MINBLOCKSIZE
;
100 abd_t
*abd
= abd_alloc_linear(size
, B_FALSE
);
102 zio_t
*pio
= zio_root(spa
, NULL
, NULL
, 0);
104 * Note: zio_vdev_child_io() adds VDEV_LABEL_START_SIZE to the offset
105 * to calculate the physical offset to write to. Passing in a negative
106 * offset lets us access the boot area.
108 zio_nowait(zio_vdev_child_io(pio
, NULL
, childvd
,
109 VDEV_BOOT_OFFSET
- VDEV_LABEL_START_SIZE
, abd
, size
, ZIO_TYPE_READ
,
110 ZIO_PRIORITY_ASYNC_READ
, 0, vdev_child_done
, pio
));
113 unsigned char *buf
= abd_to_buf(abd
);
116 * The BTX server has a special header at the begining.
118 * btx_hdr: .byte 0xeb # Machine ID
119 * .byte 0xe # Header size
120 * .ascii "BTX" # Magic
121 * .byte 0x1 # Major version
122 * .byte 0x2 # Minor version
123 * .byte BTX_FLAGS # Flags
125 if (buf
[0] == 0xeb && buf
[1] == 0x0e &&
126 buf
[2] == 'B' && buf
[3] == 'T' && buf
[4] == 'X') {