Print this page
4171 clean up spa_feature_*() interfaces
4172 implement extensible_dataset feature for use by other zpool features
Reviewed by: Max Grossman <max.grossman@delphix.com>
Reviewed by: Christopher Siden <christopher.siden@delphix.com>
Reviewed by: George Wilson <george.wilson@delphix.com>


   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) :