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 <a...@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
@@ -162,6 +162,8 @@ 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
@@ -855,6 +855,44 @@ 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
@@ -3404,6 +3404,53 @@ 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.
@@ -5605,6 +5652,9 @@ 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
@@ -839,6 +839,7 @@ 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
_______________________________________________
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "freebsd-current-unsubscr...@freebsd.org"

Reply via email to