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.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * Virtual disk server
28 */
29
30
31 #include <sys/types.h>
32 #include <sys/conf.h>
33 #include <sys/crc32.h>
34 #include <sys/ddi.h>
35 #include <sys/dkio.h>
36 #include <sys/file.h>
37 #include <sys/fs/hsfs_isospec.h>
38 #include <sys/mdeg.h>
39 #include <sys/mhd.h>
40 #include <sys/modhash.h>
41 #include <sys/note.h>
42 #include <sys/pathname.h>
43 #include <sys/sdt.h>
5815 * The minimum size for the label is 16K (EFI_MIN_ARRAY_SIZE)
5816 * for GPEs plus one block for the GPT and one for PMBR.
5817 */
5818 first_u_lba = (EFI_MIN_ARRAY_SIZE / bsize) + 2;
5819 vd->flabel_limit = (uint_t)first_u_lba;
5820 vd->flabel_size = VD_LABEL_EFI_SIZE(bsize);
5821 vd->flabel = kmem_zalloc(vd->flabel_size, KM_SLEEP);
5822 gpt = VD_LABEL_EFI_GPT(vd, bsize);
5823 gpe = VD_LABEL_EFI_GPE(vd, bsize);
5824
5825 /*
5826 * Adjust the vdisk_size, we emulate the first few blocks
5827 * for the disk label.
5828 */
5829 vd->vdisk_size += first_u_lba;
5830 s0_start = first_u_lba;
5831 s0_end = vd->vdisk_size - 1;
5832
5833 gpt->efi_gpt_Signature = LE_64(EFI_SIGNATURE);
5834 gpt->efi_gpt_Revision = LE_32(EFI_VERSION_CURRENT);
5835 gpt->efi_gpt_HeaderSize = LE_32(sizeof (efi_gpt_t));
5836 gpt->efi_gpt_FirstUsableLBA = LE_64(first_u_lba);
5837 gpt->efi_gpt_PartitionEntryLBA = LE_64(2ULL);
5838 gpt->efi_gpt_SizeOfPartitionEntry = LE_32(sizeof (efi_gpe_t));
5839
5840 UUID_LE_CONVERT(gpe[0].efi_gpe_PartitionTypeGUID, uuid);
5841 gpe[0].efi_gpe_StartingLBA = LE_64(s0_start);
5842 gpe[0].efi_gpe_EndingLBA = LE_64(s0_end);
5843
5844 if (vd_slice_single_slice) {
5845 gpt->efi_gpt_NumberOfPartitionEntries = LE_32(1);
5846 } else {
5847 /* adjust the number of slices */
5848 gpt->efi_gpt_NumberOfPartitionEntries = LE_32(VD_MAXPART);
5849 vd->nslices = V_NUMPAR;
5850
5851 /* define a fake reserved partition */
5852 UUID_LE_CONVERT(gpe[VD_MAXPART - 1].efi_gpe_PartitionTypeGUID,
5853 efi_reserved);
5854 gpe[VD_MAXPART - 1].efi_gpe_StartingLBA =
5855 LE_64(s0_end + 1);
5856 gpe[VD_MAXPART - 1].efi_gpe_EndingLBA =
5857 LE_64(s0_end + EFI_MIN_RESV_SIZE);
5858
5859 /* adjust the vdisk_size to include the reserved slice */
5860 vd->vdisk_size += EFI_MIN_RESV_SIZE;
5861 }
5862
5863 gpt->efi_gpt_LastUsableLBA = LE_64(vd->vdisk_size - 1);
5864
5865 /* adjust the vdisk size for the backup GPT and GPE */
5866 vd->vdisk_size += (EFI_MIN_ARRAY_SIZE / bsize) + 1;
5867 gpt->efi_gpt_AlternateLBA = LE_64(vd->vdisk_size - 1);
5868
5869 CRC32(crc, gpe, sizeof (efi_gpe_t) * VD_MAXPART, -1U, crc32_table);
5870 gpt->efi_gpt_PartitionEntryArrayCRC32 = LE_32(~crc);
5871
5872 CRC32(crc, gpt, sizeof (efi_gpt_t), -1U, crc32_table);
5873 gpt->efi_gpt_HeaderCRC32 = LE_32(~crc);
5874
5875 return (0);
5876 }
5877
5878 /*
5879 * Setup for a virtual disk whose backend is a file (exported as a single slice
5880 * or as a full disk). In that case, the backend is accessed using the vnode
5881 * interface.
5882 */
5883 static int
5884 vd_setup_backend_vnode(vd_t *vd)
5885 {
5886 int rval, status;
5887 dev_t dev;
5888 char *file_path = vd->device_path;
5889 ldi_handle_t lhandle;
5890 struct dk_cinfo dk_cinfo;
5891
5892 ASSERT(!vd->volume);
|
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.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2019, Joyent, Inc.
25 */
26
27 /*
28 * Virtual disk server
29 */
30
31
32 #include <sys/types.h>
33 #include <sys/conf.h>
34 #include <sys/crc32.h>
35 #include <sys/ddi.h>
36 #include <sys/dkio.h>
37 #include <sys/file.h>
38 #include <sys/fs/hsfs_isospec.h>
39 #include <sys/mdeg.h>
40 #include <sys/mhd.h>
41 #include <sys/modhash.h>
42 #include <sys/note.h>
43 #include <sys/pathname.h>
44 #include <sys/sdt.h>
5816 * The minimum size for the label is 16K (EFI_MIN_ARRAY_SIZE)
5817 * for GPEs plus one block for the GPT and one for PMBR.
5818 */
5819 first_u_lba = (EFI_MIN_ARRAY_SIZE / bsize) + 2;
5820 vd->flabel_limit = (uint_t)first_u_lba;
5821 vd->flabel_size = VD_LABEL_EFI_SIZE(bsize);
5822 vd->flabel = kmem_zalloc(vd->flabel_size, KM_SLEEP);
5823 gpt = VD_LABEL_EFI_GPT(vd, bsize);
5824 gpe = VD_LABEL_EFI_GPE(vd, bsize);
5825
5826 /*
5827 * Adjust the vdisk_size, we emulate the first few blocks
5828 * for the disk label.
5829 */
5830 vd->vdisk_size += first_u_lba;
5831 s0_start = first_u_lba;
5832 s0_end = vd->vdisk_size - 1;
5833
5834 gpt->efi_gpt_Signature = LE_64(EFI_SIGNATURE);
5835 gpt->efi_gpt_Revision = LE_32(EFI_VERSION_CURRENT);
5836 gpt->efi_gpt_HeaderSize = LE_32(EFI_HEADER_SIZE);
5837 gpt->efi_gpt_FirstUsableLBA = LE_64(first_u_lba);
5838 gpt->efi_gpt_PartitionEntryLBA = LE_64(2ULL);
5839 gpt->efi_gpt_SizeOfPartitionEntry = LE_32(sizeof (efi_gpe_t));
5840
5841 UUID_LE_CONVERT(gpe[0].efi_gpe_PartitionTypeGUID, uuid);
5842 gpe[0].efi_gpe_StartingLBA = LE_64(s0_start);
5843 gpe[0].efi_gpe_EndingLBA = LE_64(s0_end);
5844
5845 if (vd_slice_single_slice) {
5846 gpt->efi_gpt_NumberOfPartitionEntries = LE_32(1);
5847 } else {
5848 /* adjust the number of slices */
5849 gpt->efi_gpt_NumberOfPartitionEntries = LE_32(VD_MAXPART);
5850 vd->nslices = V_NUMPAR;
5851
5852 /* define a fake reserved partition */
5853 UUID_LE_CONVERT(gpe[VD_MAXPART - 1].efi_gpe_PartitionTypeGUID,
5854 efi_reserved);
5855 gpe[VD_MAXPART - 1].efi_gpe_StartingLBA =
5856 LE_64(s0_end + 1);
5857 gpe[VD_MAXPART - 1].efi_gpe_EndingLBA =
5858 LE_64(s0_end + EFI_MIN_RESV_SIZE);
5859
5860 /* adjust the vdisk_size to include the reserved slice */
5861 vd->vdisk_size += EFI_MIN_RESV_SIZE;
5862 }
5863
5864 gpt->efi_gpt_LastUsableLBA = LE_64(vd->vdisk_size - 1);
5865
5866 /* adjust the vdisk size for the backup GPT and GPE */
5867 vd->vdisk_size += (EFI_MIN_ARRAY_SIZE / bsize) + 1;
5868 gpt->efi_gpt_AlternateLBA = LE_64(vd->vdisk_size - 1);
5869
5870 CRC32(crc, gpe, sizeof (efi_gpe_t) * VD_MAXPART, -1U, crc32_table);
5871 gpt->efi_gpt_PartitionEntryArrayCRC32 = LE_32(~crc);
5872
5873 CRC32(crc, gpt, EFI_HEADER_SIZE, -1U, crc32_table);
5874 gpt->efi_gpt_HeaderCRC32 = LE_32(~crc);
5875
5876 return (0);
5877 }
5878
5879 /*
5880 * Setup for a virtual disk whose backend is a file (exported as a single slice
5881 * or as a full disk). In that case, the backend is accessed using the vnode
5882 * interface.
5883 */
5884 static int
5885 vd_setup_backend_vnode(vd_t *vd)
5886 {
5887 int rval, status;
5888 dev_t dev;
5889 char *file_path = vd->device_path;
5890 ldi_handle_t lhandle;
5891 struct dk_cinfo dk_cinfo;
5892
5893 ASSERT(!vd->volume);
|