From a7726113d41e863772580d62ba116c635183f9c9 Mon Sep 17 00:00:00 2001 From: Faruk Kasumovic Date: Fri, 4 Aug 2017 13:12:41 +0200 Subject: [PATCH] - Bug fixes for send recv, and mount --- sendrecv.go | 4 +-- zfs.c | 22 ++++++++++----- zfs.go | 78 ++++++++++++++++++++++++++++++++++++++++------------- 3 files changed, 77 insertions(+), 27 deletions(-) diff --git a/sendrecv.go b/sendrecv.go index d78eb5b..89937de 100644 --- a/sendrecv.go +++ b/sendrecv.go @@ -246,7 +246,7 @@ func (d *Dataset) SendSize(FromName string, flags SendFlags) (size uint64, err e return } -func (d *Dataset) Receive(name string, inf *os.File, flags RecvFlags) (err error) { +func (d *Dataset) Receive(inf *os.File, flags RecvFlags) (err error) { var dpath string if dpath, err = d.Path(); err != nil { return @@ -259,7 +259,7 @@ func (d *Dataset) Receive(name string, inf *os.File, flags RecvFlags) (err error defer C.nvlist_free(props) cflags := to_recvflags_t(&flags) defer C.free(unsafe.Pointer(cflags)) - dest := C.CString(dpath + "/" + name) + dest := C.CString(dpath) defer C.free(unsafe.Pointer(dest)) ec := C.zfs_receive(C.libzfsHandle, dest, cflags, C.int(inf.Fd()), nil) if ec != 0 { diff --git a/zfs.c b/zfs.c index 96bd849..09ba095 100644 --- a/zfs.c +++ b/zfs.c @@ -19,8 +19,13 @@ dataset_list_t *create_dataset_list_item() { } void dataset_list_close(dataset_list_t *list) { - zfs_close(list->zh); - free(list); + if (list != NULL) { + if (list->zh != NULL) { + zfs_close(list->zh); + list->zh = NULL; + } + free(list); + } // dataset_list_free(list); } @@ -132,15 +137,20 @@ int dataset_rename(dataset_list_ptr dataset, const char* new_name, boolean_t rec } const char *dataset_is_mounted(dataset_list_ptr dataset){ - char *mp; + char *mp = NULL; + // zfs_is_mounted returns B_TRUE or B_FALSE if (0 != zfs_is_mounted(dataset->zh, &mp)) { - return NULL; + return mp; } - return mp; + return NULL; } int dataset_mount(dataset_list_ptr dataset, const char *options, int flags) { - return zfs_mount(dataset->zh, options, flags); + if ( 0 < strlen(options)) { + return zfs_mount(dataset->zh, options, flags); + } else { + return zfs_mount(dataset->zh, NULL, flags); + } } int dataset_unmount(dataset_list_ptr dataset, int flags) { diff --git a/zfs.go b/zfs.go index 18caade..b76b0d8 100644 --- a/zfs.go +++ b/zfs.go @@ -10,6 +10,7 @@ import "C" import ( "errors" "fmt" + "strings" "unsafe" ) @@ -114,7 +115,6 @@ func DatasetOpen(path string) (d Dataset, err error) { d.Properties = make(map[Prop]Property) err = d.ReloadProperties() if err != nil { - println("reload properties failed") return } err = d.openChildren() @@ -165,10 +165,9 @@ func DatasetCreate(path string, dtype DatasetType, // Close close dataset and all its recursive children datasets (close handle // and cleanup dataset object/s from memory) func (d *Dataset) Close() { - if d.list != nil && d.list.zh != nil { - C.dataset_list_close(d.list) - d.list = nil - } + // path, _ := d.Path() + C.dataset_list_close(d.list) + d.list = nil for _, cd := range d.Children { cd.Close() } @@ -204,18 +203,51 @@ func (d *Dataset) Destroy(Defer bool) (err error) { // DestroyRecursive recursively destroy children of dataset and dataset. func (d *Dataset) DestroyRecursive() (err error) { - if len(d.Children) > 0 { - for _, c := range d.Children { - if err = c.DestroyRecursive(); err != nil { - return - } - // close handle to destroyed child dataset - c.Close() - } - // clear closed children array - d.Children = make([]Dataset, 0) + var path string + if path, err = d.Path(); err != nil { + return + } + if !strings.Contains(path, "@") { // not snapshot + if len(d.Children) > 0 { + for _, c := range d.Children { + if err = c.DestroyRecursive(); err != nil { + return + } + // close handle to destroyed child dataset + c.Close() + } + // clear closed children array + d.Children = make([]Dataset, 0) + } + err = d.Destroy(false) + } else { + var parent Dataset + tmp := strings.Split(path, "@") + ppath, snapname := tmp[0], tmp[1] + if parent, err = DatasetOpen(ppath); err != nil { + return + } + defer parent.Close() + if len(parent.Children) > 0 { + for _, c := range parent.Children { + if path, err = c.Path(); err != nil { + return + } + if strings.Contains(path, "@") { + continue // skip other snapshots + } + if c, err = DatasetOpen(path + "@" + snapname); err != nil { + continue + } + if err = c.DestroyRecursive(); err != nil { + c.Close() + return + } + c.Close() + } + } + err = d.Destroy(false) } - err = d.Destroy(false) return } @@ -241,6 +273,8 @@ func (d *Dataset) ReloadProperties() (err error) { return } d.Properties = make(map[Prop]Property) + Global.Mtx.Lock() + defer Global.Mtx.Unlock() for prop := DatasetPropType; prop < DatasetNumProps; prop++ { plist := C.read_dataset_property(d.list, C.int(prop)) if plist == nil { @@ -434,6 +468,7 @@ func (d *Dataset) IsMounted() (mounted bool, where string) { // defer C.free(mp) if mounted = (mp != nil); mounted { where = C.GoString(mp) + C.free(unsafe.Pointer(mp)) } return } @@ -471,10 +506,15 @@ func (d *Dataset) UnmountAll(flags int) (err error) { err = errors.New(msgDatasetIsNil) return } - if ec := C.dataset_unmountall(d.list, C.int(flags)); ec != 0 { - err = LastError() + // This is implemented recursive because zfs_unmountall() didn't work + if len(d.Children) > 0 { + for _, c := range d.Children { + if err = c.UnmountAll(flags); err != nil { + return + } + } } - return + return d.Unmount(flags) } // DatasetPropertyToName convert property to name