summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2017-01-25 13:23:41 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2017-01-25 13:23:41 +0000
commite6dcb886bb29fde73ee96922dc7e4545ed93f94f (patch)
tree7399fa51971b24b77c8166dd9eaab9537da8859a
parentc6f48adc748c5507279a550ec38b3545c1e8a07b (diff)
parent325bfec6aff6eb2bbacaf3bebb1eb4578418b31a (diff)
downloadillumos-joyent-e6dcb886bb29fde73ee96922dc7e4545ed93f94f.tar.gz
[illumos-gate merge]
commit 325bfec6aff6eb2bbacaf3bebb1eb4578418b31a 7764 vioif norcvbuf kstat goes up for each receive interrupt commit 1c17160ac558f98048951327f4e9248d8f46acc0 1300 filename normalization doesn't work for removes commit f3de0dd97fc8208161e42908fd1e6eecfef33f87 7681 uts: nfs_dlboot fall back to use rootpath from dhcp commit 8df617e13b42e83a38b2423a487ed1032b60018f 7802 libldap fix from Mozilla in unescape Conflicts: usr/src/uts/common/io/vioif/vioif.c
-rw-r--r--usr/src/lib/libldap5/sources/ldap/common/unescape.c11
-rw-r--r--usr/src/uts/common/fs/nfs/nfs_dlinet.c70
-rw-r--r--usr/src/uts/common/fs/zfs/dmu_objset.c5
-rw-r--r--usr/src/uts/common/fs/zfs/dsl_bookmark.c14
-rw-r--r--usr/src/uts/common/fs/zfs/dsl_dataset.c18
-rw-r--r--usr/src/uts/common/fs/zfs/sys/zap.h35
-rw-r--r--usr/src/uts/common/fs/zfs/sys/zap_impl.h3
-rw-r--r--usr/src/uts/common/fs/zfs/zap_leaf.c20
-rw-r--r--usr/src/uts/common/fs/zfs/zap_micro.c95
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_dir.c86
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_vnops.c17
-rw-r--r--usr/src/uts/common/io/vioif/vioif.c20
12 files changed, 243 insertions, 151 deletions
diff --git a/usr/src/lib/libldap5/sources/ldap/common/unescape.c b/usr/src/lib/libldap5/sources/ldap/common/unescape.c
index 65de7c03b4..70aae09642 100644
--- a/usr/src/lib/libldap5/sources/ldap/common/unescape.c
+++ b/usr/src/lib/libldap5/sources/ldap/common/unescape.c
@@ -44,12 +44,15 @@ nsldapi_hex_unescape( char *s )
for ( p = s; *s != '\0'; ++s ) {
if ( *s == '%' ) {
- if ( *++s != '\0' ) {
- *p = unhex( *s ) << 4;
+ if ( *++s == '\0' ) {
+ break;
}
- if ( *++s != '\0' ) {
- *p++ += unhex( *s );
+ *p = unhex( *s ) << 4;
+ if ( *++s == '\0' ) {
+ break;
}
+ *p++ += unhex( *s );
+
} else {
*p++ = *s;
}
diff --git a/usr/src/uts/common/fs/nfs/nfs_dlinet.c b/usr/src/uts/common/fs/nfs/nfs_dlinet.c
index 944df0336d..8ac4c84d17 100644
--- a/usr/src/uts/common/fs/nfs/nfs_dlinet.c
+++ b/usr/src/uts/common/fs/nfs/nfs_dlinet.c
@@ -23,8 +23,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/types.h>
#include <sys/systm.h>
@@ -290,7 +288,7 @@ int nfs4_no_diskless_root_support = 1;
int
mount_root(char *name, char *path, int version, struct nfs_args *args,
- int *vfsflags)
+ int *vfsflags)
{
int rc;
int proto;
@@ -400,7 +398,7 @@ errout:
*/
static int
mountnfs(struct netbuf *sa, char *server,
- char *path, fhandle_t *fh, int *proto)
+ char *path, fhandle_t *fh, int *proto)
{
struct fhstatus fhs;
enum clnt_stat stat;
@@ -480,7 +478,7 @@ mountnfs(struct netbuf *sa, char *server,
*/
static int
mountnfs3(struct netbuf *sa, char *server,
- char *path, nfs_fh3 *fh, int *proto)
+ char *path, nfs_fh3 *fh, int *proto)
{
struct mountres3 mountres3;
enum clnt_stat stat;
@@ -579,7 +577,7 @@ out:
static int
ping_prog(struct netbuf *call_addr, uint_t prog, uint_t vers, int proto,
- enum clnt_stat *statp)
+ enum clnt_stat *statp)
{
struct knetconfig *knconf;
enum clnt_stat stat;
@@ -816,7 +814,7 @@ done:
*/
static int
getfile(char *fileid,
- char *server_name, struct netbuf *server_address, char *server_path)
+ char *server_name, struct netbuf *server_address, char *server_path)
{
struct bp_getfile_arg arg;
struct bp_getfile_res res;
@@ -1186,7 +1184,7 @@ cacheinit(void)
if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
DDI_PROP_DONTPASS, BP_SERVER_IP, &str) == DDI_SUCCESS) {
if (inet_aton(str, server_ip) != 0)
- cmn_err(CE_NOTE, "server_ipaddr %s is invalid\n",
+ cmn_err(CE_NOTE, "server_ipaddr %s is invalid",
str);
ddi_prop_free(str);
if (dldebug)
@@ -1200,10 +1198,44 @@ cacheinit(void)
/* extract root path in server_path */
if (server_path_c == NULL) {
doptp = pl->vs[VS_NFSMNT_ROOTPATH];
+ if (doptp == NULL)
+ doptp = pl->opts[CD_ROOT_PATH];
if (doptp != NULL) {
- server_path_c = kmem_alloc(doptp->len + 1, KM_SLEEP);
- bcopy(doptp->value, server_path_c, doptp->len);
- server_path_c[doptp->len] = '\0';
+ int len;
+ str = NULL;
+ for (len = 0; len < doptp->len; len++) {
+ if (doptp->value[len] == ':') {
+ str = (char *)(&doptp->value[++len]);
+ break;
+ }
+ }
+ if (str != NULL) {
+ /* Do not override server_ip from property. */
+ if ((*(uint_t *)server_ip) == 0) {
+ char *ip = kmem_alloc(len, KM_SLEEP);
+ bcopy(doptp->value, ip, len);
+ ip[len - 1] = '\0';
+ if (inet_aton((ip), server_ip) != 0) {
+ cmn_err(CE_NOTE,
+ "server_ipaddr %s is "
+ "invalid", ip);
+ }
+ kmem_free(ip, len);
+ if (dldebug) {
+ printf("server ip is %s\n",
+ inet_ntoa(
+ *(struct in_addr *)
+ server_ip));
+ }
+ }
+ len = doptp->len - len;
+ } else {
+ str = (char *)doptp->value;
+ len = doptp->len;
+ }
+ server_path_c = kmem_alloc(len + 1, KM_SLEEP);
+ bcopy(str, server_path_c, len);
+ server_path_c[len] = '\0';
if (dldebug)
printf("dhcp: root path %s\n", server_path_c);
} else {
@@ -1860,7 +1892,7 @@ myxdr_fhandle3(XDR *xdrs, struct fhandle3 *objp)
*/
static enum clnt_stat
pmap_kgetport(struct knetconfig *knconf, struct netbuf *call_addr,
- rpcprog_t prog, rpcvers_t vers, rpcprot_t prot)
+ rpcprog_t prog, rpcvers_t vers, rpcprot_t prot)
{
ushort_t port;
int tries;
@@ -1942,9 +1974,9 @@ pmap_kgetport(struct knetconfig *knconf, struct netbuf *call_addr,
*/
static enum clnt_stat
pmap_rmt_call(struct knetconfig *knconf, struct netbuf *call_addr,
- bool_t bcast, rpcprog_t progn, rpcvers_t versn, rpcproc_t procn,
- xdrproc_t xdrargs, caddr_t argsp, xdrproc_t xdrres, caddr_t resp,
- struct timeval tout, struct netbuf *resp_addr)
+ bool_t bcast, rpcprog_t progn, rpcvers_t versn, rpcproc_t procn,
+ xdrproc_t xdrargs, caddr_t argsp, xdrproc_t xdrres, caddr_t resp,
+ struct timeval tout, struct netbuf *resp_addr)
{
CLIENT *cl;
enum clnt_stat stat;
@@ -2094,9 +2126,9 @@ myxdr_pmap(XDR *xdrs, struct pmap *regs)
*/
static enum clnt_stat
mycallrpc(struct knetconfig *knconf, struct netbuf *call_addr,
- rpcprog_t prognum, rpcvers_t versnum, rpcproc_t procnum,
- xdrproc_t inproc, char *in, xdrproc_t outproc, char *out,
- int timeo, int retries)
+ rpcprog_t prognum, rpcvers_t versnum, rpcproc_t procnum,
+ xdrproc_t inproc, char *in, xdrproc_t outproc, char *out,
+ int timeo, int retries)
{
CLIENT *cl;
struct timeval tv;
@@ -2436,7 +2468,7 @@ int nfs_rootopts = NFSMNT_NOCTO|NFSMNT_LLOCK|NFSMNT_INT;
static int
init_mountopts(struct nfs_args *args, int version, struct knetconfig **dl_cf,
- int *vfsflags)
+ int *vfsflags)
{
char servername[SYS_NMLN];
static int first = 0;
diff --git a/usr/src/uts/common/fs/zfs/dmu_objset.c b/usr/src/uts/common/fs/zfs/dmu_objset.c
index b71a43f7b5..a2322a90cc 100644
--- a/usr/src/uts/common/fs/zfs/dmu_objset.c
+++ b/usr/src/uts/common/fs/zfs/dmu_objset.c
@@ -18,15 +18,16 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016 by Delphix. All rights reserved.
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
- * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2015, STRATO AG, Inc. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
+ * Copyright 2017 Nexenta Systems, Inc.
*/
/* Portions Copyright 2010 Robert Milkowski */
@@ -1622,7 +1623,7 @@ dmu_snapshot_realname(objset_t *os, char *name, char *real, int maxlen,
return (zap_lookup_norm(ds->ds_dir->dd_pool->dp_meta_objset,
dsl_dataset_phys(ds)->ds_snapnames_zapobj, name, 8, 1, &ignored,
- MT_FIRST, real, maxlen, conflict));
+ MT_NORMALIZE, real, maxlen, conflict));
}
int
diff --git a/usr/src/uts/common/fs/zfs/dsl_bookmark.c b/usr/src/uts/common/fs/zfs/dsl_bookmark.c
index 39d572c411..2b9c5bbe42 100644
--- a/usr/src/uts/common/fs/zfs/dsl_bookmark.c
+++ b/usr/src/uts/common/fs/zfs/dsl_bookmark.c
@@ -12,8 +12,10 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 2013, 2014 by Delphix. All rights reserved.
+ * Copyright 2017 Nexenta Systems, Inc.
*/
#include <sys/zfs_context.h>
@@ -59,16 +61,14 @@ dsl_dataset_bmark_lookup(dsl_dataset_t *ds, const char *shortname,
{
objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
uint64_t bmark_zapobj = ds->ds_bookmarks;
- matchtype_t mt;
+ matchtype_t mt = 0;
int err;
if (bmark_zapobj == 0)
return (SET_ERROR(ESRCH));
if (dsl_dataset_phys(ds)->ds_flags & DS_FLAG_CI_DATASET)
- mt = MT_FIRST;
- else
- mt = MT_EXACT;
+ mt = MT_NORMALIZE;
err = zap_lookup_norm(mos, bmark_zapobj, shortname, sizeof (uint64_t),
sizeof (*bmark_phys) / sizeof (uint64_t), bmark_phys, mt,
@@ -339,12 +339,10 @@ dsl_dataset_bookmark_remove(dsl_dataset_t *ds, const char *name, dmu_tx_t *tx)
{
objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
uint64_t bmark_zapobj = ds->ds_bookmarks;
- matchtype_t mt;
+ matchtype_t mt = 0;
if (dsl_dataset_phys(ds)->ds_flags & DS_FLAG_CI_DATASET)
- mt = MT_FIRST;
- else
- mt = MT_EXACT;
+ mt = MT_NORMALIZE;
return (zap_remove_norm(mos, bmark_zapobj, name, mt, tx));
}
diff --git a/usr/src/uts/common/fs/zfs/dsl_dataset.c b/usr/src/uts/common/fs/zfs/dsl_dataset.c
index 8bc528e1d4..155d1cf7f2 100644
--- a/usr/src/uts/common/fs/zfs/dsl_dataset.c
+++ b/usr/src/uts/common/fs/zfs/dsl_dataset.c
@@ -18,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2016 by Delphix. All rights reserved.
@@ -26,6 +27,7 @@
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2016, OmniTI Computer Consulting, Inc. All rights reserved.
+ * Copyright 2017 Nexenta Systems, Inc.
*/
#include <sys/dmu_objset.h>
@@ -353,17 +355,15 @@ dsl_dataset_snap_lookup(dsl_dataset_t *ds, const char *name, uint64_t *value)
{
objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
uint64_t snapobj = dsl_dataset_phys(ds)->ds_snapnames_zapobj;
- matchtype_t mt;
+ matchtype_t mt = 0;
int err;
if (dsl_dataset_phys(ds)->ds_flags & DS_FLAG_CI_DATASET)
- mt = MT_FIRST;
- else
- mt = MT_EXACT;
+ mt = MT_NORMALIZE;
err = zap_lookup_norm(mos, snapobj, name, 8, 1,
value, mt, NULL, 0, NULL);
- if (err == ENOTSUP && mt == MT_FIRST)
+ if (err == ENOTSUP && (mt & MT_NORMALIZE))
err = zap_lookup(mos, snapobj, name, 8, 1, value);
return (err);
}
@@ -374,18 +374,16 @@ dsl_dataset_snap_remove(dsl_dataset_t *ds, const char *name, dmu_tx_t *tx,
{
objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
uint64_t snapobj = dsl_dataset_phys(ds)->ds_snapnames_zapobj;
- matchtype_t mt;
+ matchtype_t mt = 0;
int err;
dsl_dir_snap_cmtime_update(ds->ds_dir);
if (dsl_dataset_phys(ds)->ds_flags & DS_FLAG_CI_DATASET)
- mt = MT_FIRST;
- else
- mt = MT_EXACT;
+ mt = MT_NORMALIZE;
err = zap_remove_norm(mos, snapobj, name, mt, tx);
- if (err == ENOTSUP && mt == MT_FIRST)
+ if (err == ENOTSUP && (mt & MT_NORMALIZE))
err = zap_remove(mos, snapobj, name, tx);
if (err == 0 && adj_cnt)
diff --git a/usr/src/uts/common/fs/zfs/sys/zap.h b/usr/src/uts/common/fs/zfs/sys/zap.h
index 51d4283ef9..de4c7cced1 100644
--- a/usr/src/uts/common/fs/zfs/sys/zap.h
+++ b/usr/src/uts/common/fs/zfs/sys/zap.h
@@ -18,9 +18,11 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+ * Copyright 2017 Nexenta Systems, Inc.
*/
#ifndef _SYS_ZAP_H
@@ -88,22 +90,15 @@ extern "C" {
/*
* Specifies matching criteria for ZAP lookups.
+ * MT_NORMALIZE Use ZAP normalization flags, which can include both
+ * unicode normalization and case-insensitivity.
+ * MT_MATCH_CASE Do case-sensitive lookups even if MT_NORMALIZE is
+ * specified and ZAP normalization flags include
+ * U8_TEXTPREP_TOUPPER.
*/
-typedef enum matchtype
-{
- /* Only find an exact match (non-normalized) */
- MT_EXACT,
- /*
- * If there is an exact match, find that, otherwise find the
- * first normalized match.
- */
- MT_BEST,
- /*
- * Find the "first" normalized (case and Unicode form) match;
- * the designated "first" match will not change as long as the
- * set of entries with this normalization doesn't change.
- */
- MT_FIRST
+typedef enum matchtype {
+ MT_NORMALIZE = 1 << 0,
+ MT_MATCH_CASE = 1 << 1,
} matchtype_t;
typedef enum zap_flags {
@@ -120,16 +115,6 @@ typedef enum zap_flags {
/*
* Create a new zapobj with no attributes and return its object number.
- * MT_EXACT will cause the zap object to only support MT_EXACT lookups,
- * otherwise any matchtype can be used for lookups.
- *
- * normflags specifies what normalization will be done. values are:
- * 0: no normalization (legacy on-disk format, supports MT_EXACT matching
- * only)
- * U8_TEXTPREP_TOLOWER: case normalization will be performed.
- * MT_FIRST/MT_BEST matching will find entries that match without
- * regard to case (eg. looking for "foo" can find an entry "Foo").
- * Eventually, other flags will permit unicode normalization as well.
*/
uint64_t zap_create(objset_t *ds, dmu_object_type_t ot,
dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx);
diff --git a/usr/src/uts/common/fs/zfs/sys/zap_impl.h b/usr/src/uts/common/fs/zfs/sys/zap_impl.h
index 3e73883a43..cece948977 100644
--- a/usr/src/uts/common/fs/zfs/sys/zap_impl.h
+++ b/usr/src/uts/common/fs/zfs/sys/zap_impl.h
@@ -18,11 +18,13 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2016 by Delphix. All rights reserved.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
+ * Copyright 2017 Nexenta Systems, Inc.
*/
#ifndef _SYS_ZAP_IMPL_H
@@ -189,6 +191,7 @@ typedef struct zap_name {
int zn_key_norm_numints;
uint64_t zn_hash;
matchtype_t zn_matchtype;
+ int zn_normflags;
char zn_normbuf[ZAP_MAXNAMELEN];
} zap_name_t;
diff --git a/usr/src/uts/common/fs/zfs/zap_leaf.c b/usr/src/uts/common/fs/zfs/zap_leaf.c
index c8c3660756..35dca89728 100644
--- a/usr/src/uts/common/fs/zfs/zap_leaf.c
+++ b/usr/src/uts/common/fs/zfs/zap_leaf.c
@@ -18,9 +18,11 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2015 by Delphix. All rights reserved.
+ * Copyright 2017 Nexenta Systems, Inc.
*/
/*
@@ -361,7 +363,7 @@ zap_leaf_array_match(zap_leaf_t *l, zap_name_t *zn,
}
ASSERT(zn->zn_key_intlen == 1);
- if (zn->zn_matchtype == MT_FIRST) {
+ if (zn->zn_matchtype & MT_NORMALIZE) {
char *thisname = kmem_alloc(array_numints, KM_SLEEP);
boolean_t match;
@@ -403,7 +405,6 @@ zap_leaf_lookup(zap_leaf_t *l, zap_name_t *zn, zap_entry_handle_t *zeh)
ASSERT3U(zap_leaf_phys(l)->l_hdr.lh_magic, ==, ZAP_LEAF_MAGIC);
-again:
for (chunkp = LEAF_HASH_ENTPTR(l, zn->zn_hash);
*chunkp != CHAIN_END; chunkp = &le->le_next) {
uint16_t chunk = *chunkp;
@@ -418,9 +419,9 @@ again:
/*
* NB: the entry chain is always sorted by cd on
* normalized zap objects, so this will find the
- * lowest-cd match for MT_FIRST.
+ * lowest-cd match for MT_NORMALIZE.
*/
- ASSERT(zn->zn_matchtype == MT_EXACT ||
+ ASSERT((zn->zn_matchtype == 0) ||
(zap_leaf_phys(l)->l_hdr.lh_flags & ZLF_ENTRIES_CDSORTED));
if (zap_leaf_array_match(l, zn, le->le_name_chunk,
le->le_name_numints)) {
@@ -434,15 +435,6 @@ again:
}
}
- /*
- * NB: we could of course do this in one pass, but that would be
- * a pain. We'll see if MT_BEST is even used much.
- */
- if (zn->zn_matchtype == MT_BEST) {
- zn->zn_matchtype = MT_FIRST;
- goto again;
- }
-
return (SET_ERROR(ENOENT));
}
@@ -697,7 +689,7 @@ zap_entry_normalization_conflict(zap_entry_handle_t *zeh, zap_name_t *zn,
continue;
if (zn == NULL) {
- zn = zap_name_alloc(zap, name, MT_FIRST);
+ zn = zap_name_alloc(zap, name, MT_NORMALIZE);
allocdzn = B_TRUE;
}
if (zap_leaf_array_match(zeh->zeh_leaf, zn,
diff --git a/usr/src/uts/common/fs/zfs/zap_micro.c b/usr/src/uts/common/fs/zfs/zap_micro.c
index ad223a08c9..7086b2abad 100644
--- a/usr/src/uts/common/fs/zfs/zap_micro.c
+++ b/usr/src/uts/common/fs/zfs/zap_micro.c
@@ -18,11 +18,13 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2016 by Delphix. All rights reserved.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
+ * Copyright 2017 Nexenta Systems, Inc.
*/
#include <sys/zio.h>
@@ -133,7 +135,7 @@ zap_hash(zap_name_t *zn)
}
static int
-zap_normalize(zap_t *zap, const char *name, char *namenorm)
+zap_normalize(zap_t *zap, const char *name, char *namenorm, int normflags)
{
size_t inlen, outlen;
int err;
@@ -145,8 +147,8 @@ zap_normalize(zap_t *zap, const char *name, char *namenorm)
err = 0;
(void) u8_textprep_str((char *)name, &inlen, namenorm, &outlen,
- zap->zap_normflags | U8_TEXTPREP_IGNORE_NULL |
- U8_TEXTPREP_IGNORE_INVALID, U8_UNICODE_LATEST, &err);
+ normflags | U8_TEXTPREP_IGNORE_NULL | U8_TEXTPREP_IGNORE_INVALID,
+ U8_UNICODE_LATEST, &err);
return (err);
}
@@ -156,15 +158,15 @@ zap_match(zap_name_t *zn, const char *matchname)
{
ASSERT(!(zap_getflags(zn->zn_zap) & ZAP_FLAG_UINT64_KEY));
- if (zn->zn_matchtype == MT_FIRST) {
+ if (zn->zn_matchtype & MT_NORMALIZE) {
char norm[ZAP_MAXNAMELEN];
- if (zap_normalize(zn->zn_zap, matchname, norm) != 0)
+ if (zap_normalize(zn->zn_zap, matchname, norm,
+ zn->zn_normflags) != 0)
return (B_FALSE);
return (strcmp(zn->zn_key_norm, norm) == 0);
} else {
- /* MT_BEST or MT_EXACT */
return (strcmp(zn->zn_key_orig, matchname) == 0);
}
}
@@ -185,15 +187,30 @@ zap_name_alloc(zap_t *zap, const char *key, matchtype_t mt)
zn->zn_key_orig = key;
zn->zn_key_orig_numints = strlen(zn->zn_key_orig) + 1;
zn->zn_matchtype = mt;
+ zn->zn_normflags = zap->zap_normflags;
+
+ /*
+ * If we're dealing with a case sensitive lookup on a mixed or
+ * insensitive fs, remove U8_TEXTPREP_TOUPPER or the lookup
+ * will fold case to all caps overriding the lookup request.
+ */
+ if (mt & MT_MATCH_CASE)
+ zn->zn_normflags &= ~U8_TEXTPREP_TOUPPER;
+
if (zap->zap_normflags) {
- if (zap_normalize(zap, key, zn->zn_normbuf) != 0) {
+ /*
+ * We *must* use zap_normflags because this normalization is
+ * what the hash is computed from.
+ */
+ if (zap_normalize(zap, key, zn->zn_normbuf,
+ zap->zap_normflags) != 0) {
zap_name_free(zn);
return (NULL);
}
zn->zn_key_norm = zn->zn_normbuf;
zn->zn_key_norm_numints = strlen(zn->zn_key_norm) + 1;
} else {
- if (mt != MT_EXACT) {
+ if (mt != 0) {
zap_name_free(zn);
return (NULL);
}
@@ -202,6 +219,20 @@ zap_name_alloc(zap_t *zap, const char *key, matchtype_t mt)
}
zn->zn_hash = zap_hash(zn);
+
+ if (zap->zap_normflags != zn->zn_normflags) {
+ /*
+ * We *must* use zn_normflags because this normalization is
+ * what the matching is based on. (Not the hash!)
+ */
+ if (zap_normalize(zap, key, zn->zn_normbuf,
+ zn->zn_normflags) != 0) {
+ zap_name_free(zn);
+ return (NULL);
+ }
+ zn->zn_key_norm_numints = strlen(zn->zn_key_norm) + 1;
+ }
+
return (zn);
}
@@ -215,7 +246,7 @@ zap_name_alloc_uint64(zap_t *zap, const uint64_t *key, int numints)
zn->zn_key_intlen = sizeof (*key);
zn->zn_key_orig = zn->zn_key_norm = key;
zn->zn_key_orig_numints = zn->zn_key_norm_numints = numints;
- zn->zn_matchtype = MT_EXACT;
+ zn->zn_matchtype = 0;
zn->zn_hash = zap_hash(zn);
return (zn);
@@ -299,7 +330,6 @@ mze_find(zap_name_t *zn)
mze_tofind.mze_hash = zn->zn_hash;
mze_tofind.mze_cd = 0;
-again:
mze = avl_find(avl, &mze_tofind, &idx);
if (mze == NULL)
mze = avl_nearest(avl, idx, AVL_AFTER);
@@ -308,10 +338,7 @@ again:
if (zap_match(zn, MZE_PHYS(zn->zn_zap, mze)->mze_name))
return (mze);
}
- if (zn->zn_matchtype == MT_BEST) {
- zn->zn_matchtype = MT_FIRST;
- goto again;
- }
+
return (NULL);
}
@@ -417,8 +444,7 @@ mzap_open(objset_t *os, uint64_t obj, dmu_buf_t *db)
zap_name_t *zn;
zap->zap_m.zap_num_entries++;
- zn = zap_name_alloc(zap, mze->mze_name,
- MT_EXACT);
+ zn = zap_name_alloc(zap, mze->mze_name, 0);
mze_insert(zap, i, zn->zn_hash);
zap_name_free(zn);
}
@@ -618,7 +644,7 @@ mzap_upgrade(zap_t **zapp, void *tag, dmu_tx_t *tx, zap_flags_t flags)
continue;
dprintf("adding %s=%llu\n",
mze->mze_name, mze->mze_value);
- zn = zap_name_alloc(zap, mze->mze_name, MT_EXACT);
+ zn = zap_name_alloc(zap, mze->mze_name, 0);
err = fzap_add_cd(zn, 8, 1, &mze->mze_value, mze->mze_cd,
tag, tx);
zap = zn->zn_zap; /* fzap_add_cd() may change zap */
@@ -631,6 +657,23 @@ mzap_upgrade(zap_t **zapp, void *tag, dmu_tx_t *tx, zap_flags_t flags)
return (err);
}
+/*
+ * The "normflags" determine the behavior of the matchtype_t which is
+ * passed to zap_lookup_norm(). Names which have the same normalized
+ * version will be stored with the same hash value, and therefore we can
+ * perform normalization-insensitive lookups. We can be Unicode form-
+ * insensitive and/or case-insensitive. The following flags are valid for
+ * "normflags":
+ *
+ * U8_TEXTPREP_NFC
+ * U8_TEXTPREP_NFD
+ * U8_TEXTPREP_NFKC
+ * U8_TEXTPREP_NFKD
+ * U8_TEXTPREP_TOUPPER
+ *
+ * The *_NF* (Normalization Form) flags are mutually exclusive; at most one
+ * of them may be supplied.
+ */
void
mzap_create_impl(objset_t *os, uint64_t obj, int normflags, zap_flags_t flags,
dmu_tx_t *tx)
@@ -789,7 +832,7 @@ again:
if (zn == NULL) {
zn = zap_name_alloc(zap, MZE_PHYS(zap, mze)->mze_name,
- MT_FIRST);
+ MT_NORMALIZE);
allocdzn = B_TRUE;
}
if (zap_match(zn, MZE_PHYS(zap, other)->mze_name)) {
@@ -818,7 +861,7 @@ zap_lookup(objset_t *os, uint64_t zapobj, const char *name,
uint64_t integer_size, uint64_t num_integers, void *buf)
{
return (zap_lookup_norm(os, zapobj, name, integer_size,
- num_integers, buf, MT_EXACT, NULL, 0, NULL));
+ num_integers, buf, 0, NULL, 0, NULL));
}
static int
@@ -886,7 +929,7 @@ zap_lookup_by_dnode(dnode_t *dn, const char *name,
uint64_t integer_size, uint64_t num_integers, void *buf)
{
return (zap_lookup_norm_by_dnode(dn, name, integer_size,
- num_integers, buf, MT_EXACT, NULL, 0, NULL));
+ num_integers, buf, 0, NULL, 0, NULL));
}
int
@@ -959,7 +1002,7 @@ int
zap_contains(objset_t *os, uint64_t zapobj, const char *name)
{
int err = zap_lookup_norm(os, zapobj, name, 0,
- 0, NULL, MT_EXACT, NULL, 0, NULL);
+ 0, NULL, 0, NULL, 0, NULL);
if (err == EOVERFLOW || err == EINVAL)
err = 0; /* found, but skipped reading the value */
return (err);
@@ -977,7 +1020,7 @@ zap_length(objset_t *os, uint64_t zapobj, const char *name,
err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap);
if (err)
return (err);
- zn = zap_name_alloc(zap, name, MT_EXACT);
+ zn = zap_name_alloc(zap, name, 0);
if (zn == NULL) {
zap_unlockdir(zap, FTAG);
return (SET_ERROR(ENOTSUP));
@@ -1080,7 +1123,7 @@ zap_add(objset_t *os, uint64_t zapobj, const char *key,
err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap);
if (err)
return (err);
- zn = zap_name_alloc(zap, key, MT_EXACT);
+ zn = zap_name_alloc(zap, key, 0);
if (zn == NULL) {
zap_unlockdir(zap, FTAG);
return (SET_ERROR(ENOTSUP));
@@ -1159,7 +1202,7 @@ zap_update(objset_t *os, uint64_t zapobj, const char *name,
err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap);
if (err)
return (err);
- zn = zap_name_alloc(zap, name, MT_EXACT);
+ zn = zap_name_alloc(zap, name, 0);
if (zn == NULL) {
zap_unlockdir(zap, FTAG);
return (SET_ERROR(ENOTSUP));
@@ -1222,7 +1265,7 @@ zap_update_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key,
int
zap_remove(objset_t *os, uint64_t zapobj, const char *name, dmu_tx_t *tx)
{
- return (zap_remove_norm(os, zapobj, name, MT_EXACT, tx));
+ return (zap_remove_norm(os, zapobj, name, 0, tx));
}
int
@@ -1474,7 +1517,7 @@ zap_count_write_by_dnode(dnode_t *dn, const char *name, int add,
return (err);
if (!zap->zap_ismicro) {
- zap_name_t *zn = zap_name_alloc(zap, name, MT_EXACT);
+ zap_name_t *zn = zap_name_alloc(zap, name, 0);
if (zn) {
err = fzap_count_write(zn, add, towrite,
tooverwrite);
diff --git a/usr/src/uts/common/fs/zfs/zfs_dir.c b/usr/src/uts/common/fs/zfs/zfs_dir.c
index 4f2b3a4a4d..32fa6f6380 100644
--- a/usr/src/uts/common/fs/zfs/zfs_dir.c
+++ b/usr/src/uts/common/fs/zfs/zfs_dir.c
@@ -18,10 +18,12 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, Joyent, Inc.
* Copyright (c) 2013, 2015 by Delphix. All rights reserved.
+ * Copyright 2017 Nexenta Systems, Inc.
*/
#include <sys/types.h>
@@ -63,13 +65,12 @@
* of names after deciding which is the appropriate lookup interface.
*/
static int
-zfs_match_find(zfsvfs_t *zfsvfs, znode_t *dzp, char *name, boolean_t exact,
+zfs_match_find(zfsvfs_t *zfsvfs, znode_t *dzp, char *name, matchtype_t mt,
boolean_t update, int *deflags, pathname_t *rpnp, uint64_t *zoid)
{
int error;
if (zfsvfs->z_norm) {
- matchtype_t mt = MT_FIRST;
boolean_t conflict = B_FALSE;
size_t bufsz = 0;
char *buf = NULL;
@@ -78,8 +79,7 @@ zfs_match_find(zfsvfs_t *zfsvfs, znode_t *dzp, char *name, boolean_t exact,
buf = rpnp->pn_buf;
bufsz = rpnp->pn_bufsize;
}
- if (exact)
- mt = MT_EXACT;
+
/*
* In the non-mixed case we only expect there would ever
* be one match, but we need to use the normalizing lookup.
@@ -141,7 +141,7 @@ zfs_dirent_lock(zfs_dirlock_t **dlpp, znode_t *dzp, char *name, znode_t **zpp,
zfsvfs_t *zfsvfs = dzp->z_zfsvfs;
zfs_dirlock_t *dl;
boolean_t update;
- boolean_t exact;
+ matchtype_t mt = 0;
uint64_t zoid;
vnode_t *vp = NULL;
int error = 0;
@@ -176,13 +176,29 @@ zfs_dirent_lock(zfs_dirlock_t **dlpp, znode_t *dzp, char *name, znode_t **zpp,
*/
/*
- * Decide if exact matches should be requested when performing
- * a zap lookup on file systems supporting case-insensitive
- * access.
+ * When matching we may need to normalize & change case according to
+ * FS settings.
+ *
+ * Note that a normalized match is necessary for a case insensitive
+ * filesystem when the lookup request is not exact because normalization
+ * can fold case independent of normalizing code point sequences.
+ *
+ * See the table above zfs_dropname().
*/
- exact =
- ((zfsvfs->z_case == ZFS_CASE_INSENSITIVE) && (flag & ZCIEXACT)) ||
- ((zfsvfs->z_case == ZFS_CASE_MIXED) && !(flag & ZCILOOK));
+ if (zfsvfs->z_norm != 0) {
+ mt = MT_NORMALIZE;
+
+ /*
+ * Determine if the match needs to honor the case specified in
+ * lookup, and if so keep track of that so that during
+ * normalization we don't fold case.
+ */
+ if ((zfsvfs->z_case == ZFS_CASE_INSENSITIVE &&
+ (flag & ZCIEXACT)) ||
+ (zfsvfs->z_case == ZFS_CASE_MIXED && !(flag & ZCILOOK))) {
+ mt |= MT_MATCH_CASE;
+ }
+ }
/*
* Only look in or update the DNLC if we are looking for the
@@ -195,7 +211,7 @@ zfs_dirent_lock(zfs_dirlock_t **dlpp, znode_t *dzp, char *name, znode_t **zpp,
* case for performance improvement?
*/
update = !zfsvfs->z_norm ||
- ((zfsvfs->z_case == ZFS_CASE_MIXED) &&
+ (zfsvfs->z_case == ZFS_CASE_MIXED &&
!(zfsvfs->z_norm & ~U8_TEXTPREP_TOUPPER) && !(flag & ZCILOOK));
/*
@@ -309,7 +325,7 @@ zfs_dirent_lock(zfs_dirlock_t **dlpp, znode_t *dzp, char *name, znode_t **zpp,
*zpp = VTOZ(vp);
return (0);
} else {
- error = zfs_match_find(zfsvfs, dzp, name, exact,
+ error = zfs_match_find(zfsvfs, dzp, name, mt,
update, direntflags, realpnp, &zoid);
}
}
@@ -775,6 +791,28 @@ zfs_link_create(zfs_dirlock_t *dl, znode_t *zp, dmu_tx_t *tx, int flag)
return (0);
}
+/*
+ * The match type in the code for this function should conform to:
+ *
+ * ------------------------------------------------------------------------
+ * fs type | z_norm | lookup type | match type
+ * ---------|-------------|-------------|----------------------------------
+ * CS !norm | 0 | 0 | 0 (exact)
+ * CS norm | formX | 0 | MT_NORMALIZE
+ * CI !norm | upper | !ZCIEXACT | MT_NORMALIZE
+ * CI !norm | upper | ZCIEXACT | MT_NORMALIZE | MT_MATCH_CASE
+ * CI norm | upper|formX | !ZCIEXACT | MT_NORMALIZE
+ * CI norm | upper|formX | ZCIEXACT | MT_NORMALIZE | MT_MATCH_CASE
+ * CM !norm | upper | !ZCILOOK | MT_NORMALIZE | MT_MATCH_CASE
+ * CM !norm | upper | ZCILOOK | MT_NORMALIZE
+ * CM norm | upper|formX | !ZCILOOK | MT_NORMALIZE | MT_MATCH_CASE
+ * CM norm | upper|formX | ZCILOOK | MT_NORMALIZE
+ *
+ * Abbreviations:
+ * CS = Case Sensitive, CI = Case Insensitive, CM = Case Mixed
+ * upper = case folding set by fs type on creation (U8_TEXTPREP_TOUPPER)
+ * formX = unicode normalization form set on fs creation
+ */
static int
zfs_dropname(zfs_dirlock_t *dl, znode_t *zp, znode_t *dzp, dmu_tx_t *tx,
int flag)
@@ -782,18 +820,20 @@ zfs_dropname(zfs_dirlock_t *dl, znode_t *zp, znode_t *dzp, dmu_tx_t *tx,
int error;
if (zp->z_zfsvfs->z_norm) {
- if (((zp->z_zfsvfs->z_case == ZFS_CASE_INSENSITIVE) &&
+ matchtype_t mt = MT_NORMALIZE;
+
+ if ((zp->z_zfsvfs->z_case == ZFS_CASE_INSENSITIVE &&
(flag & ZCIEXACT)) ||
- ((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);
- else
- error = zap_remove_norm(zp->z_zfsvfs->z_os,
- dzp->z_id, dl->dl_name, MT_FIRST, tx);
+ (zp->z_zfsvfs->z_case == ZFS_CASE_MIXED &&
+ !(flag & ZCILOOK))) {
+ mt |= MT_MATCH_CASE;
+ }
+
+ error = zap_remove_norm(zp->z_zfsvfs->z_os, dzp->z_id,
+ dl->dl_name, mt, tx);
} else {
- error = zap_remove(zp->z_zfsvfs->z_os,
- dzp->z_id, dl->dl_name, tx);
+ error = zap_remove(zp->z_zfsvfs->z_os, dzp->z_id, dl->dl_name,
+ tx);
}
return (error);
diff --git a/usr/src/uts/common/fs/zfs/zfs_vnops.c b/usr/src/uts/common/fs/zfs/zfs_vnops.c
index 138d3813b2..8b55998ea1 100644
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c
+++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c
@@ -18,12 +18,13 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 by Delphix. All rights reserved.
- * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2016 Joyent, Inc.
+ * Copyright 2017 Nexenta Systems, Inc.
*/
/* Portions Copyright 2007 Jeremy Teo */
@@ -1239,7 +1240,15 @@ zfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp,
zfsvfs_t *zfsvfs = zdp->z_zfsvfs;
int error = 0;
- /* fast path */
+ /*
+ * Fast path lookup, however we must skip DNLC lookup
+ * for case folding or normalizing lookups because the
+ * DNLC code only stores the passed in name. This means
+ * creating 'a' and removing 'A' on a case insensitive
+ * file system would work, but DNLC still thinks 'a'
+ * exists and won't let you create it again on the next
+ * pass through fast path.
+ */
if (!(flags & (LOOKUP_XATTR | FIGNORECASE))) {
if (dvp->v_type != VDIR) {
@@ -1256,7 +1265,9 @@ zfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp,
return (0);
}
return (error);
- } else {
+ } else if (!zdp->z_zfsvfs->z_norm &&
+ (zdp->z_zfsvfs->z_case == ZFS_CASE_SENSITIVE)) {
+
vnode_t *tvp = dnlc_lookup(dvp, nm);
if (tvp) {
diff --git a/usr/src/uts/common/io/vioif/vioif.c b/usr/src/uts/common/io/vioif/vioif.c
index ef677d791d..dd6e72e54a 100644
--- a/usr/src/uts/common/io/vioif/vioif.c
+++ b/usr/src/uts/common/io/vioif/vioif.c
@@ -732,24 +732,10 @@ static uint_t
vioif_add_rx(struct vioif_softc *sc, int kmflag)
{
uint_t num_added = 0;
+ struct vq_entry *ve;
- for (;;) {
- struct vq_entry *ve;
- struct vioif_rx_buf *buf;
-
- ve = vq_alloc_entry(sc->sc_rx_vq);
- if (!ve) {
- /*
- * Out of free descriptors - ring already full.
- * It would be better to update sc_norxdescavail
- * but MAC does not ask for this info, hence we
- * update sc_norecvbuf.
- */
- sc->sc_rxfail_no_descriptors++;
- sc->sc_norecvbuf++;
- break;
- }
- buf = sc->sc_rxbufs[ve->qe_index];
+ while ((ve = vq_alloc_entry(sc->sc_rx_vq)) != NULL) {
+ struct vioif_rx_buf *buf = sc->sc_rxbufs[ve->qe_index];
if (!buf) {
/* First run, allocate the buffer. */