On Tue, Jan 21, 2014 at 10:47 AM, Andriy Gapon <avg_at_freebsd.org> wrote: > on 21/01/2014 13:18 Andrey V. Elsukov said the following: > > On 21.01.2014 14:45, Andriy Gapon wrote: > >>>> What do I need to do to get the boot2 code written to /dev/ada0s1a? > >>> > >>> This will work only if ada0s1a isn't in use. The debugflags trick works > >>> only for whole disk, i.e. for geoms with rank=1. Another way is > >>> calculate needed offset and write bootcode directly to ada0. > >> > >> > >> And ultimately we should extend our ZFS interface with an ioctl to > write a blob > >> to a boot code area of a specified ZFS leaf vdev. This would the right > way to > >> install zfsboot. > > > > Hi Andriy, > > > > do you have some patches to test? :-) > > > > I don't, but the following patch can serve as a very good example. > It adds an ioctl that serves a slightly different but quite similar > purpose: > > commit 54802d6659ec134fd221c3daaa8fdf9cee985d39 > Author: Andriy Gapon <avg_at_icyb.net.ua> > Date: Fri Sep 14 23:15:43 2012 +0300 > > [wip] zfs: add a new ioctl that allows to place text data into pad2 > area > > The data is placed into Pad2 area of the first vdev label of a given > vdev in a given pool. > > diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/vdev.h > b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/vdev.h > index fb30ea9..4a46cc2 100644 > --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/vdev.h > +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/vdev.h > _at__at_ -162,6 +162,8 _at__at_ typedef enum { > > extern int vdev_label_init(vdev_t *vd, uint64_t txg, vdev_labeltype_t > reason); > > +extern int vdev_label_write_pad2(vdev_t *vd, const char *buf, size_t > size); > + > #ifdef __cplusplus > } > #endif > diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_label.c > b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_label.c > index c7dd3ad..55c87d8 100644 > --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_label.c > +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_label.c > _at__at_ -855,6 +855,44 _at__at_ retry: > return (error); > } > > +int > +vdev_label_write_pad2(vdev_t *vd, const char *buf, size_t size) > +{ > + spa_t *spa = vd->vdev_spa; > + zio_t *zio; > + char *pad2; > + int flags = ZIO_FLAG_CONFIG_WRITER | ZIO_FLAG_CANFAIL; > + int error; > + > + if (size > VDEV_PAD_SIZE) > + return (EINVAL); > + > + if (!vd->vdev_ops->vdev_op_leaf) > + return (ENODEV); > + if (vdev_is_dead(vd)) > + return (ENXIO); > + > + ASSERT(spa_config_held(spa, SCL_ALL, RW_WRITER) == SCL_ALL); > + > + pad2 = zio_buf_alloc(VDEV_PAD_SIZE); > + bzero(pad2, VDEV_PAD_SIZE); > + memcpy(pad2, buf, size); > + > +retry: > + zio = zio_root(spa, NULL, NULL, flags); > + vdev_label_write(zio, vd, 0, pad2, > + offsetof(vdev_label_t, vl_pad2), > + VDEV_PAD_SIZE, NULL, NULL, flags); > + error = zio_wait(zio); > + if (error != 0 && !(flags & ZIO_FLAG_TRYHARD)) { > + flags |= ZIO_FLAG_TRYHARD; > + goto retry; > + } > + > + zio_buf_free(pad2, VDEV_PAD_SIZE); > + return (error); > +} > + > /* > * > ========================================================================== > * uberblock load/sync > diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c > b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c > index e208ed8..ff90839 100644 > --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c > +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c > _at__at_ -3404,6 +3404,53 _at__at_ zfs_ioc_log_history(const char *unused, nvlist_t > *innvl, > nvlist_t *outnvl) > return (error); > } > > +#ifdef __FreeBSD__ > +static int > +zfs_ioc_nextboot(const char *unused, nvlist_t *innvl, nvlist_t *outnvl) > +{ > + char name[MAXNAMELEN]; > + spa_t *spa; > + vdev_t *vd; > + char *command; > + uint64_t pool_guid; > + uint64_t vdev_guid; > + int error; > + > + if (nvlist_lookup_uint64(innvl, > + ZPOOL_CONFIG_POOL_GUID, &pool_guid) != 0) > + return (EINVAL); > + if (nvlist_lookup_uint64(innvl, > + ZPOOL_CONFIG_GUID, &vdev_guid) != 0) > + return (EINVAL); > + if (nvlist_lookup_string(innvl, > + "command", &command) != 0) > + return (EINVAL); > + > + mutex_enter(&spa_namespace_lock); > + spa = spa_by_guid(pool_guid, vdev_guid); > + if (spa != NULL) > + strcpy(name, spa_name(spa)); > + mutex_exit(&spa_namespace_lock); > + if (spa == NULL) > + return (ENOENT); > + > + if ((error = spa_open(name, &spa, FTAG)) != 0) > + return (error); > + spa_vdev_state_enter(spa, SCL_ALL); > + vd = spa_lookup_by_guid(spa, vdev_guid, B_TRUE); > + if (vd == NULL) { > + (void) spa_vdev_state_exit(spa, NULL, ENXIO); > + spa_close(spa, FTAG); > + return (ENODEV); > + } > + error = vdev_label_write_pad2(vd, command, strlen(command)); > + (void) spa_vdev_state_exit(spa, NULL, 0); > + txg_wait_synced(spa->spa_dsl_pool, 0); > + spa_close(spa, FTAG); > + return (error); > +} > +#endif > + > /* > * The dp_config_rwlock must not be held when calling this, because the > * unmount may need to write out data. > _at__at_ -5605,6 +5652,9 _at__at_ zfs_ioctl_init(void) > zfs_secpolicy_config, POOL_CHECK_NONE); > zfs_ioctl_register_dataset_nolog(ZFS_IOC_UNJAIL, zfs_ioc_unjail, > zfs_secpolicy_config, POOL_CHECK_NONE); > + zfs_ioctl_register("fbsd_nextboot", ZFS_IOC_NEXTBOOT, > + zfs_ioc_nextboot, zfs_secpolicy_config, NO_NAME, > + POOL_CHECK_NONE, B_FALSE, B_FALSE); > #endif > } > > diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h > b/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h > index 454c28a..917223dc 100644 > --- a/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h > +++ b/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h > _at__at_ -839,6 +839,7 _at__at_ typedef enum zfs_ioc { > ZFS_IOC_SEND_NEW, > ZFS_IOC_SEND_SPACE, > ZFS_IOC_CLONE, > + ZFS_IOC_NEXTBOOT, > ZFS_IOC_LAST > } zfs_ioc_t; > > > -- > Andriy Gapon > Thanks for the responses. My apologies for going silent, but I had to step away from the problem for a bit. I was able to resolve my problem by doing the following: After upgrading my zpools and after my aborted attempt to update the bootcode as reported above, I copied /boot/zfsboot (or more precisely /bootpool/boot/zfsboot) to a USB thumb drive. I attempted to reboot my system, which failed due to unsupported zfs features. This was expected, but I thought, hey, I might get lucky. I then booted into a Live CD, mounted my USB thumb drive on /tmp/usb and executed: sysctl kern.geom.debugflags=0x10 dd if=/tmp/usb/zfsboot of=/dev/ada0s1 count=1 dd if=/tmp/usb/zfsboot of=/dev/ada0s1d skip=1 seek=1024 Then I rebooted and all is well. All zpools support all features. While this procedure was not tedious, it would still be nice if, as Andriy stated, FreeBSD contained a native way do this zfs bootcode update for MBR schemes that is as simple as for the GPT schemes. Its been a gazillion years since I've done any C programming, but I'll take a look at the patches. Thanks, Andriy and Andrey. - TomReceived on Tue Jan 21 2014 - 20:11:24 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:46 UTC