2 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2013, 2015 by Delphix. All rights reserved.
4 * Copyright (c) 2013 Steven Hartland. All rights reserved.
5 * Copyright (c) 2016 Martin Matuska. All rights reserved.
11 * Copyright (c) 2007, The Storage Networking Industry Association.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * - Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
19 * - Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in
21 * the documentation and/or other materials provided with the
24 * - Neither the name of The Storage Networking Industry Association (SNIA)
25 * nor the names of its contributors may be used to endorse or promote
26 * products derived from this software without specific prior written
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
30 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
33 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 * POSSIBILITY OF SUCH DAMAGE.
47 typedef struct snap_param
{
52 static int cleanup_fd
= -1;
57 * Call backup function which looks for backup snapshot.
58 * This is a callback function used with zfs_iter_snapshots.
61 * zhp (input) - ZFS handle pointer
62 * data (output) - 0 - no backup snapshot
63 * 1 - has backup snapshot
70 ndmp_has_backup(zfs_handle_t
*zhp
, void *data
)
73 snap_param_t
*chp
= (snap_param_t
*)data
;
75 name
= zfs_get_name(zhp
);
77 strstr(name
, chp
->snp_name
) == NULL
) {
89 * ndmp_has_backup_snapshot
91 * Returns TRUE if the volume has an active backup snapshot, otherwise,
95 * volname (input) - name of the volume
102 ndmp_has_backup_snapshot(char *volname
, char *jobname
)
106 char chname
[ZFS_MAX_DATASET_NAME_LEN
];
108 (void) mutex_lock(&zlib_mtx
);
109 if ((zhp
= zfs_open(zlibh
, volname
, ZFS_TYPE_DATASET
)) == 0) {
110 NDMP_LOG(LOG_ERR
, "Cannot open snapshot %s.", volname
);
111 (void) mutex_unlock(&zlib_mtx
);
116 (void) snprintf(chname
, ZFS_MAX_DATASET_NAME_LEN
, "@%s", jobname
);
117 snp
.snp_name
= chname
;
119 (void) zfs_iter_snapshots(zhp
, B_FALSE
, ndmp_has_backup
, &snp
);
121 (void) mutex_unlock(&zlib_mtx
);
123 return (snp
.snp_found
);
127 * ndmp_create_snapshot
129 * This function will parse the path to get the real volume name.
130 * It will then create a snapshot based on volume and job name.
131 * This function should be called before the NDMP backup is started.
134 * vol_name (input) - name of the volume
141 ndmp_create_snapshot(char *vol_name
, char *jname
)
143 char vol
[ZFS_MAX_DATASET_NAME_LEN
];
146 get_zfsvolname(vol
, sizeof (vol
), vol_name
) == -1)
150 * If there is an old snapshot left from the previous
151 * backup it could be stale one and it must be
152 * removed before using it.
154 if (ndmp_has_backup_snapshot(vol
, jname
))
155 (void) snapshot_destroy(vol
, jname
, B_FALSE
, B_TRUE
, NULL
);
157 return (snapshot_create(vol
, jname
, B_FALSE
, B_TRUE
));
161 * ndmp_remove_snapshot
163 * This function will parse the path to get the real volume name.
164 * It will then remove the snapshot for that volume and job name.
165 * This function should be called after NDMP backup is finished.
168 * vol_name (input) - name of the volume
175 ndmp_remove_snapshot(char *vol_name
, char *jname
)
177 char vol
[ZFS_MAX_DATASET_NAME_LEN
];
180 get_zfsvolname(vol
, sizeof (vol
), vol_name
) == -1)
183 return (snapshot_destroy(vol
, jname
, B_FALSE
, B_TRUE
, NULL
));
187 * Put a hold on snapshot
190 snapshot_hold(char *volname
, char *snapname
, char *jname
, boolean_t recursive
)
195 if ((zhp
= zfs_open(zlibh
, volname
, ZFS_TYPE_DATASET
)) == 0) {
196 NDMP_LOG(LOG_ERR
, "Cannot open volume %s.", volname
);
200 if (cleanup_fd
== -1 && (cleanup_fd
= open(ZFS_DEV
,
201 O_RDWR
|O_EXCL
)) < 0) {
202 NDMP_LOG(LOG_ERR
, "Cannot open dev %d", errno
);
207 p
= strchr(snapname
, '@') + 1;
208 if (zfs_hold(zhp
, p
, jname
, recursive
, cleanup_fd
) != 0) {
209 NDMP_LOG(LOG_ERR
, "Cannot hold snapshot %s", p
);
218 snapshot_release(char *volname
, char *snapname
, char *jname
,
225 if ((zhp
= zfs_open(zlibh
, volname
, ZFS_TYPE_DATASET
)) == 0) {
226 NDMP_LOG(LOG_ERR
, "Cannot open volume %s", volname
);
230 p
= strchr(snapname
, '@') + 1;
231 if (zfs_release(zhp
, p
, jname
, recursive
) != 0) {
232 NDMP_LOG(LOG_DEBUG
, "Cannot release snapshot %s", p
);
235 if (cleanup_fd
!= -1) {
236 (void) close(cleanup_fd
);
244 * Create a snapshot on the volume
247 snapshot_create(char *volname
, char *jname
, boolean_t recursive
,
250 char snapname
[ZFS_MAX_DATASET_NAME_LEN
];
253 if (!volname
|| !*volname
)
256 (void) snprintf(snapname
, ZFS_MAX_DATASET_NAME_LEN
,
257 "%s@%s", volname
, jname
);
259 (void) mutex_lock(&zlib_mtx
);
260 if ((rv
= zfs_snapshot(zlibh
, snapname
, recursive
, NULL
))
262 if (errno
== EEXIST
) {
263 (void) mutex_unlock(&zlib_mtx
);
267 "snapshot_create: %s failed (err=%d): %s",
268 snapname
, errno
, libzfs_error_description(zlibh
));
269 (void) mutex_unlock(&zlib_mtx
);
272 if (hold
&& snapshot_hold(volname
, snapname
, jname
, recursive
) != 0) {
274 "snapshot_create: %s hold failed (err=%d): %s",
275 snapname
, errno
, libzfs_error_description(zlibh
));
276 (void) mutex_unlock(&zlib_mtx
);
280 (void) mutex_unlock(&zlib_mtx
);
285 * Remove and release the backup snapshot
288 snapshot_destroy(char *volname
, char *jname
, boolean_t recursive
,
289 boolean_t hold
, int *zfs_err
)
291 char snapname
[ZFS_MAX_DATASET_NAME_LEN
];
300 if (!volname
|| !*volname
)
304 ztype
= ZFS_TYPE_VOLUME
| ZFS_TYPE_FILESYSTEM
;
307 (void) snprintf(snapname
, ZFS_MAX_DATASET_NAME_LEN
,
308 "%s@%s", volname
, jname
);
310 ztype
= ZFS_TYPE_SNAPSHOT
;
313 (void) mutex_lock(&zlib_mtx
);
315 snapshot_release(volname
, namep
, jname
, recursive
) != 0) {
317 "snapshot_destroy: %s release failed (err=%d): %s",
318 namep
, errno
, libzfs_error_description(zlibh
));
319 (void) mutex_unlock(&zlib_mtx
);
323 if ((zhp
= zfs_open(zlibh
, namep
, ztype
)) == NULL
) {
324 NDMP_LOG(LOG_DEBUG
, "snapshot_destroy: open %s failed",
326 (void) mutex_unlock(&zlib_mtx
);
331 err
= zfs_destroy_snaps(zhp
, jname
, B_TRUE
);
333 err
= zfs_destroy(zhp
, B_TRUE
);
337 NDMP_LOG(LOG_ERR
, "%s (recursive destroy: %d): %d; %s; %s",
341 libzfs_error_action(zlibh
),
342 libzfs_error_description(zlibh
));
349 (void) mutex_unlock(&zlib_mtx
);