deviceset.go 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085
  1. // +build linux,amd64
  2. package devmapper
  3. import (
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "io/ioutil"
  9. "path"
  10. "path/filepath"
  11. "strconv"
  12. "strings"
  13. "sync"
  14. "syscall"
  15. "time"
  16. "github.com/dotcloud/docker/pkg/label"
  17. "github.com/dotcloud/docker/utils"
  18. )
  19. var (
  20. DefaultDataLoopbackSize int64 = 100 * 1024 * 1024 * 1024
  21. DefaultMetaDataLoopbackSize int64 = 2 * 1024 * 1024 * 1024
  22. DefaultBaseFsSize uint64 = 10 * 1024 * 1024 * 1024
  23. )
  24. type DevInfo struct {
  25. Hash string `json:"-"`
  26. DeviceId int `json:"device_id"`
  27. Size uint64 `json:"size"`
  28. TransactionId uint64 `json:"transaction_id"`
  29. Initialized bool `json:"initialized"`
  30. devices *DeviceSet `json:"-"`
  31. mountCount int `json:"-"`
  32. mountPath string `json:"-"`
  33. // The global DeviceSet lock guarantees that we serialize all
  34. // the calls to libdevmapper (which is not threadsafe), but we
  35. // sometimes release that lock while sleeping. In that case
  36. // this per-device lock is still held, protecting against
  37. // other accesses to the device that we're doing the wait on.
  38. //
  39. // WARNING: In order to avoid AB-BA deadlocks when releasing
  40. // the global lock while holding the per-device locks all
  41. // device locks must be aquired *before* the device lock, and
  42. // multiple device locks should be aquired parent before child.
  43. lock sync.Mutex `json:"-"`
  44. }
  45. type MetaData struct {
  46. Devices map[string]*DevInfo `json:devices`
  47. devicesLock sync.Mutex `json:"-"` // Protects all read/writes to Devices map
  48. }
  49. type DeviceSet struct {
  50. MetaData
  51. sync.Mutex // Protects Devices map and serializes calls into libdevmapper
  52. root string
  53. devicePrefix string
  54. TransactionId uint64
  55. NewTransactionId uint64
  56. nextFreeDevice int
  57. sawBusy bool
  58. }
  59. type DiskUsage struct {
  60. Used uint64
  61. Total uint64
  62. }
  63. type Status struct {
  64. PoolName string
  65. DataLoopback string
  66. MetadataLoopback string
  67. Data DiskUsage
  68. Metadata DiskUsage
  69. SectorSize uint64
  70. }
  71. type DevStatus struct {
  72. DeviceId int
  73. Size uint64
  74. TransactionId uint64
  75. SizeInSectors uint64
  76. MappedSectors uint64
  77. HighestMappedSector uint64
  78. }
  79. func getDevName(name string) string {
  80. return "/dev/mapper/" + name
  81. }
  82. func (info *DevInfo) Name() string {
  83. hash := info.Hash
  84. if hash == "" {
  85. hash = "base"
  86. }
  87. return fmt.Sprintf("%s-%s", info.devices.devicePrefix, hash)
  88. }
  89. func (info *DevInfo) DevName() string {
  90. return getDevName(info.Name())
  91. }
  92. func (devices *DeviceSet) loopbackDir() string {
  93. return path.Join(devices.root, "devicemapper")
  94. }
  95. func (devices *DeviceSet) jsonFile() string {
  96. return path.Join(devices.loopbackDir(), "json")
  97. }
  98. func (devices *DeviceSet) getPoolName() string {
  99. return devices.devicePrefix + "-pool"
  100. }
  101. func (devices *DeviceSet) getPoolDevName() string {
  102. return getDevName(devices.getPoolName())
  103. }
  104. func (devices *DeviceSet) hasImage(name string) bool {
  105. dirname := devices.loopbackDir()
  106. filename := path.Join(dirname, name)
  107. _, err := osStat(filename)
  108. return err == nil
  109. }
  110. // ensureImage creates a sparse file of <size> bytes at the path
  111. // <root>/devicemapper/<name>.
  112. // If the file already exists, it does nothing.
  113. // Either way it returns the full path.
  114. func (devices *DeviceSet) ensureImage(name string, size int64) (string, error) {
  115. dirname := devices.loopbackDir()
  116. filename := path.Join(dirname, name)
  117. if err := osMkdirAll(dirname, 0700); err != nil && !osIsExist(err) {
  118. return "", err
  119. }
  120. if _, err := osStat(filename); err != nil {
  121. if !osIsNotExist(err) {
  122. return "", err
  123. }
  124. utils.Debugf("Creating loopback file %s for device-manage use", filename)
  125. file, err := osOpenFile(filename, osORdWr|osOCreate, 0600)
  126. if err != nil {
  127. return "", err
  128. }
  129. defer file.Close()
  130. if err = file.Truncate(size); err != nil {
  131. return "", err
  132. }
  133. }
  134. return filename, nil
  135. }
  136. func (devices *DeviceSet) allocateDeviceId() int {
  137. // TODO: Add smarter reuse of deleted devices
  138. id := devices.nextFreeDevice
  139. devices.nextFreeDevice = devices.nextFreeDevice + 1
  140. return id
  141. }
  142. func (devices *DeviceSet) allocateTransactionId() uint64 {
  143. devices.NewTransactionId = devices.NewTransactionId + 1
  144. return devices.NewTransactionId
  145. }
  146. func (devices *DeviceSet) saveMetadata() error {
  147. devices.devicesLock.Lock()
  148. jsonData, err := json.Marshal(devices.MetaData)
  149. devices.devicesLock.Unlock()
  150. if err != nil {
  151. return fmt.Errorf("Error encoding metadata to json: %s", err)
  152. }
  153. tmpFile, err := ioutil.TempFile(filepath.Dir(devices.jsonFile()), ".json")
  154. if err != nil {
  155. return fmt.Errorf("Error creating metadata file: %s", err)
  156. }
  157. n, err := tmpFile.Write(jsonData)
  158. if err != nil {
  159. return fmt.Errorf("Error writing metadata to %s: %s", tmpFile.Name(), err)
  160. }
  161. if n < len(jsonData) {
  162. return io.ErrShortWrite
  163. }
  164. if err := tmpFile.Sync(); err != nil {
  165. return fmt.Errorf("Error syncing metadata file %s: %s", tmpFile.Name(), err)
  166. }
  167. if err := tmpFile.Close(); err != nil {
  168. return fmt.Errorf("Error closing metadata file %s: %s", tmpFile.Name(), err)
  169. }
  170. if err := osRename(tmpFile.Name(), devices.jsonFile()); err != nil {
  171. return fmt.Errorf("Error committing metadata file %s: %s", tmpFile.Name(), err)
  172. }
  173. if devices.NewTransactionId != devices.TransactionId {
  174. if err = setTransactionId(devices.getPoolDevName(), devices.TransactionId, devices.NewTransactionId); err != nil {
  175. return fmt.Errorf("Error setting devmapper transition ID: %s", err)
  176. }
  177. devices.TransactionId = devices.NewTransactionId
  178. }
  179. return nil
  180. }
  181. func (devices *DeviceSet) lookupDevice(hash string) (*DevInfo, error) {
  182. devices.devicesLock.Lock()
  183. defer devices.devicesLock.Unlock()
  184. info := devices.Devices[hash]
  185. if info == nil {
  186. return nil, fmt.Errorf("Unknown device %s", hash)
  187. }
  188. return info, nil
  189. }
  190. func (devices *DeviceSet) registerDevice(id int, hash string, size uint64) (*DevInfo, error) {
  191. utils.Debugf("registerDevice(%v, %v)", id, hash)
  192. info := &DevInfo{
  193. Hash: hash,
  194. DeviceId: id,
  195. Size: size,
  196. TransactionId: devices.allocateTransactionId(),
  197. Initialized: false,
  198. devices: devices,
  199. }
  200. devices.devicesLock.Lock()
  201. devices.Devices[hash] = info
  202. devices.devicesLock.Unlock()
  203. if err := devices.saveMetadata(); err != nil {
  204. // Try to remove unused device
  205. devices.devicesLock.Lock()
  206. delete(devices.Devices, hash)
  207. devices.devicesLock.Unlock()
  208. return nil, err
  209. }
  210. return info, nil
  211. }
  212. func (devices *DeviceSet) activateDeviceIfNeeded(info *DevInfo) error {
  213. utils.Debugf("activateDeviceIfNeeded(%v)", info.Hash)
  214. if devinfo, _ := getInfo(info.Name()); devinfo != nil && devinfo.Exists != 0 {
  215. return nil
  216. }
  217. return activateDevice(devices.getPoolDevName(), info.Name(), info.DeviceId, info.Size)
  218. }
  219. func (devices *DeviceSet) createFilesystem(info *DevInfo) error {
  220. devname := info.DevName()
  221. err := execRun("mkfs.ext4", "-E", "discard,lazy_itable_init=0,lazy_journal_init=0", devname)
  222. if err != nil {
  223. err = execRun("mkfs.ext4", "-E", "discard,lazy_itable_init=0", devname)
  224. }
  225. if err != nil {
  226. utils.Debugf("\n--->Err: %s\n", err)
  227. return err
  228. }
  229. return nil
  230. }
  231. func (devices *DeviceSet) loadMetaData() error {
  232. utils.Debugf("loadMetadata()")
  233. defer utils.Debugf("loadMetadata END")
  234. _, _, _, params, err := getStatus(devices.getPoolName())
  235. if err != nil {
  236. utils.Debugf("\n--->Err: %s\n", err)
  237. return err
  238. }
  239. if _, err := fmt.Sscanf(params, "%d", &devices.TransactionId); err != nil {
  240. utils.Debugf("\n--->Err: %s\n", err)
  241. return err
  242. }
  243. devices.NewTransactionId = devices.TransactionId
  244. jsonData, err := ioutil.ReadFile(devices.jsonFile())
  245. if err != nil && !osIsNotExist(err) {
  246. utils.Debugf("\n--->Err: %s\n", err)
  247. return err
  248. }
  249. devices.MetaData.Devices = make(map[string]*DevInfo)
  250. if jsonData != nil {
  251. if err := json.Unmarshal(jsonData, &devices.MetaData); err != nil {
  252. utils.Debugf("\n--->Err: %s\n", err)
  253. return err
  254. }
  255. }
  256. for hash, d := range devices.Devices {
  257. d.Hash = hash
  258. d.devices = devices
  259. if d.DeviceId >= devices.nextFreeDevice {
  260. devices.nextFreeDevice = d.DeviceId + 1
  261. }
  262. // If the transaction id is larger than the actual one we lost the device due to some crash
  263. if d.TransactionId > devices.TransactionId {
  264. utils.Debugf("Removing lost device %s with id %d", hash, d.TransactionId)
  265. delete(devices.Devices, hash)
  266. }
  267. }
  268. return nil
  269. }
  270. func (devices *DeviceSet) setupBaseImage() error {
  271. oldInfo, _ := devices.lookupDevice("")
  272. if oldInfo != nil && oldInfo.Initialized {
  273. return nil
  274. }
  275. if oldInfo != nil && !oldInfo.Initialized {
  276. utils.Debugf("Removing uninitialized base image")
  277. if err := devices.deleteDevice(oldInfo); err != nil {
  278. utils.Debugf("\n--->Err: %s\n", err)
  279. return err
  280. }
  281. }
  282. utils.Debugf("Initializing base device-manager snapshot")
  283. id := devices.allocateDeviceId()
  284. // Create initial device
  285. if err := createDevice(devices.getPoolDevName(), id); err != nil {
  286. utils.Debugf("\n--->Err: %s\n", err)
  287. return err
  288. }
  289. utils.Debugf("Registering base device (id %v) with FS size %v", id, DefaultBaseFsSize)
  290. info, err := devices.registerDevice(id, "", DefaultBaseFsSize)
  291. if err != nil {
  292. _ = deleteDevice(devices.getPoolDevName(), id)
  293. utils.Debugf("\n--->Err: %s\n", err)
  294. return err
  295. }
  296. utils.Debugf("Creating filesystem on base device-manager snapshot")
  297. if err = devices.activateDeviceIfNeeded(info); err != nil {
  298. utils.Debugf("\n--->Err: %s\n", err)
  299. return err
  300. }
  301. if err := devices.createFilesystem(info); err != nil {
  302. utils.Debugf("\n--->Err: %s\n", err)
  303. return err
  304. }
  305. info.Initialized = true
  306. if err = devices.saveMetadata(); err != nil {
  307. info.Initialized = false
  308. utils.Debugf("\n--->Err: %s\n", err)
  309. return err
  310. }
  311. return nil
  312. }
  313. func setCloseOnExec(name string) {
  314. if fileInfos, _ := ioutil.ReadDir("/proc/self/fd"); fileInfos != nil {
  315. for _, i := range fileInfos {
  316. link, _ := osReadlink(filepath.Join("/proc/self/fd", i.Name()))
  317. if link == name {
  318. fd, err := strconv.Atoi(i.Name())
  319. if err == nil {
  320. sysCloseOnExec(fd)
  321. }
  322. }
  323. }
  324. }
  325. }
  326. func (devices *DeviceSet) log(level int, file string, line int, dmError int, message string) {
  327. if level >= 7 {
  328. return // Ignore _LOG_DEBUG
  329. }
  330. if strings.Contains(message, "busy") {
  331. devices.sawBusy = true
  332. }
  333. utils.Debugf("libdevmapper(%d): %s:%d (%d) %s", level, file, line, dmError, message)
  334. }
  335. func major(device uint64) uint64 {
  336. return (device >> 8) & 0xfff
  337. }
  338. func minor(device uint64) uint64 {
  339. return (device & 0xff) | ((device >> 12) & 0xfff00)
  340. }
  341. func (devices *DeviceSet) ResizePool(size int64) error {
  342. dirname := devices.loopbackDir()
  343. datafilename := path.Join(dirname, "data")
  344. metadatafilename := path.Join(dirname, "metadata")
  345. datafile, err := osOpenFile(datafilename, osORdWr, 0)
  346. if datafile == nil {
  347. return err
  348. }
  349. defer datafile.Close()
  350. fi, err := datafile.Stat()
  351. if fi == nil {
  352. return err
  353. }
  354. if fi.Size() > size {
  355. return fmt.Errorf("Can't shrink file")
  356. }
  357. dataloopback := FindLoopDeviceFor(datafile)
  358. if dataloopback == nil {
  359. return fmt.Errorf("Unable to find loopback mount for: %s", datafilename)
  360. }
  361. defer dataloopback.Close()
  362. metadatafile, err := osOpenFile(metadatafilename, osORdWr, 0)
  363. if metadatafile == nil {
  364. return err
  365. }
  366. defer metadatafile.Close()
  367. metadataloopback := FindLoopDeviceFor(metadatafile)
  368. if metadataloopback == nil {
  369. return fmt.Errorf("Unable to find loopback mount for: %s", metadatafilename)
  370. }
  371. defer metadataloopback.Close()
  372. // Grow loopback file
  373. if err := datafile.Truncate(size); err != nil {
  374. return fmt.Errorf("Unable to grow loopback file: %s", err)
  375. }
  376. // Reload size for loopback device
  377. if err := LoopbackSetCapacity(dataloopback); err != nil {
  378. return fmt.Errorf("Unable to update loopback capacity: %s", err)
  379. }
  380. // Suspend the pool
  381. if err := suspendDevice(devices.getPoolName()); err != nil {
  382. return fmt.Errorf("Unable to suspend pool: %s", err)
  383. }
  384. // Reload with the new block sizes
  385. if err := reloadPool(devices.getPoolName(), dataloopback, metadataloopback); err != nil {
  386. return fmt.Errorf("Unable to reload pool: %s", err)
  387. }
  388. // Resume the pool
  389. if err := resumeDevice(devices.getPoolName()); err != nil {
  390. return fmt.Errorf("Unable to resume pool: %s", err)
  391. }
  392. return nil
  393. }
  394. func (devices *DeviceSet) initDevmapper(doInit bool) error {
  395. logInit(devices)
  396. // Make sure the sparse images exist in <root>/devicemapper/data and
  397. // <root>/devicemapper/metadata
  398. hasData := devices.hasImage("data")
  399. hasMetadata := devices.hasImage("metadata")
  400. if !doInit && !hasData {
  401. return errors.New("Loopback data file not found")
  402. }
  403. if !doInit && !hasMetadata {
  404. return errors.New("Loopback metadata file not found")
  405. }
  406. createdLoopback := !hasData || !hasMetadata
  407. data, err := devices.ensureImage("data", DefaultDataLoopbackSize)
  408. if err != nil {
  409. utils.Debugf("Error device ensureImage (data): %s\n", err)
  410. return err
  411. }
  412. metadata, err := devices.ensureImage("metadata", DefaultMetaDataLoopbackSize)
  413. if err != nil {
  414. utils.Debugf("Error device ensureImage (metadata): %s\n", err)
  415. return err
  416. }
  417. // Set the device prefix from the device id and inode of the docker root dir
  418. st, err := osStat(devices.root)
  419. if err != nil {
  420. return fmt.Errorf("Error looking up dir %s: %s", devices.root, err)
  421. }
  422. sysSt := toSysStatT(st.Sys())
  423. // "reg-" stands for "regular file".
  424. // In the future we might use "dev-" for "device file", etc.
  425. // docker-maj,min[-inode] stands for:
  426. // - Managed by docker
  427. // - The target of this device is at major <maj> and minor <min>
  428. // - If <inode> is defined, use that file inside the device as a loopback image. Otherwise use the device itself.
  429. devices.devicePrefix = fmt.Sprintf("docker-%d:%d-%d", major(sysSt.Dev), minor(sysSt.Dev), sysSt.Ino)
  430. utils.Debugf("Generated prefix: %s", devices.devicePrefix)
  431. // Check for the existence of the device <prefix>-pool
  432. utils.Debugf("Checking for existence of the pool '%s'", devices.getPoolName())
  433. info, err := getInfo(devices.getPoolName())
  434. if info == nil {
  435. utils.Debugf("Error device getInfo: %s", err)
  436. return err
  437. }
  438. // It seems libdevmapper opens this without O_CLOEXEC, and go exec will not close files
  439. // that are not Close-on-exec, and lxc-start will die if it inherits any unexpected files,
  440. // so we add this badhack to make sure it closes itself
  441. setCloseOnExec("/dev/mapper/control")
  442. // If the pool doesn't exist, create it
  443. if info.Exists == 0 {
  444. utils.Debugf("Pool doesn't exist. Creating it.")
  445. dataFile, err := attachLoopDevice(data)
  446. if err != nil {
  447. utils.Debugf("\n--->Err: %s\n", err)
  448. return err
  449. }
  450. defer dataFile.Close()
  451. metadataFile, err := attachLoopDevice(metadata)
  452. if err != nil {
  453. utils.Debugf("\n--->Err: %s\n", err)
  454. return err
  455. }
  456. defer metadataFile.Close()
  457. if err := createPool(devices.getPoolName(), dataFile, metadataFile); err != nil {
  458. utils.Debugf("\n--->Err: %s\n", err)
  459. return err
  460. }
  461. }
  462. // If we didn't just create the data or metadata image, we need to
  463. // load the metadata from the existing file.
  464. if !createdLoopback {
  465. if err = devices.loadMetaData(); err != nil {
  466. utils.Debugf("\n--->Err: %s\n", err)
  467. return err
  468. }
  469. }
  470. // Setup the base image
  471. if doInit {
  472. if err := devices.setupBaseImage(); err != nil {
  473. utils.Debugf("Error device setupBaseImage: %s\n", err)
  474. return err
  475. }
  476. }
  477. return nil
  478. }
  479. func (devices *DeviceSet) AddDevice(hash, baseHash string) error {
  480. baseInfo, err := devices.lookupDevice(baseHash)
  481. if err != nil {
  482. return err
  483. }
  484. baseInfo.lock.Lock()
  485. defer baseInfo.lock.Unlock()
  486. devices.Lock()
  487. defer devices.Unlock()
  488. if info, _ := devices.lookupDevice(hash); info != nil {
  489. return fmt.Errorf("device %s already exists", hash)
  490. }
  491. deviceId := devices.allocateDeviceId()
  492. if err := devices.createSnapDevice(devices.getPoolDevName(), deviceId, baseInfo.Name(), baseInfo.DeviceId); err != nil {
  493. utils.Debugf("Error creating snap device: %s\n", err)
  494. return err
  495. }
  496. if _, err := devices.registerDevice(deviceId, hash, baseInfo.Size); err != nil {
  497. deleteDevice(devices.getPoolDevName(), deviceId)
  498. utils.Debugf("Error registering device: %s\n", err)
  499. return err
  500. }
  501. return nil
  502. }
  503. func (devices *DeviceSet) deleteDevice(info *DevInfo) error {
  504. // This is a workaround for the kernel not discarding block so
  505. // on the thin pool when we remove a thinp device, so we do it
  506. // manually
  507. if err := devices.activateDeviceIfNeeded(info); err == nil {
  508. if err := BlockDeviceDiscard(info.DevName()); err != nil {
  509. utils.Debugf("Error discarding block on device: %s (ignoring)\n", err)
  510. }
  511. }
  512. devinfo, _ := getInfo(info.Name())
  513. if devinfo != nil && devinfo.Exists != 0 {
  514. if err := devices.removeDeviceAndWait(info.Name()); err != nil {
  515. utils.Debugf("Error removing device: %s\n", err)
  516. return err
  517. }
  518. }
  519. if info.Initialized {
  520. info.Initialized = false
  521. if err := devices.saveMetadata(); err != nil {
  522. utils.Debugf("Error saving meta data: %s\n", err)
  523. return err
  524. }
  525. }
  526. if err := deleteDevice(devices.getPoolDevName(), info.DeviceId); err != nil {
  527. utils.Debugf("Error deleting device: %s\n", err)
  528. return err
  529. }
  530. devices.allocateTransactionId()
  531. devices.devicesLock.Lock()
  532. delete(devices.Devices, info.Hash)
  533. devices.devicesLock.Unlock()
  534. if err := devices.saveMetadata(); err != nil {
  535. devices.devicesLock.Lock()
  536. devices.Devices[info.Hash] = info
  537. devices.devicesLock.Unlock()
  538. utils.Debugf("Error saving meta data: %s\n", err)
  539. return err
  540. }
  541. return nil
  542. }
  543. func (devices *DeviceSet) DeleteDevice(hash string) error {
  544. info, err := devices.lookupDevice(hash)
  545. if err != nil {
  546. return err
  547. }
  548. info.lock.Lock()
  549. defer info.lock.Unlock()
  550. devices.Lock()
  551. defer devices.Unlock()
  552. return devices.deleteDevice(info)
  553. }
  554. func (devices *DeviceSet) deactivatePool() error {
  555. utils.Debugf("[devmapper] deactivatePool()")
  556. defer utils.Debugf("[devmapper] deactivatePool END")
  557. devname := devices.getPoolDevName()
  558. devinfo, err := getInfo(devname)
  559. if err != nil {
  560. utils.Debugf("\n--->Err: %s\n", err)
  561. return err
  562. }
  563. if devinfo.Exists != 0 {
  564. return removeDevice(devname)
  565. }
  566. return nil
  567. }
  568. func (devices *DeviceSet) deactivateDevice(info *DevInfo) error {
  569. utils.Debugf("[devmapper] deactivateDevice(%s)", info.Hash)
  570. defer utils.Debugf("[devmapper] deactivateDevice END")
  571. // Wait for the unmount to be effective,
  572. // by watching the value of Info.OpenCount for the device
  573. if err := devices.waitClose(info); err != nil {
  574. utils.Errorf("Warning: error waiting for device %s to close: %s\n", info.Hash, err)
  575. }
  576. devinfo, err := getInfo(info.Name())
  577. if err != nil {
  578. utils.Debugf("\n--->Err: %s\n", err)
  579. return err
  580. }
  581. if devinfo.Exists != 0 {
  582. if err := devices.removeDeviceAndWait(info.Name()); err != nil {
  583. utils.Debugf("\n--->Err: %s\n", err)
  584. return err
  585. }
  586. }
  587. return nil
  588. }
  589. // Issues the underlying dm remove operation and then waits
  590. // for it to finish.
  591. func (devices *DeviceSet) removeDeviceAndWait(devname string) error {
  592. var err error
  593. for i := 0; i < 1000; i++ {
  594. devices.sawBusy = false
  595. err = removeDevice(devname)
  596. if err == nil {
  597. break
  598. }
  599. if !devices.sawBusy {
  600. return err
  601. }
  602. // If we see EBUSY it may be a transient error,
  603. // sleep a bit a retry a few times.
  604. devices.Unlock()
  605. time.Sleep(10 * time.Millisecond)
  606. devices.Lock()
  607. }
  608. if err != nil {
  609. return err
  610. }
  611. if err := devices.waitRemove(devname); err != nil {
  612. return err
  613. }
  614. return nil
  615. }
  616. // waitRemove blocks until either:
  617. // a) the device registered at <device_set_prefix>-<hash> is removed,
  618. // or b) the 10 second timeout expires.
  619. func (devices *DeviceSet) waitRemove(devname string) error {
  620. utils.Debugf("[deviceset %s] waitRemove(%s)", devices.devicePrefix, devname)
  621. defer utils.Debugf("[deviceset %s] waitRemove(%s) END", devices.devicePrefix, devname)
  622. i := 0
  623. for ; i < 1000; i += 1 {
  624. devinfo, err := getInfo(devname)
  625. if err != nil {
  626. // If there is an error we assume the device doesn't exist.
  627. // The error might actually be something else, but we can't differentiate.
  628. return nil
  629. }
  630. if i%100 == 0 {
  631. utils.Debugf("Waiting for removal of %s: exists=%d", devname, devinfo.Exists)
  632. }
  633. if devinfo.Exists == 0 {
  634. break
  635. }
  636. devices.Unlock()
  637. time.Sleep(10 * time.Millisecond)
  638. devices.Lock()
  639. }
  640. if i == 1000 {
  641. return fmt.Errorf("Timeout while waiting for device %s to be removed", devname)
  642. }
  643. return nil
  644. }
  645. // waitClose blocks until either:
  646. // a) the device registered at <device_set_prefix>-<hash> is closed,
  647. // or b) the 10 second timeout expires.
  648. func (devices *DeviceSet) waitClose(info *DevInfo) error {
  649. i := 0
  650. for ; i < 1000; i += 1 {
  651. devinfo, err := getInfo(info.Name())
  652. if err != nil {
  653. return err
  654. }
  655. if i%100 == 0 {
  656. utils.Debugf("Waiting for unmount of %s: opencount=%d", info.Hash, devinfo.OpenCount)
  657. }
  658. if devinfo.OpenCount == 0 {
  659. break
  660. }
  661. devices.Unlock()
  662. time.Sleep(10 * time.Millisecond)
  663. devices.Lock()
  664. }
  665. if i == 1000 {
  666. return fmt.Errorf("Timeout while waiting for device %s to close", info.Hash)
  667. }
  668. return nil
  669. }
  670. func (devices *DeviceSet) Shutdown() error {
  671. utils.Debugf("[deviceset %s] shutdown()", devices.devicePrefix)
  672. utils.Debugf("[devmapper] Shutting down DeviceSet: %s", devices.root)
  673. defer utils.Debugf("[deviceset %s] shutdown END", devices.devicePrefix)
  674. var devs []*DevInfo
  675. devices.devicesLock.Lock()
  676. for _, info := range devices.Devices {
  677. devs = append(devs, info)
  678. }
  679. devices.devicesLock.Unlock()
  680. for _, info := range devs {
  681. info.lock.Lock()
  682. if info.mountCount > 0 {
  683. // We use MNT_DETACH here in case it is still busy in some running
  684. // container. This means it'll go away from the global scope directly,
  685. // and the device will be released when that container dies.
  686. if err := sysUnmount(info.mountPath, syscall.MNT_DETACH); err != nil {
  687. utils.Debugf("Shutdown unmounting %s, error: %s\n", info.mountPath, err)
  688. }
  689. devices.Lock()
  690. if err := devices.deactivateDevice(info); err != nil {
  691. utils.Debugf("Shutdown deactivate %s , error: %s\n", info.Hash, err)
  692. }
  693. devices.Unlock()
  694. }
  695. info.lock.Unlock()
  696. }
  697. info, _ := devices.lookupDevice("")
  698. if info != nil {
  699. info.lock.Lock()
  700. devices.Lock()
  701. if err := devices.deactivateDevice(info); err != nil {
  702. utils.Debugf("Shutdown deactivate base , error: %s\n", err)
  703. }
  704. devices.Unlock()
  705. info.lock.Unlock()
  706. }
  707. devices.Lock()
  708. if err := devices.deactivatePool(); err != nil {
  709. utils.Debugf("Shutdown deactivate pool , error: %s\n", err)
  710. }
  711. devices.Unlock()
  712. return nil
  713. }
  714. func (devices *DeviceSet) MountDevice(hash, path, mountLabel string) error {
  715. info, err := devices.lookupDevice(hash)
  716. if err != nil {
  717. return err
  718. }
  719. info.lock.Lock()
  720. defer info.lock.Unlock()
  721. devices.Lock()
  722. defer devices.Unlock()
  723. if info.mountCount > 0 {
  724. if path != info.mountPath {
  725. return fmt.Errorf("Trying to mount devmapper device in multple places (%s, %s)", info.mountPath, path)
  726. }
  727. info.mountCount++
  728. return nil
  729. }
  730. if err := devices.activateDeviceIfNeeded(info); err != nil {
  731. return fmt.Errorf("Error activating devmapper device for '%s': %s", hash, err)
  732. }
  733. var flags uintptr = sysMsMgcVal
  734. mountOptions := label.FormatMountLabel("discard", mountLabel)
  735. err = sysMount(info.DevName(), path, "ext4", flags, mountOptions)
  736. if err != nil && err == sysEInval {
  737. mountOptions = label.FormatMountLabel("", mountLabel)
  738. err = sysMount(info.DevName(), path, "ext4", flags, mountOptions)
  739. }
  740. if err != nil {
  741. return fmt.Errorf("Error mounting '%s' on '%s': %s", info.DevName(), path, err)
  742. }
  743. info.mountCount = 1
  744. info.mountPath = path
  745. return devices.setInitialized(info)
  746. }
  747. func (devices *DeviceSet) UnmountDevice(hash string) error {
  748. utils.Debugf("[devmapper] UnmountDevice(hash=%s)", hash)
  749. defer utils.Debugf("[devmapper] UnmountDevice END")
  750. info, err := devices.lookupDevice(hash)
  751. if err != nil {
  752. return err
  753. }
  754. info.lock.Lock()
  755. defer info.lock.Unlock()
  756. devices.Lock()
  757. defer devices.Unlock()
  758. if info.mountCount == 0 {
  759. return fmt.Errorf("UnmountDevice: device not-mounted id %s\n", hash)
  760. }
  761. info.mountCount--
  762. if info.mountCount > 0 {
  763. return nil
  764. }
  765. utils.Debugf("[devmapper] Unmount(%s)", info.mountPath)
  766. if err := sysUnmount(info.mountPath, 0); err != nil {
  767. utils.Debugf("\n--->Err: %s\n", err)
  768. return err
  769. }
  770. utils.Debugf("[devmapper] Unmount done")
  771. if err := devices.deactivateDevice(info); err != nil {
  772. return err
  773. }
  774. info.mountPath = ""
  775. return nil
  776. }
  777. func (devices *DeviceSet) HasDevice(hash string) bool {
  778. devices.Lock()
  779. defer devices.Unlock()
  780. info, _ := devices.lookupDevice(hash)
  781. return info != nil
  782. }
  783. func (devices *DeviceSet) HasInitializedDevice(hash string) bool {
  784. devices.Lock()
  785. defer devices.Unlock()
  786. info, _ := devices.lookupDevice(hash)
  787. return info != nil && info.Initialized
  788. }
  789. func (devices *DeviceSet) HasActivatedDevice(hash string) bool {
  790. info, _ := devices.lookupDevice(hash)
  791. if info == nil {
  792. return false
  793. }
  794. info.lock.Lock()
  795. defer info.lock.Unlock()
  796. devices.Lock()
  797. defer devices.Unlock()
  798. devinfo, _ := getInfo(info.Name())
  799. return devinfo != nil && devinfo.Exists != 0
  800. }
  801. func (devices *DeviceSet) setInitialized(info *DevInfo) error {
  802. info.Initialized = true
  803. if err := devices.saveMetadata(); err != nil {
  804. info.Initialized = false
  805. utils.Debugf("\n--->Err: %s\n", err)
  806. return err
  807. }
  808. return nil
  809. }
  810. func (devices *DeviceSet) List() []string {
  811. devices.Lock()
  812. defer devices.Unlock()
  813. devices.devicesLock.Lock()
  814. ids := make([]string, len(devices.Devices))
  815. i := 0
  816. for k := range devices.Devices {
  817. ids[i] = k
  818. i++
  819. }
  820. devices.devicesLock.Unlock()
  821. return ids
  822. }
  823. func (devices *DeviceSet) deviceStatus(devName string) (sizeInSectors, mappedSectors, highestMappedSector uint64, err error) {
  824. var params string
  825. _, sizeInSectors, _, params, err = getStatus(devName)
  826. if err != nil {
  827. return
  828. }
  829. if _, err = fmt.Sscanf(params, "%d %d", &mappedSectors, &highestMappedSector); err == nil {
  830. return
  831. }
  832. return
  833. }
  834. func (devices *DeviceSet) GetDeviceStatus(hash string) (*DevStatus, error) {
  835. info, err := devices.lookupDevice(hash)
  836. if err != nil {
  837. return nil, err
  838. }
  839. info.lock.Lock()
  840. defer info.lock.Unlock()
  841. devices.Lock()
  842. defer devices.Unlock()
  843. status := &DevStatus{
  844. DeviceId: info.DeviceId,
  845. Size: info.Size,
  846. TransactionId: info.TransactionId,
  847. }
  848. if err := devices.activateDeviceIfNeeded(info); err != nil {
  849. return nil, fmt.Errorf("Error activating devmapper device for '%s': %s", hash, err)
  850. }
  851. if sizeInSectors, mappedSectors, highestMappedSector, err := devices.deviceStatus(info.DevName()); err != nil {
  852. return nil, err
  853. } else {
  854. status.SizeInSectors = sizeInSectors
  855. status.MappedSectors = mappedSectors
  856. status.HighestMappedSector = highestMappedSector
  857. }
  858. return status, nil
  859. }
  860. func (devices *DeviceSet) poolStatus() (totalSizeInSectors, transactionId, dataUsed, dataTotal, metadataUsed, metadataTotal uint64, err error) {
  861. var params string
  862. if _, totalSizeInSectors, _, params, err = getStatus(devices.getPoolName()); err == nil {
  863. _, err = fmt.Sscanf(params, "%d %d/%d %d/%d", &transactionId, &metadataUsed, &metadataTotal, &dataUsed, &dataTotal)
  864. }
  865. return
  866. }
  867. func (devices *DeviceSet) Status() *Status {
  868. devices.Lock()
  869. defer devices.Unlock()
  870. status := &Status{}
  871. status.PoolName = devices.getPoolName()
  872. status.DataLoopback = path.Join(devices.loopbackDir(), "data")
  873. status.MetadataLoopback = path.Join(devices.loopbackDir(), "metadata")
  874. totalSizeInSectors, _, dataUsed, dataTotal, metadataUsed, metadataTotal, err := devices.poolStatus()
  875. if err == nil {
  876. // Convert from blocks to bytes
  877. blockSizeInSectors := totalSizeInSectors / dataTotal
  878. status.Data.Used = dataUsed * blockSizeInSectors * 512
  879. status.Data.Total = dataTotal * blockSizeInSectors * 512
  880. // metadata blocks are always 4k
  881. status.Metadata.Used = metadataUsed * 4096
  882. status.Metadata.Total = metadataTotal * 4096
  883. status.SectorSize = blockSizeInSectors * 512
  884. }
  885. return status
  886. }
  887. func NewDeviceSet(root string, doInit bool) (*DeviceSet, error) {
  888. SetDevDir("/dev")
  889. devices := &DeviceSet{
  890. root: root,
  891. MetaData: MetaData{Devices: make(map[string]*DevInfo)},
  892. }
  893. if err := devices.initDevmapper(doInit); err != nil {
  894. return nil, err
  895. }
  896. return devices, nil
  897. }