Print this page
3744 zfs shouldn't ignore errors unmounting snapshots
Submitted by:   Will Andrews <willa@spectralogic.com>
Reviewed by:    Matthew Ahrens <mahrens@delphix.com>


3351                 spa_close(spa, FTAG);
3352                 return (SET_ERROR(EINVAL));
3353         }
3354 
3355         if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) {
3356                 spa_close(spa, FTAG);
3357                 return (SET_ERROR(ENOTSUP));
3358         }
3359 
3360         error = spa_history_log(spa, message);
3361         spa_close(spa, FTAG);
3362         return (error);
3363 }
3364 
3365 /*
3366  * The dp_config_rwlock must not be held when calling this, because the
3367  * unmount may need to write out data.
3368  *
3369  * This function is best-effort.  Callers must deal gracefully if it
3370  * remains mounted (or is remounted after this call).



3371  */
3372 void
3373 zfs_unmount_snap(const char *snapname)
3374 {
3375         vfs_t *vfsp;
3376         zfsvfs_t *zfsvfs;

3377 
3378         if (strchr(snapname, '@') == NULL)
3379                 return;
3380 
3381         vfsp = zfs_get_vfs(snapname);
3382         if (vfsp == NULL)
3383                 return;
3384 
3385         zfsvfs = vfsp->vfs_data;
3386         ASSERT(!dsl_pool_config_held(dmu_objset_pool(zfsvfs->z_os)));
3387 
3388         if (vn_vfswlock(vfsp->vfs_vnodecovered) != 0) {
3389                 VFS_RELE(vfsp);
3390                 return;
3391         }
3392         VFS_RELE(vfsp);


3393 
3394         /*
3395          * Always force the unmount for snapshots.
3396          */
3397         (void) dounmount(vfsp, MS_FORCE, kcred);

3398 }
3399 
3400 /* ARGSUSED */
3401 static int
3402 zfs_unmount_snap_cb(const char *snapname, void *arg)
3403 {
3404         zfs_unmount_snap(snapname);
3405         return (0);
3406 }
3407 
3408 /*
3409  * When a clone is destroyed, its origin may also need to be destroyed,
3410  * in which case it must be unmounted.  This routine will do that unmount
3411  * if necessary.
3412  */
3413 void
3414 zfs_destroy_unmount_origin(const char *fsname)
3415 {
3416         int error;
3417         objset_t *os;
3418         dsl_dataset_t *ds;
3419 
3420         error = dmu_objset_hold(fsname, FTAG, &os);
3421         if (error != 0)
3422                 return;
3423         ds = dmu_objset_ds(os);
3424         if (dsl_dir_is_clone(ds->ds_dir) && DS_IS_DEFER_DESTROY(ds->ds_prev)) {
3425                 char originname[MAXNAMELEN];
3426                 dsl_dataset_name(ds->ds_prev, originname);
3427                 dmu_objset_rele(os, FTAG);
3428                 zfs_unmount_snap(originname);
3429         } else {
3430                 dmu_objset_rele(os, FTAG);
3431         }
3432 }
3433 
3434 /*
3435  * innvl: {
3436  *     "snaps" -> { snapshot1, snapshot2 }
3437  *     (optional boolean) "defer"
3438  * }
3439  *
3440  * outnvl: snapshot -> error code (int32)
3441  *
3442  */
3443 static int
3444 zfs_ioc_destroy_snaps(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
3445 {
3446         int poollen;
3447         nvlist_t *snaps;
3448         nvpair_t *pair;
3449         boolean_t defer;
3450 
3451         if (nvlist_lookup_nvlist(innvl, "snaps", &snaps) != 0)
3452                 return (SET_ERROR(EINVAL));
3453         defer = nvlist_exists(innvl, "defer");
3454 
3455         poollen = strlen(poolname);
3456         for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
3457             pair = nvlist_next_nvpair(snaps, pair)) {
3458                 const char *name = nvpair_name(pair);
3459 
3460                 /*
3461                  * The snap must be in the specified pool.
3462                  */
3463                 if (strncmp(name, poolname, poollen) != 0 ||
3464                     (name[poollen] != '/' && name[poollen] != '@'))
3465                         return (SET_ERROR(EXDEV));
3466 
3467                 zfs_unmount_snap(name);


3468         }
3469 
3470         return (dsl_destroy_snapshots_nvl(snaps, defer, outnvl));
3471 }
3472 
3473 /*
3474  * inputs:
3475  * zc_name              name of dataset to destroy
3476  * zc_objset_type       type of objset
3477  * zc_defer_destroy     mark for deferred destroy
3478  *
3479  * outputs:             none
3480  */
3481 static int
3482 zfs_ioc_destroy(zfs_cmd_t *zc)
3483 {
3484         int err;
3485         if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS)
3486                 zfs_unmount_snap(zc->zc_name);




