usr/src/uts/common/fs/zfs/vdev_disk.c
author eschrock
Mon, 30 Jan 2006 21:34:28 -0800
changeset 1354 81359ee1ee63
parent 1171 b501e9f31cab
child 1489 fa842259660e
permissions -rw-r--r--
6362672 import gets confused about overlapping slices 6364582 need to fixup paths if they've changed
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     1
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     2
 * CDDL HEADER START
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     3
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     5
 * Common Development and Distribution License, Version 1.0 only
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     6
 * (the "License").  You may not use this file except in compliance
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     7
 * with the License.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     8
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    10
 * or http://www.opensolaris.org/os/licensing.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    11
 * See the License for the specific language governing permissions
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    12
 * and limitations under the License.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    13
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    14
 * When distributing Covered Code, include this CDDL HEADER in each
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    16
 * If applicable, add the following below this CDDL HEADER, with the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    17
 * fields enclosed by brackets "[]" replaced with your own identifying
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    18
 * information: Portions Copyright [yyyy] [name of copyright owner]
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    19
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    20
 * CDDL HEADER END
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    21
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    22
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    23
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    24
 * Use is subject to license terms.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    25
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    26
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    27
#pragma ident	"%Z%%M%	%I%	%E% SMI"
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    28
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    29
#include <sys/zfs_context.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    30
#include <sys/spa.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    31
#include <sys/vdev_disk.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    32
#include <sys/vdev_impl.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    33
#include <sys/fs/zfs.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    34
#include <sys/zio.h>
1171
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
    35
