github.com/resin-io/docker@v1.13.1/pkg/devicemapper/devmapper_wrapper.go (about) 1 // +build linux 2 3 package devicemapper 4 5 /* 6 #cgo LDFLAGS: -L. -ldevmapper 7 #include <libdevmapper.h> 8 #include <linux/fs.h> // FIXME: present only for BLKGETSIZE64, maybe we can remove it? 9 10 // FIXME: Can't we find a way to do the logging in pure Go? 11 extern void DevmapperLogCallback(int level, char *file, int line, int dm_errno_or_class, char *str); 12 13 static void log_cb(int level, const char *file, int line, int dm_errno_or_class, const char *f, ...) 14 { 15 char buffer[256]; 16 va_list ap; 17 18 va_start(ap, f); 19 vsnprintf(buffer, 256, f, ap); 20 va_end(ap); 21 22 DevmapperLogCallback(level, (char *)file, line, dm_errno_or_class, buffer); 23 } 24 25 static void log_with_errno_init() 26 { 27 dm_log_with_errno_init(log_cb); 28 } 29 */ 30 import "C" 31 32 import ( 33 "reflect" 34 "unsafe" 35 ) 36 37 type ( 38 cdmTask C.struct_dm_task 39 ) 40 41 // IOCTL consts 42 const ( 43 BlkGetSize64 = C.BLKGETSIZE64 44 BlkDiscard = C.BLKDISCARD 45 ) 46 47 // Devicemapper cookie flags. 48 const ( 49 DmUdevDisableSubsystemRulesFlag = C.DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG 50 DmUdevDisableDiskRulesFlag = C.DM_UDEV_DISABLE_DISK_RULES_FLAG 51 DmUdevDisableOtherRulesFlag = C.DM_UDEV_DISABLE_OTHER_RULES_FLAG 52 DmUdevDisableLibraryFallback = C.DM_UDEV_DISABLE_LIBRARY_FALLBACK 53 ) 54 55 // DeviceMapper mapped functions. 56 var ( 57 DmGetLibraryVersion = dmGetLibraryVersionFct 58 DmGetNextTarget = dmGetNextTargetFct 59 DmLogInitVerbose = dmLogInitVerboseFct 60 DmSetDevDir = dmSetDevDirFct 61 DmTaskAddTarget = dmTaskAddTargetFct 62 DmTaskCreate = dmTaskCreateFct 63 DmTaskDestroy = dmTaskDestroyFct 64 DmTaskGetDeps = dmTaskGetDepsFct 65 DmTaskGetInfo = dmTaskGetInfoFct 66 DmTaskGetDriverVersion = dmTaskGetDriverVersionFct 67 DmTaskRun = dmTaskRunFct 68 DmTaskSetAddNode = dmTaskSetAddNodeFct 69 DmTaskSetCookie = dmTaskSetCookieFct 70 DmTaskSetMessage = dmTaskSetMessageFct 71 DmTaskSetName = dmTaskSetNameFct 72 DmTaskSetRo = dmTaskSetRoFct 73 DmTaskSetSector = dmTaskSetSectorFct 74 DmUdevWait = dmUdevWaitFct 75 DmUdevSetSyncSupport = dmUdevSetSyncSupportFct 76 DmUdevGetSyncSupport = dmUdevGetSyncSupportFct 77 DmCookieSupported = dmCookieSupportedFct 78 LogWithErrnoInit = logWithErrnoInitFct 79 DmTaskDeferredRemove = dmTaskDeferredRemoveFct 80 DmTaskGetInfoWithDeferred = dmTaskGetInfoWithDeferredFct 81 ) 82 83 func free(p *C.char) { 84 C.free(unsafe.Pointer(p)) 85 } 86 87 func dmTaskDestroyFct(task *cdmTask) { 88 C.dm_task_destroy((*C.struct_dm_task)(task)) 89 } 90 91 func dmTaskCreateFct(taskType int) *cdmTask { 92 return (*cdmTask)(C.dm_task_create(C.int(taskType))) 93 } 94 95 func dmTaskRunFct(task *cdmTask) int { 96 ret, _ := C.dm_task_run((*C.struct_dm_task)(task)) 97 return int(ret) 98 } 99 100 func dmTaskSetNameFct(task *cdmTask, name string) int { 101 Cname := C.CString(name) 102 defer free(Cname) 103 104 return int(C.dm_task_set_name((*C.struct_dm_task)(task), Cname)) 105 } 106 107 func dmTaskSetMessageFct(task *cdmTask, message string) int { 108 Cmessage := C.CString(message) 109 defer free(Cmessage) 110 111 return int(C.dm_task_set_message((*C.struct_dm_task)(task), Cmessage)) 112 } 113 114 func dmTaskSetSectorFct(task *cdmTask, sector uint64) int { 115 return int(C.dm_task_set_sector((*C.struct_dm_task)(task), C.uint64_t(sector))) 116 } 117 118 func dmTaskSetCookieFct(task *cdmTask, cookie *uint, flags uint16) int { 119 cCookie := C.uint32_t(*cookie) 120 defer func() { 121 *cookie = uint(cCookie) 122 }() 123 return int(C.dm_task_set_cookie((*C.struct_dm_task)(task), &cCookie, C.uint16_t(flags))) 124 } 125 126 func dmTaskSetAddNodeFct(task *cdmTask, addNode AddNodeType) int { 127 return int(C.dm_task_set_add_node((*C.struct_dm_task)(task), C.dm_add_node_t(addNode))) 128 } 129 130 func dmTaskSetRoFct(task *cdmTask) int { 131 return int(C.dm_task_set_ro((*C.struct_dm_task)(task))) 132 } 133 134 func dmTaskAddTargetFct(task *cdmTask, 135 start, size uint64, ttype, params string) int { 136 137 Cttype := C.CString(ttype) 138 defer free(Cttype) 139 140 Cparams := C.CString(params) 141 defer free(Cparams) 142 143 return int(C.dm_task_add_target((*C.struct_dm_task)(task), C.uint64_t(start), C.uint64_t(size), Cttype, Cparams)) 144 } 145 146 func dmTaskGetDepsFct(task *cdmTask) *Deps { 147 Cdeps := C.dm_task_get_deps((*C.struct_dm_task)(task)) 148 if Cdeps == nil { 149 return nil 150 } 151 152 // golang issue: https://github.com/golang/go/issues/11925 153 hdr := reflect.SliceHeader{ 154 Data: uintptr(unsafe.Pointer(uintptr(unsafe.Pointer(Cdeps)) + unsafe.Sizeof(*Cdeps))), 155 Len: int(Cdeps.count), 156 Cap: int(Cdeps.count), 157 } 158 devices := *(*[]C.uint64_t)(unsafe.Pointer(&hdr)) 159 160 deps := &Deps{ 161 Count: uint32(Cdeps.count), 162 Filler: uint32(Cdeps.filler), 163 } 164 for _, device := range devices { 165 deps.Device = append(deps.Device, uint64(device)) 166 } 167 return deps 168 } 169 170 func dmTaskGetInfoFct(task *cdmTask, info *Info) int { 171 Cinfo := C.struct_dm_info{} 172 defer func() { 173 info.Exists = int(Cinfo.exists) 174 info.Suspended = int(Cinfo.suspended) 175 info.LiveTable = int(Cinfo.live_table) 176 info.InactiveTable = int(Cinfo.inactive_table) 177 info.OpenCount = int32(Cinfo.open_count) 178 info.EventNr = uint32(Cinfo.event_nr) 179 info.Major = uint32(Cinfo.major) 180 info.Minor = uint32(Cinfo.minor) 181 info.ReadOnly = int(Cinfo.read_only) 182 info.TargetCount = int32(Cinfo.target_count) 183 }() 184 return int(C.dm_task_get_info((*C.struct_dm_task)(task), &Cinfo)) 185 } 186 187 func dmTaskGetDriverVersionFct(task *cdmTask) string { 188 buffer := C.malloc(128) 189 defer C.free(buffer) 190 res := C.dm_task_get_driver_version((*C.struct_dm_task)(task), (*C.char)(buffer), 128) 191 if res == 0 { 192 return "" 193 } 194 return C.GoString((*C.char)(buffer)) 195 } 196 197 func dmGetNextTargetFct(task *cdmTask, next unsafe.Pointer, start, length *uint64, target, params *string) unsafe.Pointer { 198 var ( 199 Cstart, Clength C.uint64_t 200 CtargetType, Cparams *C.char 201 ) 202 defer func() { 203 *start = uint64(Cstart) 204 *length = uint64(Clength) 205 *target = C.GoString(CtargetType) 206 *params = C.GoString(Cparams) 207 }() 208 209 nextp := C.dm_get_next_target((*C.struct_dm_task)(task), next, &Cstart, &Clength, &CtargetType, &Cparams) 210 return nextp 211 } 212 213 func dmUdevSetSyncSupportFct(syncWithUdev int) { 214 (C.dm_udev_set_sync_support(C.int(syncWithUdev))) 215 } 216 217 func dmUdevGetSyncSupportFct() int { 218 return int(C.dm_udev_get_sync_support()) 219 } 220 221 func dmUdevWaitFct(cookie uint) int { 222 return int(C.dm_udev_wait(C.uint32_t(cookie))) 223 } 224 225 func dmCookieSupportedFct() int { 226 return int(C.dm_cookie_supported()) 227 } 228 229 func dmLogInitVerboseFct(level int) { 230 C.dm_log_init_verbose(C.int(level)) 231 } 232 233 func logWithErrnoInitFct() { 234 C.log_with_errno_init() 235 } 236 237 func dmSetDevDirFct(dir string) int { 238 Cdir := C.CString(dir) 239 defer free(Cdir) 240 241 return int(C.dm_set_dev_dir(Cdir)) 242 } 243 244 func dmGetLibraryVersionFct(version *string) int { 245 buffer := C.CString(string(make([]byte, 128))) 246 defer free(buffer) 247 defer func() { 248 *version = C.GoString(buffer) 249 }() 250 return int(C.dm_get_library_version(buffer, 128)) 251 }