usr/src/grub/grub-0.95/stage2/fsys_zfs.c
author ahrens
Fri, 29 Jun 2007 16:23:19 -0700
changeset 4577 ed36b0e652bc
parent 3912 f6891a60bd72
child 4725 0452c60b6e69
permissions -rw-r--r--
PSARC/2007/328 zfs upgrade 6552536 'zpool status -v' doesn't work with new (type-bearing) directory entries 6559635 can not import pool whose front labels are gone 6572636 need "zfs upgrade" to change ZPL version number 6572637 store object type in directory entries. 6572648 ZPL's delete queue should not be processed if the filesystem is mounted read-only 6572650 ZFS_VERSION should be SPA_VERSION for readability
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
3912
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
     1
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
     2
 *  GRUB  --  GRand Unified Bootloader
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
     3
 *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
     4
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
     5
 *  This program is free software; you can redistribute it and/or modify
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
     6
 *  it under the terms of the GNU General Public License as published by
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
     7
 *  the Free Software Foundation; either version 2 of the License, or
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
     8
 *  (at your option) any later version.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
     9
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    10
 *  This program is distributed in the hope that it will be useful,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    13
 *  GNU General Public License for more details.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    14
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    15
 *  You should have received a copy of the GNU General Public License
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    16
 *  along with this program; if not, write to the Free Software
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    17
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    18
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    19
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    20
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    21
 * Use is subject to license terms.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    22
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    23
#pragma ident	"%Z%%M%	%I%	%E% SMI"
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    24
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    25
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    26
 * The zfs plug-in routines for GRUB are:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    27
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    28
 * zfs_mount() - locates a valid uberblock of the root pool and reads
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    29
 *		in its MOS at the memory address MOS.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    30
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    31
 * zfs_open() - locates a plain file object by following the MOS
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    32
 *		and places its dnode at the memory address DNODE.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    33
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    34
 * zfs_read() - read in the data blocks pointed by the DNODE.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    35
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    36
 * ZFS_SCRATCH is used as a working area.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    37
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    38
 * (memory addr)   MOS      DNODE	ZFS_SCRATCH
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    39
 *		    |         |          |
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    40
 *	    +-------V---------V----------V---------------+
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    41
 *   memory |       | dnode   | dnode    |  scratch      |
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    42
 *	    |       | 512B    | 512B     |  area         |
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    43
 *	    +--------------------------------------------+
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    44
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    45
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    46
#ifdef	FSYS_ZFS
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    47
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    48
#include "shared.h"
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    49
#include "filesys.h"
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    50
#include "fsys_zfs.h"
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    51
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    52
/* cache for a file block of the currently zfs_open()-ed file */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    53
static void *file_buf = NULL;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    54
static uint64_t file_start = 0;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    55
static uint64_t file_end = 0;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    56
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    57
/* cache for a dnode block */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    58
static dnode_phys_t *dnode_buf = NULL;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    59
static dnode_phys_t *dnode_mdn = NULL;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    60
static uint64_t dnode_start = 0;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    61
static uint64_t dnode_end = 0;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    62
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    63
static char *stackbase;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    64
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    65
decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] =
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    66
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    67
	{"noop", 0},
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    68
	{"on", lzjb_decompress}, 	/* ZIO_COMPRESS_ON */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    69
	{"off", 0},
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    70
	{"lzjb", lzjb_decompress}	/* ZIO_COMPRESS_LZJB */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    71
};
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    72
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    73
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    74
 * Our own version of bcmp().
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    75
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    76
static int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    77
zfs_bcmp(const void *s1, const void *s2, size_t n)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    78
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    79
	const uchar_t *ps1 = s1;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    80
	const uchar_t *ps2 = s2;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    81
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    82
	if (s1 != s2 && n != 0) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    83
		do {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    84
			if (*ps1++ != *ps2++)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    85
				return (1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    86
		} while (--n != 0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    87
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    88
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    89
	return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    90
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    91
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    92
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    93
 * Our own version of log2().  Same thing as highbit()-1.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    94
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    95
static int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    96
zfs_log2(uint64_t num)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    97
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    98
	int i = 0;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
    99
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   100
	while (num > 1) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   101
		i++;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   102
		num = num >> 1;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   103
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   104
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   105
	return (i);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   106
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   107
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   108
/* Checksum Functions */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   109
static void
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   110
zio_checksum_off(const void *buf, uint64_t size, zio_cksum_t *zcp)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   111
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   112
	ZIO_SET_CHECKSUM(zcp, 0, 0, 0, 0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   113
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   114
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   115
/* Checksum Table and Values */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   116
zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   117
	NULL,			NULL,			0, 0,	"inherit",
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   118
	NULL,			NULL,			0, 0,	"on",
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   119
	zio_checksum_off,	zio_checksum_off,	0, 0,	"off",
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   120
	zio_checksum_SHA256,	zio_checksum_SHA256,	1, 1,	"label",
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   121
	zio_checksum_SHA256,	zio_checksum_SHA256,	1, 1,	"gang_header",
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   122
	fletcher_2_native,	fletcher_2_byteswap,	0, 1,	"zilog",
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   123
	fletcher_2_native,	fletcher_2_byteswap,	0, 0,	"fletcher2",
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   124
	fletcher_4_native,	fletcher_4_byteswap,	1, 0,	"fletcher4",
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   125
	zio_checksum_SHA256,	zio_checksum_SHA256,	1, 0,	"SHA256",
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   126
};
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   127
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   128
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   129
 * zio_checksum_verify: Provides support for checksum verification.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   130
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   131
 * Fletcher2, Fletcher4, and SHA256 are supported.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   132
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   133
 * Return:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   134
 * 	-1 = Failure
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   135
 *	 0 = Success
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   136
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   137
static int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   138
zio_checksum_verify(blkptr_t *bp, char *data, int size)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   139
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   140
	zio_cksum_t zc = bp->blk_cksum;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   141
	uint32_t checksum = BP_IS_GANG(bp) ? ZIO_CHECKSUM_GANG_HEADER :
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   142
	    BP_GET_CHECKSUM(bp);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   143
	int byteswap = BP_SHOULD_BYTESWAP(bp);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   144
	zio_block_tail_t *zbt = (zio_block_tail_t *)(data + size) - 1;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   145
	zio_checksum_info_t *ci = &zio_checksum_table[checksum];
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   146
	zio_cksum_t actual_cksum, expected_cksum;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   147
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   148
	/* byteswap is not supported */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   149
	if (byteswap)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   150
		return (-1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   151
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   152
	if (checksum >= ZIO_CHECKSUM_FUNCTIONS || ci->ci_func[0] == NULL)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   153
		return (-1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   154
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   155
	if (ci->ci_zbt) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   156
		if (checksum == ZIO_CHECKSUM_GANG_HEADER) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   157
			/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   158
			 * 'gang blocks' is not supported.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   159
			 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   160
			return (-1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   161
		}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   162
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   163
		if (zbt->zbt_magic == BSWAP_64(ZBT_MAGIC)) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   164
			/* byte swapping is not supported */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   165
			return (-1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   166
		} else {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   167
			expected_cksum = zbt->zbt_cksum;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   168
			zbt->zbt_cksum = zc;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   169
			ci->ci_func[0](data, size, &actual_cksum);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   170
			zbt->zbt_cksum = expected_cksum;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   171
		}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   172
		zc = expected_cksum;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   173
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   174
	} else {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   175
		if (BP_IS_GANG(bp))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   176
			return (-1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   177
		ci->ci_func[byteswap](data, size, &actual_cksum);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   178
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   179
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   180
	if ((actual_cksum.zc_word[0] - zc.zc_word[0]) |
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   181
	    (actual_cksum.zc_word[1] - zc.zc_word[1]) |
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   182
	    (actual_cksum.zc_word[2] - zc.zc_word[2]) |
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   183
	    (actual_cksum.zc_word[3] - zc.zc_word[3]))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   184
		return (-1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   185
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   186
	return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   187
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   188
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   189
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   190
 * vdev_label_offset takes "offset" (the offset within a vdev_label) and
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   191
 * returns its physical disk offset (starting from the beginning of the vdev).
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   192
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   193
 * Input:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   194
 *	psize	: Physical size of this vdev
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   195
 *      l	: Label Number (0-3)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   196
 *	offset	: The offset with a vdev_label in which we want the physical
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   197
 *		  address
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   198
 * Return:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   199
 * 	Success : physical disk offset
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   200
 * 	Failure : errnum = ERR_BAD_ARGUMENT, return value is meaningless
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   201
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   202
uint64_t
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   203
vdev_label_offset(uint64_t psize, int l, uint64_t offset)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   204
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   205
	/* XXX Need to add back label support! */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   206
	if (l >= VDEV_LABELS/2 || offset > sizeof (vdev_label_t)) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   207
		errnum = ERR_BAD_ARGUMENT;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   208
		return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   209
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   210
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   211
	return (offset + l * sizeof (vdev_label_t) + (l < VDEV_LABELS / 2 ?
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   212
	    0 : psize - VDEV_LABELS * sizeof (vdev_label_t)));
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   213
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   214
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   215
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   216
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   217
 * vdev_uberblock_compare takes two uberblock structures and returns an integer
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   218
 * indicating the more recent of the two.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   219
 * 	Return Value = 1 if ub2 is more recent
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   220
 * 	Return Value = -1 if ub1 is more recent
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   221
 * The most recent uberblock is determined using its transaction number and
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   222
 * timestamp.  The uberblock with the highest transaction number is
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   223
 * considered "newer".  If the transaction numbers of the two blocks match, the
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   224
 * timestamps are compared to determine the "newer" of the two.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   225
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   226
static int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   227
vdev_uberblock_compare(uberblock_t *ub1, uberblock_t *ub2)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   228
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   229
	if (ub1->ub_txg < ub2->ub_txg)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   230
		return (-1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   231
	if (ub1->ub_txg > ub2->ub_txg)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   232
		return (1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   233
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   234
	if (ub1->ub_timestamp < ub2->ub_timestamp)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   235
		return (-1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   236
	if (ub1->ub_timestamp > ub2->ub_timestamp)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   237
		return (1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   238
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   239
	return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   240
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   241
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   242
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   243
 * Three pieces of information are needed to verify an uberblock: the magic
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   244
 * number, the version number, and the checksum.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   245
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   246
 * Currently Implemented: version number, magic number
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   247
 * Need to Implement: checksum
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   248
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   249
 * Return:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   250
 *     0 - Success
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   251
 *    -1 - Failure
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   252
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   253
static int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   254
uberblock_verify(uberblock_phys_t *ub, int offset)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   255
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   256
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   257
	uberblock_t *uber = &ub->ubp_uberblock;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   258
	blkptr_t bp;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   259
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   260
	BP_ZERO(&bp);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   261
	BP_SET_CHECKSUM(&bp, ZIO_CHECKSUM_LABEL);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   262
	BP_SET_BYTEORDER(&bp, ZFS_HOST_BYTEORDER);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   263
	ZIO_SET_CHECKSUM(&bp.blk_cksum, offset, 0, 0, 0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   264
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   265
	if (zio_checksum_verify(&bp, (char *)ub, UBERBLOCK_SIZE) != 0)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   266
		return (-1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   267
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   268
	if (uber->ub_magic == UBERBLOCK_MAGIC &&
4577
ed36b0e652bc PSARC/2007/328 zfs upgrade
ahrens
parents: 3912
diff changeset
   269
	    uber->ub_version >= SPA_VERSION_1 &&
ed36b0e652bc PSARC/2007/328 zfs upgrade
ahrens
parents: 3912
diff changeset
   270
	    uber->ub_version <= SPA_VERSION)
3912
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   271
		return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   272
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   273
	return (-1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   274
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   275
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   276
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   277
 * Find the best uberblock.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   278
 * Return:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   279
 *    Success - Pointer to the best uberblock.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   280
 *    Failure - NULL
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   281
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   282
static uberblock_phys_t *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   283
find_bestub(uberblock_phys_t *ub_array, int label)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   284
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   285
	uberblock_phys_t *ubbest = NULL;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   286
	int i, offset;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   287
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   288
	for (i = 0; i < (VDEV_UBERBLOCK_RING >> VDEV_UBERBLOCK_SHIFT); i++) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   289
		offset = vdev_label_offset(0, label, VDEV_UBERBLOCK_OFFSET(i));
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   290
		if (errnum == ERR_BAD_ARGUMENT)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   291
			return (NULL);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   292
		if (uberblock_verify(&ub_array[i], offset) == 0) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   293
			if (ubbest == NULL) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   294
				ubbest = &ub_array[i];
4577
ed36b0e652bc PSARC/2007/328 zfs upgrade
ahrens
parents: 3912
diff changeset
   295
			} else if (vdev_uberblock_compare(
ed36b0e652bc PSARC/2007/328 zfs upgrade
ahrens
parents: 3912
diff changeset
   296
			    &(ub_array[i].ubp_uberblock),
ed36b0e652bc PSARC/2007/328 zfs upgrade
ahrens
parents: 3912
diff changeset
   297
			    &(ubbest->ubp_uberblock)) > 0) {
ed36b0e652bc PSARC/2007/328 zfs upgrade
ahrens
parents: 3912
diff changeset
   298
				ubbest = &ub_array[i];
3912
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   299
			}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   300
		}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   301
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   302
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   303
	return (ubbest);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   304
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   305
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   306
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   307
 * Read in a block and put its uncompressed data in buf.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   308
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   309
 * Return:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   310
 *	0 - success
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   311
 *	errnum - failure
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   312
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   313
static int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   314
zio_read(blkptr_t *bp, void *buf, char *stack)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   315
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   316
	uint64_t offset, sector;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   317
	int psize, lsize;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   318
	int i, comp, cksum;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   319
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   320
	psize = BP_GET_PSIZE(bp);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   321
	lsize = BP_GET_LSIZE(bp);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   322
	comp = BP_GET_COMPRESS(bp);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   323
	cksum = BP_GET_CHECKSUM(bp);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   324
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   325
	/* pick a good dva from the block pointer */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   326
	for (i = 0; i < SPA_DVAS_PER_BP; i++) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   327
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   328
		if (bp->blk_dva[i].dva_word[0] == 0 &&
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   329
		    bp->blk_dva[i].dva_word[1] == 0)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   330
			continue;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   331
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   332
		/* read in a block */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   333
		offset = DVA_GET_OFFSET(&bp->blk_dva[i]);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   334
		sector =  DVA_OFFSET_TO_PHYS_SECTOR(offset);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   335
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   336
		if (comp != ZIO_COMPRESS_OFF) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   337
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   338
			if (devread(sector, 0, psize, stack) == 0)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   339
				continue;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   340
			if (zio_checksum_verify(bp, stack, psize) != 0)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   341
				continue;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   342
			decomp_table[comp].decomp_func(stack, buf, psize,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   343
			    lsize);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   344
		} else {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   345
			if (devread(sector, 0, psize, buf) == 0)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   346
				continue;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   347
			if (zio_checksum_verify(bp, buf, psize) != 0)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   348
				continue;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   349
		}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   350
		return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   351
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   352
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   353
	return (ERR_FSYS_CORRUPT);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   354
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   355
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   356
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   357
 * Get the block from a block id.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   358
 * push the block onto the stack.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   359
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   360
 * Return:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   361
 * 	0 - success
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   362
 * 	errnum - failure
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   363
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   364
static int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   365
dmu_read(dnode_phys_t *dn, uint64_t blkid, void *buf, char *stack)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   366
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   367
	int idx, level;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   368
	blkptr_t *bp_array = dn->dn_blkptr;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   369
	int epbs = dn->dn_indblkshift - SPA_BLKPTRSHIFT;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   370
	blkptr_t *bp, *tmpbuf;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   371
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   372
	bp = (blkptr_t *)stack;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   373
	stack += sizeof (blkptr_t);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   374
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   375
	tmpbuf = (blkptr_t *)stack;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   376
	stack += 1<<dn->dn_indblkshift;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   377
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   378
	for (level = dn->dn_nlevels - 1; level >= 0; level--) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   379
		idx = (blkid >> (epbs * level)) & ((1<<epbs)-1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   380
		*bp = bp_array[idx];
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   381
		if (level == 0)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   382
			tmpbuf = buf;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   383
		if (errnum = zio_read(bp, tmpbuf, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   384
			return (errnum);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   385
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   386
		bp_array = tmpbuf;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   387
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   388
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   389
	return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   390
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   391
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   392
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   393
 * mzap_lookup: Looks up property described by "name" and returns the value
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   394
 * in "value".
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   395
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   396
 * Return:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   397
 *	0 - success
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   398
 *	errnum - failure
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   399
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   400
static int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   401
mzap_lookup(mzap_phys_t *zapobj, int objsize, char *name,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   402
	uint64_t *value)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   403
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   404
	int i, chunks;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   405
	mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   406
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   407
	chunks = objsize/MZAP_ENT_LEN - 1;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   408
	for (i = 0; i < chunks; i++) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   409
		if (grub_strcmp(mzap_ent[i].mze_name, name) == 0) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   410
			*value = mzap_ent[i].mze_value;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   411
			return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   412
		}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   413
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   414
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   415
	return (ERR_FSYS_CORRUPT);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   416
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   417
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   418
static uint64_t
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   419
zap_hash(uint64_t salt, const char *name)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   420
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   421
	static uint64_t table[256];
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   422
	const uint8_t *cp;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   423
	uint8_t c;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   424
	uint64_t crc = salt;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   425
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   426
	if (table[128] == 0) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   427
		uint64_t *ct;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   428
		int i, j;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   429
		for (i = 0; i < 256; i++) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   430
			for (ct = table + i, *ct = i, j = 8; j > 0; j--)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   431
				*ct = (*ct >> 1) ^ (-(*ct & 1) &
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   432
				    ZFS_CRC64_POLY);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   433
		}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   434
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   435
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   436
	if (crc == 0 || table[128] != ZFS_CRC64_POLY) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   437
		errnum = ERR_FSYS_CORRUPT;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   438
		return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   439
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   440
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   441
	for (cp = (const uint8_t *)name; (c = *cp) != '\0'; cp++)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   442
		crc = (crc >> 8) ^ table[(crc ^ c) & 0xFF];
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   443
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   444
	/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   445
	 * Only use 28 bits, since we need 4 bits in the cookie for the
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   446
	 * collision differentiator.  We MUST use the high bits, since
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   447
	 * those are the onces that we first pay attention to when
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   448
	 * chosing the bucket.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   449
	 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   450
	crc &= ~((1ULL << (64 - ZAP_HASHBITS)) - 1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   451
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   452
	return (crc);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   453
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   454
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   455
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   456
 * Only to be used on 8-bit arrays.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   457
 * array_len is actual len in bytes (not encoded le_value_length).
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   458
 * buf is null-terminated.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   459
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   460
static int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   461
zap_leaf_array_equal(zap_leaf_phys_t *l, int blksft, int chunk,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   462
    int array_len, const char *buf)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   463
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   464
	int bseen = 0;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   465
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   466
	while (bseen < array_len) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   467
		struct zap_leaf_array *la =
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   468
		    &ZAP_LEAF_CHUNK(l, blksft, chunk).l_array;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   469
		int toread = MIN(array_len - bseen, ZAP_LEAF_ARRAY_BYTES);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   470
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   471
		if (chunk >= ZAP_LEAF_NUMCHUNKS(blksft))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   472
			return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   473
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   474
		if (zfs_bcmp(la->la_array, buf + bseen, toread) != 0)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   475
			break;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   476
		chunk = la->la_next;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   477
		bseen += toread;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   478
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   479
	return (bseen == array_len);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   480
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   481
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   482
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   483
 * Given a zap_leaf_phys_t, walk thru the zap leaf chunks to get the
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   484
 * value for the property "name".
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   485
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   486
 * Return:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   487
 *	0 - success
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   488
 *	errnum - failure
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   489
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   490
int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   491
zap_leaf_lookup(zap_leaf_phys_t *l, int blksft, uint64_t h,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   492
    const char *name, uint64_t *value)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   493
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   494
	uint16_t chunk;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   495
	struct zap_leaf_entry *le;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   496
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   497
	/* Verify if this is a valid leaf block */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   498
	if (l->l_hdr.lh_block_type != ZBT_LEAF)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   499
		return (ERR_FSYS_CORRUPT);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   500
	if (l->l_hdr.lh_magic != ZAP_LEAF_MAGIC)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   501
		return (ERR_FSYS_CORRUPT);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   502
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   503
	for (chunk = l->l_hash[LEAF_HASH(blksft, h)];
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   504
	    chunk != CHAIN_END; chunk = le->le_next) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   505
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   506
		if (chunk >= ZAP_LEAF_NUMCHUNKS(blksft))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   507
			return (ERR_FSYS_CORRUPT);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   508
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   509
		le = ZAP_LEAF_ENTRY(l, blksft, chunk);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   510
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   511
		/* Verify the chunk entry */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   512
		if (le->le_type != ZAP_CHUNK_ENTRY)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   513
			return (ERR_FSYS_CORRUPT);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   514
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   515
		if (le->le_hash != h)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   516
			continue;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   517
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   518
		if (zap_leaf_array_equal(l, blksft, le->le_name_chunk,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   519
		    le->le_name_length, name)) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   520
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   521
			struct zap_leaf_array *la;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   522
			uint8_t *ip;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   523
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   524
			if (le->le_int_size != 8 || le->le_value_length != 1)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   525
				return (ERR_FSYS_CORRUPT);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   526
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   527
			/* get the uint64_t property value */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   528
			la = &ZAP_LEAF_CHUNK(l, blksft,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   529
			    le->le_value_chunk).l_array;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   530
			ip = la->la_array;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   531
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   532
			*value = (uint64_t)ip[0] << 56 | (uint64_t)ip[1] << 48 |
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   533
			    (uint64_t)ip[2] << 40 | (uint64_t)ip[3] << 32 |
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   534
			    (uint64_t)ip[4] << 24 | (uint64_t)ip[5] << 16 |
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   535
			    (uint64_t)ip[6] << 8 | (uint64_t)ip[7];
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   536
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   537
			return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   538
		}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   539
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   540
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   541
	return (ERR_FSYS_CORRUPT);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   542
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   543
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   544
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   545
 * Fat ZAP lookup
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   546
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   547
 * Return:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   548
 *	0 - success
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   549
 *	errnum - failure
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   550
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   551
int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   552
fzap_lookup(dnode_phys_t *zap_dnode, zap_phys_t *zap,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   553
    char *name, uint64_t *value, char *stack)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   554
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   555
	zap_leaf_phys_t *l;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   556
	uint64_t hash, idx, blkid;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   557
	int blksft = zfs_log2(zap_dnode->dn_datablkszsec << DNODE_SHIFT);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   558
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   559
	/* Verify if this is a fat zap header block */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   560
	if (zap->zap_magic != (uint64_t)ZAP_MAGIC)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   561
		return (ERR_FSYS_CORRUPT);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   562
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   563
	hash = zap_hash(zap->zap_salt, name);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   564
	if (errnum)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   565
		return (errnum);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   566
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   567
	/* get block id from index */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   568
	if (zap->zap_ptrtbl.zt_numblks != 0) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   569
		/* external pointer tables not supported */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   570
		return (ERR_FSYS_CORRUPT);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   571
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   572
	idx = ZAP_HASH_IDX(hash, zap->zap_ptrtbl.zt_shift);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   573
	blkid = ((uint64_t *)zap)[idx + (1<<(blksft-3-1))];
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   574
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   575
	/* Get the leaf block */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   576
	l = (zap_leaf_phys_t *)stack;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   577
	stack += 1<<blksft;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   578
	if (errnum = dmu_read(zap_dnode, blkid, l, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   579
		return (errnum);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   580
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   581
	return (zap_leaf_lookup(l, blksft, hash, name, value));
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   582
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   583
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   584
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   585
 * Read in the data of a zap object and find the value for a matching
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   586
 * property name.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   587
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   588
 * Return:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   589
 *	0 - success
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   590
 *	errnum - failure
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   591
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   592
static int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   593
zap_lookup(dnode_phys_t *zap_dnode, char *name, uint64_t *val, char *stack)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   594
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   595
	uint64_t block_type;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   596
	int size;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   597
	void *zapbuf;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   598
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   599
	/* Read in the first block of the zap object data. */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   600
	zapbuf = stack;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   601
	size = zap_dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   602
	stack += size;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   603
	if (errnum = dmu_read(zap_dnode, 0, zapbuf, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   604
		return (errnum);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   605
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   606
	block_type = *((uint64_t *)zapbuf);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   607
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   608
	if (block_type == ZBT_MICRO) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   609
		return (mzap_lookup(zapbuf, size, name, val));
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   610
	} else if (block_type == ZBT_HEADER) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   611
		/* this is a fat zap */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   612
		return (fzap_lookup(zap_dnode, zapbuf, name,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   613
		    val, stack));
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   614
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   615
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   616
	return (ERR_FSYS_CORRUPT);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   617
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   618
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   619
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   620
 * Get the dnode of an object number from the metadnode of an object set.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   621
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   622
 * Input
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   623
 *	mdn - metadnode to get the object dnode
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   624
 *	objnum - object number for the object dnode
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   625
 *	buf - data buffer that holds the returning dnode
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   626
 *	stack - scratch area
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   627
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   628
 * Return:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   629
 *	0 - success
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   630
 *	errnum - failure
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   631
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   632
static int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   633
dnode_get(dnode_phys_t *mdn, uint64_t objnum, uint8_t type, dnode_phys_t *buf,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   634
	char *stack)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   635
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   636
	uint64_t blkid, blksz; /* the block id this object dnode is in */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   637
	int epbs; /* shift of number of dnodes in a block */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   638
	int idx; /* index within a block */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   639
	dnode_phys_t *dnbuf;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   640
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   641
	blksz = mdn->dn_datablkszsec << SPA_MINBLOCKSHIFT;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   642
	epbs = zfs_log2(blksz) - DNODE_SHIFT;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   643
	blkid = objnum >> epbs;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   644
	idx = objnum & ((1<<epbs)-1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   645
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   646
	if (dnode_buf != NULL && dnode_mdn == mdn &&
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   647
	    objnum >= dnode_start && objnum < dnode_end) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   648
		grub_memmove(buf, &dnode_buf[idx], DNODE_SIZE);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   649
		VERIFY_DN_TYPE(buf, type);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   650
		return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   651
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   652
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   653
	if (dnode_buf && blksz == 1<<DNODE_BLOCK_SHIFT) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   654
		dnbuf = dnode_buf;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   655
		dnode_mdn = mdn;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   656
		dnode_start = blkid << epbs;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   657
		dnode_end = (blkid + 1) << epbs;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   658
	} else {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   659
		dnbuf = (dnode_phys_t *)stack;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   660
		stack += blksz;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   661
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   662
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   663
	if (errnum = dmu_read(mdn, blkid, (char *)dnbuf, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   664
		return (errnum);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   665
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   666
	grub_memmove(buf, &dnbuf[idx], DNODE_SIZE);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   667
	VERIFY_DN_TYPE(buf, type);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   668
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   669
	return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   670
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   671
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   672
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   673
 * Check if this is the "menu.lst" file.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   674
 * str starts with '/'.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   675
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   676
static int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   677
is_menu_lst(char *str)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   678
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   679
	char *tptr;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   680
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   681
	if ((tptr = grub_strstr(str, "menu.lst")) &&
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   682
	    (tptr[8] == '\0' || tptr[8] == ' ') &&
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   683
	    *(tptr-1) == '/')
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   684
		return (1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   685
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   686
	return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   687
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   688
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   689
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   690
 * Get the file dnode for a given file name where mdn is the meta dnode
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   691
 * for this ZFS object set. When found, place the file dnode in dn.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   692
 * The 'path' argument will be mangled.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   693
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   694
 * Return:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   695
 *	0 - success
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   696
 *	errnum - failure
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   697
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   698
static int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   699
dnode_get_path(dnode_phys_t *mdn, char *path, dnode_phys_t *dn,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   700
    char *stack)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   701
{
4577
ed36b0e652bc PSARC/2007/328 zfs upgrade
ahrens
parents: 3912
diff changeset
   702
	uint64_t objnum, version;
3912
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   703
	char *cname, ch;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   704
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   705
	if (errnum = dnode_get(mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   706
	    dn, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   707
		return (errnum);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   708
4577
ed36b0e652bc PSARC/2007/328 zfs upgrade
ahrens
parents: 3912
diff changeset
   709
	if (errnum = zap_lookup(dn, ZPL_VERSION_STR, &version, stack))
ed36b0e652bc PSARC/2007/328 zfs upgrade
ahrens
parents: 3912
diff changeset
   710
		return (errnum);
ed36b0e652bc PSARC/2007/328 zfs upgrade
ahrens
parents: 3912
diff changeset
   711
	if (version > ZPL_VERSION)
ed36b0e652bc PSARC/2007/328 zfs upgrade
ahrens
parents: 3912
diff changeset
   712
		return (-1);
ed36b0e652bc PSARC/2007/328 zfs upgrade
ahrens
parents: 3912
diff changeset
   713
3912
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   714
	if (errnum = zap_lookup(dn, ZFS_ROOT_OBJ, &objnum, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   715
		return (errnum);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   716
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   717
	if (errnum = dnode_get(mdn, objnum, DMU_OT_DIRECTORY_CONTENTS,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   718
	    dn, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   719
		return (errnum);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   720
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   721
	/* skip leading slashes */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   722
	while (*path == '/')
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   723
		path++;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   724
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   725
	while (*path && !isspace(*path)) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   726
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   727
		/* get the next component name */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   728
		cname = path;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   729
		while (*path && !isspace(*path) && *path != '/')
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   730
			path++;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   731
		ch = *path;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   732
		*path = 0;   /* ensure null termination */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   733
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   734
		if (errnum = zap_lookup(dn, cname, &objnum, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   735
			return (errnum);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   736
4577
ed36b0e652bc PSARC/2007/328 zfs upgrade
ahrens
parents: 3912
diff changeset
   737
		objnum = ZFS_DIRENT_OBJ(objnum);
3912
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   738
		if (errnum = dnode_get(mdn, objnum, 0, dn, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   739
			return (errnum);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   740
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   741
		*path = ch;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   742
		while (*path == '/')
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   743
			path++;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   744
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   745
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   746
	/* We found the dnode for this file. Verify if it is a plain file. */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   747
	VERIFY_DN_TYPE(dn, DMU_OT_PLAIN_FILE_CONTENTS);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   748
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   749
	return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   750
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   751
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   752
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   753
 * Get the default 'bootfs' property value from the rootpool.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   754
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   755
 * Return:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   756
 *	0 - success
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   757
 *	errnum -failure
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   758
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   759
static int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   760
get_default_bootfsobj(dnode_phys_t *mosmdn, uint64_t *obj, char *stack)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   761
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   762
	uint64_t objnum = 0;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   763
	dnode_phys_t *dn = (dnode_phys_t *)stack;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   764
	stack += DNODE_SIZE;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   765
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   766
	if (dnode_get(mosmdn, DMU_POOL_DIRECTORY_OBJECT,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   767
	    DMU_OT_OBJECT_DIRECTORY, dn, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   768
		return (ERR_FILESYSTEM_NOT_FOUND);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   769
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   770
	/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   771
	 * find the object number for 'pool_props', and get the dnode
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   772
	 * of the 'pool_props'.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   773
	 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   774
	if (zap_lookup(dn, DMU_POOL_PROPS, &objnum, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   775
		return (ERR_FILESYSTEM_NOT_FOUND);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   776
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   777
	if (dnode_get(mosmdn, objnum, DMU_OT_POOL_PROPS, dn, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   778
		return (ERR_FILESYSTEM_NOT_FOUND);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   779
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   780
	if (zap_lookup(dn, ZPOOL_PROP_BOOTFS, &objnum, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   781
		return (ERR_FILESYSTEM_NOT_FOUND);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   782
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   783
	if (!objnum)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   784
		return (ERR_FILESYSTEM_NOT_FOUND);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   785
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   786
	*obj = objnum;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   787
	return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   788
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   789
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   790
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   791
 * Given a MOS metadnode, get the metadnode of a given filesystem name (fsname),
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   792
 * e.g. pool/rootfs, or a given object number (obj), e.g. the object number
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   793
 * of pool/rootfs.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   794
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   795
 * If no fsname and no obj are given, return the DSL_DIR metadnode.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   796
 * If fsname is given, return its metadnode and its matching object number.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   797
 * If only obj is given, return the metadnode for this object number.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   798
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   799
 * Return:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   800
 *	0 - success
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   801
 *	errnum - failure
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   802
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   803
static int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   804
get_objset_mdn(dnode_phys_t *mosmdn, char *fsname, uint64_t *obj,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   805
    dnode_phys_t *mdn, char *stack)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   806
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   807
	uint64_t objnum, headobj;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   808
	char *cname, ch;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   809
	blkptr_t *bp;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   810
	objset_phys_t *osp;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   811
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   812
	if (fsname == NULL && obj) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   813
		headobj = *obj;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   814
		goto skip;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   815
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   816
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   817
	if (errnum = dnode_get(mosmdn, DMU_POOL_DIRECTORY_OBJECT,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   818
	    DMU_OT_OBJECT_DIRECTORY, mdn, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   819
		return (errnum);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   820
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   821
	if (errnum = zap_lookup(mdn, DMU_POOL_ROOT_DATASET, &objnum,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   822
	    stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   823
		return (errnum);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   824
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   825
	if (errnum = dnode_get(mosmdn, objnum, DMU_OT_DSL_DIR, mdn, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   826
		return (errnum);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   827
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   828
	if (fsname == NULL) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   829
		headobj =
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   830
		    ((dsl_dir_phys_t *)DN_BONUS(mdn))->dd_head_dataset_obj;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   831
		goto skip;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   832
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   833
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   834
	/* take out the pool name */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   835
	while (*fsname && !isspace(*fsname) && *fsname != '/')
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   836
		fsname++;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   837
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   838
	while (*fsname && !isspace(*fsname)) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   839
		uint64_t childobj;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   840
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   841
		while (*fsname == '/')
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   842
			fsname++;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   843
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   844
		cname = fsname;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   845
		while (*fsname && !isspace(*fsname) && *fsname != '/')
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   846
			fsname++;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   847
		ch = *fsname;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   848
		*fsname = 0;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   849
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   850
		childobj =
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   851
		    ((dsl_dir_phys_t *)DN_BONUS(mdn))->dd_child_dir_zapobj;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   852
		if (errnum = dnode_get(mosmdn, childobj,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   853
		    DMU_OT_DSL_DIR_CHILD_MAP, mdn, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   854
			return (errnum);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   855
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   856
		if (errnum = zap_lookup(mdn, cname, &objnum, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   857
			return (errnum);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   858
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   859
		if (errnum = dnode_get(mosmdn, objnum, DMU_OT_DSL_DIR,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   860
		    mdn, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   861
			return (errnum);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   862
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   863
		*fsname = ch;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   864
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   865
	headobj = ((dsl_dir_phys_t *)DN_BONUS(mdn))->dd_head_dataset_obj;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   866
	if (obj)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   867
		*obj = headobj;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   868
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   869
skip:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   870
	if (errnum = dnode_get(mosmdn, headobj, DMU_OT_DSL_DATASET, mdn, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   871
		return (errnum);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   872
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   873
	/* TODO: Add snapshot support here - for fsname=snapshot-name */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   874
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   875
	bp = &((dsl_dataset_phys_t *)DN_BONUS(mdn))->ds_bp;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   876
	osp = (objset_phys_t *)stack;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   877
	stack += sizeof (objset_phys_t);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   878
	if (errnum = zio_read(bp, osp, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   879
		return (errnum);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   880
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   881
	grub_memmove((char *)mdn, (char *)&osp->os_meta_dnode, DNODE_SIZE);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   882
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   883
	return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   884
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   885
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   886
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   887
 * Parse the packed nvlist and search for the string value of a given name.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   888
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   889
 * An XDR packed nvlist is encoded as (from nvs_xdr_create) :
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   890
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   891
 *      encoding method/host endian     (4 bytes)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   892
 *      nvl_version                     (4 bytes)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   893
 *      nvl_nvflag                      (4 bytes)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   894
 *	encoded nvpairs:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   895
 *		encoded size of the nvpair      (4 bytes)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   896
 *		decoded size of the nvpair      (4 bytes)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   897
 *		name string size                (4 bytes)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   898
 *		name string data                (sizeof(NV_ALIGN4(string))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   899
 *		data type                       (4 bytes)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   900
 *		# of elements in the nvpair     (4 bytes)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   901
 *		data
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   902
 *      2 zero's for the last nvpair
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   903
 *		(end of the entire list)	(8 bytes)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   904
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   905
 * Return:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   906
 *	0 - success
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   907
 *	1 - failure
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   908
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   909
int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   910
nvlist_lookup_value(char *nvlist, char *name, void *val, int valtype)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   911
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   912
	int name_len, type, nelm, slen, encode_size;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   913
	char *nvpair, *nvp_name, *strval = val;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   914
	uint64_t *intval = val;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   915
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   916
	/* Verify if the 1st and 2nd byte in the nvlist are valid. */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   917
	if (nvlist[0] != NV_ENCODE_XDR || nvlist[1] != HOST_ENDIAN)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   918
		return (1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   919
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   920
	/* skip the header, nvl_version, and nvl_nvflag */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   921
	nvlist = nvlist + 4 * 3;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   922
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   923
	/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   924
	 * Loop thru the nvpair list
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   925
	 * The XDR representation of an integer is in big-endian byte order.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   926
	 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   927
	while (encode_size = BSWAP_32(*(uint32_t *)nvlist))  {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   928
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   929
		nvpair = nvlist + 4 * 2; /* skip the encode/decode size */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   930
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   931
		name_len = BSWAP_32(*(uint32_t *)nvpair);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   932
		nvpair += 4;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   933
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   934
		nvp_name = nvpair;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   935
		nvpair = nvpair + ((name_len + 3) & ~3); /* align */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   936
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   937
		type = BSWAP_32(*(uint32_t *)nvpair);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   938
		nvpair += 4;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   939
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   940
		if ((grub_strncmp(nvp_name, name, name_len) == 0) &&
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   941
		    type == valtype) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   942
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   943
			if ((nelm = BSWAP_32(*(uint32_t *)nvpair)) != 1)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   944
				return (1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   945
			nvpair += 4;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   946
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   947
			switch (valtype) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   948
			case DATA_TYPE_STRING:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   949
				slen = BSWAP_32(*(uint32_t *)nvpair);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   950
				nvpair += 4;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   951
				grub_memmove(strval, nvpair, slen);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   952
				strval[slen] = '\0';
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   953
				return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   954
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   955
			case DATA_TYPE_UINT64:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   956
				*intval = BSWAP_64(*(uint64_t *)nvpair);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   957
				return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   958
			}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   959
		}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   960
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   961
		nvlist += encode_size; /* goto the next nvpair */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   962
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   963
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   964
	return (1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   965
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   966
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   967
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   968
 * Get the pool name of the root pool from the vdev nvpair list of the label.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   969
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   970
 * Return:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   971
 *	0 - success
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   972
 *	errnum - failure
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   973
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   974
int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   975
get_pool_name_value(int label, char *name, void *value, int valtype,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   976
    char *stack)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   977
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   978
	vdev_phys_t *vdev;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   979
	uint64_t sector;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   980
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   981
	sector = (label * sizeof (vdev_label_t) + VDEV_SKIP_SIZE +
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   982
	    VDEV_BOOT_HEADER_SIZE) >> SPA_MINBLOCKSHIFT;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   983
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   984
	/* Read in the vdev name-value pair list (112K). */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   985
	if (devread(sector, 0, VDEV_PHYS_SIZE, stack) == 0)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   986
		return (ERR_READ);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   987
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   988
	vdev = (vdev_phys_t *)stack;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   989
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   990
	if (nvlist_lookup_value(vdev->vp_nvlist, name, value, valtype))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   991
		return (ERR_FSYS_CORRUPT);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   992
	else
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   993
		return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   994
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   995
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   996
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   997
 * zfs_mount() locates a valid uberblock of the root pool and read in its MOS
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   998
 * to the memory address MOS.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
   999
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1000
 * Return:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1001
 *	1 - success
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1002
 *	0 - failure
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1003
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1004
int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1005
zfs_mount(void)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1006
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1007
	char *stack;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1008
	int label = 0;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1009
	uberblock_phys_t *ub_array, *ubbest = NULL;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1010
	objset_phys_t *osp;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1011
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1012
	/* if zfs is already mounted, don't do it again */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1013
	if (is_zfs_mount == 1)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1014
		return (1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1015
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1016
	stackbase = ZFS_SCRATCH;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1017
	stack = stackbase;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1018
	ub_array = (uberblock_phys_t *)stack;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1019
	stack += VDEV_UBERBLOCK_RING;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1020
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1021
	osp = (objset_phys_t *)stack;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1022
	stack += sizeof (objset_phys_t);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1023
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1024
	/* XXX add back labels support? */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1025
	for (label = 0; ubbest == NULL && label < (VDEV_LABELS/2); label++) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1026
		uint64_t sector = (label * sizeof (vdev_label_t) +
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1027
		    VDEV_SKIP_SIZE + VDEV_BOOT_HEADER_SIZE +
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1028
		    VDEV_PHYS_SIZE) >> SPA_MINBLOCKSHIFT;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1029
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1030
		/* Read in the uberblock ring (128K). */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1031
		if (devread(sector, 0, VDEV_UBERBLOCK_RING,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1032
		    (char *)ub_array) == 0)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1033
			continue;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1034
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1035
		if ((ubbest = find_bestub(ub_array, label)) != NULL &&
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1036
		    zio_read(&ubbest->ubp_uberblock.ub_rootbp, osp, stack)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1037
		    == 0) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1038
			uint64_t pool_state;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1039
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1040
			VERIFY_OS_TYPE(osp, DMU_OST_META);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1041
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1042
			/* Got the MOS. Save it at the memory addr MOS. */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1043
			grub_memmove(MOS, &osp->os_meta_dnode, DNODE_SIZE);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1044
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1045
			if (get_pool_name_value(label, ZPOOL_CONFIG_POOL_STATE,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1046
			    &pool_state, DATA_TYPE_UINT64, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1047
				return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1048
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1049
			if (pool_state == POOL_STATE_DESTROYED)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1050
				return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1051
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1052
			if (get_pool_name_value(label, ZPOOL_CONFIG_POOL_NAME,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1053
			    current_rootpool, DATA_TYPE_STRING, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1054
				return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1055
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1056
			is_zfs_mount = 1;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1057
			return (1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1058
		}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1059
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1060
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1061
	return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1062
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1063
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1064
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1065
 * zfs_open() locates a file in the rootpool by following the
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1066
 * MOS and places the dnode of the file in the memory address DNODE.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1067
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1068
 * Return:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1069
 *	1 - success
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1070
 *	0 - failure
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1071
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1072
int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1073
zfs_open(char *filename)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1074
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1075
	char *stack;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1076
	dnode_phys_t *mdn;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1077
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1078
	file_buf = NULL;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1079
	stackbase = ZFS_SCRATCH;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1080
	stack = stackbase;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1081
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1082
	mdn = (dnode_phys_t *)stack;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1083
	stack += sizeof (dnode_phys_t);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1084
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1085
	dnode_mdn = NULL;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1086
	dnode_buf = (dnode_phys_t *)stack;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1087
	stack += 1<<DNODE_BLOCK_SHIFT;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1088
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1089
	/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1090
	 * menu.lst is placed at the root pool filesystem level,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1091
	 * do not goto 'current_bootfs'.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1092
	 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1093
	if (is_menu_lst(filename)) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1094
		if (errnum = get_objset_mdn(MOS, NULL, NULL, mdn, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1095
			return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1096
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1097
		current_bootfs_obj = 0;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1098
	} else {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1099
		if (current_bootfs[0] == '\0') {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1100
			/* Get the default root filesystem object number */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1101
			if (get_default_bootfsobj(MOS,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1102
			    &current_bootfs_obj, stack)) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1103
				errnum = ERR_FILESYSTEM_NOT_FOUND;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1104
				return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1105
			}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1106
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1107
			if (errnum = get_objset_mdn(MOS, NULL,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1108
			    &current_bootfs_obj, mdn, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1109
				return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1110
		} else {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1111
			if (errnum = get_objset_mdn(MOS,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1112
			    current_bootfs, &current_bootfs_obj, mdn, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1113
				return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1114
		}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1115
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1116
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1117
	if (dnode_get_path(mdn, filename, DNODE, stack)) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1118
		errnum = ERR_FILE_NOT_FOUND;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1119
		return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1120
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1121
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1122
	/* get the file size and set the file position to 0 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1123
	filemax = ((znode_phys_t *)DN_BONUS(DNODE))->zp_size;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1124
	filepos = 0;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1125
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1126
	dnode_buf = NULL;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1127
	return (1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1128
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1129
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1130
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1131
 * zfs_read reads in the data blocks pointed by the DNODE.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1132
 *
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1133
 * Return:
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1134
 *	len - the length successfully read in to the buffer
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1135
 *	0   - failure
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1136
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1137
int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1138
zfs_read(char *buf, int len)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1139
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1140
	char *stack;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1141
	char *tmpbuf;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1142
	int blksz, length, movesize;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1143
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1144
	if (file_buf == NULL) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1145
		file_buf = stackbase;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1146
		stackbase += SPA_MAXBLOCKSIZE;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1147
		file_start = file_end = 0;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1148
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1149
	stack = stackbase;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1150
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1151
	/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1152
	 * If offset is in memory, move it into the buffer provided and return.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1153
	 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1154
	if (filepos >= file_start && filepos+len <= file_end) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1155
		grub_memmove(buf, file_buf + filepos - file_start, len);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1156
		filepos += len;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1157
		return (len);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1158
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1159
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1160
	blksz = DNODE->dn_datablkszsec << SPA_MINBLOCKSHIFT;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1161
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1162
	/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1163
	 * Entire Dnode is too big to fit into the space available.  We
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1164
	 * will need to read it in chunks.  This could be optimized to
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1165
	 * read in as large a chunk as there is space available, but for
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1166
	 * now, this only reads in one data block at a time.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1167
	 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1168
	length = len;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1169
	while (length) {
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1170
		/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1171
		 * Find requested blkid and the offset within that block.
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1172
		 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1173
		uint64_t blkid = filepos / blksz;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1174
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1175
		if (errnum = dmu_read(DNODE, blkid, file_buf, stack))
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1176
			return (0);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1177
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1178
		file_start = blkid * blksz;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1179
		file_end = file_start + blksz;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1180
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1181
		movesize = MIN(length, file_end - filepos);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1182
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1183
		grub_memmove(buf, file_buf + filepos - file_start,
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1184
		    movesize);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1185
		buf += movesize;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1186
		length -= movesize;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1187
		filepos += movesize;
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1188
	}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1189
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1190
	return (len);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1191
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1192
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1193
/*
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1194
 * No-Op
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1195
 */
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1196
int
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1197
zfs_embed(int *start_sector, int needed_sectors)
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1198
{
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1199
	return (1);
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1200
}
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1201
f6891a60bd72 PSARC 2007/083 ZFS bootable datasets
lling
parents:
diff changeset
  1202
#endif /* FSYS_ZFS */