summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/fs/zfs/zfs_ctldir.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/fs/zfs/zfs_ctldir.c')
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_ctldir.c77
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);