6622831 normalization properties are not preserved by "zfs send"
6625194 delegate 'clone' privilege broken
6626152 zfs should initialize the fuid lock it uses
Contributed by Pawel Dawidek
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/uts/common/fs/zfs/sys/zfs_i18n.h Tue Nov 20 05:42:50 2007 -0800
@@ -0,0 +1,71 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_ZFS_I18N_H
+#define _SYS_ZFS_I18N_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/sunddi.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * z_case behaviors
+ * The first two describe the extent of case insensitivity.
+ * The third describes matching behavior when mixed sensitivity
+ * is allowed.
+ */
+#define ZFS_CI_ONLY 0x01 /* all lookups case-insensitive */
+#define ZFS_CI_MIXD 0x02 /* some lookups case-insensitive */
+
+/*
+ * ZFS_UTF8_ONLY
+ * If set, the file system should reject non-utf8 characters in names.
+ */
+#define ZFS_UTF8_ONLY 0x04
+
+enum zfs_case {
+ ZFS_CASE_SENSITIVE,
+ ZFS_CASE_INSENSITIVE,
+ ZFS_CASE_MIXED
+};
+
+enum zfs_normal {
+ ZFS_NORMALIZE_NONE,
+ ZFS_NORMALIZE_D,
+ ZFS_NORMALIZE_KC,
+ ZFS_NORMALIZE_C,
+ ZFS_NORMALIZE_KD
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_ZFS_I18N_H */
--- a/usr/src/common/zfs/zfs_prop.c Mon Nov 19 21:07:12 2007 -0800
+++ b/usr/src/common/zfs/zfs_prop.c Tue Nov 20 05:42:50 2007 -0800
@@ -27,10 +27,10 @@
#include <sys/zio.h>
#include <sys/spa.h>
+#include <sys/u8_textprep.h>
#include <sys/zfs_acl.h>
#include <sys/zfs_ioctl.h>
#include <sys/zfs_znode.h>
-#include <sys/zfs_i18n.h>
#include "zfs_prop.h"
#include "zfs_deleg.h"
@@ -115,12 +115,17 @@
{ NULL }
};
+ /*
+ * Use the unique flags we have to send to u8_strcmp() and/or
+ * u8_textprep() to represent the various normalization property
+ * values.
+ */
static zprop_index_t normalize_table[] = {
- { "none", ZFS_NORMALIZE_NONE },
- { "formD", ZFS_NORMALIZE_D },
- { "formKC", ZFS_NORMALIZE_KC },
- { "formC", ZFS_NORMALIZE_C },
- { "formKD", ZFS_NORMALIZE_KD },
+ { "none", 0 },
+ { "formD", U8_TEXTPREP_NFD },
+ { "formKC", U8_TEXTPREP_NFKC },
+ { "formC", U8_TEXTPREP_NFC },
+ { "formKD", U8_TEXTPREP_NFKD },
{ NULL }
};
@@ -202,7 +207,7 @@
ZFS_TYPE_FILESYSTEM, "yes | no", "MOUNTED", boolean_table);
/* set once index properties */
- register_index(ZFS_PROP_NORMALIZE, "normalization", ZFS_NORMALIZE_NONE,
+ register_index(ZFS_PROP_NORMALIZE, "normalization", 0,
PROP_ONETIME, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT,
"none | formC | formD | formKC | formKD", "NORMALIZATION",
normalize_table);
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c Mon Nov 19 21:07:12 2007 -0800
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c Tue Nov 20 05:42:50 2007 -0800
@@ -51,7 +51,6 @@
#include <sys/spa.h>
#include <sys/zap.h>
-#include <sys/zfs_i18n.h>
#include <libzfs.h>
#include "zfs_namecheck.h"
@@ -480,7 +479,6 @@
char *strval;
zfs_prop_t prop;
nvlist_t *ret;
- int chosen_sense = -1;
int chosen_normal = -1;
int chosen_utf = -1;
@@ -748,9 +746,6 @@
}
break;
- case ZFS_PROP_CASE:
- chosen_sense = (int)intval;
- break;
case ZFS_PROP_UTF8ONLY:
chosen_utf = (int)intval;
break;
@@ -810,32 +805,19 @@
}
/*
- * Temporarily disallow any non-default settings for
- * casesensitivity, normalization, and/or utf8only.
- */
- if (chosen_sense > ZFS_CASE_SENSITIVE || chosen_utf > 0 ||
- chosen_normal > ZFS_NORMALIZE_NONE) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "Non-default values for casesensitivity, utf8only, and "
- "normalization are (temporarily) disabled"));
- (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
- goto error;
- }
-
- /*
* If normalization was chosen, but no UTF8 choice was made,
* enforce rejection of non-UTF8 names.
*
* If normalization was chosen, but rejecting non-UTF8 names
* was explicitly not chosen, it is an error.
*/
- if (chosen_normal > ZFS_NORMALIZE_NONE && chosen_utf < 0) {
+ if (chosen_normal > 0 && chosen_utf < 0) {
if (nvlist_add_uint64(ret,
zfs_prop_to_name(ZFS_PROP_UTF8ONLY), 1) != 0) {
(void) no_memory(hdl);
goto error;
}
- } else if (chosen_normal > ZFS_NORMALIZE_NONE && chosen_utf == 0) {
+ } else if (chosen_normal > 0 && chosen_utf == 0) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"'%s' must be set 'on' if normalization chosen"),
zfs_prop_to_name(ZFS_PROP_UTF8ONLY));
@@ -1880,6 +1862,7 @@
char **source, uint64_t *val)
{
zfs_cmd_t zc = { 0 };
+ nvlist_t *zplprops;
struct mnttab mnt;
char *mntopt_on = NULL;
char *mntopt_off = NULL;
@@ -2001,17 +1984,32 @@
break;
case ZFS_PROP_VERSION:
- if (!zfs_prop_valid_for_type(prop, zhp->zfs_head_type))
+ case ZFS_PROP_NORMALIZE:
+ case ZFS_PROP_UTF8ONLY:
+ case ZFS_PROP_CASE:
+ if (!zfs_prop_valid_for_type(prop, zhp->zfs_head_type) ||
+ zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
return (-1);
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
- if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_OBJSET_VERSION, &zc) ||
- (zc.zc_cookie == 0)) {
+ if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_OBJSET_ZPLPROPS, &zc)) {
+ zcmd_free_nvlists(&zc);
zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
- "unable to get version property"));
+ "unable to get %s property"),
+ zfs_prop_to_name(prop));
return (zfs_error(zhp->zfs_hdl, EZFS_BADVERSION,
dgettext(TEXT_DOMAIN, "internal error")));
}
- *val = zc.zc_cookie;
+ if (zcmd_read_dst_nvlist(zhp->zfs_hdl, &zc, &zplprops) != 0 ||
+ nvlist_lookup_uint64(zplprops, zfs_prop_to_name(prop),
+ val) != 0) {
+ zcmd_free_nvlists(&zc);
+ zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
+ "unable to get %s property"),
+ zfs_prop_to_name(prop));
+ return (zfs_error(zhp->zfs_hdl, EZFS_NOMEM,
+ dgettext(TEXT_DOMAIN, "internal error")));
+ }
+ zcmd_free_nvlists(&zc);
break;
default:
--- a/usr/src/lib/libzpool/common/sys/zfs_context.h Mon Nov 19 21:07:12 2007 -0800
+++ b/usr/src/lib/libzpool/common/sys/zfs_context.h Tue Nov 20 05:42:50 2007 -0800
@@ -73,6 +73,7 @@
#include <sys/zfs_debug.h>
#include <sys/sdt.h>
#include <sys/kstat.h>
+#include <sys/u8_textprep.h>
#include <sys/sysevent/eventdefs.h>
/*
@@ -520,25 +521,6 @@
extern int zfs_secpolicy_destroy_perms(const char *name, cred_t *cr);
extern zoneid_t getzoneid(void);
-/*
- * UTF-8 text preparation functions and their macros.
- * (sunddi.h)
- */
-#define U8_STRCMP_CS 0x00000001
-#define U8_STRCMP_CI_UPPER 0x00000002
-#define U8_STRCMP_CI_LOWER 0x00000004
-
-#define U8_TEXTPREP_TOUPPER U8_STRCMP_CI_UPPER
-#define U8_TEXTPREP_TOLOWER U8_STRCMP_CI_LOWER
-#define U8_TEXTPREP_IGNORE_NULL 0x00010000
-
-#define U8_UNICODE_320 (0)
-#define U8_UNICODE_500 (1)
-#define U8_UNICODE_LATEST U8_UNICODE_500
-
-extern size_t u8_textprep_str(char *, size_t *, char *, size_t *, int, size_t,
- int *);
-
#ifdef __cplusplus
}
#endif
--- a/usr/src/uts/common/fs/zfs/sys/zap_leaf.h Mon Nov 19 21:07:12 2007 -0800
+++ b/usr/src/uts/common/fs/zfs/sys/zap_leaf.h Tue Nov 20 05:42:50 2007 -0800
@@ -232,9 +232,9 @@
* Other stuff.
*/
-extern void zap_leaf_init(zap_leaf_t *l, int version);
+extern void zap_leaf_init(zap_leaf_t *l, boolean_t sort);
extern void zap_leaf_byteswap(zap_leaf_phys_t *buf, int len);
-extern void zap_leaf_split(zap_leaf_t *l, zap_leaf_t *nl, int version);
+extern void zap_leaf_split(zap_leaf_t *l, zap_leaf_t *nl, boolean_t sort);
extern void zap_leaf_stats(zap_t *zap, zap_leaf_t *l, zap_stats_t *zs);
#ifdef __cplusplus
--- a/usr/src/uts/common/fs/zfs/sys/zfs_i18n.h Mon Nov 19 21:07:12 2007 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _SYS_ZFS_I18N_H
-#define _SYS_ZFS_I18N_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <sys/sunddi.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * z_case behaviors
- * The first two describe the extent of case insensitivity.
- * The third describes matching behavior when mixed sensitivity
- * is allowed.
- */
-#define ZFS_CI_ONLY 0x01 /* all lookups case-insensitive */
-#define ZFS_CI_MIXD 0x02 /* some lookups case-insensitive */
-
-/*
- * ZFS_UTF8_ONLY
- * If set, the file system should reject non-utf8 characters in names.
- */
-#define ZFS_UTF8_ONLY 0x04
-
-enum zfs_case {
- ZFS_CASE_SENSITIVE,
- ZFS_CASE_INSENSITIVE,
- ZFS_CASE_MIXED
-};
-
-enum zfs_normal {
- ZFS_NORMALIZE_NONE,
- ZFS_NORMALIZE_D,
- ZFS_NORMALIZE_KC,
- ZFS_NORMALIZE_C,
- ZFS_NORMALIZE_KD
-};
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SYS_ZFS_I18N_H */
--- a/usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h Mon Nov 19 21:07:12 2007 -0800
+++ b/usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h Tue Nov 20 05:42:50 2007 -0800
@@ -131,6 +131,18 @@
uint64_t z_sharemax; /* max length of share string */
} zfs_share_t;
+/*
+ * ZFS file systems may behave the usual, POSIX-compliant way, where
+ * name lookups are case-sensitive. They may also be set up so that
+ * all the name lookups are case-insensitive, or so that only some
+ * lookups, the ones that set an FIGNORECASE flag, are case-insensitive.
+ */
+typedef enum zfs_case {
+ ZFS_CASE_SENSITIVE,
+ ZFS_CASE_INSENSITIVE,
+ ZFS_CASE_MIXED
+} zfs_case_t;
+
typedef struct zfs_cmd {
char zc_name[MAXPATHLEN];
char zc_value[MAXPATHLEN * 2];
@@ -161,7 +173,7 @@
#ifdef _KERNEL
typedef struct zfs_creat {
- int zct_norm;
+ nvlist_t *zct_zplprops;
nvlist_t *zct_props;
} zfs_creat_t;
--- a/usr/src/uts/common/fs/zfs/sys/zfs_vfsops.h Mon Nov 19 21:07:12 2007 -0800
+++ b/usr/src/uts/common/fs/zfs/sys/zfs_vfsops.h Tue Nov 20 05:42:50 2007 -0800
@@ -34,6 +34,7 @@
#include <sys/vfs.h>
#include <sys/zil.h>
#include <sys/rrwlock.h>
+#include <sys/zfs_ioctl.h>
#ifdef __cplusplus
extern "C" {
@@ -58,7 +59,8 @@
zilog_t *z_log; /* intent log pointer */
uint_t z_acl_mode; /* acl chmod/mode behavior */
uint_t z_acl_inherit; /* acl inheritance behavior */
- uint_t z_case; /* case-insensitive behavior */
+ zfs_case_t z_case; /* case-sense */
+ boolean_t z_utf8; /* utf8-only */
int z_norm; /* normalization flags */
boolean_t z_atime; /* enable atimes mount option */
boolean_t z_unmounted; /* unmounted */
--- a/usr/src/uts/common/fs/zfs/sys/zfs_znode.h Mon Nov 19 21:07:12 2007 -0800
+++ b/usr/src/uts/common/fs/zfs/sys/zfs_znode.h Tue Nov 20 05:42:50 2007 -0800
@@ -102,7 +102,6 @@
#define ZPL_VERSION_STR "VERSION"
#define ZFS_FUID_TABLES "FUID"
-
#define ZFS_MAX_BLOCKSIZE (SPA_MAXBLOCKSIZE)
/* Path component length */
@@ -293,7 +292,7 @@
extern int zfs_init_fs(zfsvfs_t *, znode_t **, cred_t *);
extern void zfs_set_dataprop(objset_t *);
-extern void zfs_create_fs(objset_t *os, cred_t *cr, uint64_t, int,
+extern void zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *,
dmu_tx_t *tx);
extern void zfs_time_stamper(znode_t *, uint_t, dmu_tx_t *);
extern void zfs_time_stamper_locked(znode_t *, uint_t, dmu_tx_t *);
@@ -310,7 +309,7 @@
extern int zfs_create_op_tables();
extern int zfs_sync(vfs_t *vfsp, short flag, cred_t *cr);
extern dev_t zfs_cmpldev(uint64_t);
-extern int zfs_get_version(objset_t *os, uint64_t *version);
+extern int zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value);
extern int zfs_set_version(const char *name, uint64_t newvers);
extern int zfs_get_stats(objset_t *os, nvlist_t *nv);
--- a/usr/src/uts/common/fs/zfs/zap.c Mon Nov 19 21:07:12 2007 -0800
+++ b/usr/src/uts/common/fs/zfs/zap.c Tue Nov 20 05:42:50 2007 -0800
@@ -44,6 +44,7 @@
#include <sys/spa.h>
#include <sys/dmu.h>
#include <sys/zfs_context.h>
+#include <sys/zfs_znode.h>
#include <sys/zap.h>
#include <sys/refcount.h>
#include <sys/zap_impl.h>
@@ -119,7 +120,7 @@
l->l_dbuf = db;
l->l_phys = db->db_data;
- zap_leaf_init(l, spa_version(dmu_objset_spa(zap->zap_objset)));
+ zap_leaf_init(l, zp->zap_normflags != 0);
kmem_free(l, sizeof (zap_leaf_t));
dmu_buf_rele(db, FTAG);
@@ -399,7 +400,7 @@
ASSERT(winner == NULL);
dmu_buf_will_dirty(l->l_dbuf, tx);
- zap_leaf_init(l, spa_version(dmu_objset_spa(zap->zap_objset)));
+ zap_leaf_init(l, zap->zap_normflags != 0);
zap->zap_f.zap_phys->zap_num_leafs++;
@@ -646,7 +647,7 @@
}
nl = zap_create_leaf(zap, tx);
- zap_leaf_split(l, nl, spa_version(dmu_objset_spa(zap->zap_objset)));
+ zap_leaf_split(l, nl, zap->zap_normflags != 0);
/* set sibling pointers */
for (i = 0; i < (1ULL<<prefix_diff); i++) {
--- a/usr/src/uts/common/fs/zfs/zap_leaf.c Mon Nov 19 21:07:12 2007 -0800
+++ b/usr/src/uts/common/fs/zfs/zap_leaf.c Tue Nov 20 05:42:50 2007 -0800
@@ -152,7 +152,7 @@
}
void
-zap_leaf_init(zap_leaf_t *l, int version)
+zap_leaf_init(zap_leaf_t *l, boolean_t sort)
{
int i;
@@ -167,7 +167,7 @@
l->l_phys->l_hdr.lh_block_type = ZBT_LEAF;
l->l_phys->l_hdr.lh_magic = ZAP_LEAF_MAGIC;
l->l_phys->l_hdr.lh_nfree = ZAP_LEAF_NUMCHUNKS(l);
- if (version >= SPA_VERSION_NORMALIZATION)
+ if (sort)
l->l_phys->l_hdr.lh_flags |= ZLF_ENTRIES_CDSORTED;
}
@@ -769,7 +769,7 @@
* Transfer the entries whose hash prefix ends in 1 to the new leaf.
*/
void
-zap_leaf_split(zap_leaf_t *l, zap_leaf_t *nl, int version)
+zap_leaf_split(zap_leaf_t *l, zap_leaf_t *nl, boolean_t sort)
{
int i;
int bit = 64 - 1 - l->l_phys->l_hdr.lh_prefix_len;
@@ -783,7 +783,7 @@
/* break existing hash chains */
zap_memset(l->l_phys->l_hash, CHAIN_END, 2*ZAP_LEAF_HASH_NUMENTRIES(l));
- if (version >= SPA_VERSION_NORMALIZATION)
+ if (sort)
l->l_phys->l_hdr.lh_flags |= ZLF_ENTRIES_CDSORTED;
/*
@@ -838,7 +838,7 @@
n = 1 + ZAP_LEAF_ARRAY_NCHUNKS(le->le_name_length) +
ZAP_LEAF_ARRAY_NCHUNKS(le->le_value_length *
- le->le_int_size);
+ le->le_int_size);
n = MIN(n, ZAP_HISTOGRAM_SIZE-1);
zs->zs_entries_using_n_chunks[n]++;
--- a/usr/src/uts/common/fs/zfs/zap_micro.c Mon Nov 19 21:07:12 2007 -0800
+++ b/usr/src/uts/common/fs/zfs/zap_micro.c Tue Nov 20 05:42:50 2007 -0800
@@ -33,7 +33,10 @@
#include <sys/zap_impl.h>
#include <sys/zap_leaf.h>
#include <sys/avl.h>
-#include <sys/zfs_i18n.h>
+
+#ifdef _KERNEL
+#include <sys/sunddi.h>
+#endif
static int mzap_upgrade(zap_t **zapp, dmu_tx_t *tx);
@@ -492,8 +495,6 @@
dmu_buf_t *db;
mzap_phys_t *zp;
- ASSERT(normflags == 0 ||
- spa_version(dmu_objset_spa(os)) >= SPA_VERSION_NORMALIZATION);
VERIFY(0 == dmu_buf_hold(os, obj, 0, FTAG, &db));
#ifdef ZFS_DEBUG
--- a/usr/src/uts/common/fs/zfs/zfs_dir.c Mon Nov 19 21:07:12 2007 -0800
+++ b/usr/src/uts/common/fs/zfs/zfs_dir.c Tue Nov 20 05:42:50 2007 -0800
@@ -42,6 +42,7 @@
#include <sys/errno.h>
#include <sys/stat.h>
#include <sys/unistd.h>
+#include <sys/sunddi.h>
#include <sys/random.h>
#include <sys/policy.h>
#include <sys/zfs_dir.h>
@@ -55,7 +56,6 @@
#include <sys/zfs_fuid.h>
#include <sys/dnlc.h>
#include <sys/extdirent.h>
-#include <sys/zfs_i18n.h>
/*
* zfs_match_find() is used by zfs_dirent_lock() to peform zap lookups
@@ -177,8 +177,9 @@
* a zap lookup on file systems supporting case-insensitive
* access.
*/
- exact = ((zfsvfs->z_case & ZFS_CI_ONLY) && (flag & ZCIEXACT)) ||
- ((zfsvfs->z_case & ZFS_CI_MIXD) && !(flag & ZCILOOK));
+ exact =
+ ((zfsvfs->z_case == ZFS_CASE_INSENSITIVE) && (flag & ZCIEXACT)) ||
+ ((zfsvfs->z_case == ZFS_CASE_MIXED) && !(flag & ZCILOOK));
/*
* Only look in or update the DNLC if we are looking for the
@@ -191,7 +192,7 @@
* case for performance improvement?
*/
update = !zfsvfs->z_norm ||
- ((zfsvfs->z_case & ZFS_CI_MIXD) &&
+ ((zfsvfs->z_case == ZFS_CASE_MIXED) &&
!(zfsvfs->z_norm & ~U8_TEXTPREP_TOUPPER) && !(flag & ZCILOOK));
/*
@@ -761,9 +762,9 @@
mutex_exit(&dzp->z_lock);
if (zp->z_zfsvfs->z_norm) {
- if (((zp->z_zfsvfs->z_case & ZFS_CI_ONLY) &&
+ if (((zp->z_zfsvfs->z_case == ZFS_CASE_INSENSITIVE) &&
(flag & ZCIEXACT)) ||
- ((zp->z_zfsvfs->z_case & ZFS_CI_MIXD) &&
+ ((zp->z_zfsvfs->z_case == ZFS_CASE_MIXED) &&
!(flag & ZCILOOK)))
error = zap_remove_norm(zp->z_zfsvfs->z_os,
dzp->z_id, dl->dl_name, MT_EXACT, tx);
--- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c Mon Nov 19 21:07:12 2007 -0800
+++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c Tue Nov 20 05:42:50 2007 -0800
@@ -38,7 +38,6 @@
#include <sys/cmn_err.h>
#include <sys/stat.h>
#include <sys/zfs_ioctl.h>
-#include <sys/zfs_i18n.h>
#include <sys/zfs_znode.h>
#include <sys/zap.h>
#include <sys/spa.h>
@@ -65,8 +64,6 @@
#include <sys/zfs_dir.h>
#include <sys/zvol.h>
#include <sharefs/share.h>
-#include <sys/zfs_znode.h>
-#include <sys/zfs_vfsops.h>
#include <sys/dmu_objset.h>
#include "zfs_namecheck.h"
@@ -1095,6 +1092,30 @@
return (error);
}
+static int
+zfs_os_open_retry(char *name, objset_t **os)
+{
+ int error;
+
+retry:
+ error = dmu_objset_open(name, DMU_OST_ANY,
+ DS_MODE_STANDARD | DS_MODE_READONLY, os);
+ if (error != 0) {
+ /*
+ * This is ugly: dmu_objset_open() can return EBUSY if
+ * the objset is held exclusively. Fortunately this hold is
+ * only for a short while, so we retry here.
+ * This avoids user code having to handle EBUSY,
+ * for example for a "zfs list".
+ */
+ if (error == EBUSY) {
+ delay(1);
+ goto retry;
+ }
+ }
+ return (error);
+}
+
/*
* inputs:
* zc_name name of filesystem
@@ -1113,23 +1134,8 @@
int error;
nvlist_t *nv;
-retry:
- error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
- DS_MODE_STANDARD | DS_MODE_READONLY, &os);
- if (error != 0) {
- /*
- * This is ugly: dmu_objset_open() can return EBUSY if
- * the objset is held exclusively. Fortunately this hold is
- * only for a short while, so we retry here.
- * This avoids user code having to handle EBUSY,
- * for example for a "zfs list".
- */
- if (error == EBUSY) {
- delay(1);
- goto retry;
- }
+ if ((error = zfs_os_open_retry(zc->zc_name, &os)) != 0)
return (error);
- }
dmu_objset_fast_stat(os, &zc->zc_objset_stats);
@@ -1156,6 +1162,66 @@
return (error);
}
+static int
+nvl_add_zplprop(objset_t *os, nvlist_t *props, zfs_prop_t prop)
+{
+ uint64_t value;
+ int error;
+
+ /*
+ * zfs_get_zplprop() will either find a value or give us
+ * the default value (if there is one).
+ */
+ if ((error = zfs_get_zplprop(os, prop, &value)) != 0)
+ return (error);
+ VERIFY(nvlist_add_uint64(props, zfs_prop_to_name(prop), value) == 0);
+ return (0);
+}
+
+/*
+ * inputs:
+ * zc_name name of filesystem
+ * zc_nvlist_dst_size size of buffer for zpl property nvlist
+ *
+ * outputs:
+ * zc_nvlist_dst zpl property nvlist
+ * zc_nvlist_dst_size size of zpl property nvlist
+ */
+static int
+zfs_ioc_objset_zplprops(zfs_cmd_t *zc)
+{
+ objset_t *os;
+ int err;
+
+ if ((err = zfs_os_open_retry(zc->zc_name, &os)) != 0)
+ return (err);
+
+ dmu_objset_fast_stat(os, &zc->zc_objset_stats);
+
+ /*
+ * NB: nvl_add_zplprop() will read the objset contents,
+ * which we aren't supposed to do with a DS_MODE_STANDARD
+ * open, because it could be inconsistent.
+ */
+ if (zc->zc_nvlist_dst != NULL &&
+ !zc->zc_objset_stats.dds_inconsistent &&
+ dmu_objset_type(os) == DMU_OST_ZFS) {
+ nvlist_t *nv;
+
+ VERIFY(nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) == 0);
+ if ((err = nvl_add_zplprop(os, nv, ZFS_PROP_VERSION)) == 0 &&
+ (err = nvl_add_zplprop(os, nv, ZFS_PROP_NORMALIZE)) == 0 &&
+ (err = nvl_add_zplprop(os, nv, ZFS_PROP_UTF8ONLY)) == 0 &&
+ (err = nvl_add_zplprop(os, nv, ZFS_PROP_CASE)) == 0)
+ err = put_nvlist(zc, nv);
+ nvlist_free(nv);
+ } else {
+ err = ENOENT;
+ }
+ dmu_objset_close(os);
+ return (err);
+}
+
/*
* inputs:
* zc_name name of filesystem
@@ -1170,68 +1236,13 @@
* zc_value alternate root
*/
static int
-zfs_ioc_objset_version(zfs_cmd_t *zc)
-{
- objset_t *os = NULL;
- int error;
-
-retry:
- error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
- DS_MODE_STANDARD | DS_MODE_READONLY, &os);
- if (error != 0) {
- /*
- * This is ugly: dmu_objset_open() can return EBUSY if
- * the objset is held exclusively. Fortunately this hold is
- * only for a short while, so we retry here.
- * This avoids user code having to handle EBUSY,
- * for example for a "zfs list".
- */
- if (error == EBUSY) {
- delay(1);
- goto retry;
- }
- return (error);
- }
-
- dmu_objset_fast_stat(os, &zc->zc_objset_stats);
-
- /*
- * NB: zfs_get_version() will read the objset contents,
- * which we aren't supposed to do with a
- * DS_MODE_STANDARD open, because it could be
- * inconsistent. So this is a bit of a workaround...
- */
- zc->zc_cookie = 0;
- if (!zc->zc_objset_stats.dds_inconsistent)
- if (dmu_objset_type(os) == DMU_OST_ZFS)
- (void) zfs_get_version(os, &zc->zc_cookie);
-
- dmu_objset_close(os);
- return (0);
-}
-
-static int
zfs_ioc_dataset_list_next(zfs_cmd_t *zc)
{
objset_t *os;
int error;
char *p;
-retry:
- error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
- DS_MODE_STANDARD | DS_MODE_READONLY, &os);
- if (error != 0) {
- /*
- * This is ugly: dmu_objset_open() can return EBUSY if
- * the objset is held exclusively. Fortunately this hold is
- * only for a short while, so we retry here.
- * This avoids user code having to handle EBUSY,
- * for example for a "zfs list".
- */
- if (error == EBUSY) {
- delay(1);
- goto retry;
- }
+ if ((error = zfs_os_open_retry(zc->zc_name, &os)) != 0) {
if (error == ENOENT)
error = ESRCH;
return (error);
@@ -1281,21 +1292,7 @@
objset_t *os;
int error;
-retry:
- error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
- DS_MODE_STANDARD | DS_MODE_READONLY, &os);
- if (error != 0) {
- /*
- * This is ugly: dmu_objset_open() can return EBUSY if
- * the objset is held exclusively. Fortunately this hold is
- * only for a short while, so we retry here.
- * This avoids user code having to handle EBUSY,
- * for example for a "zfs list".
- */
- if (error == EBUSY) {
- delay(1);
- goto retry;
- }
+ if ((error = zfs_os_open_retry(zc->zc_name, &os)) != 0) {
if (error == ENOENT)
error = ESRCH;
return (error);
@@ -1385,12 +1382,6 @@
if (zfs_check_version(name, SPA_VERSION_DITTO_BLOCKS))
return (ENOTSUP);
break;
- case ZFS_PROP_NORMALIZE:
- case ZFS_PROP_UTF8ONLY:
- case ZFS_PROP_CASE:
- if (zfs_check_version(name, SPA_VERSION_NORMALIZATION))
- return (ENOTSUP);
-
}
if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0)
return (error);
@@ -1759,172 +1750,112 @@
zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx)
{
zfs_creat_t *zct = arg;
- uint64_t version;
-
- if (spa_version(dmu_objset_spa(os)) >= SPA_VERSION_FUID)
- version = ZPL_VERSION;
- else
- version = ZPL_VERSION_FUID - 1;
-
- (void) nvlist_lookup_uint64(zct->zct_props,
- zfs_prop_to_name(ZFS_PROP_VERSION), &version);
-
- zfs_create_fs(os, cr, version, zct->zct_norm, tx);
+
+ zfs_create_fs(os, cr, zct->zct_zplprops, tx);
}
+#define ZFS_PROP_UNDEFINED ((uint64_t)-1)
+
/*
- * zfs_prop_lookup()
+ * inputs:
+ * createprops list of properties requested by creator
+ * dataset name of dataset we are creating
*
- * Look for the property first in the existing property nvlist. If
- * it's already present, you're done. If it's not there, attempt to
- * find the property value from a parent dataset. If that fails, fall
- * back to the property's default value. In either of these two
- * cases, if update is TRUE, add a value for the property to the
- * property nvlist.
- *
- * If the rval pointer is non-NULL, copy the discovered value to rval.
- *
- * If we get any unexpected errors, bail and return the error number
- * to the caller.
+ * outputs:
+ * zplprops values for the zplprops we attach to the master node object
*
- * If we succeed, return 0.
- */
-static int
-zfs_prop_lookup(const char *parentname, zfs_prop_t propnum,
- nvlist_t *proplist, uint64_t *rval, boolean_t update)
-{
- const char *propname;
- uint64_t value;
- int error = ENOENT;
-
- propname = zfs_prop_to_name(propnum);
- if (proplist != NULL)
- error = nvlist_lookup_uint64(proplist, propname, &value);
- if (error == ENOENT) {
- error = dsl_prop_get_integer(parentname, propname,
- &value, NULL);
- if (error == ENOENT)
- value = zfs_prop_default_numeric(propnum);
- else if (error != 0)
- return (error);
- if (update) {
- ASSERT(proplist != NULL);
- error = nvlist_add_uint64(proplist, propname, value);
- }
- }
- if (error == 0 && rval)
- *rval = value;
- return (error);
-}
-
-/*
- * zfs_normalization_get
- *
- * Get the normalization flag value. If the properties have
- * non-default values, make sure the pool version is recent enough to
- * support these choices.
+ * Determine the settings for utf8only, normalization and
+ * casesensitivity. Specific values may have been requested by the
+ * creator and/or we can inherit values from the parent dataset. If
+ * the file system is of too early a vintage, a creator can not
+ * request settings for these properties, even if the requested
+ * setting is the default value. We don't actually want to create dsl
+ * properties for these, so remove them from the source nvlist after
+ * processing.
*/
static int
-zfs_normalization_get(const char *dataset, nvlist_t *proplist, int *norm,
- boolean_t update)
+zfs_fill_zplprops(const char *dataset, nvlist_t *createprops,
+ nvlist_t *zplprops, uint64_t zplver)
{
+ objset_t *os;
char parentname[MAXNAMELEN];
- char poolname[MAXNAMELEN];
char *cp;
- uint64_t value;
- int check = 0;
- int error;
-
- ASSERT(norm != NULL);
- *norm = 0;
-
- (void) strncpy(parentname, dataset, sizeof (parentname));
- cp = strrchr(parentname, '@');
- if (cp != NULL) {
- cp[0] = '\0';
- } else {
- cp = strrchr(parentname, '/');
- if (cp == NULL)
- return (ENOENT);
- cp[0] = '\0';
- }
-
- (void) strncpy(poolname, dataset, sizeof (poolname));
- cp = strchr(poolname, '/');
- if (cp != NULL)
- cp[0] = '\0';
+ uint64_t sense = ZFS_PROP_UNDEFINED;
+ uint64_t norm = ZFS_PROP_UNDEFINED;
+ uint64_t u8 = ZFS_PROP_UNDEFINED;
+ int error = 0;
+
+ ASSERT(zplprops != NULL);
+
+ (void) strlcpy(parentname, dataset, sizeof (parentname));
+ cp = strrchr(parentname, '/');
+ ASSERT(cp != NULL);
+ cp[0] = '\0';
/*
- * Make sure pool is of new enough vintage to support normalization.
+ * Pull out creator prop choices, if any.
*/
- if (zfs_check_version(poolname, SPA_VERSION_NORMALIZATION))
- return (0);
-
- error = zfs_prop_lookup(parentname, ZFS_PROP_UTF8ONLY,
- proplist, &value, update);
- if (error != 0)
- return (error);
- if (value != zfs_prop_default_numeric(ZFS_PROP_UTF8ONLY))
- check = 1;
-
- error = zfs_prop_lookup(parentname, ZFS_PROP_NORMALIZE,
- proplist, &value, update);
- if (error != 0)
- return (error);
- if (value != zfs_prop_default_numeric(ZFS_PROP_NORMALIZE)) {
- check = 1;
- switch ((int)value) {
- case ZFS_NORMALIZE_NONE:
- break;
- case ZFS_NORMALIZE_C:
- *norm |= U8_TEXTPREP_NFC;
- break;
- case ZFS_NORMALIZE_D:
- *norm |= U8_TEXTPREP_NFD;
- break;
- case ZFS_NORMALIZE_KC:
- *norm |= U8_TEXTPREP_NFKC;
- break;
- case ZFS_NORMALIZE_KD:
- *norm |= U8_TEXTPREP_NFKD;
- break;
- default:
- ASSERT((int)value >= ZFS_NORMALIZE_NONE);
- ASSERT((int)value <= ZFS_NORMALIZE_KD);
- break;
- }
- }
-
- error = zfs_prop_lookup(parentname, ZFS_PROP_CASE,
- proplist, &value, update);
- if (error != 0)
- return (error);
- if (value != zfs_prop_default_numeric(ZFS_PROP_CASE)) {
- check = 1;
- switch ((int)value) {
- case ZFS_CASE_SENSITIVE:
- break;
- case ZFS_CASE_INSENSITIVE:
- *norm |= U8_TEXTPREP_TOUPPER;
- break;
- case ZFS_CASE_MIXED:
- *norm |= U8_TEXTPREP_TOUPPER;
- break;
- default:
- ASSERT((int)value >= ZFS_CASE_SENSITIVE);
- ASSERT((int)value <= ZFS_CASE_MIXED);
- break;
- }
+ if (createprops) {
+ (void) nvlist_lookup_uint64(createprops,
+ zfs_prop_to_name(ZFS_PROP_NORMALIZE), &norm);
+ (void) nvlist_remove_all(createprops,
+ zfs_prop_to_name(ZFS_PROP_NORMALIZE));
+ (void) nvlist_lookup_uint64(createprops,
+ zfs_prop_to_name(ZFS_PROP_UTF8ONLY), &u8);
+ (void) nvlist_remove_all(createprops,
+ zfs_prop_to_name(ZFS_PROP_UTF8ONLY));
+ (void) nvlist_lookup_uint64(createprops,
+ zfs_prop_to_name(ZFS_PROP_CASE), &sense);
+ (void) nvlist_remove_all(createprops,
+ zfs_prop_to_name(ZFS_PROP_CASE));
}
/*
- * At the moment we are disabling non-default values for these
- * properties because they cannot be preserved properly with a
- * zfs send.
+ * If the file system or pool is version is too "young" to
+ * support normalization and the creator tried to set a value
+ * for one of the props, error out. We only need check the
+ * ZPL version because we've already checked by now that the
+ * SPA version is compatible with the selected ZPL version.
+ */
+ if (zplver < ZPL_VERSION_NORMALIZATION &&
+ (norm != ZFS_PROP_UNDEFINED || u8 != ZFS_PROP_UNDEFINED ||
+ sense != ZFS_PROP_UNDEFINED))
+ return (ENOTSUP);
+
+ /*
+ * Put the version in the zplprops
+ */
+ VERIFY(nvlist_add_uint64(zplprops,
+ zfs_prop_to_name(ZFS_PROP_VERSION), zplver) == 0);
+
+ /*
+ * Open parent object set so we can inherit zplprop values if
+ * necessary.
*/
- if (check == 1)
- return (ENOTSUP);
-
+ if ((error = zfs_os_open_retry(parentname, &os)) != 0)
+ return (error);
+
+ if (norm == ZFS_PROP_UNDEFINED)
+ VERIFY(zfs_get_zplprop(os, ZFS_PROP_NORMALIZE, &norm) == 0);
+ VERIFY(nvlist_add_uint64(zplprops,
+ zfs_prop_to_name(ZFS_PROP_NORMALIZE), norm) == 0);
+
+ /*
+ * If we're normalizing, names must always be valid UTF-8 strings.
+ */
+ if (norm)
+ u8 = 1;
+ if (u8 == ZFS_PROP_UNDEFINED)
+ VERIFY(zfs_get_zplprop(os, ZFS_PROP_UTF8ONLY, &u8) == 0);
+ VERIFY(nvlist_add_uint64(zplprops,
+ zfs_prop_to_name(ZFS_PROP_UTF8ONLY), u8) == 0);
+
+ if (sense == ZFS_PROP_UNDEFINED)
+ VERIFY(zfs_get_zplprop(os, ZFS_PROP_CASE, &sense) == 0);
+ VERIFY(nvlist_add_uint64(zplprops,
+ zfs_prop_to_name(ZFS_PROP_CASE), sense) == 0);
+
+ dmu_objset_close(os);
return (0);
}
@@ -1935,7 +1866,7 @@
* zc_value name of snapshot to clone from (may be empty)
* zc_nvlist_src{_size} nvlist of properties to apply
*
- * outputs: none
+ * outputs: none
*/
static int
zfs_ioc_create(zfs_cmd_t *zc)
@@ -1969,7 +1900,7 @@
&nvprops)) != 0)
return (error);
- zct.zct_norm = 0;
+ zct.zct_zplprops = NULL;
zct.zct_props = nvprops;
if (zc->zc_value[0] != '\0') {
@@ -1994,29 +1925,6 @@
nvlist_free(nvprops);
return (error);
}
- /*
- * If caller did not provide any properties, allocate
- * an nvlist for properties, as we will be adding our set-once
- * properties to it. This carries the choices made on the
- * original file system into the clone.
- */
- if (nvprops == NULL)
- VERIFY(nvlist_alloc(&nvprops,
- NV_UNIQUE_NAME, KM_SLEEP) == 0);
-
- /*
- * We have to have normalization and case-folding
- * flags correct when we do the file system creation,
- * so go figure them out now. All we really care about
- * here is getting these values into the property list.
- */
- error = zfs_normalization_get(zc->zc_value, nvprops,
- &zct.zct_norm, B_TRUE);
- if (error != 0) {
- dmu_objset_close(clone);
- nvlist_free(nvprops);
- return (error);
- }
dmu_objset_close(clone);
} else {
if (cbfunc == NULL) {
@@ -2057,15 +1965,29 @@
uint64_t version;
int error;
- error = nvlist_lookup_uint64(nvprops,
+ /*
+ * Default ZPL version to non-FUID capable if the
+ * pool is not upgraded to support FUIDs.
+ */
+ if (zfs_check_version(zc->zc_name, SPA_VERSION_FUID))
+ version = ZPL_VERSION_FUID - 1;
+ else
+ version = ZPL_VERSION;
+
+ /*
+ * Potentially override default ZPL version based
+ * on creator's request.
+ */
+ (void) nvlist_lookup_uint64(nvprops,
zfs_prop_to_name(ZFS_PROP_VERSION), &version);
- if (error == 0 && (version < ZPL_VERSION_INITIAL ||
- version > ZPL_VERSION)) {
- nvlist_free(nvprops);
- return (ENOTSUP);
- } else if (error == 0 && version >= ZPL_VERSION_FUID &&
- zfs_check_version(zc->zc_name, SPA_VERSION_FUID)) {
+ /*
+ * Make sure version we ended up with is kosher
+ */
+ if ((version < ZPL_VERSION_INITIAL ||
+ version > ZPL_VERSION) ||
+ (version >= ZPL_VERSION_FUID &&
+ zfs_check_version(zc->zc_name, SPA_VERSION_FUID))) {
nvlist_free(nvprops);
return (ENOTSUP);
}
@@ -2074,19 +1996,21 @@
* We have to have normalization and
* case-folding flags correct when we do the
* file system creation, so go figure them out
- * now. The final argument to zfs_normalization_get()
- * tells that routine not to update the nvprops
- * list.
+ * now.
*/
- error = zfs_normalization_get(zc->zc_name, nvprops,
- &zct.zct_norm, B_FALSE);
+ VERIFY(nvlist_alloc(&zct.zct_zplprops,
+ NV_UNIQUE_NAME, KM_SLEEP) == 0);
+ error = zfs_fill_zplprops(zc->zc_name, nvprops,
+ zct.zct_zplprops, version);
if (error != 0) {
nvlist_free(nvprops);
+ nvlist_free(zct.zct_zplprops);
return (error);
}
}
error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc,
&zct);
+ nvlist_free(zct.zct_zplprops);
}
/*
@@ -2793,7 +2717,7 @@
{ zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE },
{ zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE },
{ zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE },
- { zfs_ioc_objset_version, zfs_secpolicy_read, DATASET_NAME, B_FALSE },
+ { zfs_ioc_objset_zplprops, zfs_secpolicy_read, DATASET_NAME, B_FALSE },
{ zfs_ioc_dataset_list_next, zfs_secpolicy_read,
DATASET_NAME, B_FALSE },
{ zfs_ioc_snapshot_list_next, zfs_secpolicy_read,
--- a/usr/src/uts/common/fs/zfs/zfs_vfsops.c Mon Nov 19 21:07:12 2007 -0800
+++ b/usr/src/uts/common/fs/zfs/zfs_vfsops.c Tue Nov 20 05:42:50 2007 -0800
@@ -40,7 +40,6 @@
#include "fs/fs_subr.h"
#include <sys/zfs_znode.h>
#include <sys/zfs_dir.h>
-#include <sys/zfs_i18n.h>
#include <sys/zil.h>
#include <sys/fs/zfs.h>
#include <sys/dmu.h>
@@ -385,73 +384,6 @@
}
static int
-zfs_normalization_set(char *osname, zfsvfs_t *zfsvfs)
-{
- uint64_t pval;
- int error;
-
- if (zfsvfs->z_version < ZPL_VERSION_FUID)
- return (0);
-
- error = dsl_prop_get_integer(osname, "normalization", &pval, NULL);
- if (error)
- goto normquit;
- switch ((int)pval) {
- case ZFS_NORMALIZE_NONE:
- break;
- case ZFS_NORMALIZE_C:
- zfsvfs->z_norm |= U8_TEXTPREP_NFC;
- break;
- case ZFS_NORMALIZE_KC:
- zfsvfs->z_norm |= U8_TEXTPREP_NFKC;
- break;
- case ZFS_NORMALIZE_D:
- zfsvfs->z_norm |= U8_TEXTPREP_NFD;
- break;
- case ZFS_NORMALIZE_KD:
- zfsvfs->z_norm |= U8_TEXTPREP_NFKD;
- break;
- default:
- ASSERT(pval <= ZFS_NORMALIZE_KD);
- break;
- }
-
- error = dsl_prop_get_integer(osname, "utf8only", &pval, NULL);
- if (error)
- goto normquit;
- if (pval)
- zfsvfs->z_case |= ZFS_UTF8_ONLY;
- else
- zfsvfs->z_case &= ~ZFS_UTF8_ONLY;
-
- error = dsl_prop_get_integer(osname, "casesensitivity", &pval, NULL);
- if (error)
- goto normquit;
- vfs_set_feature(zfsvfs->z_vfs, VFSFT_DIRENTFLAGS);
- switch ((int)pval) {
- case ZFS_CASE_SENSITIVE:
- break;
- case ZFS_CASE_INSENSITIVE:
- zfsvfs->z_norm |= U8_TEXTPREP_TOUPPER;
- zfsvfs->z_case |= ZFS_CI_ONLY;
- vfs_set_feature(zfsvfs->z_vfs, VFSFT_CASEINSENSITIVE);
- vfs_set_feature(zfsvfs->z_vfs, VFSFT_NOCASESENSITIVE);
- break;
- case ZFS_CASE_MIXED:
- zfsvfs->z_norm |= U8_TEXTPREP_TOUPPER;
- zfsvfs->z_case |= ZFS_CI_MIXD;
- vfs_set_feature(zfsvfs->z_vfs, VFSFT_CASEINSENSITIVE);
- break;
- default:
- ASSERT(pval <= ZFS_CASE_MIXED);
- break;
- }
-
-normquit:
- return (error);
-}
-
-static int
zfs_register_callbacks(vfs_t *vfsp)
{
struct dsl_dataset *ds = NULL;
@@ -722,6 +654,7 @@
offsetof(znode_t, z_link_node));
rrw_init(&zfsvfs->z_teardown_lock);
rw_init(&zfsvfs->z_teardown_inactive_lock, NULL, RW_DEFAULT, NULL);
+ rw_init(&zfsvfs->z_fuid_lock, NULL, RW_DEFAULT, NULL);
/* Initialize the generic filesystem structure. */
vfsp->vfs_bcount = 0;
@@ -776,15 +709,14 @@
vfs_set_feature(vfsp, VFSFT_ACEMASKONACCESS);
vfs_set_feature(vfsp, VFSFT_ACLONCREATE);
}
-
- /*
- * Set normalization regardless of whether or not the object
- * set is a snapshot. Snapshots and clones need to have
- * identical normalization as did the file system they
- * originated from.
- */
- if ((error = zfs_normalization_set(osname, zfsvfs)) != 0)
- goto out;
+ if (zfsvfs->z_case == ZFS_CASE_INSENSITIVE) {
+ vfs_set_feature(vfsp, VFSFT_DIRENTFLAGS);
+ vfs_set_feature(vfsp, VFSFT_CASEINSENSITIVE);
+ vfs_set_feature(vfsp, VFSFT_NOCASESENSITIVE);
+ } else if (zfsvfs->z_case == ZFS_CASE_MIXED) {
+ vfs_set_feature(vfsp, VFSFT_DIRENTFLAGS);
+ vfs_set_feature(vfsp, VFSFT_CASEINSENSITIVE);
+ }
if (dmu_objset_is_snapshot(zfsvfs->z_os)) {
uint64_t pval;
@@ -810,6 +742,7 @@
list_destroy(&zfsvfs->z_all_znodes);
rrw_destroy(&zfsvfs->z_teardown_lock);
rw_destroy(&zfsvfs->z_teardown_inactive_lock);
+ rw_destroy(&zfsvfs->z_fuid_lock);
kmem_free(zfsvfs, sizeof (zfsvfs_t));
} else {
atomic_add_32(&zfs_active_fs_count, 1);
@@ -1562,6 +1495,7 @@
rrw_destroy(&zfsvfs->z_teardown_lock);
rw_destroy(&zfsvfs->z_teardown_inactive_lock);
zfs_fuid_destroy(zfsvfs);
+ rw_destroy(&zfsvfs->z_fuid_lock);
kmem_free(zfsvfs, sizeof (zfsvfs_t));
atomic_add_32(&zfs_active_fs_count, -1);
@@ -1637,15 +1571,6 @@
}
int
-zfs_get_version(objset_t *os, uint64_t *version)
-{
- int error;
-
- error = zap_lookup(os, MASTER_NODE_OBJ, ZPL_VERSION_STR, 8, 1, version);
- return (error);
-}
-
-int
zfs_set_version(const char *name, uint64_t newvers)
{
int error;
@@ -1696,6 +1621,49 @@
return (error);
}
+/*
+ * Read a property stored within the master node.
+ */
+int
+zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value)
+{
+ const char *pname;
+ int error;
+
+ /*
+ * Look up the file system's value for the property. For the
+ * version property, we look up a slightly different string.
+ * Also, there is no default VERSION value, so if we don't
+ * find it, return the error.
+ */
+ if (prop == ZFS_PROP_VERSION)
+ pname = ZPL_VERSION_STR;
+ else
+ pname = zfs_prop_to_name(prop);
+
+ error = zap_lookup(os, MASTER_NODE_OBJ, pname, 8, 1, value);
+
+ if (!error) {
+ return (0);
+ } else if (prop == ZFS_PROP_VERSION || error != ENOENT) {
+ return (error);
+ } else {
+ /* No value set, use the default value */
+ switch (prop) {
+ case ZFS_PROP_NORMALIZE:
+ case ZFS_PROP_UTF8ONLY:
+ *value = 0;
+ break;
+ case ZFS_PROP_CASE:
+ *value = ZFS_CASE_SENSITIVE;
+ break;
+ default:
+ return (ENOENT);
+ }
+ }
+ return (0);
+}
+
static vfsdef_t vfw = {
VFSDEF_VERSION,
MNTTYPE_ZFS,
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c Mon Nov 19 21:07:12 2007 -0800
+++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c Tue Nov 20 05:42:50 2007 -0800
@@ -52,11 +52,9 @@
#include <sys/cmn_err.h>
#include <sys/errno.h>
#include <sys/unistd.h>
-#include <sys/zfs_vfsops.h>
#include <sys/zfs_dir.h>
#include <sys/zfs_acl.h>
#include <sys/zfs_ioctl.h>
-#include <sys/zfs_i18n.h>
#include <sys/fs/zfs.h>
#include <sys/dmu.h>
#include <sys/spa.h>
@@ -1056,7 +1054,7 @@
return (error);
}
- if (zfsvfs->z_case & ZFS_UTF8_ONLY && u8_validate(nm, strlen(nm),
+ if (zfsvfs->z_utf8 && u8_validate(nm, strlen(nm),
NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
ZFS_EXIT(zfsvfs);
return (EILSEQ);
@@ -1139,7 +1137,7 @@
os = zfsvfs->z_os;
zilog = zfsvfs->z_log;
- if (zfsvfs->z_case & ZFS_UTF8_ONLY && u8_validate(name, strlen(name),
+ if (zfsvfs->z_utf8 && u8_validate(name, strlen(name),
NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
ZFS_EXIT(zfsvfs);
return (EILSEQ);
@@ -1589,7 +1587,7 @@
return (EINVAL);
}
- if (zfsvfs->z_case & ZFS_UTF8_ONLY && u8_validate(dirname,
+ if (zfsvfs->z_utf8 && u8_validate(dirname,
strlen(dirname), NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
ZFS_EXIT(zfsvfs);
return (EILSEQ);
@@ -2849,7 +2847,7 @@
tdzp = VTOZ(tdvp);
ZFS_VERIFY_ZP(tdzp);
- if (zfsvfs->z_case & ZFS_UTF8_ONLY && u8_validate(tnm,
+ if (zfsvfs->z_utf8 && u8_validate(tnm,
strlen(tnm), NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
ZFS_EXIT(zfsvfs);
return (EILSEQ);
@@ -2892,7 +2890,7 @@
int nofold = (zfsvfs->z_norm & ~U8_TEXTPREP_TOUPPER);
cmp = u8_strcmp(snm, tnm, 0, nofold, U8_UNICODE_LATEST, &error);
- ASSERT(error == 0 || !(zfsvfs->z_case & ZFS_UTF8_ONLY));
+ ASSERT(error == 0 || !zfsvfs->z_utf8);
if (cmp == 0) {
/*
* POSIX: "If the old argument and the new argument
@@ -2921,8 +2919,9 @@
* is an exact match, we will allow this to proceed as
* a name-change request.
*/
- if ((zfsvfs->z_case & ZFS_CI_ONLY ||
- (zfsvfs->z_case & ZFS_CI_MIXD && flags & FIGNORECASE)) &&
+ if ((zfsvfs->z_case == ZFS_CASE_INSENSITIVE ||
+ (zfsvfs->z_case == ZFS_CASE_MIXED &&
+ flags & FIGNORECASE)) &&
u8_strcmp(snm, tnm, 0, zfsvfs->z_norm, U8_UNICODE_LATEST,
&error) == 0) {
/*
@@ -3130,7 +3129,7 @@
ZFS_VERIFY_ZP(dzp);
zilog = zfsvfs->z_log;
- if (zfsvfs->z_case & ZFS_UTF8_ONLY && u8_validate(name, strlen(name),
+ if (zfsvfs->z_utf8 && u8_validate(name, strlen(name),
NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
ZFS_EXIT(zfsvfs);
return (EILSEQ);
@@ -3339,7 +3338,7 @@
szp = VTOZ(svp);
ZFS_VERIFY_ZP(szp);
- if (zfsvfs->z_case & ZFS_UTF8_ONLY && u8_validate(name,
+ if (zfsvfs->z_utf8 && u8_validate(name,
strlen(name), NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
ZFS_EXIT(zfsvfs);
return (EILSEQ);
@@ -4288,7 +4287,6 @@
case _PC_SATTR_ENABLED:
case _PC_SATTR_EXISTS:
- zp = VTOZ(vp);
*valp = vfs_has_feature(vp->v_vfsp, VFSFT_XVATTR) &&
(vp->v_type == VREG || vp->v_type == VDIR);
return (0);
--- a/usr/src/uts/common/fs/zfs/zfs_znode.c Mon Nov 19 21:07:12 2007 -0800
+++ b/usr/src/uts/common/fs/zfs/zfs_znode.c Tue Nov 20 05:42:50 2007 -0800
@@ -36,6 +36,7 @@
#include <sys/resource.h>
#include <sys/mntent.h>
#include <sys/mkdev.h>
+#include <sys/u8_textprep.h>
#include <sys/vfs.h>
#include <sys/vfs_opreg.h>
#include <sys/vnode.h>
@@ -52,7 +53,6 @@
#include <sys/zfs_ioctl.h>
#include <sys/zfs_rlock.h>
#include <sys/zfs_fuid.h>
-#include <sys/zfs_i18n.h>
#include <sys/fs/zfs.h>
#include <sys/kidmap.h>
#endif /* _KERNEL */
@@ -63,6 +63,8 @@
#include <sys/zap.h>
#include <sys/zfs_znode.h>
+#include "zfs_prop.h"
+
/*
* Functions needed for userland (ie: libzpool) are not put under
* #ifdef_KERNEL; the rest of the functions have dependencies
@@ -255,6 +257,7 @@
int i, error;
dmu_object_info_t doi;
uint64_t fsid_guid;
+ uint64_t zval;
*zpp = NULL;
@@ -265,6 +268,7 @@
if (dmu_object_info(os, MASTER_NODE_OBJ, &doi) == ENOENT) {
dmu_tx_t *tx = dmu_tx_create(os);
uint64_t zpl_version;
+ nvlist_t *zprops;
dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, TRUE, NULL); /* master */
dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, TRUE, NULL); /* del queue */
@@ -275,12 +279,16 @@
zpl_version = ZPL_VERSION;
else
zpl_version = ZPL_VERSION_FUID - 1;
- zfs_create_fs(os, cr, zpl_version, 0, tx);
+
+ VERIFY(nvlist_alloc(&zprops, NV_UNIQUE_NAME, KM_SLEEP) == 0);
+ VERIFY(nvlist_add_uint64(zprops,
+ zfs_prop_to_name(ZFS_PROP_VERSION), zpl_version) == 0);
+ zfs_create_fs(os, cr, zprops, tx);
+ nvlist_free(zprops);
dmu_tx_commit(tx);
}
- error = zap_lookup(os, MASTER_NODE_OBJ, ZPL_VERSION_STR, 8, 1,
- &zfsvfs->z_version);
+ error = zfs_get_zplprop(os, ZFS_PROP_VERSION, &zfsvfs->z_version);
if (error) {
return (error);
} else if (zfsvfs->z_version > ZPL_VERSION) {
@@ -291,6 +299,23 @@
return (ENOTSUP);
}
+ if ((error = zfs_get_zplprop(os, ZFS_PROP_NORMALIZE, &zval)) != 0)
+ return (error);
+ zfsvfs->z_norm = (int)zval;
+ if ((error = zfs_get_zplprop(os, ZFS_PROP_UTF8ONLY, &zval)) != 0)
+ return (error);
+ zfsvfs->z_utf8 = (zval != 0);
+ if ((error = zfs_get_zplprop(os, ZFS_PROP_CASE, &zval)) != 0)
+ return (error);
+ zfsvfs->z_case = (uint_t)zval;
+ /*
+ * Fold case on file systems that are always or sometimes case
+ * insensitive.
+ */
+ if (zfsvfs->z_case == ZFS_CASE_INSENSITIVE ||
+ zfsvfs->z_case == ZFS_CASE_MIXED)
+ zfsvfs->z_norm |= U8_TEXTPREP_TOUPPER;
+
/*
* The fsid is 64 bits, composed of an 8-bit fs type, which
* separates our fsid from any other filesystem types, and a
@@ -1170,11 +1195,14 @@
}
void
-zfs_create_fs(objset_t *os, cred_t *cr, uint64_t version,
- int norm, dmu_tx_t *tx)
+zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
{
zfsvfs_t zfsvfs;
uint64_t moid, doid;
+ uint64_t version = 0;
+ uint64_t sense = ZFS_CASE_SENSITIVE;
+ uint64_t norm = 0;
+ nvpair_t *elem;
int error;
znode_t *rootzp = NULL;
vnode_t *vp;
@@ -1196,9 +1224,29 @@
/*
* Set starting attributes.
*/
+ elem = NULL;
+ while ((elem = nvlist_next_nvpair(zplprops, elem)) != NULL) {
+ /* For the moment we expect all zpl props to be uint64_ts */
+ uint64_t val;
+ char *name;
- error = zap_update(os, moid, ZPL_VERSION_STR, 8, 1, &version, tx);
- ASSERT(error == 0);
+ ASSERT(nvpair_type(elem) == DATA_TYPE_UINT64);
+ ASSERT(nvpair_value_uint64(elem, &val) == 0);
+ name = nvpair_name(elem);
+ if (strcmp(name, zfs_prop_to_name(ZFS_PROP_VERSION)) == 0) {
+ version = val;
+ error = zap_update(os, moid, ZPL_VERSION_STR,
+ 8, 1, &version, tx);
+ } else {
+ error = zap_update(os, moid, name, 8, 1, &val, tx);
+ }
+ ASSERT(error == 0);
+ if (strcmp(name, zfs_prop_to_name(ZFS_PROP_NORMALIZE)) == 0)
+ norm = val;
+ else if (strcmp(name, zfs_prop_to_name(ZFS_PROP_CASE)) == 0)
+ sense = val;
+ }
+ ASSERT(version != 0);
/*
* Create a delete queue.
@@ -1235,6 +1283,12 @@
zfsvfs.z_version = version;
zfsvfs.z_use_fuids = USE_FUIDS(version, os);
zfsvfs.z_norm = norm;
+ /*
+ * Fold case on file systems that are always or sometimes case
+ * insensitive.
+ */
+ if (sense == ZFS_CASE_INSENSITIVE || sense == ZFS_CASE_MIXED)
+ zfsvfs.z_norm |= U8_TEXTPREP_TOUPPER;
mutex_init(&zfsvfs.z_znodes_lock, NULL, MUTEX_DEFAULT, NULL);
list_create(&zfsvfs.z_all_znodes, sizeof (znode_t),
--- a/usr/src/uts/common/sys/fs/zfs.h Mon Nov 19 21:07:12 2007 -0800
+++ b/usr/src/uts/common/sys/fs/zfs.h Tue Nov 20 05:42:50 2007 -0800
@@ -253,7 +253,6 @@
#define SPA_VERSION_SLOGS SPA_VERSION_7
#define SPA_VERSION_DELEGATED_PERMS SPA_VERSION_8
#define SPA_VERSION_FUID SPA_VERSION_9
-#define SPA_VERSION_NORMALIZATION SPA_VERSION_9
#define SPA_VERSION_REFRESERVATION SPA_VERSION_9
#define SPA_VERSION_REFQUOTA SPA_VERSION_9
#define SPA_VERSION_UNIQUE_ACCURATE SPA_VERSION_9
@@ -276,6 +275,7 @@
#define ZPL_VERSION_INITIAL ZPL_VERSION_1
#define ZPL_VERSION_DIRENT_TYPE ZPL_VERSION_2
#define ZPL_VERSION_FUID ZPL_VERSION_3
+#define ZPL_VERSION_NORMALIZATION ZPL_VERSION_3
#define ZPL_VERSION_SYSATTR ZPL_VERSION_3
/*
@@ -497,7 +497,7 @@
ZFS_IOC_VDEV_DETACH,
ZFS_IOC_VDEV_SETPATH,
ZFS_IOC_OBJSET_STATS,
- ZFS_IOC_OBJSET_VERSION,
+ ZFS_IOC_OBJSET_ZPLPROPS,
ZFS_IOC_DATASET_LIST_NEXT,
ZFS_IOC_SNAPSHOT_LIST_NEXT,
ZFS_IOC_SET_PROP,