#include <sys/sunldi.h>
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    36
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    37
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    38
 * Virtual device vector for disks.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    39
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    40
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    41
extern ldi_ident_t zfs_li;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    42
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    43
typedef struct vdev_disk_buf {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    44
	buf_t	vdb_buf;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    45
	zio_t	*vdb_io;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    46
} vdev_disk_buf_t;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    47
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    48
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    49
vdev_disk_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    50
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    51
	vdev_disk_t *dvd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    52
	int error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    53
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    54
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    55
	 * We must have a pathname, and it must be absolute.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    56
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    57
	if (vd->vdev_path == NULL || vd->vdev_path[0] != '/') {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    58
		vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    59
		return (EINVAL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    60
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    61
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    62
	dvd = vd->vdev_tsd = kmem_zalloc(sizeof (vdev_disk_t), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    63
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    64
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    65
	 * When opening a disk device, we want to preserve the user's original
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    66
	 * intent.  We always want to open the device by the path the user gave
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    67
	 * us, even if it is one of multiple paths to the save device.  But we
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    68
	 * also want to be able to survive disks being removed/recabled.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    69
	 * Therefore the sequence of opening devices is:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    70
	 *
1171
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
    71
	 * 1. Try opening the device by path.  For legacy pools without the
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
    72
	 *    'whole_disk' property, attempt to fix the path by appending 's0'.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    73
	 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    74
	 * 2. If the devid of the device matches the stored value, return
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    75
	 *    success.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    76
	 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    77
	 * 3. Otherwise, the device may have moved.  Try opening the device
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    78
	 *    by the devid instead.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    79
	 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    80
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    81
	if (vd->vdev_devid != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    82
		if (ddi_devid_str_decode(vd->vdev_devid, &dvd->vd_devid,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    83
		    &dvd->vd_minor) != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    84
			vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    85
			return (EINVAL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    86
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    87
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    88
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    89
	error = EINVAL;		/* presume failure */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    90
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    91
	if (vd->vdev_path != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    92
		ddi_devid_t devid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    93
1171
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
    94
		if (vd->vdev_wholedisk == -1ULL) {
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
    95
			size_t len = strlen(vd->vdev_path) + 3;
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
    96
			char *buf = kmem_alloc(len, KM_SLEEP);
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
    97
			ldi_handle_t lh;
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
    98
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
    99
			(void) snprintf(buf, len, "%ss0", vd->vdev_path);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   100
1171
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   101
			if (ldi_open_by_name(buf, spa_mode, kcred,
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   102
			    &lh, zfs_li) == 0) {
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   103
				spa_strfree(vd->vdev_path);
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   104
				vd->vdev_path = buf;
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   105
				vd->vdev_wholedisk = 1ULL;
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   106
				(void) ldi_close(lh, spa_mode, kcred);
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   107
			} else {
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   108
				kmem_free(buf, len);
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   109
			}
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   110
		}
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   111
1171
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   112
		error = ldi_open_by_name(vd->vdev_path, spa_mode, kcred,
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   113
		    &dvd->vd_lh, zfs_li);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   114
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   115
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   116
		 * Compare the devid to the stored value.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   117
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   118
		if (error == 0 && vd->vdev_devid != NULL &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   119
		    ldi_get_devid(dvd->vd_lh, &devid) == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   120
			if (ddi_devid_compare(devid, dvd->vd_devid) != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   121
				error = EINVAL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   122
				(void) ldi_close(dvd->vd_lh, spa_mode, kcred);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   123
				dvd->vd_lh = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   124
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   125
			ddi_devid_free(devid);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   126
		}
1171
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   127
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   128
		/*
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   129
		 * If we succeeded in opening the device, but 'vdev_wholedisk'
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   130
		 * is not yet set, then this must be a slice.
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   131
		 */
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   132
		if (error == 0 && vd->vdev_wholedisk == -1ULL)
b501e9f31cab 6344272 re-think how whole disks are stored
eschrock
parents: 789
diff changeset
   133
			vd->vdev_wholedisk = 0;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   134
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   135
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   136
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   137
	 * If we were unable to open by path, or the devid check fails, open by
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   138
	 * devid instead.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   139
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   140
	if (error != 0 && vd->vdev_devid != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   141
		error = ldi_open_by_devid(dvd->vd_devid, dvd->vd_minor,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   142
		    spa_mode, kcred, &dvd->vd_lh, zfs_li);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   143
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   144
	if (error) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   145
		vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   146
		return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   147
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   148
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   149
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   150
	 * Determine the actual size of the device.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   151
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   152
	if (ldi_get_size(dvd->vd_lh, psize) != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   153
		vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   154
		return (EINVAL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   155
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   156
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   157
	*ashift = SPA_MINBLOCKSHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   158
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   159
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   160
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   161
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   162
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   163
vdev_disk_close(vdev_t *vd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   164
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   165
	vdev_disk_t *dvd = vd->vdev_tsd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   166
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   167
	if (dvd == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   168
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   169
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   170
	dprintf("removing disk %s, devid %s\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   171
	    vd->vdev_path ? vd->vdev_path : "<none>",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   172
	    vd->vdev_devid ? vd->vdev_devid : "<none>");
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   173
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   174
	if (dvd->vd_minor != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   175
		ddi_devid_str_free(dvd->vd_minor);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   176
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   177
	if (dvd->vd_devid != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   178
		ddi_devid_free(dvd->vd_devid);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   179
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   180
	if (dvd->vd_lh != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   181
		(void) ldi_close(dvd->vd_lh, spa_mode, kcred);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   182
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   183
	kmem_free(dvd, sizeof (vdev_disk_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   184
	vd->vdev_tsd = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   185
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   186
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   187
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   188
vdev_disk_io_intr(buf_t *bp)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   189
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   190
	vdev_disk_buf_t *vdb = (vdev_disk_buf_t *)bp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   191
	zio_t *zio = vdb->vdb_io;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   192
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   193
	if ((zio->io_error = geterror(bp)) == 0 && bp->b_resid != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   194
		zio->io_error = EIO;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   195
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   196
	kmem_free(vdb, sizeof (vdev_disk_buf_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   197
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   198
	zio_next_stage_async(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   199
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   200
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   201
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   202
vdev_disk_ioctl_done(void *zio_arg, int error)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   203
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   204
	zio_t *zio = zio_arg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   205
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   206
	zio->io_error = error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   207
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   208
	zio_next_stage_async(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   209
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   210
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   211
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   212
vdev_disk_io_start(zio_t *zio)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   213
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   214
	vdev_t *vd = zio->io_vd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   215
	vdev_disk_t *dvd = vd->vdev_tsd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   216
	vdev_disk_buf_t *vdb;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   217
	buf_t *bp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   218
	int flags, error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   219
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   220
	if (zio->io_type == ZIO_TYPE_IOCTL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   221
		zio_vdev_io_bypass(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   222
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   223
		/* XXPOLICY */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   224
		if (vdev_is_dead(vd)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   225
			zio->io_error = ENXIO;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   226
			zio_next_stage_async(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   227
			return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   228
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   229
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   230
		switch (zio->io_cmd) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   231
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   232
		case DKIOCFLUSHWRITECACHE:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   233
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   234
			zio->io_dk_callback.dkc_callback = vdev_disk_ioctl_done;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   235
			zio->io_dk_callback.dkc_cookie = zio;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   236
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   237
			error = ldi_ioctl(dvd->vd_lh, zio->io_cmd,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   238
			    (uintptr_t)&zio->io_dk_callback,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   239
			    FKIOCTL, kcred, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   240
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   241
			if (error == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   242
				/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   243
				 * The ioctl will be done asychronously,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   244
				 * and will call vdev_disk_ioctl_done()
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   245
				 * upon completion.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   246
				 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   247
				return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   248
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   249
			zio->io_error = error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   250
			break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   251
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   252
		default:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   253
			zio->io_error = ENOTSUP;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   254
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   255
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   256
		zio_next_stage_async(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   257
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   258
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   259
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   260
	if (zio->io_type == ZIO_TYPE_READ && vdev_cache_read(zio) == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   261
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   262
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   263
	if ((zio = vdev_queue_io(zio)) == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   264
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   265
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   266
	flags = (zio->io_type == ZIO_TYPE_READ ? B_READ : B_WRITE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   267
	flags |= B_BUSY | B_NOCACHE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   268
	if (zio->io_flags & ZIO_FLAG_FAILFAST)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   269
		flags |= B_FAILFAST;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   270
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   271
	vdb = kmem_alloc(sizeof (vdev_disk_buf_t), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   272
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   273
	vdb->vdb_io = zio;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   274
	bp = &vdb->vdb_buf;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   275
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   276
	bioinit(bp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   277
	bp->b_flags = flags;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   278
	bp->b_bcount = zio->io_size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   279
	bp->b_un.b_addr = zio->io_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   280
	bp->b_lblkno = lbtodb(zio->io_offset);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   281
	bp->b_bufsize = zio->io_size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   282
	bp->b_iodone = (int (*)())vdev_disk_io_intr;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   283
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   284
	/* XXPOLICY */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   285
	error = vdev_is_dead(vd) ? ENXIO : vdev_error_inject(vd, zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   286
	if (error) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   287
		zio->io_error = error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   288
		bioerror(bp, error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   289
		bp->b_resid = bp->b_bcount;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   290
		bp->b_iodone(bp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   291
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   292
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   293
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   294
	error = ldi_strategy(dvd->vd_lh, bp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   295
	/* ldi_strategy() will return non-zero only on programming errors */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   296
	ASSERT(error == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   297
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   298
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   299
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   300
vdev_disk_io_done(zio_t *zio)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   301
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   302
	vdev_queue_io_done(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   303
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   304
	if (zio->io_type == ZIO_TYPE_WRITE)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   305
		vdev_cache_write(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   306
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   307
	zio_next_stage(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   308
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   309
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   310
vdev_ops_t vdev_disk_ops = {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   311
	vdev_disk_open,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   312
	vdev_disk_close,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   313
	vdev_default_asize,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   314
	vdev_disk_io_start,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   315
	vdev_disk_io_done,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   316
	NULL,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   317
	VDEV_TYPE_DISK,		/* name of this vdev type */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   318
	B_TRUE			/* leaf vdev */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   319
};