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 } }, |