]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Fix filesystem destroy with receive_resume_token
authorRoman Strashkin <roman.strashkin@nexenta.com>
Tue, 12 Jul 2016 17:53:53 +0000 (20:53 +0300)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 15 Jul 2016 22:34:46 +0000 (15:34 -0700)
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 <roman.strashkin@nexenta.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #4818

module/zfs/zfs_ioctl.c

index 37104fb9fbdd09f749a4a095a6347b6c8d0e71d0..3cd3628ce616db37d39f2cd58857f8f3dacef064 100644 (file)
@@ -25,7 +25,7 @@
  * Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
  * Portions Copyright 2012 Pawel Jakub Dawidek <pawel@dawidek.net>
  * 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);
 }