devmapper.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  1. package devmapper
  2. /*
  3. #cgo LDFLAGS: -L. -ldevmapper
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7. #include <libdevmapper.h>
  8. #include <linux/loop.h>
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include <fcntl.h>
  12. #include <sys/ioctl.h>
  13. #include <linux/fs.h>
  14. #include <errno.h>
  15. #ifndef LOOP_CTL_GET_FREE
  16. #define LOOP_CTL_GET_FREE 0x4C82
  17. #endif
  18. // FIXME: this could easily be rewritten in go
  19. char* attach_loop_device(const char *filename, int *loop_fd_out)
  20. {
  21. struct loop_info64 loopinfo = {0};
  22. struct stat st;
  23. char buf[64];
  24. int i, loop_fd, fd, start_index;
  25. char* loopname;
  26. *loop_fd_out = -1;
  27. start_index = 0;
  28. fd = open("/dev/loop-control", O_RDONLY);
  29. if (fd >= 0) {
  30. start_index = ioctl(fd, LOOP_CTL_GET_FREE);
  31. close(fd);
  32. if (start_index < 0)
  33. start_index = 0;
  34. }
  35. fd = open(filename, O_RDWR);
  36. if (fd < 0) {
  37. perror("open");
  38. return NULL;
  39. }
  40. loop_fd = -1;
  41. for (i = start_index ; loop_fd < 0 ; i++ ) {
  42. if (sprintf(buf, "/dev/loop%d", i) < 0) {
  43. close(fd);
  44. return NULL;
  45. }
  46. if (stat(buf, &st)) {
  47. if (!S_ISBLK(st.st_mode)) {
  48. fprintf(stderr, "[error] Loopback device %s is not a block device.\n", buf);
  49. } else if (errno == ENOENT) {
  50. fprintf(stderr, "[error] There are no more loopback device available.\n");
  51. } else {
  52. fprintf(stderr, "[error] Unkown error trying to stat the loopback device %s (errno: %d).\n", buf, errno);
  53. }
  54. close(fd);
  55. return NULL;
  56. }
  57. loop_fd = open(buf, O_RDWR);
  58. if (loop_fd < 0 && errno == ENOENT) {
  59. fprintf(stderr, "[error] The loopback device %s does not exists.\n", buf);
  60. close(fd);
  61. return NULL;
  62. } else if (loop_fd < 0) {
  63. fprintf(stderr, "[error] Unkown error openning the loopback device %s. (errno: %d)\n", buf, errno);
  64. continue;
  65. }
  66. if (ioctl(loop_fd, LOOP_SET_FD, (void *)(size_t)fd) < 0) {
  67. int errsv = errno;
  68. close(loop_fd);
  69. loop_fd = -1;
  70. if (errsv != EBUSY) {
  71. close(fd);
  72. fprintf(stderr, "cannot set up loopback device %s: %s", buf, strerror(errsv));
  73. return NULL;
  74. }
  75. continue;
  76. }
  77. close(fd);
  78. strncpy((char*)loopinfo.lo_file_name, buf, LO_NAME_SIZE);
  79. loopinfo.lo_offset = 0;
  80. loopinfo.lo_flags = LO_FLAGS_AUTOCLEAR;
  81. if (ioctl(loop_fd, LOOP_SET_STATUS64, &loopinfo) < 0) {
  82. perror("ioctl LOOP_SET_STATUS64");
  83. if (ioctl(loop_fd, LOOP_CLR_FD, 0) < 0) {
  84. perror("ioctl LOOP_CLR_FD");
  85. }
  86. close(loop_fd);
  87. fprintf (stderr, "cannot set up loopback device info");
  88. return (NULL);
  89. }
  90. loopname = strdup(buf);
  91. if (loopname == NULL) {
  92. close(loop_fd);
  93. return (NULL);
  94. }
  95. *loop_fd_out = loop_fd;
  96. return (loopname);
  97. }
  98. return (NULL);
  99. }
  100. static int64_t get_block_size(int fd)
  101. {
  102. uint64_t size;
  103. if (ioctl(fd, BLKGETSIZE64, &size) == -1)
  104. return -1;
  105. return ((int64_t)size);
  106. }
  107. extern void DevmapperLogCallback(int level, char *file, int line, int dm_errno_or_class, char *str);
  108. static void
  109. log_cb(int level, const char *file, int line,
  110. int dm_errno_or_class, const char *f, ...)
  111. {
  112. char buffer[256];
  113. va_list ap;
  114. va_start(ap, f);
  115. vsnprintf(buffer, 256, f, ap);
  116. va_end(ap);
  117. DevmapperLogCallback(level, (char *)file, line, dm_errno_or_class, buffer);
  118. }
  119. static void
  120. log_with_errno_init ()
  121. {
  122. dm_log_with_errno_init(log_cb);
  123. }
  124. */
  125. import "C"
  126. import (
  127. "errors"
  128. "fmt"
  129. "github.com/dotcloud/docker/utils"
  130. "os"
  131. "runtime"
  132. "syscall"
  133. "unsafe"
  134. )
  135. type DevmapperLogger interface {
  136. log(level int, file string, line int, dmError int, message string)
  137. }
  138. const (
  139. DeviceCreate TaskType = iota
  140. DeviceReload
  141. DeviceRemove
  142. DeviceRemoveAll
  143. DeviceSuspend
  144. DeviceResume
  145. DeviceInfo
  146. DeviceDeps
  147. DeviceRename
  148. DeviceVersion
  149. DeviceStatus
  150. DeviceTable
  151. DeviceWaitevent
  152. DeviceList
  153. DeviceClear
  154. DeviceMknodes
  155. DeviceListVersions
  156. DeviceTargetMsg
  157. DeviceSetGeometry
  158. )
  159. const (
  160. AddNodeOnResume AddNodeType = iota
  161. AddNodeOnCreate
  162. )
  163. var (
  164. ErrTaskRun = errors.New("dm_task_run failed")
  165. ErrTaskSetName = errors.New("dm_task_set_name failed")
  166. ErrTaskSetMessage = errors.New("dm_task_set_message failed")
  167. ErrTaskSetAddNode = errors.New("dm_task_set_add_node failed")
  168. ErrTaskSetRO = errors.New("dm_task_set_ro failed")
  169. ErrTaskAddTarget = errors.New("dm_task_add_target failed")
  170. ErrGetDriverVersion = errors.New("dm_task_get_driver_version failed")
  171. ErrAttachLoopbackDevice = errors.New("loopback mounting failed")
  172. ErrGetBlockSize = errors.New("Can't get block size")
  173. ErrUdevWait = errors.New("wait on udev cookie failed")
  174. ErrSetDevDir = errors.New("dm_set_dev_dir failed")
  175. ErrGetLibraryVersion = errors.New("dm_get_library_version failed")
  176. ErrCreateRemoveTask = errors.New("Can't create task of type DeviceRemove")
  177. ErrRunRemoveDevice = errors.New("running removeDevice failed")
  178. )
  179. type (
  180. Task struct {
  181. unmanaged *C.struct_dm_task
  182. }
  183. Info struct {
  184. Exists int
  185. Suspended int
  186. LiveTable int
  187. InactiveTable int
  188. OpenCount int32
  189. EventNr uint32
  190. Major uint32
  191. Minor uint32
  192. ReadOnly int
  193. TargetCount int32
  194. }
  195. TaskType int
  196. AddNodeType int
  197. )
  198. func (t *Task) destroy() {
  199. if t != nil {
  200. C.dm_task_destroy(t.unmanaged)
  201. runtime.SetFinalizer(t, nil)
  202. }
  203. }
  204. func TaskCreate(tasktype TaskType) *Task {
  205. c_task := C.dm_task_create(C.int(tasktype))
  206. if c_task == nil {
  207. return nil
  208. }
  209. task := &Task{unmanaged: c_task}
  210. runtime.SetFinalizer(task, (*Task).destroy)
  211. return task
  212. }
  213. func (t *Task) Run() error {
  214. if res := C.dm_task_run(t.unmanaged); res != 1 {
  215. return ErrTaskRun
  216. }
  217. return nil
  218. }
  219. func (t *Task) SetName(name string) error {
  220. c_name := C.CString(name)
  221. defer free(c_name)
  222. if res := C.dm_task_set_name(t.unmanaged, c_name); res != 1 {
  223. return ErrTaskSetName
  224. }
  225. return nil
  226. }
  227. func (t *Task) SetMessage(message string) error {
  228. c_message := C.CString(message)
  229. defer free(c_message)
  230. if res := C.dm_task_set_message(t.unmanaged, c_message); res != 1 {
  231. return ErrTaskSetMessage
  232. }
  233. return nil
  234. }
  235. func (t *Task) SetSector(sector uint64) error {
  236. if res := C.dm_task_set_sector(t.unmanaged, C.uint64_t(sector)); res != 1 {
  237. return ErrTaskSetAddNode
  238. }
  239. return nil
  240. }
  241. func (t *Task) SetCookie(cookie *uint32, flags uint16) error {
  242. c_cookie := C.uint32_t(*cookie)
  243. if res := C.dm_task_set_cookie(t.unmanaged, &c_cookie, C.uint16_t(flags)); res != 1 {
  244. return ErrTaskSetAddNode
  245. }
  246. *cookie = uint32(c_cookie)
  247. return nil
  248. }
  249. func (t *Task) SetAddNode(add_node AddNodeType) error {
  250. if res := C.dm_task_set_add_node(t.unmanaged, C.dm_add_node_t(add_node)); res != 1 {
  251. return ErrTaskSetAddNode
  252. }
  253. return nil
  254. }
  255. func (t *Task) SetRo() error {
  256. if res := C.dm_task_set_ro(t.unmanaged); res != 1 {
  257. return ErrTaskSetRO
  258. }
  259. return nil
  260. }
  261. func (t *Task) AddTarget(start uint64, size uint64, ttype string, params string) error {
  262. c_ttype := C.CString(ttype)
  263. defer free(c_ttype)
  264. c_params := C.CString(params)
  265. defer free(c_params)
  266. if res := C.dm_task_add_target(t.unmanaged, C.uint64_t(start), C.uint64_t(size), c_ttype, c_params); res != 1 {
  267. return ErrTaskAddTarget
  268. }
  269. return nil
  270. }
  271. func (t *Task) GetDriverVersion() (string, error) {
  272. buffer := C.CString(string(make([]byte, 128)))
  273. defer free(buffer)
  274. if res := C.dm_task_get_driver_version(t.unmanaged, buffer, 128); res != 1 {
  275. return "", ErrGetDriverVersion
  276. }
  277. return C.GoString(buffer), nil
  278. }
  279. func (t *Task) GetInfo() (*Info, error) {
  280. c_info := C.struct_dm_info{}
  281. if res := C.dm_task_get_info(t.unmanaged, &c_info); res != 1 {
  282. return nil, ErrGetDriverVersion
  283. }
  284. return &Info{
  285. Exists: int(c_info.exists),
  286. Suspended: int(c_info.suspended),
  287. LiveTable: int(c_info.live_table),
  288. InactiveTable: int(c_info.inactive_table),
  289. OpenCount: int32(c_info.open_count),
  290. EventNr: uint32(c_info.event_nr),
  291. Major: uint32(c_info.major),
  292. Minor: uint32(c_info.minor),
  293. ReadOnly: int(c_info.read_only),
  294. TargetCount: int32(c_info.target_count),
  295. }, nil
  296. }
  297. func (t *Task) GetNextTarget(next uintptr) (uintptr, uint64, uint64, string, string) {
  298. var (
  299. c_start, c_length C.uint64_t
  300. c_target_type, c_params *C.char
  301. )
  302. nextp := C.dm_get_next_target(t.unmanaged, unsafe.Pointer(next), &c_start, &c_length, &c_target_type, &c_params)
  303. return uintptr(nextp), uint64(c_start), uint64(c_length), C.GoString(c_target_type), C.GoString(c_params)
  304. }
  305. func AttachLoopDevice(filename string) (*os.File, error) {
  306. c_filename := C.CString(filename)
  307. defer free(c_filename)
  308. var fd C.int
  309. res := C.attach_loop_device(c_filename, &fd)
  310. if res == nil {
  311. if os.Getenv("DEBUG") != "" {
  312. C.perror(C.CString(fmt.Sprintf("[debug] Error attach_loop_device(%s, %d)", filename, int(fd))))
  313. }
  314. return nil, ErrAttachLoopbackDevice
  315. }
  316. defer free(res)
  317. return os.NewFile(uintptr(fd), C.GoString(res)), nil
  318. }
  319. func getBlockSize(fd uintptr) int {
  320. var size uint64
  321. if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, C.BLKGETSIZE64, uintptr(unsafe.Pointer(&size))); err != 0 {
  322. utils.Debugf("Error ioctl: %s", err)
  323. return -1
  324. }
  325. return int(size)
  326. }
  327. func GetBlockDeviceSize(file *os.File) (uint64, error) {
  328. if size := C.get_block_size(C.int(file.Fd())); size == -1 {
  329. return 0, ErrGetBlockSize
  330. } else {
  331. return uint64(size), nil
  332. }
  333. }
  334. func UdevWait(cookie uint32) error {
  335. if res := C.dm_udev_wait(C.uint32_t(cookie)); res != 1 {
  336. utils.Debugf("Failed to wait on udev cookie %d", cookie)
  337. return ErrUdevWait
  338. }
  339. return nil
  340. }
  341. func LogInitVerbose(level int) {
  342. C.dm_log_init_verbose(C.int(level))
  343. }
  344. var dmLogger DevmapperLogger = nil
  345. func logInit(logger DevmapperLogger) {
  346. dmLogger = logger
  347. C.log_with_errno_init()
  348. }
  349. func SetDevDir(dir string) error {
  350. c_dir := C.CString(dir)
  351. defer free(c_dir)
  352. if res := C.dm_set_dev_dir(c_dir); res != 1 {
  353. utils.Debugf("Error dm_set_dev_dir")
  354. return ErrSetDevDir
  355. }
  356. return nil
  357. }
  358. func GetLibraryVersion() (string, error) {
  359. buffer := C.CString(string(make([]byte, 128)))
  360. defer free(buffer)
  361. if res := C.dm_get_library_version(buffer, 128); res != 1 {
  362. return "", ErrGetLibraryVersion
  363. }
  364. return C.GoString(buffer), nil
  365. }
  366. // Useful helper for cleanup
  367. func RemoveDevice(name string) error {
  368. task := TaskCreate(DeviceRemove)
  369. if task == nil {
  370. return ErrCreateRemoveTask
  371. }
  372. if err := task.SetName(name); err != nil {
  373. utils.Debugf("Can't set task name %s", name)
  374. return err
  375. }
  376. if err := task.Run(); err != nil {
  377. return ErrRunRemoveDevice
  378. }
  379. return nil
  380. }
  381. func free(p *C.char) {
  382. C.free(unsafe.Pointer(p))
  383. }
  384. // This is the programmatic example of "dmsetup create"
  385. func createPool(poolName string, dataFile *os.File, metadataFile *os.File) error {
  386. task, err := createTask(DeviceCreate, poolName)
  387. if task == nil {
  388. return err
  389. }
  390. size, err := GetBlockDeviceSize(dataFile)
  391. if err != nil {
  392. return fmt.Errorf("Can't get data size")
  393. }
  394. params := metadataFile.Name() + " " + dataFile.Name() + " 128 32768"
  395. if err := task.AddTarget(0, size/512, "thin-pool", params); err != nil {
  396. return fmt.Errorf("Can't add target")
  397. }
  398. var cookie uint32 = 0
  399. if err := task.SetCookie(&cookie, 0); err != nil {
  400. return fmt.Errorf("Can't set cookie")
  401. }
  402. if err := task.Run(); err != nil {
  403. return fmt.Errorf("Error running DeviceCreate")
  404. }
  405. UdevWait(cookie)
  406. return nil
  407. }
  408. func createTask(t TaskType, name string) (*Task, error) {
  409. task := TaskCreate(t)
  410. if task == nil {
  411. return nil, fmt.Errorf("Can't create task of type %d", int(t))
  412. }
  413. if err := task.SetName(name); err != nil {
  414. return nil, fmt.Errorf("Can't set task name %s", name)
  415. }
  416. return task, nil
  417. }
  418. func getInfo(name string) (*Info, error) {
  419. task, err := createTask(DeviceInfo, name)
  420. if task == nil {
  421. return nil, err
  422. }
  423. if err := task.Run(); err != nil {
  424. return nil, err
  425. }
  426. return task.GetInfo()
  427. }
  428. func getStatus(name string) (uint64, uint64, string, string, error) {
  429. task, err := createTask(DeviceStatus, name)
  430. if task == nil {
  431. utils.Debugf("getStatus: Error createTask: %s", err)
  432. return 0, 0, "", "", err
  433. }
  434. if err := task.Run(); err != nil {
  435. utils.Debugf("getStatus: Error Run: %s", err)
  436. return 0, 0, "", "", err
  437. }
  438. devinfo, err := task.GetInfo()
  439. if err != nil {
  440. utils.Debugf("getStatus: Error GetInfo: %s", err)
  441. return 0, 0, "", "", err
  442. }
  443. if devinfo.Exists == 0 {
  444. utils.Debugf("getStatus: Non existing device %s", name)
  445. return 0, 0, "", "", fmt.Errorf("Non existing device %s", name)
  446. }
  447. _, start, length, target_type, params := task.GetNextTarget(0)
  448. return start, length, target_type, params, nil
  449. }
  450. func setTransactionId(poolName string, oldId uint64, newId uint64) error {
  451. task, err := createTask(DeviceTargetMsg, poolName)
  452. if task == nil {
  453. return err
  454. }
  455. if err := task.SetSector(0); err != nil {
  456. return fmt.Errorf("Can't set sector")
  457. }
  458. if err := task.SetMessage(fmt.Sprintf("set_transaction_id %d %d", oldId, newId)); err != nil {
  459. return fmt.Errorf("Can't set message")
  460. }
  461. if err := task.Run(); err != nil {
  462. return fmt.Errorf("Error running setTransactionId")
  463. }
  464. return nil
  465. }
  466. func suspendDevice(name string) error {
  467. task, err := createTask(DeviceSuspend, name)
  468. if task == nil {
  469. return err
  470. }
  471. if err := task.Run(); err != nil {
  472. return fmt.Errorf("Error running DeviceSuspend")
  473. }
  474. return nil
  475. }
  476. func resumeDevice(name string) error {
  477. task, err := createTask(DeviceResume, name)
  478. if task == nil {
  479. return err
  480. }
  481. var cookie uint32 = 0
  482. if err := task.SetCookie(&cookie, 0); err != nil {
  483. return fmt.Errorf("Can't set cookie")
  484. }
  485. if err := task.Run(); err != nil {
  486. return fmt.Errorf("Error running DeviceSuspend")
  487. }
  488. UdevWait(cookie)
  489. return nil
  490. }
  491. func createDevice(poolName string, deviceId int) error {
  492. utils.Debugf("[devmapper] createDevice(poolName=%v, deviceId=%v)", poolName, deviceId)
  493. task, err := createTask(DeviceTargetMsg, poolName)
  494. if task == nil {
  495. return err
  496. }
  497. if err := task.SetSector(0); err != nil {
  498. return fmt.Errorf("Can't set sector")
  499. }
  500. if err := task.SetMessage(fmt.Sprintf("create_thin %d", deviceId)); err != nil {
  501. return fmt.Errorf("Can't set message")
  502. }
  503. if err := task.Run(); err != nil {
  504. return fmt.Errorf("Error running createDevice")
  505. }
  506. return nil
  507. }
  508. func deleteDevice(poolName string, deviceId int) error {
  509. task, err := createTask(DeviceTargetMsg, poolName)
  510. if task == nil {
  511. return err
  512. }
  513. if err := task.SetSector(0); err != nil {
  514. return fmt.Errorf("Can't set sector")
  515. }
  516. if err := task.SetMessage(fmt.Sprintf("delete %d", deviceId)); err != nil {
  517. return fmt.Errorf("Can't set message")
  518. }
  519. if err := task.Run(); err != nil {
  520. return fmt.Errorf("Error running deleteDevice")
  521. }
  522. return nil
  523. }
  524. func removeDevice(name string) error {
  525. utils.Debugf("[devmapper] removeDevice START")
  526. defer utils.Debugf("[devmapper] removeDevice END")
  527. task, err := createTask(DeviceRemove, name)
  528. if task == nil {
  529. return err
  530. }
  531. if err = task.Run(); err != nil {
  532. return fmt.Errorf("Error running removeDevice")
  533. }
  534. return nil
  535. }
  536. func activateDevice(poolName string, name string, deviceId int, size uint64) error {
  537. task, err := createTask(DeviceCreate, name)
  538. if task == nil {
  539. return err
  540. }
  541. params := fmt.Sprintf("%s %d", poolName, deviceId)
  542. if err := task.AddTarget(0, size/512, "thin", params); err != nil {
  543. return fmt.Errorf("Can't add target")
  544. }
  545. if err := task.SetAddNode(AddNodeOnCreate); err != nil {
  546. return fmt.Errorf("Can't add node")
  547. }
  548. var cookie uint32 = 0
  549. if err := task.SetCookie(&cookie, 0); err != nil {
  550. return fmt.Errorf("Can't set cookie")
  551. }
  552. if err := task.Run(); err != nil {
  553. return fmt.Errorf("Error running DeviceCreate")
  554. }
  555. UdevWait(cookie)
  556. return nil
  557. }
  558. func (devices *DeviceSet) createSnapDevice(poolName string, deviceId int, baseName string, baseDeviceId int) error {
  559. devinfo, _ := getInfo(baseName)
  560. doSuspend := devinfo != nil && devinfo.Exists != 0
  561. if doSuspend {
  562. if err := suspendDevice(baseName); err != nil {
  563. return err
  564. }
  565. }
  566. task, err := createTask(DeviceTargetMsg, poolName)
  567. if task == nil {
  568. if doSuspend {
  569. resumeDevice(baseName)
  570. }
  571. return err
  572. }
  573. if err := task.SetSector(0); err != nil {
  574. if doSuspend {
  575. resumeDevice(baseName)
  576. }
  577. return fmt.Errorf("Can't set sector")
  578. }
  579. if err := task.SetMessage(fmt.Sprintf("create_snap %d %d", deviceId, baseDeviceId)); err != nil {
  580. if doSuspend {
  581. resumeDevice(baseName)
  582. }
  583. return fmt.Errorf("Can't set message")
  584. }
  585. if err := task.Run(); err != nil {
  586. if doSuspend {
  587. resumeDevice(baseName)
  588. }
  589. return fmt.Errorf("Error running DeviceCreate")
  590. }
  591. if doSuspend {
  592. if err := resumeDevice(baseName); err != nil {
  593. return err
  594. }
  595. }
  596. return nil
  597. }