3487 
3488         if (strchr(zc->zc_name, '@'))
3489                 err = dsl_destroy_snapshot(zc->zc_name, zc->zc_defer_destroy);
3490         else
3491                 err = dsl_destroy_head(zc->zc_name);
3492         if (zc->zc_objset_type == DMU_OST_ZVOL && err == 0)
3493                 (void) zvol_remove_minor(zc->zc_name);
3494         return (err);
3495 }
3496 
3497 /*
3498  * inputs:
3499  * zc_name      name of dataset to rollback (to most recent snapshot)
3500  *
3501  * outputs:     none
3502  */
3503 static int
3504 zfs_ioc_rollback(zfs_cmd_t *zc)
3505 {
3506         zfsvfs_t *zfsvfs;


3512                         int resume_err;
3513 
3514                         error = dsl_dataset_rollback(zc->zc_name);
3515                         resume_err = zfs_resume_fs(zfsvfs, zc->zc_name);
3516                         error = error ? error : resume_err;
3517                 }
3518                 VFS_RELE(zfsvfs->z_vfs);
3519         } else {
3520                 error = dsl_dataset_rollback(zc->zc_name);
3521         }
3522         return (error);
3523 }
3524 
3525 static int
3526 recursive_unmount(const char *fsname, void *arg)
3527 {
3528         const char *snapname = arg;
3529         char fullname[MAXNAMELEN];
3530 
3531         (void) snprintf(fullname, sizeof (fullname), "%s@%s", fsname, snapname);
3532         zfs_unmount_snap(fullname);
3533         return (0);
3534 }
3535 
3536 /*
3537  * inputs:
3538  * zc_name      old name of dataset
3539  * zc_value     new name of dataset
3540  * zc_cookie    recursive flag (only valid for snapshots)
3541  *
3542  * outputs:     none
3543  */
3544 static int
3545 zfs_ioc_rename(zfs_cmd_t *zc)
3546 {
3547         boolean_t recursive = zc->zc_cookie & 1;
3548         char *at;
3549 
3550         zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
3551         if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
3552             strchr(zc->zc_value, '%'))
3553                 return (SET_ERROR(EINVAL));


