diff options
Diffstat (limited to 'usr/src/uts/common/fs/zfs/zfs_ctldir.c')
-rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_ctldir.c | 77 |
1 files changed, 66 insertions, 11 deletions
diff --git a/usr/src/uts/common/fs/zfs/zfs_ctldir.c b/usr/src/uts/common/fs/zfs/zfs_ctldir.c index 98a3c67245..56bf50e842 100644 --- a/usr/src/uts/common/fs/zfs/zfs_ctldir.c +++ b/usr/src/uts/common/fs/zfs/zfs_ctldir.c @@ -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 @@ zfsctl_root_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp, 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_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, { 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; - err = zfsctl_snapshot_zname(sdvp, snm, MAXNAMELEN, from); - if (err) - return (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(tdvp, tnm, MAXNAMELEN, to); + 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); - if (err = zfs_secpolicy_rename_perms(from, to, cr)) - return (err); /* * Cannot move snapshots out of the snapdir. */ @@ -575,16 +593,34 @@ zfsctl_snapdir_remove(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr, 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_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp, 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 @@ zfsctl_snapdir_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp, 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 @@ zfsctl_snapshot_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct) 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); |