graph driver-device mapper-03thin pool基本操作

简介:
//	在thin pool中创建一个新thin device
//	调用路径:driver.Create()
1.1 func (devices *DeviceSet) AddDevice(hash, baseHash string) error {
	//查找父device
	baseInfo, err := devices.lookupDevice(baseHash)
	if err != nil {
		return err
	}

	baseInfo.lock.Lock()
	defer baseInfo.lock.Unlock()

	devices.Lock()
	defer devices.Unlock()

	//检查imageid/containerid对应的image是否存在
	if info, _ := devices.lookupDevice(hash); info != nil {
		return fmt.Errorf("device %s already exists", hash)
	}

	deviceId := devices.nextDeviceId

	//创建父设备的镜像
	if err := createSnapDevice(devices.getPoolDevName(), &deviceId, baseInfo.Name(), baseInfo.DeviceId); err != nil {
		utils.Debugf("Error creating snap device: %s\n", err)
		return err
	}
	//创建thin device的DevInfo,并保存信息到/var/lib/docker/devicemapper/metadata/$id文件中
	if _, err := devices.registerDevice(deviceId, hash, baseInfo.Size); err != nil {
		deleteDevice(devices.getPoolDevName(), deviceId)
		utils.Debugf("Error registering device: %s\n", err)
		return err
	}
	return nil
}

//	创建镜像文件的快照
//		libdevmapper通过发送msg发送命令
//	调用路径:AddDevice->createSnapDevice
1.2 func createSnapDevice(poolName string, deviceId *int, baseName string, baseDeviceId int) error {
	devinfo, _ := getInfo(baseName)
	doSuspend := devinfo != nil && devinfo.Exists != 0

	//设备存在,则在快照前要先挂起父设备
	if doSuspend {
		if err := suspendDevice(baseName); err != nil {
			return err
		}
	}

	for {
		//创建task,libdevmapper通过msg传递命令
		task, err := createTask(DeviceTargetMsg, poolName)
		if task == nil {
			//创建task失败,恢复父device
			if doSuspend {
				resumeDevice(baseName)
			}
			return err
		}

		if err := task.SetSector(0); err != nil {
			if doSuspend {
				resumeDevice(baseName)
			}
			return fmt.Errorf("Can't set sector %s", err)
		}

		//发送创建命令
		if err := task.SetMessage(fmt.Sprintf("create_snap %d %d", *deviceId, baseDeviceId)); err != nil {
			if doSuspend {
				resumeDevice(baseName)
			}
			return fmt.Errorf("Can't set message %s", err)
		}

		dmSawExist = false
		if err := task.Run(); err != nil {
			//deviceid已存在,继续尝试下一个id
			if dmSawExist {
				*deviceId++
				continue
			}

			if doSuspend {
				resumeDevice(baseName)
			}
			return fmt.Errorf("Error running DeviceCreate (createSnapDevice) %s", err)
		}

		break
	}
	//创建成功,恢复父设备
	if doSuspend {
		if err := resumeDevice(baseName); err != nil {
			return err
		}
	}

	return nil
}

//	注册thin device信息
//	添加devinfo到devices.Devices哈希表,并保存devinfo到/var/lib/docker/devicemapper/metadata/$id文件
//	调用路径:AddDevice->registerDevice
1.3 func (devices *DeviceSet) registerDevice(id int, hash string, size uint64) (*DevInfo, error) {
	
	info := &DevInfo{
		Hash:          hash,
		DeviceId:      id,
		Size:          size,
		//分配一个新的transactionid
		TransactionId: devices.allocateTransactionId(),
		Initialized:   false,
		devices:       devices,
	}

	devices.devicesLock.Lock()
	//添加devinfo到hash表
	devices.Devices[hash] = info
	devices.devicesLock.Unlock()

	//保存devinfo到/var/lib/docker/devicemapper/metadata/$id文件
	if err := devices.saveMetadata(info); err != nil {
		devices.devicesLock.Lock()
		delete(devices.Devices, hash)
		devices.devicesLock.Unlock()
		return nil, err
	}

	return info, nil
}

