diff options
author | Roman Strashkin <[email protected]> | 2016-07-12 20:53:53 +0300 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2016-07-15 15:34:46 -0700 |
commit | 1b87e0f53249a17f2fbb1d5ca725e65add391ace (patch) | |
tree | 22a45ad7198504860e5d216766e84f739e5b2b45 /module/zfs/zfs_ioctl.c | |
parent | 35a76a0366372d89a0f1ac3cebd5bc7646aadec3 (diff) |
Fix filesystem destroy with receive_resume_token
It is possible that the given DS may have hidden child (%recv)
datasets - "leftovers" resulting from the previously interrupted
'zfs receieve'. Try to remove the hidden child (%recv) and after
that try to remove the target dataset. If the hidden child
(%recv) does not exist the original error (EEXIST) will be returned.
Signed-off-by: Roman Strashkin <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes #4818
Diffstat (limited to 'module/zfs/zfs_ioctl.c')
-rw-r--r-- | module/zfs/zfs_ioctl.c | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index 37104fb9f..3cd3628ce 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -25,7 +25,7 @@ * Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved. * Portions Copyright 2012 Pawel Jakub Dawidek <[email protected]> * Copyright (c) 2012, Joyent, Inc. All rights reserved. - * Copyright 2015 Nexenta Systems, Inc. All rights reserved. + * Copyright 2016 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2014, Joyent, Inc. All rights reserved. * Copyright (c) 2011, 2015 by Delphix. All rights reserved. * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. @@ -3568,10 +3568,37 @@ zfs_ioc_destroy(zfs_cmd_t *zc) return (err); } - if (strchr(zc->zc_name, '@')) + if (strchr(zc->zc_name, '@')) { err = dsl_destroy_snapshot(zc->zc_name, zc->zc_defer_destroy); - else + } else { err = dsl_destroy_head(zc->zc_name); + if (err == EEXIST) { + /* + * It is possible that the given DS may have + * hidden child (%recv) datasets - "leftovers" + * resulting from the previously interrupted + * 'zfs receive'. + * + * 6 extra bytes for /%recv + */ + char namebuf[ZFS_MAX_DATASET_NAME_LEN + 6]; + + (void) snprintf(namebuf, sizeof (namebuf), + "%s/%s", zc->zc_name, recv_clone_name); + + /* + * Try to remove the hidden child (%recv) and after + * that try to remove the target dataset. + * If the hidden child (%recv) does not exist + * the original error (EEXIST) will be returned + */ + err = dsl_destroy_head(namebuf); + if (err == 0) + err = dsl_destroy_head(zc->zc_name); + else if (err == ENOENT) + err = EEXIST; + } + } return (err); } |