4972 {
4973         return (dsl_dataset_get_holds(snapname, outnvl));
4974 }
4975 
4976 /*
4977  * innvl: {
4978  *     snapname -> { holdname, ... }
4979  *     ...
4980  * }
4981  *
4982  * outnvl: {
4983  *     snapname -> error value (int32)
4984  *     ...
4985  * }
4986  */
4987 /* ARGSUSED */
4988 static int
4989 zfs_ioc_release(const char *pool, nvlist_t *holds, nvlist_t *errlist)
4990 {
4991         nvpair_t *pair;

4992 
4993         /*
4994          * The release may cause the snapshot to be destroyed; make sure it
4995          * is not mounted.
4996          */
4997         for (pair = nvlist_next_nvpair(holds, NULL); pair != NULL;
4998             pair = nvlist_next_nvpair(holds, pair))
4999                 zfs_unmount_snap(nvpair_name(pair));



5000 
5001         return (dsl_dataset_user_release(holds, errlist));
5002 }
5003 
5004 /*
5005  * inputs:
5006  * zc_name              name of new filesystem or snapshot
5007  * zc_value             full name of old snapshot
5008  *
5009  * outputs:
5010  * zc_cookie            space in bytes
5011  * zc_objset_type       compressed space in bytes
5012  * zc_perm_action       uncompressed space in bytes
5013  */
5014 static int
5015 zfs_ioc_space_written(zfs_cmd_t *zc)
5016 {
5017         int error;
5018         dsl_pool_t *dp;
5019         dsl_dataset_t *new, *old;




3351                 spa_close(spa, FTAG);
3352                 return (SET_ERROR(EINVAL));
3353         }
3354 
3355         if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) {
3356                 spa_close(spa, FTAG);
3357                 return (SET_ERROR(ENOTSUP));
3358         }
3359 
3360         error = spa_history_log(spa, message);
3361         spa_close(spa, FTAG);
3362         return (error);
3363 }
3364 
3365 /*
3366  * The dp_config_rwlock must not be held when calling this, because the
3367  * unmount may need to write out data.
3368  *
3369  * This function is best-effort.  Callers must deal gracefully if it
3370  * remains mounted (or is remounted after this call).
3371  *
3372  * Returns 0 if the argument is not a snapshot, or it is not currently a
3373  * filesystem, or we were able to unmount it.  Returns error code otherwise.
3374  */
3375 int
3376 zfs_unmount_snap(const char *snapname)
3377 {
3378         vfs_t *vfsp;
3379         zfsvfs_t *zfsvfs;
3380         int err;
3381 
3382         if (strchr(snapname, '@') == NULL)
3383                 return (0);
3384 
3385         vfsp = zfs_get_vfs(snapname);
3386         if (vfsp == NULL)
3387                 return (0);
3388 
3389         zfsvfs = vfsp->vfs_data;
3390         ASSERT(!dsl_pool_config_held(dmu_objset_pool(zfsvfs->z_os)));
3391 
3392         err = vn_vfswlock(vfsp->vfs_vnodecovered);



3393         VFS_RELE(vfsp);
3394         if (err != 0)
3395                 return (err);
3396 
3397         /*
3398          * Always force the unmount for snapshots.
3399          */
3400         (void) dounmount(vfsp, MS_FORCE, kcred);
3401         return (0);
3402 }
3403 
3404 /* ARGSUSED */
3405 static int
3406 zfs_unmount_snap_cb(const char *snapname, void *arg)
3407 {
3408         return (zfs_unmount_snap(snapname));

3409 }
3410 
3411 /*
3412  * When a clone is destroyed, its origin may also need to be destroyed,
3413  * in which case it must be unmounted.  This routine will do that unmount
3414  * if necessary.
3415  */
3416 void
3417 zfs_destroy_unmount_origin(const char *fsname)
3418 {
3419         int error;
3420         objset_t *os;
3421         dsl_dataset_t *ds;
3422 
3423         error = dmu_objset_hold(fsname, FTAG, &os);
3424         if (error != 0)
3425                 return;
3426         ds = dmu_objset_ds(os);
3427         if (dsl_dir_is_clone(ds->ds_dir) && DS_IS_DEFER_DESTROY(ds->ds_prev)) {
3428                 char originname[MAXNAMELEN];
3429                 dsl_dataset_name(ds->ds_prev, originname);
3430                 dmu_objset_rele(os, FTAG);
3431                 (void) zfs_unmount_snap(originname);
3432         } else {
3433                 dmu_objset_rele(os, FTAG);
3434         }
3435 }
3436 
3437 /*
3438  * innvl: {
3439  *     "snaps" -> { snapshot1, snapshot2 }
3440  *     (optional boolean) "defer"
3441  * }
3442  *
3443  * outnvl: snapshot -> error code (int32)
3444  *
3445  */
3446 static int
3447 zfs_ioc_destroy_snaps(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
3448 {
3449         int error, poollen;
3450         nvlist_t *snaps;
3451         nvpair_t *pair;
3452         boolean_t defer;
3453 
3454         if (nvlist_lookup_nvlist(innvl, "snaps", &snaps) != 0)
3455                 return (SET_ERROR(EINVAL));
3456         defer = nvlist_exists(innvl, "defer");
3457 
3458         poollen = strlen(poolname);
3459         for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
3460             pair = nvlist_next_nvpair(snaps, pair)) {
3461                 const char *name = nvpair_name(pair);
3462 
3463                 /*
3464                  * The snap must be in the specified pool.
3465                  */
3466                 if (strncmp(name, poolname, poollen) != 0 ||
3467                     (name[poollen] != '/' && name[poollen] != '@'))
3468                         return (SET_ERROR(EXDEV));
3469 
3470                 error = zfs_unmount_snap(name);
3471                 if (error)
3472                         return (SET_ERROR(error));
3473         }
3474 
3475         return (dsl_destroy_snapshots_nvl(snaps, defer, outnvl));
3476 }
3477 
3478 /*
3479  * inputs:
3480  * zc_name              name of dataset to destroy
3481  * zc_objset_type       type of objset
3482  * zc_defer_destroy     mark for deferred destroy
3483  *
3484  * outputs:             none
3485  */
3486 static int
3487 zfs_ioc_destroy(zfs_cmd_t *zc)
3488 {
3489         int err;
3490 
3491         if (zc->zc_objset_type == DMU_OST_ZFS) {
3492                 err = zfs_unmount_snap(zc->zc_name);
3493                 if (err)
3494                         return (err);
3495         }
3496 
3497         if (strchr(zc->zc_name, '@'))
3498                 err = dsl_destroy_snapshot(zc->zc_name, zc->zc_defer_destroy);
3499         else
3500                 err = dsl_destroy_head(zc->zc_name);
3501         if (zc->zc_objset_type == DMU_OST_ZVOL && err == 0)
3502                 (void) zvol_remove_minor(zc->zc_name);
3503         return (err);
3504 }
3505 
3506 /*
3507  * inputs:
3508  * zc_name      name of dataset to rollback (to most recent snapshot)
3509  *
3510  * outputs:     none
3511  */
3512 static int
3513 zfs_ioc_rollback(zfs_cmd_t *zc)
3514 {
3515         zfsvfs_t *zfsvfs;


3521                         int resume_err;
3522 
3523                         error = dsl_dataset_rollback(zc->zc_name);
3524                         resume_err = zfs_resume_fs(zfsvfs, zc->zc_name);
3525                         error = error ? error : resume_err;
3526                 }
3527                 VFS_RELE(zfsvfs->z_vfs);
3528         } else {
3529                 error = dsl_dataset_rollback(zc->zc_name);
3530         }
3531         return (error);
3532 }
3533 
3534 static int
3535 recursive_unmount(const char *fsname, void *arg)
3536 {
3537         const char *snapname = arg;
3538         char fullname[MAXNAMELEN];
3539 
3540         (void) snprintf(fullname, sizeof (fullname), "%s@%s", fsname, snapname);
3541         return (zfs_unmount_snap(fullname));

3542 }
3543 
3544 /*
3545  * inputs:
3546  * zc_name      old name of dataset
3547  * zc_value     new name of dataset
3548  * zc_cookie    recursive flag (only valid for snapshots)
3549  *
3550  * outputs:     none
3551  */
3552 static int
3553 zfs_ioc_rename(zfs_cmd_t *zc)
3554 {
3555         boolean_t recursive = zc->zc_cookie & 1;
3556         char *at;
3557 
3558         zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
3559         if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
3560             strchr(zc->zc_value, '%'))
3561                 return (SET_ERROR(EINVAL));


