6654808 FIGNORECASE lookups in a zfs xattr dir don't provide 'realname' data
6666748 System panic occurred when attempting to view .zfs snapshot directory from CIFS client.
6693201 libzpool needlessly defines u8_textprep_str()
6694236 case-insensitive zfs file system doesn't work when created on sparc and then imported on x86
--- a/usr/src/cmd/ztest/ztest.c Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/cmd/ztest/ztest.c Sun Apr 27 10:20:38 2008 -0700
@@ -1237,8 +1237,8 @@
/*
* Verify that we can create a new dataset.
*/
- error = dmu_objset_create(name, DMU_OST_OTHER, NULL, ztest_create_cb,
- NULL);
+ error = dmu_objset_create(name, DMU_OST_OTHER, NULL, 0,
+ ztest_create_cb, NULL);
if (error) {
if (error == ENOSPC) {
ztest_record_enospc("dmu_objset_create");
@@ -1293,7 +1293,7 @@
/*
* Verify that we cannot create an existing dataset.
*/
- error = dmu_objset_create(name, DMU_OST_OTHER, NULL, NULL, NULL);
+ error = dmu_objset_create(name, DMU_OST_OTHER, NULL, 0, NULL, NULL);
if (error != EEXIST)
fatal(0, "created existing dataset, error = %d", error);
@@ -3219,7 +3219,7 @@
int test_future = FALSE;
(void) rw_rdlock(&ztest_shared->zs_name_lock);
(void) snprintf(name, 100, "%s/%s_%d", pool, pool, d);
- error = dmu_objset_create(name, DMU_OST_OTHER, NULL,
+ error = dmu_objset_create(name, DMU_OST_OTHER, NULL, 0,
ztest_create_cb, NULL);
if (error == EEXIST) {
test_future = TRUE;
--- a/usr/src/lib/libzpool/common/kernel.c Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/lib/libzpool/common/kernel.c Sun Apr 27 10:20:38 2008 -0700
@@ -825,14 +825,6 @@
return (ret);
}
-/*ARGSUSED*/
-size_t u8_textprep_str(char *i, size_t *il, char *o, size_t *ol, int nf,
- size_t vers, int *err)
-{
- *err = EINVAL;
- return ((size_t)-1);
-}
-
uid_t
crgetuid(cred_t *cr)
{
--- a/usr/src/uts/common/fs/ctfs/ctfs_all.c Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/fs/ctfs/ctfs_all.c Sun Apr 27 10:20:38 2008 -0700
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -51,7 +51,7 @@
static int ctfs_adir_do_readdir(vnode_t *, void *, int *, offset_t *,
offset_t *, void *, int);
static int ctfs_adir_do_lookup(vnode_t *, const char *, vnode_t **, ino64_t *,
- cred_t *);
+ cred_t *, int, int *, pathname_t *);
/*
* ctfs_create_adirnode
@@ -98,7 +98,7 @@
/* ARGSUSED */
static int
ctfs_adir_do_lookup(vnode_t *vp, const char *nm, vnode_t **vpp, ino64_t *inop,
- cred_t *cr)
+ cred_t *cr, int flags, int *deflags, pathname_t *rpnp)
{
int i;
contract_t *ct;
@@ -127,9 +127,7 @@
ctid_t next;
struct dirent64 *odp = dp;
- /* ctfs does not support V_RDDIR_ENTFLAGS */
- if (flags & V_RDDIR_ENTFLAGS)
- return (ENOTSUP);
+ ASSERT(!(flags & V_RDDIR_ENTFLAGS));
zuniqid = VTOZONE(vp)->zone_uniqid;
next = contract_lookup(zuniqid, *offp);
--- a/usr/src/uts/common/fs/ctfs/ctfs_latest.c Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/fs/ctfs/ctfs_latest.c Sun Apr 27 10:20:38 2008 -0700
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -77,7 +77,8 @@
gfs_file_set_index(cvp, -1);
- VERIFY(gfs_dir_lookup(cvp, "status", &svp, cr) == 0);
+ VERIFY(gfs_dir_lookup(cvp, "status", &svp,
+ cr, 0, NULL, NULL) == 0);
VN_RELE(cvp);
--- a/usr/src/uts/common/fs/ctfs/ctfs_tdir.c Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/fs/ctfs/ctfs_tdir.c Sun Apr 27 10:20:38 2008 -0700
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -59,7 +59,7 @@
static int ctfs_tdir_do_readdir(vnode_t *, void *, int *, offset_t *,
offset_t *, void *, int);
static int ctfs_tdir_do_lookup(vnode_t *, const char *, vnode_t **, ino64_t *,
- cred_t *);
+ cred_t *, int, int *, pathname_t *);
static ino64_t ctfs_tdir_do_inode(vnode_t *, int);
/*
@@ -115,9 +115,7 @@
ct_type_t *ty = ct_types[gfs_file_index(vp)];
struct dirent64 *odp = dp;
- /* ctfs does not support V_RDDIR_ENTFLAGS */
- if (flags & V_RDDIR_ENTFLAGS)
- return (ENOTSUP);
+ ASSERT(!(flags & V_RDDIR_ENTFLAGS));
zuniqid = VTOZONE(vp)->zone_uniqid;
next = contract_type_lookup(ty, zuniqid, *offp);
@@ -138,7 +136,7 @@
/* ARGSUSED */
static int
ctfs_tdir_do_lookup(vnode_t *vp, const char *nm, vnode_t **vpp, ino64_t *inop,
- cred_t *cr)
+ cred_t *cr, int flags, int *deflags, pathname_t *rpnp)
{
int i;
contract_t *ct;
--- a/usr/src/uts/common/fs/gfs.c Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/fs/gfs.c Sun Apr 27 10:20:38 2008 -0700
@@ -35,6 +35,7 @@
#include <sys/mutex.h>
#include <sys/sysmacros.h>
#include <sys/systm.h>
+#include <sys/sunddi.h>
#include <sys/uio.h>
#include <sys/vmsystm.h>
#include <sys/vfs.h>
@@ -706,43 +707,102 @@
}
/*
- * gfs_dir_lookup()
+ * gfs_dir_lookup_dynamic()
*
- * Looks up the given name in the directory and returns the corresponding vnode,
- * if found.
+ * This routine looks up the provided name amongst the dynamic entries
+ * in the gfs directory and returns the corresponding vnode, if found.
*
- * First, we search statically defined entries, if any. If a match is found,
- * and GFS_CACHE_VNODE is set and the vnode exists, we simply return the
- * existing vnode. Otherwise, we call the static entry's callback routine,
- * caching the result if necessary.
+ * The gfs directory is expected to be locked by the caller prior to
+ * calling this function. The directory will be unlocked during the
+ * execution of this function, but will be locked upon return from the
+ * function. This function returns 0 on success, non-zero on error.
*
- * If no static entry is found, we invoke the lookup callback, if any. The
- * arguments to this callback are:
+ * The dynamic lookups are performed by invoking the lookup
+ * callback, which is passed to this function as the first argument.
+ * The arguments to the callback are:
*
- * int gfs_lookup_cb(vnode_t *pvp, const char *nm, vnode_t **vpp, cred_t *cr);
+ * int gfs_lookup_cb(vnode_t *pvp, const char *nm, vnode_t **vpp, cred_t *cr,
+ * int flags, int *deflgs, pathname_t *rpnp);
*
* pvp - parent vnode
* nm - name of entry
* vpp - pointer to resulting vnode
* cr - pointer to cred
+ * flags - flags value from lookup request
+ * ignored here; currently only used to request
+ * insensitive lookups
+ * direntflgs - output parameter, directory entry flags
+ * ignored here; currently only used to indicate a lookup
+ * has more than one possible match when case is not considered
+ * realpnp - output parameter, real pathname
+ * ignored here; when lookup was performed case-insensitively,
+ * this field contains the "real" name of the file.
*
* Returns 0 on success, non-zero on error.
*/
-int
-gfs_dir_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp, cred_t *cr)
+static int
+gfs_dir_lookup_dynamic(gfs_lookup_cb callback, gfs_dir_t *dp,
+ const char *nm, vnode_t *dvp, vnode_t **vpp, cred_t *cr, int flags,
+ int *direntflags, pathname_t *realpnp)
{
- int i;
+ gfs_file_t *fp;
+ ino64_t ino;
+ int ret;
+
+ ASSERT(GFS_DIR_LOCKED(dp));
+
+ /*
+ * Drop the directory lock, as the lookup routine
+ * will need to allocate memory, or otherwise deadlock on this
+ * directory.
+ */
+ gfs_dir_unlock(dp);
+ ret = callback(dvp, nm, vpp, &ino, cr, flags, direntflags, realpnp);
+ gfs_dir_lock(dp);
+
+ /*
+ * The callback for extended attributes returns a vnode
+ * with v_data from an underlying fs.
+ */
+ if (ret == 0 && !IS_XATTRDIR(dvp)) {
+ fp = (gfs_file_t *)((*vpp)->v_data);
+ fp->gfs_index = -1;
+ fp->gfs_ino = ino;
+ }
+
+ return (ret);
+}
+
+/*
+ * gfs_dir_lookup_static()
+ *
+ * This routine looks up the provided name amongst the static entries
+ * in the gfs directory and returns the corresponding vnode, if found.
+ * The first argument to the function is a pointer to the comparison
+ * function this function should use to decide if names are a match.
+ *
+ * If a match is found, and GFS_CACHE_VNODE is set and the vnode
+ * exists, we simply return the existing vnode. Otherwise, we call
+ * the static entry's callback routine, caching the result if
+ * necessary. If the idx pointer argument is non-NULL, we use it to
+ * return the index of the matching static entry.
+ *
+ * The gfs directory is expected to be locked by the caller prior to calling
+ * this function. The directory may be unlocked during the execution of
+ * this function, but will be locked upon return from the function.
+ *
+ * This function returns 0 if a match is found, ENOENT if not.
+ */
+static int
+gfs_dir_lookup_static(int (*compare)(const char *, const char *),
+ gfs_dir_t *dp, const char *nm, vnode_t *dvp, int *idx,
+ vnode_t **vpp, pathname_t *rpnp)
+{
gfs_dirent_t *ge;
- vnode_t *vp;
- gfs_dir_t *dp = dvp->v_data;
- int ret = 0;
+ vnode_t *vp = NULL;
+ int i;
- ASSERT(dvp->v_type == VDIR);
-
- if (gfs_lookup_dot(vpp, dvp, dp->gfsd_file.gfs_parent, nm) == 0)
- return (0);
-
- gfs_dir_lock(dp);
+ ASSERT(GFS_DIR_LOCKED(dp));
/*
* Search static entries.
@@ -750,12 +810,16 @@
for (i = 0; i < dp->gfsd_nstatic; i++) {
ge = &dp->gfsd_static[i];
- if (strcmp(ge->gfse_name, nm) == 0) {
+ if (compare(ge->gfse_name, nm) == 0) {
+ if (rpnp)
+ (void) strlcpy(rpnp->pn_buf, ge->gfse_name,
+ rpnp->pn_bufsize);
+
if (ge->gfse_vnode) {
ASSERT(ge->gfse_flags & GFS_CACHE_VNODE);
vp = ge->gfse_vnode;
VN_HOLD(vp);
- goto out;
+ break;
}
/*
@@ -763,8 +827,8 @@
* need to do KM_SLEEP allocations. If we return from
* the constructor only to find that a parallel
* operation has completed, and GFS_CACHE_VNODE is set
- * for this entry, we discard the result in favor of the
- * cached vnode.
+ * for this entry, we discard the result in favor of
+ * the cached vnode.
*/
gfs_dir_unlock(dp);
vp = ge->gfse_ctor(dvp);
@@ -797,57 +861,94 @@
gfs_dir_lock(dp);
}
}
-
- goto out;
+ break;
}
}
- /*
- * See if there is a dynamic constructor.
- */
- if (dp->gfsd_lookup) {
- ino64_t ino;
- gfs_file_t *fp;
+ if (vp == NULL)
+ return (ENOENT);
+ else if (idx)
+ *idx = i;
+ *vpp = vp;
+ return (0);
+}
- /*
- * Once again, drop the directory lock, as the lookup routine
- * will need to allocate memory, or otherwise deadlock on this
- * directory.
- */
- gfs_dir_unlock(dp);
- ret = dp->gfsd_lookup(dvp, nm, &vp, &ino, cr);
- gfs_dir_lock(dp);
- if (ret != 0)
- goto out;
+/*
+ * gfs_dir_lookup()
+ *
+ * Looks up the given name in the directory and returns the corresponding
+ * vnode, if found.
+ *
+ * First, we search statically defined entries, if any, with a call to
+ * gfs_dir_lookup_static(). If no static entry is found, and we have
+ * a callback function we try a dynamic lookup via gfs_dir_lookup_dynamic().
+ *
+ * This function returns 0 on success, non-zero on error.
+ */
+int
+gfs_dir_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp, cred_t *cr,
+ int flags, int *direntflags, pathname_t *realpnp)
+{
+ gfs_dir_t *dp = dvp->v_data;
+ boolean_t casecheck;
+ vnode_t *dynvp = NULL;
+ vnode_t *vp = NULL;
+ int (*compare)(const char *, const char *);
+ int error, idx;
+
+ ASSERT(dvp->v_type == VDIR);
+
+ if (gfs_lookup_dot(vpp, dvp, dp->gfsd_file.gfs_parent, nm) == 0)
+ return (0);
- /*
- * The lookup_cb might be returning a non-GFS vnode.
- * Currently this is true for extended attributes,
- * where we're returning a vnode with v_data from an
- * underlying fs.
- */
- if ((dvp->v_flag & V_XATTRDIR) == 0) {
- fp = (gfs_file_t *)vp->v_data;
- fp->gfs_index = -1;
- fp->gfs_ino = ino;
+ casecheck = (flags & FIGNORECASE) != 0 && direntflags != NULL;
+ if (vfs_has_feature(dvp->v_vfsp, VFSFT_NOCASESENSITIVE) ||
+ (flags & FIGNORECASE))
+ compare = strcasecmp;
+ else
+ compare = strcmp;
+
+ gfs_dir_lock(dp);
+
+ error = gfs_dir_lookup_static(compare, dp, nm, dvp, &idx, &vp, realpnp);
+
+ if (vp && casecheck) {
+ gfs_dirent_t *ge;
+ int i;
+
+ for (i = idx + 1; i < dp->gfsd_nstatic; i++) {
+ ge = &dp->gfsd_static[i];
+
+ if (strcasecmp(ge->gfse_name, nm) == 0) {
+ *direntflags |= ED_CASE_CONFLICT;
+ goto out;
+ }
}
- } else {
- /*
- * No static entry found, and there is no lookup callback, so
- * return ENOENT.
- */
- ret = ENOENT;
+ }
+
+ if ((error || casecheck) && dp->gfsd_lookup)
+ error = gfs_dir_lookup_dynamic(dp->gfsd_lookup, dp, nm, dvp,
+ &dynvp, cr, flags, direntflags, vp ? NULL : realpnp);
+
+ if (vp && dynvp) {
+ /* static and dynamic entries are case-insensitive conflict */
+ ASSERT(casecheck);
+ *direntflags |= ED_CASE_CONFLICT;
+ VN_RELE(dynvp);
+ } else if (vp == NULL) {
+ vp = dynvp;
+ } else if (error == ENOENT) {
+ error = 0;
+ } else if (error) {
+ VN_RELE(vp);
+ vp = NULL;
}
out:
gfs_dir_unlock(dp);
- if (ret == 0)
- *vpp = vp;
- else
- *vpp = NULL;
-
- return (ret);
+ *vpp = vp;
+ return (error);
}
/*
@@ -964,7 +1065,7 @@
int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
int *direntflags, pathname_t *realpnp)
{
- return (gfs_dir_lookup(dvp, nm, vpp, cr));
+ return (gfs_dir_lookup(dvp, nm, vpp, cr, flags, direntflags, realpnp));
}
/*
--- a/usr/src/uts/common/fs/lookup.c Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/fs/lookup.c Sun Apr 27 10:20:38 2008 -0700
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -525,7 +525,7 @@
* Return the case-preserved name
* within the resolved path.
*/
- error = copystr(pp->pn_path,
+ error = copystr(pp->pn_buf,
rpnp->pn_path + rpnp->pn_pathlen,
rpnp->pn_bufsize - rpnp->pn_pathlen, &len);
} else {
--- a/usr/src/uts/common/fs/objfs/objfs_root.c Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/fs/objfs/objfs_root.c Sun Apr 27 10:20:38 2008 -0700
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -39,7 +39,7 @@
extern int last_module_id;
static int objfs_root_do_lookup(vnode_t *, const char *, vnode_t **, ino64_t *,
- cred_t *);
+ cred_t *, int, int *, pathname_t *);
static int objfs_root_do_readdir(vnode_t *, void *, int *,
offset_t *, offset_t *, void *, int);
@@ -72,7 +72,7 @@
/* ARGSUSED */
static int
objfs_root_do_lookup(vnode_t *vp, const char *nm, vnode_t **vpp, ino64_t *inop,
- cred_t *cr)
+ cred_t *cr, int flags, int *deflags, pathname_t *rpnp)
{
int result = ENOENT;
struct modctl *mp;
@@ -112,9 +112,7 @@
struct modctl *mp = *mpp;
struct dirent64 *odp = dp;
- /* objfs does not support V_RDDIR_ENTFLAGS */
- if (flags & V_RDDIR_ENTFLAGS)
- return (ENOTSUP);
+ ASSERT(!(flags & V_RDDIR_ENTFLAGS));
mutex_enter(&mod_lock);
--- a/usr/src/uts/common/fs/xattr.c Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/fs/xattr.c Sun Apr 27 10:20:38 2008 -0700
@@ -978,7 +978,7 @@
* Don't allow creation of extended attributes with sysattr names.
*/
if (is_sattr_name(name)) {
- return (gfs_dir_lookup(dvp, name, vpp, cr));
+ return (gfs_dir_lookup(dvp, name, vpp, cr, 0, NULL, NULL));
}
error = xattr_dir_realdir(dvp, &pvp, LOOKUP_XATTR|CREATE_XATTR_DIR,
@@ -1096,14 +1096,13 @@
int error;
vnode_t *vp;
struct pathname pn;
- int flags = FIGNORECASE;
*eflags = 0;
error = pn_get(nm, UIO_SYSSPACE, &pn);
if (error == 0) {
- error = VOP_LOOKUP(dvp, nm, &vp, &pn, LOOKUP_XATTR, rootvp,
- cr, ct, &flags, NULL);
+ error = VOP_LOOKUP(dvp, nm, &vp, &pn,
+ FIGNORECASE, rootvp, cr, ct, NULL, NULL);
if (error == 0) {
*eflags = ED_CASE_CONFLICT;
VN_RELE(vp);
@@ -1170,13 +1169,14 @@
while ((error = gfs_readdir_pred(&gstate, uiop, &off)) == 0 &&
!*eofp) {
if (off >= 0 && off < dp->gfsd_nstatic) {
- int eflags = 0;
+ int eflags;
/*
* Check to see if this sysattr set name has a
* case-insensitive conflict with a real xattr
* name.
*/
+ eflags = 0;
if ((flags & V_RDDIR_ENTFLAGS) && has_xattrs) {
error = readdir_xattr_casecmp(pvp,
dp->gfsd_static[off].gfse_name,
@@ -1286,7 +1286,7 @@
static int
xattr_lookup_cb(vnode_t *vp, const char *nm, vnode_t **vpp, ino64_t *inop,
- cred_t *cr)
+ cred_t *cr, int flags, int *deflags, pathname_t *rpnp)
{
vnode_t *pvp;
struct pathname pn;
@@ -1310,8 +1310,8 @@
error = pn_get((char *)nm, UIO_SYSSPACE, &pn);
if (error == 0) {
- error = VOP_LOOKUP(pvp, (char *)nm, vpp, &pn, 0, rootvp,
- cr, NULL, NULL, NULL);
+ error = VOP_LOOKUP(pvp, (char *)nm, vpp, &pn, flags, rootvp,
+ cr, NULL, deflags, rpnp);
pn_free(&pn);
}
VN_RELE(pvp);
--- a/usr/src/uts/common/fs/zfs/dmu_objset.c Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/fs/zfs/dmu_objset.c Sun Apr 27 10:20:38 2008 -0700
@@ -481,6 +481,7 @@
dsl_dataset_t *clone_parent;
const char *lastname;
dmu_objset_type_t type;
+ uint64_t flags;
};
/*ARGSUSED*/
@@ -527,7 +528,7 @@
ASSERT(dmu_tx_is_syncing(tx));
dsobj = dsl_dataset_create_sync(dd, oa->lastname,
- oa->clone_parent, cr, tx);
+ oa->clone_parent, oa->flags, cr, tx);
VERIFY(0 == dsl_dataset_open_obj(dd->dd_pool, dsobj, NULL,
DS_MODE_STANDARD | DS_MODE_READONLY, FTAG, &ds));
@@ -551,7 +552,7 @@
int
dmu_objset_create(const char *name, dmu_objset_type_t type,
- objset_t *clone_parent,
+ objset_t *clone_parent, uint64_t flags,
void (*func)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx), void *arg)
{
dsl_dir_t *pdd;
@@ -574,6 +575,7 @@
oa.userarg = arg;
oa.lastname = tail;
oa.type = type;
+ oa.flags = flags;
if (clone_parent != NULL) {
/*
@@ -946,6 +948,21 @@
}
int
+dmu_snapshot_realname(objset_t *os, char *name, char *real, int maxlen,
+ boolean_t *conflict)
+{
+ dsl_dataset_t *ds = os->os->os_dsl_dataset;
+ uint64_t ignored;
+
+ if (ds->ds_phys->ds_snapnames_zapobj == 0)
+ return (ENOENT);
+
+ return (zap_lookup_norm(ds->ds_dir->dd_pool->dp_meta_objset,
+ ds->ds_phys->ds_snapnames_zapobj, name, 8, 1, &ignored, MT_FIRST,
+ real, maxlen, conflict));
+}
+
+int
dmu_snapshot_list_next(objset_t *os, int namelen, char *name,
uint64_t *idp, uint64_t *offp, boolean_t *case_conflict)
{
--- a/usr/src/uts/common/fs/zfs/dmu_send.c Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/fs/zfs/dmu_send.c Sun Apr 27 10:20:38 2008 -0700
@@ -269,6 +269,9 @@
if (fromorigin)
drr->drr_u.drr_begin.drr_flags |= DRR_FLAG_CLONE;
drr->drr_u.drr_begin.drr_toguid = ds->ds_phys->ds_guid;
+ if (ds->ds_phys->ds_flags & DS_FLAG_CI_DATASET)
+ drr->drr_u.drr_begin.drr_flags |= DRR_FLAG_CI_DATA;
+
if (fromds)
drr->drr_u.drr_begin.drr_fromguid = fromds->ds_phys->ds_guid;
dsl_dataset_name(ds, drr->drr_u.drr_begin.drr_toname);
@@ -322,6 +325,7 @@
dmu_objset_type_t type;
void *tag;
boolean_t force;
+ uint64_t dsflags;
char clonelastname[MAXNAMELEN];
dsl_dataset_t *ds; /* the ds to recv into; returned from the syncfunc */
};
@@ -340,9 +344,6 @@
ds, &ds->ds_phys->ds_bp, type, tx);
}
- dmu_buf_will_dirty(ds->ds_dbuf, tx);
- ds->ds_phys->ds_flags |= DS_FLAG_INCONSISTENT;
-
spa_history_internal_log(LOG_DS_REPLAY_FULL_SYNC,
ds->ds_dir->dd_pool->dp_spa, tx, cr, "dataset = %lld",
ds->ds_phys->ds_dir_obj);
@@ -385,9 +386,12 @@
dsl_dir_t *dd = arg1;
struct recvbeginsyncarg *rbsa = arg2;
uint64_t dsobj;
+ uint64_t flags = DS_FLAG_INCONSISTENT;
+
+ flags |= rbsa->dsflags;
dsobj = dsl_dataset_create_sync(dd, strrchr(rbsa->tofs, '/') + 1,
- rbsa->origin, cr, tx);
+ rbsa->origin, flags, cr, tx);
rbsa->ds = recv_full_sync_impl(dd->dd_pool, dsobj,
rbsa->origin ? DMU_OST_NONE : rbsa->type, cr, tx);
@@ -432,6 +436,9 @@
struct recvbeginsyncarg *rbsa = arg2;
dsl_dir_t *dd = ds->ds_dir;
uint64_t dsobj;
+ uint64_t flags = DS_FLAG_INCONSISTENT;
+
+ flags |= rbsa->dsflags;
/*
* NB: caller must provide an extra hold on the dsl_dir_t, so it
@@ -440,7 +447,7 @@
*/
dsl_dataset_destroy_sync(ds, rbsa->tag, cr, tx);
- dsobj = dsl_dataset_create_sync_impl(dd, rbsa->origin, tx);
+ dsobj = dsl_dataset_create_sync_impl(dd, rbsa->origin, flags, tx);
rbsa->ds = recv_full_sync_impl(dd->dd_pool, dsobj,
rbsa->origin ? DMU_OST_NONE : rbsa->type, cr, tx);
@@ -495,12 +502,15 @@
dsl_pool_t *dp = ohds->ds_dir->dd_pool;
dsl_dataset_t *ods, *cds;
uint64_t dsobj;
+ uint64_t flags = DS_FLAG_INCONSISTENT;
+
+ flags |= rbsa->dsflags;
/* create the temporary clone */
VERIFY(0 == dsl_dataset_open_obj(dp, ohds->ds_phys->ds_prev_snap_obj,
NULL, DS_MODE_STANDARD, FTAG, &ods));
dsobj = dsl_dataset_create_sync(ohds->ds_dir,
- rbsa->clonelastname, ods, cr, tx);
+ rbsa->clonelastname, ods, flags, cr, tx);
dsl_dataset_close(ods, DS_MODE_STANDARD, FTAG);
/* open the temporary clone */
@@ -511,9 +521,6 @@
if (ohds->ds_quota > 0)
dsl_dataset_set_quota_sync(cds, &ohds->ds_quota, cr, tx);
- dmu_buf_will_dirty(cds->ds_dbuf, tx);
- cds->ds_phys->ds_flags |= DS_FLAG_INCONSISTENT;
-
rbsa->ds = cds;
spa_history_internal_log(LOG_DS_REPLAY_INC_SYNC,
@@ -563,6 +570,7 @@
rbsa.fromguid = drrb->drr_fromguid;
rbsa.type = drrb->drr_type;
rbsa.tag = FTAG;
+ rbsa.dsflags = 0;
version = drrb->drr_version;
flags = drrb->drr_flags;
@@ -578,6 +586,9 @@
((flags & DRR_FLAG_CLONE) && origin == NULL))
return (EINVAL);
+ if (flags & DRR_FLAG_CI_DATA)
+ rbsa.dsflags = DS_FLAG_CI_DATASET;
+
bzero(drc, sizeof (dmu_recv_cookie_t));
drc->drc_drrb = drrb;
drc->drc_tosnap = tosnap;
--- a/usr/src/uts/common/fs/zfs/dsl_dataset.c Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/fs/zfs/dsl_dataset.c Sun Apr 27 10:20:38 2008 -0700
@@ -290,6 +290,43 @@
return (err);
}
+static int
+dsl_dataset_snap_lookup(objset_t *os, uint64_t flags,
+ uint64_t snapnames_zapobj, const char *name, uint64_t *value)
+{
+ matchtype_t mt;
+ int err;
+
+ if (flags & DS_FLAG_CI_DATASET)
+ mt = MT_FIRST;
+ else
+ mt = MT_EXACT;
+
+ err = zap_lookup_norm(os, snapnames_zapobj, name, 8, 1,
+ value, mt, NULL, 0, NULL);
+ if (err == ENOTSUP && mt == MT_FIRST)
+ err = zap_lookup(os, snapnames_zapobj, name, 8, 1, value);
+ return (err);
+}
+
+static int
+dsl_dataset_snap_remove(objset_t *os, uint64_t flags,
+ uint64_t snapnames_zapobj, char *name, dmu_tx_t *tx)
+{
+ matchtype_t mt;
+ int err;
+
+ if (flags & DS_FLAG_CI_DATASET)
+ mt = MT_FIRST;
+ else
+ mt = MT_EXACT;
+
+ err = zap_remove_norm(os, snapnames_zapobj, name, mt, tx);
+ if (err == ENOTSUP && mt == MT_FIRST)
+ err = zap_remove(os, snapnames_zapobj, name, tx);
+ return (err);
+}
+
int
dsl_dataset_open_obj(dsl_pool_t *dp, uint64_t dsobj, const char *snapname,
int mode, void *tag, dsl_dataset_t **dsp)
@@ -355,12 +392,14 @@
ds->ds_dir->dd_phys->dd_head_dataset_obj,
FTAG, &headdbuf);
if (err == 0) {
+ uint64_t foundobj;
+
headphys = headdbuf->db_data;
- uint64_t foundobj;
- err = zap_lookup(dp->dp_meta_objset,
+ err = dsl_dataset_snap_lookup(
+ dp->dp_meta_objset,
+ headphys->ds_flags,
headphys->ds_snapnames_zapobj,
- snapname, sizeof (foundobj), 1,
- &foundobj);
+ snapname, &foundobj);
ASSERT3U(foundobj, ==, dsobj);
dmu_buf_rele(headdbuf, FTAG);
}
@@ -469,11 +508,13 @@
if (tail != NULL) {
objset_t *mos = dp->dp_meta_objset;
+ uint64_t flags;
err = dsl_dataset_open_obj(dp, obj, NULL,
DS_MODE_NONE, tag, &ds);
if (err)
goto out;
+ flags = ds->ds_phys->ds_flags;
obj = ds->ds_phys->ds_snapnames_zapobj;
dsl_dataset_close(ds, DS_MODE_NONE, tag);
ds = NULL;
@@ -490,7 +531,7 @@
goto out;
}
dprintf("looking for snapshot '%s'\n", tail);
- err = zap_lookup(mos, obj, tail, 8, 1, &obj);
+ err = dsl_dataset_snap_lookup(mos, flags, obj, tail, &obj);
if (err)
goto out;
}
@@ -632,7 +673,8 @@
(void) random_get_pseudo_bytes((void*)&dsphys->ds_guid,
sizeof (dsphys->ds_guid));
dsphys->ds_snapnames_zapobj =
- zap_create(mos, DMU_OT_DSL_DS_SNAP_MAP, DMU_OT_NONE, 0, tx);
+ zap_create_norm(mos, U8_TEXTPREP_TOUPPER, DMU_OT_DSL_DS_SNAP_MAP,
+ DMU_OT_NONE, 0, tx);
dsphys->ds_creation_time = gethrestime_sec();
dsphys->ds_creation_txg = tx->tx_txg;
dsphys->ds_deadlist_obj =
@@ -653,7 +695,8 @@
}
uint64_t
-dsl_dataset_create_sync_impl(dsl_dir_t *dd, dsl_dataset_t *origin, dmu_tx_t *tx)
+dsl_dataset_create_sync_impl(dsl_dir_t *dd, dsl_dataset_t *origin,
+ uint64_t flags, dmu_tx_t *tx)
{
dsl_pool_t *dp = dd->dd_pool;
dmu_buf_t *dbuf;
@@ -672,17 +715,17 @@
dmu_buf_will_dirty(dbuf, tx);
dsphys = dbuf->db_data;
dsphys->ds_dir_obj = dd->dd_object;
+ dsphys->ds_flags = flags;
dsphys->ds_fsid_guid = unique_create();
(void) random_get_pseudo_bytes((void*)&dsphys->ds_guid,
sizeof (dsphys->ds_guid));
dsphys->ds_snapnames_zapobj =
- zap_create(mos, DMU_OT_DSL_DS_SNAP_MAP, DMU_OT_NONE, 0, tx);
+ zap_create_norm(mos, U8_TEXTPREP_TOUPPER, DMU_OT_DSL_DS_SNAP_MAP,
+ DMU_OT_NONE, 0, tx);
dsphys->ds_creation_time = gethrestime_sec();
dsphys->ds_creation_txg = tx->tx_txg;
dsphys->ds_deadlist_obj =
bplist_create(mos, DSL_DEADLIST_BLOCKSIZE, tx);
- if (spa_version(dp->dp_spa) >= SPA_VERSION_UNIQUE_ACCURATE)
- dsphys->ds_flags |= DS_FLAG_UNIQUE_ACCURATE;
if (origin) {
dsphys->ds_prev_snap_obj = origin->ds_object;
@@ -695,6 +738,7 @@
dsphys->ds_uncompressed_bytes =
origin->ds_phys->ds_uncompressed_bytes;
dsphys->ds_bp = origin->ds_phys->ds_bp;
+ dsphys->ds_flags = origin->ds_phys->ds_flags;
dmu_buf_will_dirty(origin->ds_dbuf, tx);
origin->ds_phys->ds_num_children++;
@@ -702,6 +746,10 @@
dmu_buf_will_dirty(dd->dd_dbuf, tx);
dd->dd_phys->dd_origin_obj = origin->ds_object;
}
+
+ if (spa_version(dp->dp_spa) >= SPA_VERSION_UNIQUE_ACCURATE)
+ dsphys->ds_flags |= DS_FLAG_UNIQUE_ACCURATE;
+
dmu_buf_rele(dbuf, FTAG);
dmu_buf_will_dirty(dd->dd_dbuf, tx);
@@ -711,8 +759,8 @@
}
uint64_t
-dsl_dataset_create_sync(dsl_dir_t *pdd,
- const char *lastname, dsl_dataset_t *origin, cred_t *cr, dmu_tx_t *tx)
+dsl_dataset_create_sync(dsl_dir_t *pdd, const char *lastname,
+ dsl_dataset_t *origin, uint64_t flags, cred_t *cr, dmu_tx_t *tx)
{
dsl_pool_t *dp = pdd->dd_pool;
uint64_t dsobj, ddobj;
@@ -723,7 +771,7 @@
ddobj = dsl_dir_create_sync(pdd, lastname, tx);
VERIFY(0 == dsl_dir_open_obj(dp, ddobj, lastname, FTAG, &dd));
- dsobj = dsl_dataset_create_sync_impl(dd, origin, tx);
+ dsobj = dsl_dataset_create_sync_impl(dd, origin, flags, tx);
dsl_deleg_set_create_perms(dd, tx, cr);
@@ -1518,14 +1566,18 @@
#ifdef ZFS_DEBUG
{
uint64_t val;
- err = zap_lookup(mos,
+
+ err = dsl_dataset_snap_lookup(mos,
+ ds_head->ds_phys->ds_flags,
ds_head->ds_phys->ds_snapnames_zapobj,
- ds->ds_snapname, 8, 1, &val);
+ ds->ds_snapname, &val);
ASSERT3U(err, ==, 0);
ASSERT3U(val, ==, obj);
}
#endif
- err = zap_remove(mos, ds_head->ds_phys->ds_snapnames_zapobj,
+ err = dsl_dataset_snap_remove(mos,
+ ds_head->ds_phys->ds_flags,
+ ds_head->ds_phys->ds_snapnames_zapobj,
ds->ds_snapname, tx);
ASSERT(err == 0);
dsl_dataset_close(ds_head, DS_MODE_NONE, FTAG);
@@ -1590,8 +1642,8 @@
/*
* Check for conflicting name snapshot name.
*/
- err = zap_lookup(mos, ds->ds_phys->ds_snapnames_zapobj,
- snapname, 8, 1, &value);
+ err = dsl_dataset_snap_lookup(mos, ds->ds_phys->ds_flags,
+ ds->ds_phys->ds_snapnames_zapobj, snapname, &value);
if (err == 0)
return (EEXIST);
if (err != ENOENT)
@@ -1840,8 +1892,8 @@
return (err);
/* new name better not be in use */
- err = zap_lookup(mos, hds->ds_phys->ds_snapnames_zapobj,
- newsnapname, 8, 1, &val);
+ err = dsl_dataset_snap_lookup(mos, hds->ds_phys->ds_flags,
+ hds->ds_phys->ds_snapnames_zapobj, newsnapname, &val);
dsl_dataset_close(hds, DS_MODE_NONE, FTAG);
if (err == 0)
@@ -1873,8 +1925,8 @@
dd->dd_phys->dd_head_dataset_obj, NULL, DS_MODE_NONE, FTAG, &hds));
VERIFY(0 == dsl_dataset_get_snapname(ds));
- err = zap_remove(mos, hds->ds_phys->ds_snapnames_zapobj,
- ds->ds_snapname, tx);
+ err = dsl_dataset_snap_remove(mos, hds->ds_phys->ds_flags,
+ hds->ds_phys->ds_snapnames_zapobj, ds->ds_snapname, tx);
ASSERT3U(err, ==, 0);
mutex_enter(&ds->ds_lock);
(void) strcpy(ds->ds_snapname, newsnapname);
@@ -2069,7 +2121,7 @@
struct promotearg {
uint64_t used, comp, uncomp, unique;
- uint64_t newnext_obj, snapnames_obj;
+ uint64_t ds_flags, newnext_obj, snapnames_obj;
};
/* ARGSUSED */
@@ -2110,6 +2162,7 @@
odd->dd_phys->dd_head_dataset_obj,
NULL, DS_MODE_NONE, FTAG, &phds))
goto out;
+ pa->ds_flags = phds->ds_phys->ds_flags;
pa->snapnames_obj = phds->ds_phys->ds_snapnames_zapobj;
dsl_dataset_close(phds, DS_MODE_NONE, FTAG);
}
@@ -2153,9 +2206,9 @@
/* Check that the snapshot name does not conflict */
dsl_dataset_name(ds, name);
- err = zap_lookup(dd->dd_pool->dp_meta_objset,
- hds->ds_phys->ds_snapnames_zapobj, ds->ds_snapname,
- 8, 1, &val);
+ err = dsl_dataset_snap_lookup(dd->dd_pool->dp_meta_objset,
+ hds->ds_phys->ds_flags, hds->ds_phys->ds_snapnames_zapobj,
+ ds->ds_snapname, &val);
if (err != ENOENT) {
if (err == 0)
err = EEXIST;
@@ -2245,8 +2298,8 @@
/* move snap name entry */
dsl_dataset_name(ds, name);
- VERIFY(0 == zap_remove(dp->dp_meta_objset,
- pa->snapnames_obj, ds->ds_snapname, tx));
+ VERIFY(0 == dsl_dataset_snap_remove(dp->dp_meta_objset,
+ pa->ds_flags, pa->snapnames_obj, ds->ds_snapname, tx));
VERIFY(0 == zap_add(dp->dp_meta_objset,
hds->ds_phys->ds_snapnames_zapobj, ds->ds_snapname,
8, 1, &ds->ds_object, tx));
--- a/usr/src/uts/common/fs/zfs/sys/dmu.h Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/fs/zfs/sys/dmu.h Sun Apr 27 10:20:38 2008 -0700
@@ -166,7 +166,7 @@
void dmu_objset_close(objset_t *os);
int dmu_objset_evict_dbufs(objset_t *os);
int dmu_objset_create(const char *name, dmu_objset_type_t type,
- objset_t *clone_parent,
+ objset_t *clone_parent, uint64_t flags,
void (*func)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx), void *arg);
int dmu_objset_destroy(const char *name);
int dmu_snapshots_destroy(char *fsname, char *snapname);
@@ -540,6 +540,8 @@
extern uint64_t dmu_objset_id(objset_t *os);
extern int dmu_snapshot_list_next(objset_t *os, int namelen, char *name,
uint64_t *id, uint64_t *offp, boolean_t *case_conflict);
+extern int dmu_snapshot_realname(objset_t *os, char *name, char *real,
+ int maxlen, boolean_t *conflict);
extern int dmu_dir_list_next(objset_t *os, int namelen, char *name,
uint64_t *idp, uint64_t *offp);
extern void dmu_objset_set_user(objset_t *os, void *user_ptr);
--- a/usr/src/uts/common/fs/zfs/sys/dmu_objset.h Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/fs/zfs/sys/dmu_objset.h Sun Apr 27 10:20:38 2008 -0700
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -99,7 +99,7 @@
objset_t **osp);
void dmu_objset_close(objset_t *os);
int dmu_objset_create(const char *name, dmu_objset_type_t type,
- objset_t *clone_parent,
+ objset_t *clone_parent, uint64_t flags,
void (*func)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx), void *arg);
int dmu_objset_destroy(const char *name);
int dmu_objset_rollback(objset_t *os);
--- a/usr/src/uts/common/fs/zfs/sys/dsl_dataset.h Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/fs/zfs/sys/dsl_dataset.h Sun Apr 27 10:20:38 2008 -0700
@@ -62,6 +62,12 @@
*/
#define DS_FLAG_UNIQUE_ACCURATE (1ULL<<2)
+/*
+ * DS_FLAG_CI_DATASET is set if the dataset contains a file system whose
+ * name lookups should be performed case-insensitively.
+ */
+#define DS_FLAG_CI_DATASET (1ULL<<16)
+
typedef struct dsl_dataset_phys {
uint64_t ds_dir_obj;
uint64_t ds_prev_snap_obj;
@@ -145,9 +151,10 @@
void dsl_dataset_downgrade(dsl_dataset_t *ds, int oldmode, int newmode);
boolean_t dsl_dataset_tryupgrade(dsl_dataset_t *ds, int oldmode, int newmode);
uint64_t dsl_dataset_create_sync_impl(dsl_dir_t *dd, dsl_dataset_t *origin,
- dmu_tx_t *tx);
+ uint64_t flags, dmu_tx_t *tx);
uint64_t dsl_dataset_create_sync(dsl_dir_t *pds,
- const char *lastname, dsl_dataset_t *origin, cred_t *, dmu_tx_t *);
+ const char *lastname, dsl_dataset_t *origin, uint64_t flags,
+ cred_t *, dmu_tx_t *);
int dsl_dataset_destroy(dsl_dataset_t *ds, void *tag);
int dsl_snapshots_destroy(char *fsname, char *snapname);
dsl_checkfunc_t dsl_dataset_destroy_check;
@@ -199,6 +206,7 @@
void dsl_dataset_set_quota_sync(void *arg1, void *arg2, cred_t *cr,
dmu_tx_t *tx);
int dsl_dataset_set_reservation(const char *dsname, uint64_t reservation);
+void dsl_dataset_set_flags(dsl_dataset_t *ds, uint64_t flags);
#ifdef ZFS_DEBUG
#define dprintf_ds(ds, fmt, ...) do { \
--- a/usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h Sun Apr 27 10:20:38 2008 -0700
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -51,7 +51,8 @@
#define DMU_BACKUP_HEADER_VERSION (2ULL)
#define DMU_BACKUP_MAGIC 0x2F5bacbacULL
-#define DRR_FLAG_CLONE (1<<0)
+#define DRR_FLAG_CLONE (1<<0)
+#define DRR_FLAG_CI_DATA (1<<1)
/*
* zfs ioctl command structure
--- a/usr/src/uts/common/fs/zfs/zap_micro.c Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/fs/zfs/zap_micro.c Sun Apr 27 10:20:38 2008 -0700
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -139,6 +139,7 @@
int i, max;
buf->mz_block_type = BSWAP_64(buf->mz_block_type);
buf->mz_salt = BSWAP_64(buf->mz_salt);
+ buf->mz_normflags = BSWAP_64(buf->mz_normflags);
max = (size / MZAP_ENT_LEN) - 1;
for (i = 0; i < max; i++) {
buf->mz_chunk[i].mze_value =
--- a/usr/src/uts/common/fs/zfs/zfs_ctldir.c Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_ctldir.c Sun Apr 27 10:20:38 2008 -0700
@@ -76,6 +76,7 @@
#include <sys/dmu.h>
#include <sys/dsl_deleg.h>
#include <sys/mount.h>
+#include <sys/sunddi.h>
typedef struct zfsctl_node {
gfs_dir_t zc_gfs_private;
@@ -399,7 +400,8 @@
if (strcmp(nm, "..") == 0) {
err = VFS_ROOT(dvp->v_vfsp, vpp);
} else {
- err = gfs_dir_lookup(dvp, nm, vpp, cr);
+ err = gfs_vop_lookup(dvp, nm, vpp, pnp, flags, rdir,
+ cr, ct, direntflags, realpnp);
}
ZFS_EXIT(zfsvfs);
@@ -527,20 +529,36 @@
{
zfsctl_snapdir_t *sdp = sdvp->v_data;
zfs_snapentry_t search, *sep;
+ zfsvfs_t *zfsvfs;
avl_index_t where;
char from[MAXNAMELEN], to[MAXNAMELEN];
+ char real[MAXNAMELEN];
int err;
+ zfsvfs = sdvp->v_vfsp->vfs_data;
+ ZFS_ENTER(zfsvfs);
+
+ if ((flags & FIGNORECASE) || zfsvfs->z_case == ZFS_CASE_INSENSITIVE) {
+ err = dmu_snapshot_realname(zfsvfs->z_os, snm, real,
+ MAXNAMELEN, NULL);
+ if (err == 0) {
+ snm = real;
+ } else if (err != ENOTSUP) {
+ ZFS_EXIT(zfsvfs);
+ return (err);
+ }
+ }
+
+ ZFS_EXIT(zfsvfs);
+
err = zfsctl_snapshot_zname(sdvp, snm, MAXNAMELEN, from);
+ if (!err)
+ err = zfsctl_snapshot_zname(tdvp, tnm, MAXNAMELEN, to);
+ if (!err)
+ err = zfs_secpolicy_rename_perms(from, to, cr);
if (err)
return (err);
- err = zfsctl_snapshot_zname(tdvp, tnm, MAXNAMELEN, to);
- if (err)
- return (err);
-
- if (err = zfs_secpolicy_rename_perms(from, to, cr))
- return (err);
/*
* Cannot move snapshots out of the snapdir.
*/
@@ -575,16 +593,34 @@
zfsctl_snapdir_t *sdp = dvp->v_data;
zfs_snapentry_t *sep;
zfs_snapentry_t search;
+ zfsvfs_t *zfsvfs;
char snapname[MAXNAMELEN];
+ char real[MAXNAMELEN];
int err;
+ zfsvfs = dvp->v_vfsp->vfs_data;
+ ZFS_ENTER(zfsvfs);
+
+ if ((flags & FIGNORECASE) || zfsvfs->z_case == ZFS_CASE_INSENSITIVE) {
+
+ err = dmu_snapshot_realname(zfsvfs->z_os, name, real,
+ MAXNAMELEN, NULL);
+ if (err == 0) {
+ name = real;
+ } else if (err != ENOTSUP) {
+ ZFS_EXIT(zfsvfs);
+ return (err);
+ }
+ }
+
+ ZFS_EXIT(zfsvfs);
+
err = zfsctl_snapshot_zname(dvp, name, MAXNAMELEN, snapname);
+ if (!err)
+ err = zfs_secpolicy_destroy_perms(snapname, cr);
if (err)
return (err);
- if (err = zfs_secpolicy_destroy_perms(snapname, cr))
- return (err);
-
mutex_enter(&sdp->sd_lock);
search.se_name = name;
@@ -651,6 +687,7 @@
zfsctl_snapdir_t *sdp = dvp->v_data;
objset_t *snap;
char snapname[MAXNAMELEN];
+ char real[MAXNAMELEN];
char *mountpoint;
zfs_snapentry_t *sep, search;
struct mounta margs;
@@ -682,6 +719,24 @@
ZFS_ENTER(zfsvfs);
+ if (flags & FIGNORECASE) {
+ boolean_t conflict = B_FALSE;
+
+ err = dmu_snapshot_realname(zfsvfs->z_os, nm, real,
+ MAXNAMELEN, &conflict);
+ if (err == 0) {
+ nm = real;
+ } else if (err != ENOTSUP) {
+ ZFS_EXIT(zfsvfs);
+ return (err);
+ }
+ if (realpnp)
+ (void) strlcpy(realpnp->pn_buf, nm,
+ realpnp->pn_bufsize);
+ if (conflict && direntflags)
+ *direntflags = ED_CASE_CONFLICT;
+ }
+
mutex_enter(&sdp->sd_lock);
search.se_name = (char *)nm;
if ((sep = avl_find(&sdp->sd_snaps, &search, &where)) != NULL) {
@@ -938,7 +993,7 @@
zfs_snapentry_t *sep, *next;
vnode_t *dvp;
- VERIFY(gfs_dir_lookup(vp, "..", &dvp, cr) == 0);
+ VERIFY(gfs_dir_lookup(vp, "..", &dvp, cr, 0, NULL, NULL) == 0);
sdp = dvp->v_data;
mutex_enter(&sdp->sd_lock);
--- a/usr/src/uts/common/fs/zfs/zfs_dir.c Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_dir.c Sun Apr 27 10:20:38 2008 -0700
@@ -74,7 +74,7 @@
char *buf = NULL;
if (rpnp) {
- buf = rpnp->pn_path;
+ buf = rpnp->pn_buf;
bufsz = rpnp->pn_bufsize;
}
if (exact)
@@ -85,7 +85,7 @@
*/
error = zap_lookup_norm(zfsvfs->z_os, dzp->z_id, name, 8, 1,
zoid, mt, buf, bufsz, &conflict);
- if (deflags)
+ if (!error && deflags)
*deflags = conflict ? ED_CASE_CONFLICT : 0;
} else {
error = zap_lookup(zfsvfs->z_os, dzp->z_id, name, 8, 1, zoid);
@@ -401,8 +401,8 @@
rpnp = NULL;
}
- if ((flags & FIGNORECASE) && rpnp)
- (void) strlcpy(rpnp->pn_path, name, rpnp->pn_bufsize);
+ if ((flags & FIGNORECASE) && rpnp && !error)
+ (void) strlcpy(rpnp->pn_buf, name, rpnp->pn_bufsize);
return (error);
}
--- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c Sun Apr 27 10:20:38 2008 -0700
@@ -1811,7 +1811,7 @@
*/
static int
zfs_fill_zplprops(const char *dataset, nvlist_t *createprops,
- nvlist_t *zplprops, uint64_t zplver)
+ nvlist_t *zplprops, uint64_t zplver, boolean_t *is_ci)
{
objset_t *os;
char parentname[MAXNAMELEN];
@@ -1891,6 +1891,9 @@
VERIFY(nvlist_add_uint64(zplprops,
zfs_prop_to_name(ZFS_PROP_CASE), sense) == 0);
+ if (is_ci)
+ *is_ci = (sense == ZFS_CASE_INSENSITIVE);
+
dmu_objset_close(os);
return (0);
}
@@ -1956,7 +1959,9 @@
nvlist_free(nvprops);
return (error);
}
- error = dmu_objset_create(zc->zc_name, type, clone, NULL, NULL);
+
+ error = dmu_objset_create(zc->zc_name, type, clone, 0,
+ NULL, NULL);
if (error) {
dmu_objset_close(clone);
nvlist_free(nvprops);
@@ -1964,6 +1969,8 @@
}
dmu_objset_close(clone);
} else {
+ boolean_t is_insensitive = B_FALSE;
+
if (cbfunc == NULL) {
nvlist_free(nvprops);
return (EINVAL);
@@ -2038,17 +2045,16 @@
VERIFY(nvlist_alloc(&zct.zct_zplprops,
NV_UNIQUE_NAME, KM_SLEEP) == 0);
error = zfs_fill_zplprops(zc->zc_name, nvprops,
- zct.zct_zplprops, version);
+ zct.zct_zplprops, version, &is_insensitive);
if (error != 0) {
nvlist_free(nvprops);
nvlist_free(zct.zct_zplprops);
return (error);
}
}
- error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc,
- &zct);
+ error = dmu_objset_create(zc->zc_name, type, NULL,
+ is_insensitive ? DS_FLAG_CI_DATASET : 0, cbfunc, &zct);
nvlist_free(zct.zct_zplprops);
-
}
/*
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c Sun Apr 27 10:20:38 2008 -0700
@@ -1421,7 +1421,7 @@
vnevent_remove(vp, dvp, name, ct);
if (realnmp)
- dnlc_remove(dvp, realnmp->pn_path);
+ dnlc_remove(dvp, realnmp->pn_buf);
else
dnlc_remove(dvp, name);
--- a/usr/src/uts/common/fs/zfs/zfs_znode.c Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_znode.c Sun Apr 27 10:20:38 2008 -0700
@@ -37,6 +37,7 @@
#include <sys/mntent.h>
#include <sys/mkdev.h>
#include <sys/u8_textprep.h>
+#include <sys/dsl_dataset.h>
#include <sys/vfs.h>
#include <sys/vfs_opreg.h>
#include <sys/vnode.h>
--- a/usr/src/uts/common/sys/gfs.h Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/sys/gfs.h Sun Apr 27 10:20:38 2008 -0700
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -78,7 +78,7 @@
typedef int (*gfs_readdir_cb)(vnode_t *, void *, int *, offset_t *,
offset_t *, void *, int);
typedef int (*gfs_lookup_cb)(vnode_t *, const char *, vnode_t **, ino64_t *,
- cred_t *);
+ cred_t *, int, int *, pathname_t *);
typedef ino64_t (*gfs_inode_cb)(vnode_t *, int);
typedef struct gfs_dir {
@@ -105,12 +105,16 @@
extern void *gfs_file_inactive(vnode_t *);
extern void *gfs_dir_inactive(vnode_t *);
-extern int gfs_dir_lookup(vnode_t *, const char *, vnode_t **, cred_t *);
+extern int gfs_dir_case_lookup(vnode_t *, const char *, vnode_t **, cred_t *,
+ int, int *, pathname_t *);
+extern int gfs_dir_lookup(vnode_t *, const char *, vnode_t **, cred_t *,
+ int, int *, pathname_t *);
extern int gfs_dir_readdir(vnode_t *, uio_t *, int *, void *, cred_t *,
caller_context_t *, int flags);
#define gfs_dir_lock(gd) mutex_enter(&(gd)->gfsd_lock)
#define gfs_dir_unlock(gd) mutex_exit(&(gd)->gfsd_lock)
+#define GFS_DIR_LOCKED(gd) MUTEX_HELD(&(gd)->gfsd_lock)
#define gfs_file_parent(vp) (((gfs_file_t *)(vp)->v_data)->gfs_parent)
--- a/usr/src/uts/common/sys/vnode.h Sat Apr 26 21:58:06 2008 -0700
+++ b/usr/src/uts/common/sys/vnode.h Sun Apr 27 10:20:38 2008 -0700
@@ -321,6 +321,8 @@
#define V_XATTRDIR 0x4000 /* attribute unnamed directory */
+#define IS_XATTRDIR(vp) ((vp)->v_flag & V_XATTRDIR)
+
#define V_LOCALITY 0x8000 /* whether locality aware */
/*