devmapper.go 12 KB

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