Mercurial > illumos > illumos-gate
changeset 6492:903545192033
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
line wrap: on
line diff
--- 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 */ /*