1 /*
   2  * CDDL HEADER START
   3  *
   4  * This file and its contents are supplied under the terms of the
   5  * Common Development and Distribution License ("CDDL"), version 1.0.
   6  * You may only use this file in accordance with the terms of version
   7  * 1.0 of the CDDL.
   8  *
   9  * A full copy of the text of the CDDL should have accompanied this
  10  * source.  A copy of the CDDL is also available via the Internet at
  11  * http://www.illumos.org/license/CDDL.
  12  *
  13  * CDDL HEADER END
  14  */
  15 /*
  16  * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
  17  */
  18 
  19 #include <syslog.h>
  20 #include <stdio.h>
  21 #include <string.h>
  22 #include "ndmpd.h"
  23 #include <libzfs.h>
  24 #include <zlib.h>
  25 
  26 /*
  27  * ndmp_clone_snapshot
  28  *
  29  * Given a snapshot name in the file system, create a clone and
  30  * and mount it in a well known place for ndmpd to traverse it.
  31  *
  32  * Parameters:
  33  *   nlp (input) -  ndmp_lbr_params_t pointer contrining
  34  *                  name of the snapshot, and clone.
  35  *
  36  * Returns:
  37  *   0: on success
  38  *   -1: otherwise
  39  */
  40 int
  41 ndmp_clone_snapshot(ndmp_lbr_params_t *nlp)
  42 {
  43         int             res = 0;
  44         int             err;
  45         zfs_handle_t    *zhp;
  46         zfs_handle_t    *clone;
  47         nvlist_t        *props = NULL;
  48 
  49         if ((zhp = zfs_open(zlibh, nlp->nlp_snapname,
  50             ZFS_TYPE_SNAPSHOT)) == NULL) {
  51                 syslog(LOG_ERR,
  52                     "Could not open snapshot [%s]\n", nlp->nlp_snapname);
  53                 return (-1);
  54         }
  55 
  56         (void) snprintf(nlp->nlp_mountpoint, sizeof (nlp->nlp_mountpoint),
  57             "/%s", nlp->nlp_clonename);
  58 
  59         if ((nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) ||
  60             (nvlist_add_string(props, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
  61             nlp->nlp_mountpoint) != 0)) {
  62                 nvlist_free(props);
  63                 syslog(LOG_ERR, "could not create snapshot clone "
  64                     "%s: out of memory\n", nlp->nlp_clonename);
  65                 zfs_close(zhp);
  66                 return (-1);
  67         }
  68 
  69         err = zfs_clone(zhp, nlp->nlp_clonename, props);
  70         zfs_close(zhp);
  71         nvlist_free(props);
  72 
  73         if (err != 0) {
  74                 syslog(LOG_ERR, "zfs_clone error [%d]\n", err);
  75                 return (-1);
  76         }
  77 
  78         syslog(LOG_DEBUG, "Cloned snapshot [%s] "
  79             "clone name [%s] mount point [%s]\n",
  80             nlp->nlp_snapname, nlp->nlp_clonename,
  81             nlp->nlp_mountpoint);
  82 
  83         if ((clone = zfs_open(zlibh, nlp->nlp_clonename,
  84             ZFS_TYPE_DATASET)) == NULL) {
  85                 syslog(LOG_ERR,
  86                     "zfs_open failed on clone_name [%s]\n", nlp->nlp_clonename);
  87                 return (-1);
  88         }
  89 
  90         if (zfs_mount(clone, NULL, 0) != 0) {
  91                 syslog(LOG_ERR, "could not mount ZFS clone "
  92                     "%s\n", zfs_get_name(clone));
  93                 res = -1;
  94         }
  95         zfs_close(clone);
  96         return (res);
  97 }