//	删除设备
//	调用路径:driver.Remove()
2.1 func (devices *DeviceSet) DeleteDevice(hash string) error {
	//检查设备是否存在
	info, err := devices.lookupDevice(hash)
	if err != nil {
		return err
	}

	info.lock.Lock()
	defer info.lock.Unlock()

	devices.Lock()
	defer devices.Unlock()
	//传递devinfo,删除设备
	return devices.deleteDevice(info)


//	删除设备
//		1.discard thin device的block
//		2.传递device name删除设备名
//		3.传递device id删除设备
//		4.删除/var/lib/docker/devicemapper/metadata/$id文件
//	调用路径:DeleteDevice->deleteDevice
2.2 func (devices *DeviceSet) deleteDevice(info *DevInfo) error {
	//删除设备时,discard其占用的block
	if devices.doBlkDiscard {
		//激活thin device设备
		if err := devices.activateDeviceIfNeeded(info); err == nil {
			//discard设备占用的block
			if err := BlockDeviceDiscard(info.DevName()); err != nil {
				utils.Debugf("Error discarding block on device: %s (ignoring)\n", err)
			}
		}
	}

	devinfo, _ := getInfo(info.Name())
	if devinfo != nil && devinfo.Exists != 0 {
		//传递thin device名(docker-$major:$minor-$inode-$id)给libdevmapper,删除设备名
		if err := devices.removeDeviceAndWait(info.Name()); err != nil {
			utils.Debugf("Error removing device: %s\n", err)
			return err
		}
	}

	//通过thin device id删除设备
	if err := deleteDevice(devices.getPoolDevName(), info.DeviceId); err != nil {
		utils.Debugf("Error deleting device: %s\n", err)
		return err
	}

	devices.allocateTransactionId()
	devices.devicesLock.Lock()
	//从内存中删除devinfo
	delete(devices.Devices, info.Hash)
	devices.devicesLock.Unlock()

	//删除/var/lib/docker/devicemapper/metadata/$id文件
	if err := devices.removeMetadata(info); err != nil {
		devices.devicesLock.Lock()
		devices.Devices[info.Hash] = info
		devices.devicesLock.Unlock()
		utils.Debugf("Error removing meta data: %s\n", err)
		return err
	}

	return nil
}

//	挂载设备到指定路径
//		hash指定要挂载的thin device id
//		path指定要挂载到的路径
//	一个thin device可以被多次挂载到同一个路径
//	调用路径:driver.Get()
3.1 func (devices *DeviceSet) MountDevice(hash, path, mountLabel string) error {
	info, err := devices.lookupDevice(hash)
	if err != nil {
		return err
	}

	info.lock.Lock()
	defer info.lock.Unlock()

	devices.Lock()
	defer devices.Unlock()

	//thin device不允许被挂载到多个不同路径
	if info.mountCount > 0 {
		if path != info.mountPath {
			return fmt.Errorf("Trying to mount devmapper device in multple places (%s, %s)", info.mountPath, path)
		}

		info.mountCount++
		return nil
	}
	//激活设备
	if err := devices.activateDeviceIfNeeded(info); err != nil {
		return fmt.Errorf("Error activating devmapper device for '%s': %s", hash, err)
	}

	var flags uintptr = syscall.MS_MGC_VAL

	//获取thin device上文件系统的类型
	//info.DevName()传递
	fstype, err := ProbeFsType(info.DevName())
	if err != nil {
		return err
	}

	options := ""

	//通过--storage-option 传递的mount选项
	options = joinMountOptions(options, devices.mountOptions)
	options = joinMountOptions(options, label.FormatMountLabel("", mountLabel))

	//mount thin device到指定path
	err = syscall.Mount(info.DevName(), path, fstype, flags, joinMountOptions("discard", options))
	if err != nil && err == syscall.EINVAL {
		err = syscall.Mount(info.DevName(), path, fstype, flags, options)
	}
	if err != nil {
		return fmt.Errorf("Error mounting '%s' on '%s': %s", info.DevName(), path, err)
	}

	info.mountCount = 1
	info.mountPath = path

	return nil
}

//	解挂thin device
//		hash为imageid或containerid
//	直到挂载计数=0时才真正解挂
//	调用路径:driver.Put()
4.1 func (devices *DeviceSet) UnmountDevice(hash string) error {
	
	//查找devinfo
	info, err := devices.lookupDevice(hash)
	if err != nil {
		return err
	}

	info.lock.Lock()
	defer info.lock.Unlock()

	devices.Lock()
	defer devices.Unlock()

	//挂载了不止一次,成功返回
	info.mountCount--
	if info.mountCount > 0 {
		return nil
	}

	//从指定路径解挂
	if err := syscall.Unmount(info.mountPath, 0); err != nil {
		return err
	}
	//停止设备
	if err := devices.deactivateDevice(info); err != nil {
		return err
	}

	info.mountPath = ""

	return nil
}

//	停止thin device
//	等待thin device从/var/lib/docker/devicemapper/mnt/$id解挂,删除thin device名
//	调用路径:UnmountDevice->deactivateDevice
4.2 func (devices *DeviceSet) deactivateDevice(info *DevInfo) error {

	//等待thin device解挂,通过device id获取设备信息,打开计数降到0
	if err := devices.waitClose(info); err != nil {
		utils.Errorf("Warning: error waiting for device %s to close: %s\n", info.Hash, err)
	}

	devinfo, err := getInfo(info.Name())
	if err != nil {
		return err
	}
	if devinfo.Exists != 0 {
		//删除设备名
		if err := devices.removeDeviceAndWait(info.Name()); err != nil {
			return err
		}
	}
	return nil
}

目录
相关文章
|
存储 弹性计算 自然语言处理
PB级数据量背后阿里云 Elasticsearch 的内核优化实践
本文将揭秘阿里云在面对 PB 级数据量挑战下所做的内核优化实践。
6379 0
PB级数据量背后阿里云 Elasticsearch 的内核优化实践
|
11月前
|
机器学习/深度学习 PyTorch 测试技术
TurboAttention:基于多项式近似和渐进式量化的高效注意力机制优化方案,降低LLM计算成本70%
**TurboAttention**提出了一种全新的LLM信息处理方法。该方法通过一系列优化手段替代了传统的二次复杂度注意力机制,包括稀疏多项式软最大值近似和高效量化技术。
465 5
TurboAttention:基于多项式近似和渐进式量化的高效注意力机制优化方案,降低LLM计算成本70%
|
编译器 API 语音技术
SDK介绍
【10月更文挑战第21天】
|
存储 分布式计算 安全
MaxCompute Bloomfilter index 在蚂蚁安全溯源场景大规模点查询的最佳实践
MaxCompute 在11月最新版本中全新上线了 Bloomfilter index 能力,针对大规模数据点查场景,支持更细粒度的数据裁剪,减少查询过程中不必要的数据扫描,从而提高整体的查询效率和性能。
|
监控 安全 物联网
5G技术的革命性进步及其对社会的影响
5G技术作为移动通信领域的革命性进步,正深刻地影响着我们的生活和社会。它不仅提供了更快的数据传输速率和更低的延迟,还将引领着各个领域的创新和发展。从移动通信、工业、医疗到智能城市,5G技术正在改变着我们的世界,为未来带来更多可能性。然而,我们也需要解决一些挑战,确保5G技术的安全和可持续发展。随着技术的不断进步,5G技术的前景依然充满希望,将为我们的社会带来更多的创新和变革。
1451 1
5G技术的革命性进步及其对社会的影响
|
监控 算法 Java
保卫你的API:深入了解接口限流
保卫你的API:深入了解接口限流
971 0
|
应用服务中间件 nginx Docker
【Docker】搭建私有镜像仓库(带有图形化界面版本)
【Docker】搭建私有镜像仓库(带有图形化界面版本)
1074 0
|
Java 数据安全/隐私保护 iOS开发
Windows 平台上也可以进行 iOS App 的开发
为了将 iOS APP 上架至 App Store,我们需要准备以下基本需求资料:1. 苹果开发者账号(如果还没有账号,需要先申请,可以参考苹果开发者账号申请教程)
An工具介绍之摄像头
An工具介绍之摄像头
657 0
An工具介绍之摄像头
阿里云人工客服怎么先联系?400客服电话
阿里云人工客服怎么联系?可以通过人工客服24小时电话、在线转人工或钉钉移动端、提交工单、建议与投诉四种加急处理方法,阿里云百科来详细说下联系阿里云人工客服的详细操作流程
8391 0
阿里云人工客服怎么先联系?400客服电话