devmapper.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. // +build linux
  2. package devmapper
  3. import (
  4. "errors"
  5. "fmt"
  6. "os"
  7. "runtime"
  8. "syscall"
  9. "github.com/docker/docker/pkg/log"
  10. )
  11. type DevmapperLogger interface {
  12. log(level int, file string, line int, dmError int, message string)
  13. }
  14. const (
  15. DeviceCreate TaskType = iota
  16. DeviceReload
  17. DeviceRemove
  18. DeviceRemoveAll
  19. DeviceSuspend
  20. DeviceResume
  21. DeviceInfo
  22. DeviceDeps
  23. DeviceRename
  24. DeviceVersion
  25. DeviceStatus
  26. DeviceTable
  27. DeviceWaitevent
  28. DeviceList
  29. DeviceClear
  30. DeviceMknodes
  31. DeviceListVersions
  32. DeviceTargetMsg
  33. DeviceSetGeometry
  34. )
  35. const (
  36. AddNodeOnResume AddNodeType = iota
  37. AddNodeOnCreate
  38. )
  39. var (
  40. ErrTaskRun = errors.New("dm_task_run failed")
  41. ErrTaskSetName = errors.New("dm_task_set_name failed")
  42. ErrTaskSetMessage = errors.New("dm_task_set_message failed")
  43. ErrTaskSetAddNode = errors.New("dm_task_set_add_node failed")
  44. ErrTaskSetRo = errors.New("dm_task_set_ro failed")
  45. ErrTaskAddTarget = errors.New("dm_task_add_target failed")
  46. ErrTaskSetSector = errors.New("dm_task_set_sector failed")
  47. ErrTaskGetInfo = errors.New("dm_task_get_info failed")
  48. ErrTaskGetDriverVersion = errors.New("dm_task_get_driver_version failed")
  49. ErrTaskSetCookie = errors.New("dm_task_set_cookie failed")
  50. ErrNilCookie = errors.New("cookie ptr can't be nil")
  51. ErrAttachLoopbackDevice = errors.New("loopback mounting failed")
  52. ErrGetBlockSize = errors.New("Can't get block size")
  53. ErrUdevWait = errors.New("wait on udev cookie failed")
  54. ErrSetDevDir = errors.New("dm_set_dev_dir failed")
  55. ErrGetLibraryVersion = errors.New("dm_get_library_version failed")
  56. ErrCreateRemoveTask = errors.New("Can't create task of type DeviceRemove")
  57. ErrRunRemoveDevice = errors.New("running removeDevice failed")
  58. ErrInvalidAddNode = errors.New("Invalide AddNoce type")
  59. ErrGetLoopbackBackingFile = errors.New("Unable to get loopback backing file")
  60. ErrLoopbackSetCapacity = errors.New("Unable set loopback capacity")
  61. ErrBusy = errors.New("Device is Busy")
  62. dmSawBusy bool
  63. dmSawExist bool
  64. )
  65. type (
  66. Task struct {
  67. unmanaged *CDmTask
  68. }
  69. Info struct {
  70. Exists int
  71. Suspended int
  72. LiveTable int
  73. InactiveTable int
  74. OpenCount int32
  75. EventNr uint32
  76. Major uint32
  77. Minor uint32
  78. ReadOnly int
  79. TargetCount int32
  80. }
  81. TaskType int
  82. AddNodeType int
  83. )
  84. func (t *Task) destroy() {
  85. if t != nil {
  86. DmTaskDestroy(t.unmanaged)
  87. runtime.SetFinalizer(t, nil)
  88. }
  89. }
  90. func TaskCreate(tasktype TaskType) *Task {
  91. Ctask := DmTaskCreate(int(tasktype))
  92. if Ctask == nil {
  93. return nil
  94. }
  95. task := &Task{unmanaged: Ctask}
  96. runtime.SetFinalizer(task, (*Task).destroy)
  97. return task
  98. }
  99. func (t *Task) Run() error {
  100. if res := DmTaskRun(t.unmanaged); res != 1 {
  101. return ErrTaskRun
  102. }
  103. return nil
  104. }
  105. func (t *Task) SetName(name string) error {
  106. if res := DmTaskSetName(t.unmanaged, name); res != 1 {
  107. return ErrTaskSetName
  108. }
  109. return nil
  110. }
  111. func (t *Task) SetMessage(message string) error {
  112. if res := DmTaskSetMessage(t.unmanaged, message); res != 1 {
  113. return ErrTaskSetMessage
  114. }
  115. return nil
  116. }
  117. func (t *Task) SetSector(sector uint64) error {
  118. if res := DmTaskSetSector(t.unmanaged, sector); res != 1 {
  119. return ErrTaskSetSector
  120. }
  121. return nil
  122. }
  123. func (t *Task) SetCookie(cookie *uint, flags uint16) error {
  124. if cookie == nil {
  125. return ErrNilCookie
  126. }
  127. if res := DmTaskSetCookie(t.unmanaged, cookie, flags); res != 1 {
  128. return ErrTaskSetCookie
  129. }
  130. return nil
  131. }
  132. func (t *Task) SetAddNode(addNode AddNodeType) error {
  133. if addNode != AddNodeOnResume && addNode != AddNodeOnCreate {
  134. return ErrInvalidAddNode
  135. }
  136. if res := DmTaskSetAddNode(t.unmanaged, addNode); res != 1 {
  137. return ErrTaskSetAddNode
  138. }
  139. return nil
  140. }
  141. func (t *Task) SetRo() error {
  142. if res := DmTaskSetRo(t.unmanaged); res != 1 {
  143. return ErrTaskSetRo
  144. }
  145. return nil
  146. }
  147. func (t *Task) AddTarget(start, size uint64, ttype, params string) error {
  148. if res := DmTaskAddTarget(t.unmanaged, start, size,
  149. ttype, params); res != 1 {
  150. return ErrTaskAddTarget
  151. }
  152. return nil
  153. }
  154. func (t *Task) GetInfo() (*Info, error) {
  155. info := &Info{}
  156. if res := DmTaskGetInfo(t.unmanaged, info); res != 1 {
  157. return nil, ErrTaskGetInfo
  158. }
  159. return info, nil
  160. }
  161. func (t *Task) GetDriverVersion() (string, error) {
  162. res := DmTaskGetDriverVersion(t.unmanaged)
  163. if res == "" {
  164. return "", ErrTaskGetDriverVersion
  165. }
  166. return res, nil
  167. }
  168. func (t *Task) GetNextTarget(next uintptr) (nextPtr uintptr, start uint64,
  169. length uint64, targetType string, params string) {
  170. return DmGetNextTarget(t.unmanaged, next, &start, &length,
  171. &targetType, &params),
  172. start, length, targetType, params
  173. }
  174. func getLoopbackBackingFile(file *os.File) (uint64, uint64, error) {
  175. loopInfo, err := ioctlLoopGetStatus64(file.Fd())
  176. if err != nil {
  177. log.Errorf("Error get loopback backing file: %s", err)
  178. return 0, 0, ErrGetLoopbackBackingFile
  179. }
  180. return loopInfo.loDevice, loopInfo.loInode, nil
  181. }
  182. func LoopbackSetCapacity(file *os.File) error {
  183. if err := ioctlLoopSetCapacity(file.Fd(), 0); err != nil {
  184. log.Errorf("Error loopbackSetCapacity: %s", err)
  185. return ErrLoopbackSetCapacity
  186. }
  187. return nil
  188. }
  189. func FindLoopDeviceFor(file *os.File) *os.File {
  190. stat, err := file.Stat()
  191. if err != nil {
  192. return nil
  193. }
  194. targetInode := stat.Sys().(*syscall.Stat_t).Ino
  195. targetDevice := stat.Sys().(*syscall.Stat_t).Dev
  196. for i := 0; true; i++ {
  197. path := fmt.Sprintf("/dev/loop%d", i)
  198. file, err := os.OpenFile(path, os.O_RDWR, 0)
  199. if err != nil {
  200. if os.IsNotExist(err) {
  201. return nil
  202. }
  203. // Ignore all errors until the first not-exist
  204. // we want to continue looking for the file
  205. continue
  206. }
  207. dev, inode, err := getLoopbackBackingFile(file)
  208. if err == nil && dev == targetDevice && inode == targetInode {
  209. return file
  210. }
  211. file.Close()
  212. }
  213. return nil
  214. }
  215. func UdevWait(cookie uint) error {
  216. if res := DmUdevWait(cookie); res != 1 {
  217. log.Debugf("Failed to wait on udev cookie %d", cookie)
  218. return ErrUdevWait
  219. }
  220. return nil
  221. }
  222. func LogInitVerbose(level int) {
  223. DmLogInitVerbose(level)
  224. }
  225. var dmLogger DevmapperLogger = nil
  226. func logInit(logger DevmapperLogger) {
  227. dmLogger = logger
  228. LogWithErrnoInit()
  229. }
  230. func SetDevDir(dir string) error {
  231. if res := DmSetDevDir(dir); res != 1 {
  232. log.Debugf("Error dm_set_dev_dir")
  233. return ErrSetDevDir
  234. }
  235. return nil
  236. }
  237. func GetLibraryVersion() (string, error) {
  238. var version string
  239. if res := DmGetLibraryVersion(&version); res != 1 {
  240. return "", ErrGetLibraryVersion
  241. }
  242. return version, nil
  243. }
  244. // Useful helper for cleanup
  245. func RemoveDevice(name string) error {
  246. task := TaskCreate(DeviceRemove)
  247. if task == nil {
  248. return ErrCreateRemoveTask
  249. }
  250. if err := task.SetName(name); err != nil {
  251. log.Debugf("Can't set task name %s", name)
  252. return err
  253. }
  254. if err := task.Run(); err != nil {
  255. return ErrRunRemoveDevice
  256. }
  257. return nil
  258. }
  259. func GetBlockDeviceSize(file *os.File) (uint64, error) {
  260. size, err := ioctlBlkGetSize64(file.Fd())
  261. if err != nil {
  262. log.Errorf("Error getblockdevicesize: %s", err)
  263. return 0, ErrGetBlockSize
  264. }
  265. return uint64(size), nil
  266. }
  267. func BlockDeviceDiscard(path string) error {
  268. file, err := os.OpenFile(path, os.O_RDWR, 0)
  269. if err != nil {
  270. return err
  271. }
  272. defer file.Close()
  273. size, err := GetBlockDeviceSize(file)
  274. if err != nil {
  275. return err
  276. }
  277. if err := ioctlBlkDiscard(file.Fd(), 0, size); err != nil {
  278. return err
  279. }
  280. // Without this sometimes the remove of the device that happens after
  281. // discard fails with EBUSY.
  282. syscall.Sync()
  283. return nil
  284. }
  285. // This is the programmatic example of "dmsetup create"
  286. func createPool(poolName string, dataFile, metadataFile *os.File, poolBlockSize uint32) error {
  287. task, err := createTask(DeviceCreate, poolName)
  288. if task == nil {
  289. return err
  290. }
  291. size, err := GetBlockDeviceSize(dataFile)
  292. if err != nil {
  293. return fmt.Errorf("Can't get data size %s", err)
  294. }
  295. params := fmt.Sprintf("%s %s %d 32768 1 skip_block_zeroing", metadataFile.Name(), dataFile.Name(), poolBlockSize)
  296. if err := task.AddTarget(0, size/512, "thin-pool", params); err != nil {
  297. return fmt.Errorf("Can't add target %s", err)
  298. }
  299. var cookie uint = 0
  300. if err := task.SetCookie(&cookie, 0); err != nil {
  301. return fmt.Errorf("Can't set cookie %s", err)
  302. }
  303. if err := task.Run(); err != nil {
  304. return fmt.Errorf("Error running DeviceCreate (createPool) %s", err)
  305. }
  306. UdevWait(cookie)
  307. return nil
  308. }
  309. func reloadPool(poolName string, dataFile, metadataFile *os.File, poolBlockSize uint32) error {
  310. task, err := createTask(DeviceReload, poolName)
  311. if task == nil {
  312. return err
  313. }
  314. size, err := GetBlockDeviceSize(dataFile)
  315. if err != nil {
  316. return fmt.Errorf("Can't get data size %s", err)
  317. }
  318. params := fmt.Sprintf("%s %s %d 32768 1 skip_block_zeroing", metadataFile.Name(), dataFile.Name(), poolBlockSize)
  319. if err := task.AddTarget(0, size/512, "thin-pool", params); err != nil {
  320. return fmt.Errorf("Can't add target %s", err)
  321. }
  322. if err := task.Run(); err != nil {
  323. return fmt.Errorf("Error running DeviceCreate %s", err)
  324. }
  325. return nil
  326. }
  327. func createTask(t TaskType, name string) (*Task, error) {
  328. task := TaskCreate(t)
  329. if task == nil {
  330. return nil, fmt.Errorf("Can't create task of type %d", int(t))
  331. }
  332. if err := task.SetName(name); err != nil {
  333. return nil, fmt.Errorf("Can't set task name %s", name)
  334. }
  335. return task, nil
  336. }
  337. func getInfo(name string) (*Info, error) {
  338. task, err := createTask(DeviceInfo, name)
  339. if task == nil {
  340. return nil, err
  341. }
  342. if err := task.Run(); err != nil {
  343. return nil, err
  344. }
  345. return task.GetInfo()
  346. }
  347. func getDriverVersion() (string, error) {
  348. task := TaskCreate(DeviceVersion)
  349. if task == nil {
  350. return "", fmt.Errorf("Can't create DeviceVersion task")
  351. }
  352. if err := task.Run(); err != nil {
  353. return "", err
  354. }
  355. return task.GetDriverVersion()
  356. }
  357. func getStatus(name string) (uint64, uint64, string, string, error) {
  358. task, err := createTask(DeviceStatus, name)
  359. if task == nil {
  360. log.Debugf("getStatus: Error createTask: %s", err)
  361. return 0, 0, "", "", err
  362. }
  363. if err := task.Run(); err != nil {
  364. log.Debugf("getStatus: Error Run: %s", err)
  365. return 0, 0, "", "", err
  366. }
  367. devinfo, err := task.GetInfo()
  368. if err != nil {
  369. log.Debugf("getStatus: Error GetInfo: %s", err)
  370. return 0, 0, "", "", err
  371. }
  372. if devinfo.Exists == 0 {
  373. log.Debugf("getStatus: Non existing device %s", name)
  374. return 0, 0, "", "", fmt.Errorf("Non existing device %s", name)
  375. }
  376. _, start, length, targetType, params := task.GetNextTarget(0)
  377. return start, length, targetType, params, nil
  378. }
  379. func setTransactionId(poolName string, oldId uint64, newId uint64) error {
  380. task, err := createTask(DeviceTargetMsg, poolName)
  381. if task == nil {
  382. return err
  383. }
  384. if err := task.SetSector(0); err != nil {
  385. return fmt.Errorf("Can't set sector %s", err)
  386. }
  387. if err := task.SetMessage(fmt.Sprintf("set_transaction_id %d %d", oldId, newId)); err != nil {
  388. return fmt.Errorf("Can't set message %s", err)
  389. }
  390. if err := task.Run(); err != nil {
  391. return fmt.Errorf("Error running setTransactionId %s", err)
  392. }
  393. return nil
  394. }
  395. func suspendDevice(name string) error {
  396. task, err := createTask(DeviceSuspend, name)
  397. if task == nil {
  398. return err
  399. }
  400. if err := task.Run(); err != nil {
  401. return fmt.Errorf("Error running DeviceSuspend %s", err)
  402. }
  403. return nil
  404. }
  405. func resumeDevice(name string) error {
  406. task, err := createTask(DeviceResume, name)
  407. if task == nil {
  408. return err
  409. }
  410. var cookie uint = 0
  411. if err := task.SetCookie(&cookie, 0); err != nil {
  412. return fmt.Errorf("Can't set cookie %s", err)
  413. }
  414. if err := task.Run(); err != nil {
  415. return fmt.Errorf("Error running DeviceResume %s", err)
  416. }
  417. UdevWait(cookie)
  418. return nil
  419. }
  420. func createDevice(poolName string, deviceId *int) error {
  421. log.Debugf("[devmapper] createDevice(poolName=%v, deviceId=%v)", poolName, *deviceId)
  422. for {
  423. task, err := createTask(DeviceTargetMsg, poolName)
  424. if task == nil {
  425. return err
  426. }
  427. if err := task.SetSector(0); err != nil {
  428. return fmt.Errorf("Can't set sector %s", err)
  429. }
  430. if err := task.SetMessage(fmt.Sprintf("create_thin %d", *deviceId)); err != nil {
  431. return fmt.Errorf("Can't set message %s", err)
  432. }
  433. dmSawExist = false
  434. if err := task.Run(); err != nil {
  435. if dmSawExist {
  436. // Already exists, try next id
  437. *deviceId++
  438. continue
  439. }
  440. return fmt.Errorf("Error running createDevice %s", err)
  441. }
  442. break
  443. }
  444. return nil
  445. }
  446. func deleteDevice(poolName string, deviceId int) error {
  447. task, err := createTask(DeviceTargetMsg, poolName)
  448. if task == nil {
  449. return err
  450. }
  451. if err := task.SetSector(0); err != nil {
  452. return fmt.Errorf("Can't set sector %s", err)
  453. }
  454. if err := task.SetMessage(fmt.Sprintf("delete %d", deviceId)); err != nil {
  455. return fmt.Errorf("Can't set message %s", err)
  456. }
  457. if err := task.Run(); err != nil {
  458. return fmt.Errorf("Error running deleteDevice %s", err)
  459. }
  460. return nil
  461. }
  462. func removeDevice(name string) error {
  463. log.Debugf("[devmapper] removeDevice START")
  464. defer log.Debugf("[devmapper] removeDevice END")
  465. task, err := createTask(DeviceRemove, name)
  466. if task == nil {
  467. return err
  468. }
  469. dmSawBusy = false
  470. if err = task.Run(); err != nil {
  471. if dmSawBusy {
  472. return ErrBusy
  473. }
  474. return fmt.Errorf("Error running removeDevice %s", err)
  475. }
  476. return nil
  477. }
  478. func activateDevice(poolName string, name string, deviceId int, size uint64) error {
  479. task, err := createTask(DeviceCreate, name)
  480. if task == nil {
  481. return err
  482. }
  483. params := fmt.Sprintf("%s %d", poolName, deviceId)
  484. if err := task.AddTarget(0, size/512, "thin", params); err != nil {
  485. return fmt.Errorf("Can't add target %s", err)
  486. }
  487. if err := task.SetAddNode(AddNodeOnCreate); err != nil {
  488. return fmt.Errorf("Can't add node %s", err)
  489. }
  490. var cookie uint = 0
  491. if err := task.SetCookie(&cookie, 0); err != nil {
  492. return fmt.Errorf("Can't set cookie %s", err)
  493. }
  494. if err := task.Run(); err != nil {
  495. return fmt.Errorf("Error running DeviceCreate (activateDevice) %s", err)
  496. }
  497. UdevWait(cookie)
  498. return nil
  499. }
  500. func createSnapDevice(poolName string, deviceId *int, baseName string, baseDeviceId int) error {
  501. devinfo, _ := getInfo(baseName)
  502. doSuspend := devinfo != nil && devinfo.Exists != 0
  503. if doSuspend {
  504. if err := suspendDevice(baseName); err != nil {
  505. return err
  506. }
  507. }
  508. for {
  509. task, err := createTask(DeviceTargetMsg, poolName)
  510. if task == nil {
  511. if doSuspend {
  512. resumeDevice(baseName)
  513. }
  514. return err
  515. }
  516. if err := task.SetSector(0); err != nil {
  517. if doSuspend {
  518. resumeDevice(baseName)
  519. }
  520. return fmt.Errorf("Can't set sector %s", err)
  521. }
  522. if err := task.SetMessage(fmt.Sprintf("create_snap %d %d", *deviceId, baseDeviceId)); err != nil {
  523. if doSuspend {
  524. resumeDevice(baseName)
  525. }
  526. return fmt.Errorf("Can't set message %s", err)
  527. }
  528. dmSawExist = false
  529. if err := task.Run(); err != nil {
  530. if dmSawExist {
  531. // Already exists, try next id
  532. *deviceId++
  533. continue
  534. }
  535. if doSuspend {
  536. resumeDevice(baseName)
  537. }
  538. return fmt.Errorf("Error running DeviceCreate (createSnapDevice) %s", err)
  539. }
  540. break
  541. }
  542. if doSuspend {
  543. if err := resumeDevice(baseName); err != nil {
  544. return err
  545. }
  546. }
  547. return nil
  548. }