diff options
| author | Chris Kirby <Chris.Kirby@oracle.com> | 2010-06-01 17:04:42 -0600 |
|---|---|---|
| committer | Chris Kirby <Chris.Kirby@oracle.com> | 2010-06-01 17:04:42 -0600 |
| commit | c99e4bdccfb4ac4da569c64a43baaf908d726329 (patch) | |
| tree | c1bb8cf62d52a712b2a961a1a3a5cb634f4fdfae /usr/src/lib/libzfs/common | |
| parent | ea408ca7befa82c08eb7affd8f29f1692188f34a (diff) | |
| download | illumos-joyent-c99e4bdccfb4ac4da569c64a43baaf908d726329.tar.gz | |
6884007 zfs_send() can leave temporary holds around
6954429 ZFS_IOC_VDEV_SPLIT missing from truss/codes.c
Diffstat (limited to 'usr/src/lib/libzfs/common')
| -rw-r--r-- | usr/src/lib/libzfs/common/libzfs.h | 4 | ||||
| -rw-r--r-- | usr/src/lib/libzfs/common/libzfs_dataset.c | 18 | ||||
| -rw-r--r-- | usr/src/lib/libzfs/common/libzfs_sendrecv.c | 69 |
3 files changed, 52 insertions, 39 deletions
diff --git a/usr/src/lib/libzfs/common/libzfs.h b/usr/src/lib/libzfs/common/libzfs.h index 6f7fed62c4..8969b44c01 100644 --- a/usr/src/lib/libzfs/common/libzfs.h +++ b/usr/src/lib/libzfs/common/libzfs.h @@ -533,9 +533,9 @@ extern int zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, extern int zfs_promote(zfs_handle_t *); extern int zfs_hold(zfs_handle_t *, const char *, const char *, boolean_t, - boolean_t, boolean_t); + boolean_t, boolean_t, int); extern int zfs_hold_range(zfs_handle_t *, const char *, const char *, - const char *, boolean_t, boolean_t, snapfilter_cb_t, void *); + const char *, boolean_t, boolean_t, snapfilter_cb_t, void *, int); extern int zfs_release(zfs_handle_t *, const char *, const char *, boolean_t); extern int zfs_release_range(zfs_handle_t *, const char *, const char *, const char *, boolean_t); diff --git a/usr/src/lib/libzfs/common/libzfs_dataset.c b/usr/src/lib/libzfs/common/libzfs_dataset.c index 5be559fdc2..f863b8f369 100644 --- a/usr/src/lib/libzfs/common/libzfs_dataset.c +++ b/usr/src/lib/libzfs/common/libzfs_dataset.c @@ -3926,7 +3926,8 @@ zfs_userspace(zfs_handle_t *zhp, zfs_userquota_prop_t type, int zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag, - boolean_t recursive, boolean_t temphold, boolean_t enoent_ok) + boolean_t recursive, boolean_t temphold, boolean_t enoent_ok, + int cleanup_fd) { zfs_cmd_t zc = { 0 }; libzfs_handle_t *hdl = zhp->zfs_hdl; @@ -3938,6 +3939,7 @@ zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag, return (zfs_error(hdl, EZFS_TAGTOOLONG, tag)); zc.zc_cookie = recursive; zc.zc_temphold = temphold; + zc.zc_cleanup_fd = cleanup_fd; if (zfs_ioctl(hdl, ZFS_IOC_HOLD, &zc) != 0) { char errbuf[ZFS_MAXNAMELEN+32]; @@ -3990,6 +3992,7 @@ struct hold_range_arg { boolean_t recursive; snapfilter_cb_t *filter_cb; void *filter_cb_arg; + int cleanup_fd; }; static int @@ -4023,7 +4026,7 @@ zfs_hold_range_one(zfs_handle_t *zhp, void *arg) if (hra->holding) { /* We could be racing with destroy, so ignore ENOENT. */ error = zfs_hold(hra->origin, thissnap, hra->tag, - hra->recursive, hra->temphold, B_TRUE); + hra->recursive, hra->temphold, B_TRUE, hra->cleanup_fd); if (error == 0) { (void) strlcpy(hra->lastsnapheld, zfs_get_name(zhp), sizeof (hra->lastsnapheld)); @@ -4045,7 +4048,7 @@ zfs_hold_range_one(zfs_handle_t *zhp, void *arg) int zfs_hold_range(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, const char *tag, boolean_t recursive, boolean_t temphold, - snapfilter_cb_t filter_cb, void *cbarg) + snapfilter_cb_t filter_cb, void *cbarg, int cleanup_fd) { struct hold_range_arg arg = { 0 }; int error; @@ -4060,13 +4063,17 @@ zfs_hold_range(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, arg.seenfrom = (fromsnap == NULL); arg.filter_cb = filter_cb; arg.filter_cb_arg = cbarg; + arg.cleanup_fd = cleanup_fd; error = zfs_iter_snapshots_sorted(zhp, zfs_hold_range_one, &arg); /* - * Make sure we either hold the entire range or none. + * Make sure we either hold the entire range or none. If we're + * using cleanup-on-exit, we'll let the closing of the cleanup_fd + * do the work for us. */ - if (error && arg.lastsnapheld[0] != '\0') { + if (error && arg.lastsnapheld[0] != '\0' && + (cleanup_fd == -1 || !temphold)) { (void) zfs_release_range(zhp, fromsnap, (const char *)arg.lastsnapheld, tag, recursive); } @@ -4130,6 +4137,7 @@ zfs_release_range(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, arg.tag = tag; arg.recursive = recursive; arg.seenfrom = (fromsnap == NULL); + arg.cleanup_fd = -1; return (zfs_iter_snapshots_sorted(zhp, zfs_hold_range_one, &arg)); } diff --git a/usr/src/lib/libzfs/common/libzfs_sendrecv.c b/usr/src/lib/libzfs/common/libzfs_sendrecv.c index 672e004ef5..0762451554 100644 --- a/usr/src/lib/libzfs/common/libzfs_sendrecv.c +++ b/usr/src/lib/libzfs/common/libzfs_sendrecv.c @@ -51,7 +51,7 @@ extern void zfs_setprop_error(libzfs_handle_t *, zfs_prop_t, int, char *); static int zfs_receive_impl(libzfs_handle_t *, const char *, recvflags_t, - int, const char *, nvlist_t *, avl_tree_t *, char **); + int, const char *, nvlist_t *, avl_tree_t *, char **, int, uint64_t *); static const zio_cksum_t zero_cksum = { 0 }; @@ -1210,6 +1210,7 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, int pipefd[2]; dedup_arg_t dda = { 0 }; int featureflags = 0; + int cleanup_fd = -1; if (zhp->zfs_type == ZFS_TYPE_FILESYSTEM) { uint64_t version; @@ -1259,12 +1260,17 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, zio_cksum_t zc = { 0 }; if (holdsnaps) { + ++holdseq; (void) snprintf(holdtag, sizeof (holdtag), ".send-%d-%llu", getpid(), (u_longlong_t)holdseq); - ++holdseq; + cleanup_fd = open(ZFS_DEV, O_RDWR|O_EXCL); + if (cleanup_fd < 0) { + err = errno; + goto stderr_out; + } err = zfs_hold_range(zhp, fromsnap, tosnap, holdtag, flags.replicate, B_TRUE, filter_func, - cb_arg); + cb_arg, cleanup_fd); if (err) goto err_out; } @@ -1285,13 +1291,8 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, err = gather_nvlist(zhp->zfs_hdl, zhp->zfs_name, fromsnap, tosnap, flags.replicate, &fss, &fsavl); - if (err) { - if (holdsnaps) { - (void) zfs_release_range(zhp, fromsnap, - tosnap, holdtag, flags.replicate); - } + if (err) goto err_out; - } VERIFY(0 == nvlist_add_nvlist(hdrnv, "fss", fss)); err = nvlist_pack(hdrnv, &packbuf, &buflen, NV_ENCODE_XDR, 0); @@ -1302,10 +1303,6 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, if (err) { fsavl_destroy(fsavl); nvlist_free(fss); - if (holdsnaps) { - (void) zfs_release_range(zhp, fromsnap, - tosnap, holdtag, flags.replicate); - } goto stderr_out; } } @@ -1331,10 +1328,6 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, if (err == -1) { fsavl_destroy(fsavl); nvlist_free(fss); - if (holdsnaps) { - (void) zfs_release_range(zhp, fromsnap, tosnap, - holdtag, flags.replicate); - } err = errno; goto stderr_out; } @@ -1349,10 +1342,6 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, fsavl_destroy(fsavl); nvlist_free(fss); err = errno; - if (holdsnaps) { - (void) zfs_release_range(zhp, fromsnap, - tosnap, holdtag, flags.replicate); - } goto stderr_out; } } @@ -1384,6 +1373,11 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, (void) pthread_join(tid, NULL); } + if (cleanup_fd != -1) { + VERIFY(0 == close(cleanup_fd)); + cleanup_fd = -1; + } + if (flags.replicate || flags.doall || flags.props) { /* * write final end record. NB: want to do this even if @@ -1392,10 +1386,6 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, */ dmu_replay_record_t drr = { 0 }; drr.drr_type = DRR_END; - if (holdsnaps) { - (void) zfs_release_range(zhp, fromsnap, tosnap, - holdtag, flags.replicate); - } if (write(outfd, &drr, sizeof (drr)) == -1) { return (zfs_standard_error(zhp->zfs_hdl, errno, errbuf)); @@ -1407,6 +1397,8 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, stderr_out: err = zfs_standard_error(zhp->zfs_hdl, err, errbuf); err_out: + if (cleanup_fd != -1) + VERIFY(0 == close(cleanup_fd)); if (flags.dedup) { (void) pthread_cancel(tid); (void) pthread_join(tid, NULL); @@ -1992,7 +1984,7 @@ again: static int zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname, recvflags_t flags, dmu_replay_record_t *drr, zio_cksum_t *zc, - char **top_zfs) + char **top_zfs, int cleanup_fd, uint64_t *action_handlep) { nvlist_t *stream_nv = NULL; avl_tree_t *stream_avl = NULL; @@ -2158,7 +2150,8 @@ zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname, * recv_skip() and return 0). */ error = zfs_receive_impl(hdl, destname, flags, fd, - sendfs, stream_nv, stream_avl, top_zfs); + sendfs, stream_nv, stream_avl, top_zfs, cleanup_fd, + action_handlep); if (error == ENODATA) { error = 0; break; @@ -2281,7 +2274,8 @@ static int zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, recvflags_t flags, dmu_replay_record_t *drr, dmu_replay_record_t *drr_noswap, const char *sendfs, - nvlist_t *stream_nv, avl_tree_t *stream_avl, char **top_zfs) + nvlist_t *stream_nv, avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd, + uint64_t *action_handlep) { zfs_cmd_t zc = { 0 }; time_t begin_time; @@ -2609,6 +2603,8 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, zc.zc_nvlist_dst = (uint64_t)(uintptr_t)prop_errbuf; zc.zc_nvlist_dst_size = sizeof (prop_errbuf); + zc.zc_cleanup_fd = cleanup_fd; + zc.zc_action_handle = *action_handlep; err = ioctl_err = zfs_ioctl(hdl, ZFS_IOC_RECV, &zc); ioctl_errno = errno; @@ -2796,6 +2792,8 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, if (err || ioctl_err) return (-1); + *action_handlep = zc.zc_action_handle; + if (flags.verbose) { char buf1[64]; char buf2[64]; @@ -2816,7 +2814,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, static int zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap, recvflags_t flags, int infd, const char *sendfs, nvlist_t *stream_nv, avl_tree_t *stream_avl, - char **top_zfs) + char **top_zfs, int cleanup_fd, uint64_t *action_handlep) { int err; dmu_replay_record_t drr, drr_noswap; @@ -2909,12 +2907,12 @@ zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap, recvflags_t flags, } return (zfs_receive_one(hdl, infd, tosnap, flags, &drr, &drr_noswap, sendfs, stream_nv, stream_avl, - top_zfs)); + top_zfs, cleanup_fd, action_handlep)); } else { assert(DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) == DMU_COMPOUNDSTREAM); return (zfs_receive_package(hdl, infd, tosnap, flags, - &drr, &zcksum, top_zfs)); + &drr, &zcksum, top_zfs, cleanup_fd, action_handlep)); } } @@ -2930,9 +2928,16 @@ zfs_receive(libzfs_handle_t *hdl, const char *tosnap, recvflags_t flags, { char *top_zfs = NULL; int err; + int cleanup_fd; + uint64_t action_handle = 0; + + cleanup_fd = open(ZFS_DEV, O_RDWR|O_EXCL); + VERIFY(cleanup_fd >= 0); err = zfs_receive_impl(hdl, tosnap, flags, infd, NULL, NULL, - stream_avl, &top_zfs); + stream_avl, &top_zfs, cleanup_fd, &action_handle); + + VERIFY(0 == close(cleanup_fd)); if (err == 0 && !flags.nomount && top_zfs) { zfs_handle_t *zhp; |
