zfeature_common.c revision 239774
115103Sphk/* 215103Sphk * CDDL HEADER START 315103Sphk * 415103Sphk * The contents of this file are subject to the terms of the 515103Sphk * Common Development and Distribution License (the "License"). 615103Sphk * You may not use this file except in compliance with the License. 715103Sphk * 815103Sphk * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 915103Sphk * or http://www.opensolaris.org/os/licensing. 1015103Sphk * See the License for the specific language governing permissions 1115103Sphk * and limitations under the License. 1215103Sphk * 1315103Sphk * When distributing Covered Code, include this CDDL HEADER in each 1415103Sphk * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1515103Sphk * If applicable, add the following below this CDDL HEADER, with the 1615103Sphk * fields enclosed by brackets "[]" replaced with your own identifying 1715103Sphk * information: Portions Copyright [yyyy] [name of copyright owner] 1815103Sphk * 1915103Sphk * CDDL HEADER END 2015103Sphk */ 2115103Sphk 2215103Sphk/* 2315103Sphk * Copyright (c) 2012 by Delphix. All rights reserved. 2415103Sphk */ 2515103Sphk 2615103Sphk#ifdef _KERNEL 2715103Sphk#include <sys/systm.h> 2815103Sphk#else 2915103Sphk#include <errno.h> 3015103Sphk#include <string.h> 3115103Sphk#endif 3215103Sphk#include <sys/debug.h> 3315103Sphk#include <sys/fs/zfs.h> 3415103Sphk#include <sys/types.h> 3515103Sphk#include "zfeature_common.h" 3615103Sphk 3715103Sphk/* 38116182Sobrien * Set to disable all feature checks while opening pools, allowing pools with 39116182Sobrien * unsupported features to be opened. Set for testing only. 40116182Sobrien */ 41175417Sjhbboolean_t zfeature_checks_disable = B_FALSE; 4286190Srwatson 43169604Swkoszekzfeature_info_t spa_feature_table[SPA_FEATURES]; 4484611Srwatson 4515103Sphk/* 4615103Sphk * Valid characters for feature guids. This list is mainly for aesthetic 47169507Swkoszek * purposes and could be expanded in the future. There are different allowed 4815103Sphk * characters in the guids reverse dns portion (before the colon) and its 4915103Sphk * short name (after the colon). 5015103Sphk */ 5187275Srwatsonstatic int 5287275Srwatsonvalid_char(char c, boolean_t after_colon) 5346155Sphk{ 5476078Sjhb return ((c >= 'a' && c <= 'z') || 55105046Smike (c >= '0' && c <= '9') || 5628918Skato c == (after_colon ? '_' : '.')); 5715103Sphk} 5815103Sphk 5915103Sphk/* 6015103Sphk * Every feature guid must contain exactly one colon which separates a reverse 6115103Sphk * dns organization name from the feature's "short" name (e.g. 6215103Sphk * "com.company:feature_name"). 6323382Sbde */ 6415103Sphkboolean_t 6515103Sphkzfeature_is_valid_guid(const char *name) 6615103Sphk{ 6715103Sphk int i; 6815103Sphk boolean_t has_colon = B_FALSE; 6948891Sphk 7048891Sphk i = 0; 7115103Sphk while (name[i] != '\0') { 7215103Sphk char c = name[i++]; 7315103Sphk if (c == ':') { 7415103Sphk if (has_colon) 7515103Sphk return (B_FALSE); 7615103Sphk has_colon = B_TRUE; 7734925Sdufault continue; 7834925Sdufault } 7934029Sdufault if (!valid_char(c, has_colon)) 8050465Smarcel return (B_FALSE); 8150465Smarcel } 8289414Sarr 8389414Sarr return (has_colon); 8486190Srwatson} 8586190Srwatson 8686190Srwatsonboolean_t 8786190Srwatsonzfeature_is_supported(const char *guid) 8850465Smarcel{ 89116090Sjmallett if (zfeature_checks_disable) 90116105Sjmallett return (B_TRUE); 91116090Sjmallett 9286189Srwatson return (0 == zfeature_lookup_guid(guid, NULL)); 9388019Sluigi} 9415103Sphk 9586189Srwatsonint 9646381Sbillfzfeature_lookup_guid(const char *guid, zfeature_info_t **res) 9715103Sphk{ 9886189Srwatson for (int i = 0; i < SPA_FEATURES; i++) { 9946381Sbillf zfeature_info_t *feature = &spa_feature_table[i]; 10015103Sphk if (strcmp(guid, feature->fi_guid) == 0) { 10186189Srwatson if (res != NULL) 10246381Sbillf *res = feature; 10315103Sphk return (0); 104119203Seivind } 105119203Seivind } 106119203Seivind 107119203Seivind return (ENOENT); 10886189Srwatson} 109119203Seivind 11015103Sphkint 111121307Ssilbyzfeature_lookup_name(const char *name, zfeature_info_t **res) 11246381Sbillf{ 11315103Sphk for (int i = 0; i < SPA_FEATURES; i++) { 11486189Srwatson zfeature_info_t *feature = &spa_feature_table[i]; 11546381Sbillf if (strcmp(name, feature->fi_uname) == 0) { 11615103Sphk if (res != NULL) 117121307Ssilby *res = feature; 11880418Speter return (0); 11980418Speter } 12086189Srwatson } 12146381Sbillf 12215103Sphk return (ENOENT); 12386189Srwatson} 124105046Smike 12515103Sphkstatic void 12686189Srwatsonzfeature_register(int fid, const char *guid, const char *name, const char *desc, 12746381Sbillf boolean_t readonly, boolean_t mos, zfeature_info_t **deps) 12815103Sphk{ 12986189Srwatson zfeature_info_t *feature = &spa_feature_table[fid]; 13046381Sbillf static zfeature_info_t *nodeps[] = { NULL }; 13115103Sphk 13215103Sphk ASSERT(name != NULL); 13386189Srwatson ASSERT(desc != NULL); 13446381Sbillf ASSERT(!readonly || !mos); 13515103Sphk ASSERT3U(fid, <, SPA_FEATURES); 13686189Srwatson ASSERT(zfeature_is_valid_guid(guid)); 13746381Sbillf 13815103Sphk if (deps == NULL) 13915103Sphk deps = nodeps; 14015103Sphk 14115103Sphk feature->fi_guid = guid; 14286189Srwatson feature->fi_uname = name; 14346381Sbillf feature->fi_desc = desc; 14415103Sphk feature->fi_can_readonly = readonly; 14586189Srwatson feature->fi_mos = mos; 14646381Sbillf feature->fi_depends = deps; 14715103Sphk} 14886189Srwatson 14946381Sbillfvoid 15015103Sphkzpool_feature_init(void) 15186189Srwatson{ 15246381Sbillf zfeature_register(SPA_FEATURE_ASYNC_DESTROY, 15315103Sphk "com.delphix:async_destroy", "async_destroy", 154106605Stmm "Destroy filesystems asynchronously.", B_TRUE, B_FALSE, NULL); 155169727Skan zfeature_register(SPA_FEATURE_EMPTY_BPOBJ, 156169727Skan "com.delphix:empty_bpobj", "empty_bpobj", 157169727Skan "Snapshots use less space.", B_TRUE, B_FALSE, NULL); 158169727Skan} 159169727Skan