6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 /*
21 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
22 * Use is subject to license terms.
23 */
24
25 /*
26 * Copyright (c) 2012 by Delphix. All rights reserved.
27 * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
28 */
29
30 /*
31 * The zfs plug-in routines for GRUB are:
32 *
33 * zfs_mount() - locates a valid uberblock of the root pool and reads
34 * in its MOS at the memory address MOS.
35 *
36 * zfs_open() - locates a plain file object by following the MOS
37 * and places its dnode at the memory address DNODE.
38 *
39 * zfs_read() - read in the data blocks pointed by the DNODE.
40 *
41 * ZFS_SCRATCH is used as a working area.
42 *
43 * (memory addr) MOS DNODE ZFS_SCRATCH
44 * | | |
45 * +-------V---------V----------V---------------+
46 * memory | | dnode | dnode | scratch |
949 if (zap_lookup(dn, ZPOOL_PROP_BOOTFS, &objnum, stack))
950 return (ERR_FILESYSTEM_NOT_FOUND);
951
952 if (!objnum)
953 return (ERR_FILESYSTEM_NOT_FOUND);
954
955 *obj = objnum;
956 return (0);
957 }
958
959 /*
960 * List of pool features that the grub implementation of ZFS supports for
961 * read. Note that features that are only required for write do not need
962 * to be listed here since grub opens pools in read-only mode.
963 *
964 * When this list is updated the version number in usr/src/grub/capability
965 * must be incremented to ensure the new grub gets installed.
966 */
967 static const char *spa_feature_names[] = {
968 "org.illumos:lz4_compress",
969 NULL
970 };
971
972 /*
973 * Checks whether the MOS features that are active are supported by this
974 * (GRUB's) implementation of ZFS.
975 *
976 * Return:
977 * 0: Success.
978 * errnum: Failure.
979 */
980 static int
981 check_mos_features(dnode_phys_t *mosmdn, char *stack)
982 {
983 uint64_t objnum;
984 dnode_phys_t *dn;
985 uint8_t error = 0;
986
987 dn = (dnode_phys_t *)stack;
988 stack += DNODE_SIZE;
1027 uint64_t objnum, headobj;
1028 char *cname, ch;
1029 blkptr_t *bp;
1030 objset_phys_t *osp;
1031 int issnapshot = 0;
1032 char *snapname;
1033
1034 if (fsname == NULL && obj) {
1035 headobj = *obj;
1036 goto skip;
1037 }
1038
1039 if (errnum = dnode_get(mosmdn, DMU_POOL_DIRECTORY_OBJECT,
1040 DMU_OT_OBJECT_DIRECTORY, mdn, stack))
1041 return (errnum);
1042
1043 if (errnum = zap_lookup(mdn, DMU_POOL_ROOT_DATASET, &objnum,
1044 stack))
1045 return (errnum);
1046
1047 if (errnum = dnode_get(mosmdn, objnum, DMU_OT_DSL_DIR, mdn, stack))
1048 return (errnum);
1049
1050 if (fsname == NULL) {
1051 headobj =
1052 ((dsl_dir_phys_t *)DN_BONUS(mdn))->dd_head_dataset_obj;
1053 goto skip;
1054 }
1055
1056 /* take out the pool name */
1057 while (*fsname && !grub_isspace(*fsname) && *fsname != '/')
1058 fsname++;
1059
1060 while (*fsname && !grub_isspace(*fsname)) {
1061 uint64_t childobj;
1062
1063 while (*fsname == '/')
1064 fsname++;
1065
1066 cname = fsname;
1067 while (*fsname && !grub_isspace(*fsname) && *fsname != '/')
1069 ch = *fsname;
1070 *fsname = 0;
1071
1072 snapname = cname;
1073 while (*snapname && !grub_isspace(*snapname) && *snapname !=
1074 '@')
1075 snapname++;
1076 if (*snapname == '@') {
1077 issnapshot = 1;
1078 *snapname = 0;
1079 }
1080 childobj =
1081 ((dsl_dir_phys_t *)DN_BONUS(mdn))->dd_child_dir_zapobj;
1082 if (errnum = dnode_get(mosmdn, childobj,
1083 DMU_OT_DSL_DIR_CHILD_MAP, mdn, stack))
1084 return (errnum);
1085
1086 if (zap_lookup(mdn, cname, &objnum, stack))
1087 return (ERR_FILESYSTEM_NOT_FOUND);
1088
1089 if (errnum = dnode_get(mosmdn, objnum, DMU_OT_DSL_DIR,
1090 mdn, stack))
1091 return (errnum);
1092
1093 *fsname = ch;
1094 if (issnapshot)
1095 *snapname = '@';
1096 }
1097 headobj = ((dsl_dir_phys_t *)DN_BONUS(mdn))->dd_head_dataset_obj;
1098 if (obj)
1099 *obj = headobj;
1100
1101 skip:
1102 if (errnum = dnode_get(mosmdn, headobj, DMU_OT_DSL_DATASET, mdn, stack))
1103 return (errnum);
1104 if (issnapshot) {
1105 uint64_t snapobj;
1106
1107 snapobj = ((dsl_dataset_phys_t *)DN_BONUS(mdn))->
1108 ds_snapnames_zapobj;
1109
1110 if (errnum = dnode_get(mosmdn, snapobj,
1111 DMU_OT_DSL_DS_SNAP_MAP, mdn, stack))
1112 return (errnum);
1113 if (zap_lookup(mdn, snapname + 1, &headobj, stack))
1114 return (ERR_FILESYSTEM_NOT_FOUND);
1115 if (errnum = dnode_get(mosmdn, headobj,
1116 DMU_OT_DSL_DATASET, mdn, stack))
1117 return (errnum);
1118 if (obj)
1119 *obj = headobj;
1120 }
1121
1122 bp = &((dsl_dataset_phys_t *)DN_BONUS(mdn))->ds_bp;
1123 osp = (objset_phys_t *)stack;
1124 stack += sizeof (objset_phys_t);
1125 if (errnum = zio_read(bp, osp, stack))
1126 return (errnum);
1127
1128 grub_memmove((char *)mdn, (char *)&osp->os_meta_dnode, DNODE_SIZE);
1129
1130 return (0);
1131 }
1132
1133 /*
1134 * For a given XDR packed nvlist, verify the first 4 bytes and move on.
1135 *
1136 * An XDR packed nvlist is encoded as (comments from nvs_xdr_create) :
|
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 /*
21 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
22 * Use is subject to license terms.
23 */
24
25 /*
26 * Copyright (c) 2013 by Delphix. All rights reserved.
27 * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
28 */
29
30 /*
31 * The zfs plug-in routines for GRUB are:
32 *
33 * zfs_mount() - locates a valid uberblock of the root pool and reads
34 * in its MOS at the memory address MOS.
35 *
36 * zfs_open() - locates a plain file object by following the MOS
37 * and places its dnode at the memory address DNODE.
38 *
39 * zfs_read() - read in the data blocks pointed by the DNODE.
40 *
41 * ZFS_SCRATCH is used as a working area.
42 *
43 * (memory addr) MOS DNODE ZFS_SCRATCH
44 * | | |
45 * +-------V---------V----------V---------------+
46 * memory | | dnode | dnode | scratch |
949 if (zap_lookup(dn, ZPOOL_PROP_BOOTFS, &objnum, stack))
950 return (ERR_FILESYSTEM_NOT_FOUND);
951
952 if (!objnum)
953 return (ERR_FILESYSTEM_NOT_FOUND);
954
955 *obj = objnum;
956 return (0);
957 }
958
959 /*
960 * List of pool features that the grub implementation of ZFS supports for
961 * read. Note that features that are only required for write do not need
962 * to be listed here since grub opens pools in read-only mode.
963 *
964 * When this list is updated the version number in usr/src/grub/capability
965 * must be incremented to ensure the new grub gets installed.
966 */
967 static const char *spa_feature_names[] = {
968 "org.illumos:lz4_compress",
969 "com.delphix:extensible_dataset",
970 NULL
971 };
972
973 /*
974 * Checks whether the MOS features that are active are supported by this
975 * (GRUB's) implementation of ZFS.
976 *
977 * Return:
978 * 0: Success.
979 * errnum: Failure.
980 */
981 static int
982 check_mos_features(dnode_phys_t *mosmdn, char *stack)
983 {
984 uint64_t objnum;
985 dnode_phys_t *dn;
986 uint8_t error = 0;
987
988 dn = (dnode_phys_t *)stack;
989 stack += DNODE_SIZE;
1028 uint64_t objnum, headobj;
1029 char *cname, ch;
1030 blkptr_t *bp;
1031 objset_phys_t *osp;
1032 int issnapshot = 0;
1033 char *snapname;
1034
1035 if (fsname == NULL && obj) {
1036 headobj = *obj;
1037 goto skip;
1038 }
1039
1040 if (errnum = dnode_get(mosmdn, DMU_POOL_DIRECTORY_OBJECT,
1041 DMU_OT_OBJECT_DIRECTORY, mdn, stack))
1042 return (errnum);
1043
1044 if (errnum = zap_lookup(mdn, DMU_POOL_ROOT_DATASET, &objnum,
1045 stack))
1046 return (errnum);
1047
1048 if (errnum = dnode_get(mosmdn, objnum, 0, mdn, stack))
1049 return (errnum);
1050
1051 if (fsname == NULL) {
1052 headobj =
1053 ((dsl_dir_phys_t *)DN_BONUS(mdn))->dd_head_dataset_obj;
1054 goto skip;
1055 }
1056
1057 /* take out the pool name */
1058 while (*fsname && !grub_isspace(*fsname) && *fsname != '/')
1059 fsname++;
1060
1061 while (*fsname && !grub_isspace(*fsname)) {
1062 uint64_t childobj;
1063
1064 while (*fsname == '/')
1065 fsname++;
1066
1067 cname = fsname;
1068 while (*fsname && !grub_isspace(*fsname) && *fsname != '/')
1070 ch = *fsname;
1071 *fsname = 0;
1072
1073 snapname = cname;
1074 while (*snapname && !grub_isspace(*snapname) && *snapname !=
1075 '@')
1076 snapname++;
1077 if (*snapname == '@') {
1078 issnapshot = 1;
1079 *snapname = 0;
1080 }
1081 childobj =
1082 ((dsl_dir_phys_t *)DN_BONUS(mdn))->dd_child_dir_zapobj;
1083 if (errnum = dnode_get(mosmdn, childobj,
1084 DMU_OT_DSL_DIR_CHILD_MAP, mdn, stack))
1085 return (errnum);
1086
1087 if (zap_lookup(mdn, cname, &objnum, stack))
1088 return (ERR_FILESYSTEM_NOT_FOUND);
1089
1090 if (errnum = dnode_get(mosmdn, objnum, 0,
1091 mdn, stack))
1092 return (errnum);
1093
1094 *fsname = ch;
1095 if (issnapshot)
1096 *snapname = '@';
1097 }
1098 headobj = ((dsl_dir_phys_t *)DN_BONUS(mdn))->dd_head_dataset_obj;
1099 if (obj)
1100 *obj = headobj;
1101
1102 skip:
1103 if (errnum = dnode_get(mosmdn, headobj, 0, mdn, stack))
1104 return (errnum);
1105 if (issnapshot) {
1106 uint64_t snapobj;
1107
1108 snapobj = ((dsl_dataset_phys_t *)DN_BONUS(mdn))->
1109 ds_snapnames_zapobj;
1110
1111 if (errnum = dnode_get(mosmdn, snapobj,
1112 DMU_OT_DSL_DS_SNAP_MAP, mdn, stack))
1113 return (errnum);
1114 if (zap_lookup(mdn, snapname + 1, &headobj, stack))
1115 return (ERR_FILESYSTEM_NOT_FOUND);
1116 if (errnum = dnode_get(mosmdn, headobj, 0, mdn, stack))
1117 return (errnum);
1118 if (obj)
1119 *obj = headobj;
1120 }
1121
1122 bp = &((dsl_dataset_phys_t *)DN_BONUS(mdn))->ds_bp;
1123 osp = (objset_phys_t *)stack;
1124 stack += sizeof (objset_phys_t);
1125 if (errnum = zio_read(bp, osp, stack))
1126 return (errnum);
1127
1128 grub_memmove((char *)mdn, (char *)&osp->os_meta_dnode, DNODE_SIZE);
1129
1130 return (0);
1131 }
1132
1133 /*
1134 * For a given XDR packed nvlist, verify the first 4 bytes and move on.
1135 *
1136 * An XDR packed nvlist is encoded as (comments from nvs_xdr_create) :
|