--- a/usr/src/uts/common/fs/zfs/zfs_ctldir.c Mon Jun 25 23:50:40 2007 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_ctldir.c Tue Jun 26 07:44:24 2007 -0700
@@ -63,6 +63,7 @@
#include <sys/gfs.h>
#include <sys/stat.h>
#include <sys/dmu.h>
+#include <sys/dsl_deleg.h>
#include <sys/mount.h>
typedef struct {
@@ -411,7 +412,7 @@
return (0);
}
-static int
+int
zfsctl_unmount_snap(vnode_t *dvp, const char *name, int force, cred_t *cr)
{
zfsctl_snapdir_t *sdp = dvp->v_data;
@@ -514,10 +515,13 @@
err = zfsctl_snapshot_zname(sdvp, snm, MAXNAMELEN, from);
if (err)
return (err);
- err = zfs_secpolicy_write(from, cr);
+
+ 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.
*/
@@ -527,10 +531,6 @@
if (strcmp(snm, tnm) == 0)
return (0);
- err = zfsctl_snapshot_zname(tdvp, tnm, MAXNAMELEN, to);
- if (err)
- return (err);
-
mutex_enter(&sdp->sd_lock);
search.se_name = (char *)snm;
@@ -559,13 +559,13 @@
err = zfsctl_snapshot_zname(dvp, name, MAXNAMELEN, snapname);
if (err)
return (err);
- err = zfs_secpolicy_write(snapname, cr);
- if (err)
+
+ if (err = zfs_secpolicy_destroy_perms(snapname, cr))
return (err);
mutex_enter(&sdp->sd_lock);
- err = zfsctl_unmount_snap(dvp, name, 0, cr);
+ err = zfsctl_unmount_snap(dvp, name, MS_FORCE, cr);
if (err) {
mutex_exit(&sdp->sd_lock);
return (err);
@@ -578,6 +578,35 @@
return (err);
}
+/* ARGSUSED */
+static int
+zfsctl_snapdir_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp,
+ cred_t *cr)
+{
+ zfsvfs_t *zfsvfs = dvp->v_vfsp->vfs_data;
+ char name[MAXNAMELEN];
+ int err;
+ static enum symfollow follow = NO_FOLLOW;
+ static enum uio_seg seg = UIO_SYSSPACE;
+
+ dmu_objset_name(zfsvfs->z_os, name);
+
+ *vpp = NULL;
+
+ err = zfs_secpolicy_snapshot_perms(name, cr);
+ if (err)
+ return (err);
+
+ if (err == 0) {
+ err = dmu_objset_snapshot(name, dirname, B_FALSE);
+ if (err)
+ return (err);
+ err = lookupnameat(dirname, seg, follow, NULL, vpp, dvp);
+ }
+
+ return (err);
+}
+
/*
* Lookup entry point for the 'snapshot' directory. Try to open the
* snapshot if it exist, creating the pseudo filesystem vnode as necessary.
@@ -796,6 +825,7 @@
{ VOPNAME_ACCESS, { .vop_access = zfsctl_common_access } },
{ VOPNAME_RENAME, { .vop_rename = zfsctl_snapdir_rename } },
{ VOPNAME_RMDIR, { .vop_rmdir = zfsctl_snapdir_remove } },
+ { VOPNAME_MKDIR, { .vop_mkdir = zfsctl_snapdir_mkdir } },
{ VOPNAME_READDIR, { .vop_readdir = gfs_vop_readdir } },
{ VOPNAME_LOOKUP, { .vop_lookup = zfsctl_snapdir_lookup } },
{ VOPNAME_SEEK, { .vop_seek = fs_seek } },