devmapper.go 13 KB

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