usr/src/uts/common/fs/zfs/zfs_ctldir.c
changeset 4543 12bb2876a62e
parent 4007 c6f5c6753018
child 4736 f8714efb3e12
equal deleted inserted replaced
4542:ad60c8518fd5 4543:12bb2876a62e
    61 #include <sys/zfs_vfsops.h>
    61 #include <sys/zfs_vfsops.h>
    62 #include <sys/vfs_opreg.h>
    62 #include <sys/vfs_opreg.h>
    63 #include <sys/gfs.h>
    63 #include <sys/gfs.h>
    64 #include <sys/stat.h>
    64 #include <sys/stat.h>
    65 #include <sys/dmu.h>
    65 #include <sys/dmu.h>
       
    66 #include <sys/dsl_deleg.h>
    66 #include <sys/mount.h>
    67 #include <sys/mount.h>
    67 
    68 
    68 typedef struct {
    69 typedef struct {
    69 	char		*se_name;
    70 	char		*se_name;
    70 	vnode_t		*se_root;
    71 	vnode_t		*se_root;
   409 	(void) strcat(zname, "@");
   410 	(void) strcat(zname, "@");
   410 	(void) strcat(zname, name);
   411 	(void) strcat(zname, name);
   411 	return (0);
   412 	return (0);
   412 }
   413 }
   413 
   414 
   414 static int
   415 int
   415 zfsctl_unmount_snap(vnode_t *dvp, const char *name, int force, cred_t *cr)
   416 zfsctl_unmount_snap(vnode_t *dvp, const char *name, int force, cred_t *cr)
   416 {
   417 {
   417 	zfsctl_snapdir_t *sdp = dvp->v_data;
   418 	zfsctl_snapdir_t *sdp = dvp->v_data;
   418 	zfs_snapentry_t search, *sep;
   419 	zfs_snapentry_t search, *sep;
   419 	avl_index_t where;
   420 	avl_index_t where;
   512 	int err;
   513 	int err;
   513 
   514 
   514 	err = zfsctl_snapshot_zname(sdvp, snm, MAXNAMELEN, from);
   515 	err = zfsctl_snapshot_zname(sdvp, snm, MAXNAMELEN, from);
   515 	if (err)
   516 	if (err)
   516 		return (err);
   517 		return (err);
   517 	err = zfs_secpolicy_write(from, cr);
   518 
       
   519 	err = zfsctl_snapshot_zname(tdvp, tnm, MAXNAMELEN, to);
   518 	if (err)
   520 	if (err)
   519 		return (err);
   521 		return (err);
   520 
   522 
       
   523 	if (err = zfs_secpolicy_rename_perms(from, to, cr))
       
   524 		return (err);
   521 	/*
   525 	/*
   522 	 * Cannot move snapshots out of the snapdir.
   526 	 * Cannot move snapshots out of the snapdir.
   523 	 */
   527 	 */
   524 	if (sdvp != tdvp)
   528 	if (sdvp != tdvp)
   525 		return (EINVAL);
   529 		return (EINVAL);
   526 
   530 
   527 	if (strcmp(snm, tnm) == 0)
   531 	if (strcmp(snm, tnm) == 0)
   528 		return (0);
   532 		return (0);
   529 
   533 
   530 	err = zfsctl_snapshot_zname(tdvp, tnm, MAXNAMELEN, to);
       
   531 	if (err)
       
   532 		return (err);
       
   533 
       
   534 	mutex_enter(&sdp->sd_lock);
   534 	mutex_enter(&sdp->sd_lock);
   535 
   535 
   536 	search.se_name = (char *)snm;
   536 	search.se_name = (char *)snm;
   537 	if ((sep = avl_find(&sdp->sd_snaps, &search, &where)) == NULL) {
   537 	if ((sep = avl_find(&sdp->sd_snaps, &search, &where)) == NULL) {
   538 		mutex_exit(&sdp->sd_lock);
   538 		mutex_exit(&sdp->sd_lock);
   557 	int err;
   557 	int err;
   558 
   558 
   559 	err = zfsctl_snapshot_zname(dvp, name, MAXNAMELEN, snapname);
   559 	err = zfsctl_snapshot_zname(dvp, name, MAXNAMELEN, snapname);
   560 	if (err)
   560 	if (err)
   561 		return (err);
   561 		return (err);
   562 	err = zfs_secpolicy_write(snapname, cr);
   562 
   563 	if (err)
   563 	if (err = zfs_secpolicy_destroy_perms(snapname, cr))
   564 		return (err);
   564 		return (err);
   565 
   565 
   566 	mutex_enter(&sdp->sd_lock);
   566 	mutex_enter(&sdp->sd_lock);
   567 
   567 
   568 	err = zfsctl_unmount_snap(dvp, name, 0, cr);
   568 	err = zfsctl_unmount_snap(dvp, name, MS_FORCE, cr);
   569 	if (err) {
   569 	if (err) {
   570 		mutex_exit(&sdp->sd_lock);
   570 		mutex_exit(&sdp->sd_lock);
   571 		return (err);
   571 		return (err);
   572 	}
   572 	}
   573 
   573 
   574 	err = dmu_objset_destroy(snapname);
   574 	err = dmu_objset_destroy(snapname);
   575 
   575 
   576 	mutex_exit(&sdp->sd_lock);
   576 	mutex_exit(&sdp->sd_lock);
       
   577 
       
   578 	return (err);
       
   579 }
       
   580 
       
   581 /* ARGSUSED */
       
   582 static int
       
   583 zfsctl_snapdir_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t  **vpp,
       
   584     cred_t *cr)
       
   585 {
       
   586 	zfsvfs_t *zfsvfs = dvp->v_vfsp->vfs_data;
       
   587 	char name[MAXNAMELEN];
       
   588 	int err;
       
   589 	static enum symfollow follow = NO_FOLLOW;
       
   590 	static enum uio_seg seg = UIO_SYSSPACE;
       
   591 
       
   592 	dmu_objset_name(zfsvfs->z_os, name);
       
   593 
       
   594 	*vpp = NULL;
       
   595 
       
   596 	err = zfs_secpolicy_snapshot_perms(name, cr);
       
   597 	if (err)
       
   598 		return (err);
       
   599 
       
   600 	if (err == 0) {
       
   601 		err = dmu_objset_snapshot(name, dirname, B_FALSE);
       
   602 		if (err)
       
   603 			return (err);
       
   604 		err = lookupnameat(dirname, seg, follow, NULL, vpp, dvp);
       
   605 	}
   577 
   606 
   578 	return (err);
   607 	return (err);
   579 }
   608 }
   580 
   609 
   581 /*
   610 /*
   794 	{ VOPNAME_IOCTL,	{ .error = fs_inval }			},
   823 	{ VOPNAME_IOCTL,	{ .error = fs_inval }			},
   795 	{ VOPNAME_GETATTR,	{ .vop_getattr = zfsctl_snapdir_getattr } },
   824 	{ VOPNAME_GETATTR,	{ .vop_getattr = zfsctl_snapdir_getattr } },
   796 	{ VOPNAME_ACCESS,	{ .vop_access = zfsctl_common_access }	},
   825 	{ VOPNAME_ACCESS,	{ .vop_access = zfsctl_common_access }	},
   797 	{ VOPNAME_RENAME,	{ .vop_rename = zfsctl_snapdir_rename }	},
   826 	{ VOPNAME_RENAME,	{ .vop_rename = zfsctl_snapdir_rename }	},
   798 	{ VOPNAME_RMDIR,	{ .vop_rmdir = zfsctl_snapdir_remove }	},
   827 	{ VOPNAME_RMDIR,	{ .vop_rmdir = zfsctl_snapdir_remove }	},
       
   828 	{ VOPNAME_MKDIR,	{ .vop_mkdir = zfsctl_snapdir_mkdir }	},
   799 	{ VOPNAME_READDIR,	{ .vop_readdir = gfs_vop_readdir }	},
   829 	{ VOPNAME_READDIR,	{ .vop_readdir = gfs_vop_readdir }	},
   800 	{ VOPNAME_LOOKUP,	{ .vop_lookup = zfsctl_snapdir_lookup }	},
   830 	{ VOPNAME_LOOKUP,	{ .vop_lookup = zfsctl_snapdir_lookup }	},
   801 	{ VOPNAME_SEEK,		{ .vop_seek = fs_seek }			},
   831 	{ VOPNAME_SEEK,		{ .vop_seek = fs_seek }			},
   802 	{ VOPNAME_INACTIVE,	{ .vop_inactive = zfsctl_snapdir_inactive } },
   832 	{ VOPNAME_INACTIVE,	{ .vop_inactive = zfsctl_snapdir_inactive } },
   803 	{ VOPNAME_FID,		{ .vop_fid = zfsctl_common_fid }	},
   833 	{ VOPNAME_FID,		{ .vop_fid = zfsctl_common_fid }	},