4980 {
4981         return (dsl_dataset_get_holds(snapname, outnvl));
4982 }
4983 
4984 /*
4985  * innvl: {
4986  *     snapname -> { holdname, ... }
4987  *     ...
4988  * }
4989  *
4990  * outnvl: {
4991  *     snapname -> error value (int32)
4992  *     ...
4993  * }
4994  */
4995 /* ARGSUSED */
4996 static int
4997 zfs_ioc_release(const char *pool, nvlist_t *holds, nvlist_t *errlist)
4998 {
4999         nvpair_t *pair;
5000         int err;
5001 
5002         /*
5003          * The release may cause the snapshot to be destroyed; make sure it
5004          * is not mounted.
5005          */
5006         for (pair = nvlist_next_nvpair(holds, NULL); pair != NULL;
5007             pair = nvlist_next_nvpair(holds, pair)) {
5008                 err = zfs_unmount_snap(nvpair_name(pair));
5009                 if (err)
5010                         return (err);
5011         }
5012 
5013         return (dsl_dataset_user_release(holds, errlist));
5014 }
5015 
5016 /*
5017  * inputs:
5018  * zc_name              name of new filesystem or snapshot
5019  * zc_value             full name of old snapshot
5020  *
5021  * outputs:
5022  * zc_cookie            space in bytes
5023  * zc_objset_type       compressed space in bytes
5024  * zc_perm_action       uncompressed space in bytes
5025  */
5026 static int
5027 zfs_ioc_space_written(zfs_cmd_t *zc)
5028 {
5029         int error;
5030         dsl_pool_t *dp;
5031         dsl_dataset_t *new, *old;