// Create ZFS pool per specs, features and properties of pool and root dataset func PoolCreate(name string, vdevs []VDevSpec, features map[string]string, props PoolProperties, fsprops ZFSProperties) (pool Pool, err error) { // create root vdev nvroot var nvroot *C.nvlist_t = nil if r := C.nvlist_alloc(&nvroot, C.NV_UNIQUE_NAME, 0); r != 0 { err = errors.New("Failed to allocate root vdev") return } if r := C.nvlist_add_string(nvroot, C.CString(C.ZPOOL_CONFIG_TYPE), C.CString(string(VDevTypeRoot))); r != 0 { err = errors.New("Failed to allocate root vdev") return } defer C.nvlist_free(nvroot) // Now we need to build specs (vdev hierarchy) if err = buildVDevSpec(nvroot, VDevTypeRoot, vdevs, props); err != nil { return } // convert properties cprops := toCPoolProperties(props) if cprops != nil { defer C.nvlist_free(cprops) } else if len(props) > 0 { err = errors.New("Failed to allocate pool properties") return } cfsprops := toCZFSProperties(fsprops) if cfsprops != nil { defer C.nvlist_free(cfsprops) } else if len(fsprops) > 0 { err = errors.New("Failed to allocate FS properties") return } for fname, fval := range features { sfname := fmt.Sprintf("feature@%s", fname) r := C.add_prop_list(C.CString(sfname), C.CString(fval), &cprops, C.boolean_t(1)) if r != 0 { if cprops != nil { C.nvlist_free(cprops) cprops = nil } return } } // Create actual pool then open if r := C.zpool_create(libzfs_handle, C.CString(name), nvroot, cprops, cfsprops); r != 0 { err = LastError() return } pool, err = PoolOpen(name) return }
func toCZFSProperties(props ZFSProperties) (cprops *C.nvlist_t) { cprops = nil for prop, value := range props { name := C.zfs_prop_to_name(C.zfs_prop_t(prop)) r := C.add_prop_list(name, C.CString(value), &cprops, C.boolean_t(0)) if r != 0 { if cprops != nil { C.nvlist_free(cprops) cprops = nil } return } } return }