Print this page
%B


   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  */
  28 
  29 /*
  30  * The zfs plug-in routines for GRUB are:
  31  *
  32  * zfs_mount() - locates a valid uberblock of the root pool and reads
  33  *              in its MOS at the memory address MOS.
  34  *
  35  * zfs_open() - locates a plain file object by following the MOS
  36  *              and places its dnode at the memory address DNODE.
  37  *
  38  * zfs_read() - read in the data blocks pointed by the DNODE.
  39  *
  40  * ZFS_SCRATCH is used as a working area.
  41  *
  42  * (memory addr)   MOS      DNODE       ZFS_SCRATCH
  43  *                  |         |          |
  44  *          +-------V---------V----------V---------------+
  45  *   memory |       | dnode   | dnode    |  scratch      |
  46  *          |       | 512B    | 512B     |  area         |


  57 static void *file_buf = NULL;
  58 static uint64_t file_start = 0;
  59 static uint64_t file_end = 0;
  60 
  61 /* cache for a dnode block */
  62 static dnode_phys_t *dnode_buf = NULL;
  63 static dnode_phys_t *dnode_mdn = NULL;
  64 static uint64_t dnode_start = 0;
  65 static uint64_t dnode_end = 0;
  66 
  67 static uint64_t pool_guid = 0;
  68 static uberblock_t current_uberblock;
  69 static char *stackbase;
  70 
  71 decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] =
  72 {
  73         {"inherit", 0},                 /* ZIO_COMPRESS_INHERIT */
  74         {"on", lzjb_decompress},        /* ZIO_COMPRESS_ON */
  75         {"off", 0},                     /* ZIO_COMPRESS_OFF */
  76         {"lzjb", lzjb_decompress},      /* ZIO_COMPRESS_LZJB */
  77         {"empty", 0}                    /* ZIO_COMPRESS_EMPTY */











  78 };
  79 
  80 static int zio_read_data(blkptr_t *bp, void *buf, char *stack);
  81 
  82 /*
  83  * Our own version of bcmp().
  84  */
  85 static int
  86 zfs_bcmp(const void *s1, const void *s2, size_t n)
  87 {
  88         const uchar_t *ps1 = s1;
  89         const uchar_t *ps2 = s2;
  90 
  91         if (s1 != s2 && n != 0) {
  92                 do {
  93                         if (*ps1++ != *ps2++)
  94                                 return (1);
  95                 } while (--n != 0);
  96         }
  97 


 395                 grub_printf("not enough memory allocated\n");
 396                 return (ERR_WONT_FIT);
 397         }
 398 
 399         retbuf = buf;
 400         if (comp != ZIO_COMPRESS_OFF) {
 401                 buf = stack;
 402                 stack += psize;
 403         }
 404 
 405         if (zio_read_data(bp, buf, stack) != 0) {
 406                 grub_printf("zio_read_data failed\n");
 407                 return (ERR_FSYS_CORRUPT);
 408         }
 409 
 410         if (zio_checksum_verify(bp, buf, psize) != 0) {
 411                 grub_printf("checksum verification failed\n");
 412                 return (ERR_FSYS_CORRUPT);
 413         }
 414 
 415         if (comp != ZIO_COMPRESS_OFF)
 416                 decomp_table[comp].decomp_func(buf, retbuf, psize, lsize);





 417 
 418         return (0);
 419 }
 420 
 421 /*
 422  * Get the block from a block id.
 423  * push the block onto the stack.
 424  *
 425  * Return:
 426  *      0 - success
 427  *      errnum - failure
 428  */
 429 static int
 430 dmu_read(dnode_phys_t *dn, uint64_t blkid, void *buf, char *stack)
 431 {
 432         int idx, level;
 433         blkptr_t *bp_array = dn->dn_blkptr;
 434         int epbs = dn->dn_indblkshift - SPA_BLKPTRSHIFT;
 435         blkptr_t *bp, *tmpbuf;
 436 


 928 
 929         if (errnum = dnode_get(mosmdn, objnum, DMU_OT_POOL_PROPS, dn, stack))
 930                 return (errnum);
 931 
 932         if (zap_lookup(dn, ZPOOL_PROP_BOOTFS, &objnum, stack))
 933                 return (ERR_FILESYSTEM_NOT_FOUND);
 934 
 935         if (!objnum)
 936                 return (ERR_FILESYSTEM_NOT_FOUND);
 937 
 938         *obj = objnum;
 939         return (0);
 940 }
 941 
 942 /*
 943  * List of pool features that the grub implementation of ZFS supports for
 944  * read. Note that features that are only required for write do not need
 945  * to be listed here since grub opens pools in read-only mode.
 946  */
 947 static const char *spa_feature_names[] = {

 948         NULL
 949 };
 950 
 951 /*
 952  * Checks whether the MOS features that are active are supported by this
 953  * (GRUB's) implementation of ZFS.
 954  *
 955  * Return:
 956  *      0: Success.
 957  *      errnum: Failure.
 958  */
 959 static int
 960 check_mos_features(dnode_phys_t *mosmdn, char *stack)
 961 {
 962         uint64_t objnum;
 963         dnode_phys_t *dn;
 964         uint8_t error = 0;
 965 
 966         dn = (dnode_phys_t *)stack;
 967         stack += DNODE_SIZE;




   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      |
  47  *          |       | 512B    | 512B     |  area         |


  58 static void *file_buf = NULL;
  59 static uint64_t file_start = 0;
  60 static uint64_t file_end = 0;
  61 
  62 /* cache for a dnode block */
  63 static dnode_phys_t *dnode_buf = NULL;
  64 static dnode_phys_t *dnode_mdn = NULL;
  65 static uint64_t dnode_start = 0;
  66 static uint64_t dnode_end = 0;
  67 
  68 static uint64_t pool_guid = 0;
  69 static uberblock_t current_uberblock;
  70 static char *stackbase;
  71 
  72 decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] =
  73 {
  74         {"inherit", 0},                 /* ZIO_COMPRESS_INHERIT */
  75         {"on", lzjb_decompress},        /* ZIO_COMPRESS_ON */
  76         {"off", 0},                     /* ZIO_COMPRESS_OFF */
  77         {"lzjb", lzjb_decompress},      /* ZIO_COMPRESS_LZJB */
  78         {"empty", 0},                   /* ZIO_COMPRESS_EMPTY */
  79         {"gzip-1", 0},                  /* ZIO_COMPRESS_GZIP_1 */
  80         {"gzip-2", 0},                  /* ZIO_COMPRESS_GZIP_2 */
  81         {"gzip-3", 0},                  /* ZIO_COMPRESS_GZIP_3 */
  82         {"gzip-4", 0},                  /* ZIO_COMPRESS_GZIP_4 */
  83         {"gzip-5", 0},                  /* ZIO_COMPRESS_GZIP_5 */
  84         {"gzip-6", 0},                  /* ZIO_COMPRESS_GZIP_6 */
  85         {"gzip-7", 0},                  /* ZIO_COMPRESS_GZIP_7 */
  86         {"gzip-8", 0},                  /* ZIO_COMPRESS_GZIP_8 */
  87         {"gzip-9", 0},                  /* ZIO_COMPRESS_GZIP_9 */
  88         {"zle", 0},                     /* ZIO_COMPRESS_ZLE */
  89         {"lz4", lz4_decompress}         /* ZIO_COMPRESS_LZ4 */
  90 };
  91 
  92 static int zio_read_data(blkptr_t *bp, void *buf, char *stack);
  93 
  94 /*
  95  * Our own version of bcmp().
  96  */
  97 static int
  98 zfs_bcmp(const void *s1, const void *s2, size_t n)
  99 {
 100         const uchar_t *ps1 = s1;
 101         const uchar_t *ps2 = s2;
 102 
 103         if (s1 != s2 && n != 0) {
 104                 do {
 105                         if (*ps1++ != *ps2++)
 106                                 return (1);
 107                 } while (--n != 0);
 108         }
 109 


 407                 grub_printf("not enough memory allocated\n");
 408                 return (ERR_WONT_FIT);
 409         }
 410 
 411         retbuf = buf;
 412         if (comp != ZIO_COMPRESS_OFF) {
 413                 buf = stack;
 414                 stack += psize;
 415         }
 416 
 417         if (zio_read_data(bp, buf, stack) != 0) {
 418                 grub_printf("zio_read_data failed\n");
 419                 return (ERR_FSYS_CORRUPT);
 420         }
 421 
 422         if (zio_checksum_verify(bp, buf, psize) != 0) {
 423                 grub_printf("checksum verification failed\n");
 424                 return (ERR_FSYS_CORRUPT);
 425         }
 426 
 427         if (comp != ZIO_COMPRESS_OFF) {
 428                 if (decomp_table[comp].decomp_func(buf, retbuf, psize,
 429                     lsize) != 0) {
 430                         grub_printf("zio_read decompression failed\n");
 431                         return (ERR_FSYS_CORRUPT);
 432                 }
 433         }
 434 
 435         return (0);
 436 }
 437 
 438 /*
 439  * Get the block from a block id.
 440  * push the block onto the stack.
 441  *
 442  * Return:
 443  *      0 - success
 444  *      errnum - failure
 445  */
 446 static int
 447 dmu_read(dnode_phys_t *dn, uint64_t blkid, void *buf, char *stack)
 448 {
 449         int idx, level;
 450         blkptr_t *bp_array = dn->dn_blkptr;
 451         int epbs = dn->dn_indblkshift - SPA_BLKPTRSHIFT;
 452         blkptr_t *bp, *tmpbuf;
 453 


 945 
 946         if (errnum = dnode_get(mosmdn, objnum, DMU_OT_POOL_PROPS, dn, stack))
 947                 return (errnum);
 948 
 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 static const char *spa_feature_names[] = {
 965         "org.illumos:lz4_compress",
 966         NULL
 967 };
 968 
 969 /*
 970  * Checks whether the MOS features that are active are supported by this
 971  * (GRUB's) implementation of ZFS.
 972  *
 973  * Return:
 974  *      0: Success.
 975  *      errnum: Failure.
 976  */
 977 static int
 978 check_mos_features(dnode_phys_t *mosmdn, char *stack)
 979 {
 980         uint64_t objnum;
 981         dnode_phys_t *dn;
 982         uint8_t error = 0;
 983 
 984         dn = (dnode_phys_t *)stack;
 985         stack += DNODE_SIZE;