1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <fcntl.h>
17 #include <stdlib.h>
18 #include <errno.h>
19 #include <limits.h>
20 #include <sys/types.h>
21 #include <sys/sysmacros.h>
22
23 #include "securec.h"
24 #include "beget_ext.h"
25 #include "fs_dm_linear.h"
26
27 #ifdef __cplusplus
28 #if __cplusplus
29 extern "C" {
30 #endif
31 #endif
32
LoadDmLinearDeviceTable(int fd,const char * devName,DmLinearTarget * target,uint32_t targetNum)33 static int LoadDmLinearDeviceTable(int fd, const char *devName, DmLinearTarget *target, uint32_t targetNum)
34 {
35 struct dm_ioctl *io = NULL;
36 struct dm_target_spec *ts = NULL;
37 size_t parasTotalSize = DM_ALIGN(sizeof(*io) + sizeof(*ts) * targetNum);
38 for (uint32_t index = 0; index < targetNum; index++) {
39 parasTotalSize += target[index].paras_len + 1;
40 }
41
42 char *parasBuf = calloc(1, parasTotalSize);
43 BEGET_ERROR_CHECK(parasBuf != NULL, return -1, "error, calloc dm table fail");
44 io = (struct dm_ioctl *)parasBuf;
45 int rc = InitDmIo(io, devName);
46 BEGET_ERROR_CHECK(rc == 0, free(parasBuf); return rc, "error %d, init dm io", rc);
47 io->data_size = parasTotalSize;
48 io->data_start = sizeof(*io);
49 io->target_count = targetNum;
50 uint32_t i = 0;
51 uint32_t len = 0;
52 char *paras = NULL;
53 do {
54 FS_DM_RETURN_ERR_IF_NULL(target[i].paras);
55 ts = (struct dm_target_spec *)(parasBuf + sizeof(*io) + len);
56 ts->status = 0;
57 ts->sector_start = target[i].start;
58 ts->length = target[i].length;
59
60 rc = strcpy_s(ts->target_type, sizeof(ts->target_type), "linear");
61 BEGET_ERROR_CHECK(rc == EOK, free(parasBuf); return -1, "error %d, cp target type", rc);
62 len += sizeof((*ts));
63 paras = parasBuf + sizeof(*io) + len;
64 rc = strcpy_s(paras, target[i].paras_len + 1, target[i].paras);
65 BEGET_ERROR_CHECK(rc == EOK, free(parasBuf); return -1, "error %d, cp target paras", rc);
66 BEGET_LOGI("linear target.paras = %s, ts->target_type = %s", target[i].paras, ts->target_type);
67 len += target[i].paras_len + 1;
68 ts->next = target[i].paras_len + 1 + sizeof((*ts));
69 i++;
70 } while (i < targetNum);
71
72 rc = ioctl(fd, DM_TABLE_LOAD, io);
73 if (rc != 0) {
74 BEGET_LOGE("error %d, DM_TABLE_LOAD failed for %s", rc, devName);
75 }
76 free(parasBuf);
77 BEGET_LOGI("LoadDmLinearDeviceTable end, dev is [%s] rc is [%d]", devName, rc);
78 return rc;
79 }
80
FsDmCreateMultiTargetLinearDevice(const char * devName,char * dmDevPath,uint64_t dmDevPathLen,DmLinearTarget * target,uint32_t targetNum)81 int FsDmCreateMultiTargetLinearDevice(const char *devName, char *dmDevPath, uint64_t dmDevPathLen,
82 DmLinearTarget *target, uint32_t targetNum)
83 {
84 if (devName == NULL || dmDevPath == NULL || target == NULL) {
85 BEGET_LOGE("argc is null");
86 return -1;
87 }
88 if (targetNum == 0 || targetNum > MAX_TARGET_NUM) {
89 BEGET_LOGE("targetNum:%u is invalid", targetNum);
90 return -1;
91 }
92
93 int fd = open(DEVICE_MAPPER_PATH, O_RDWR | O_CLOEXEC);
94 if (fd < 0) {
95 BEGET_LOGE("open mapper path failed errno %d", errno);
96 return -1;
97 }
98
99 int rc = 0;
100
101 do {
102 rc = CreateDmDev(fd, devName);
103 if (rc != 0) {
104 BEGET_LOGE("create dm device failed %d", rc);
105 break;
106 }
107 rc = DmGetDeviceName(fd, devName, dmDevPath, dmDevPathLen);
108 if (rc != 0) {
109 BEGET_LOGE("get dm device name failed");
110 break;
111 }
112 rc = LoadDmLinearDeviceTable(fd, devName, target, targetNum);
113 if (rc != 0) {
114 BEGET_LOGE("load dm device name failed");
115 break;
116 }
117
118 rc = ActiveDmDevice(fd, devName);
119 if (rc != 0) {
120 BEGET_LOGE("active dm device name failed");
121 break;
122 }
123
124 BEGET_LOGI("fs create linear device success, dev is [%s] dmDevPath is [%s]", devName, dmDevPath);
125 } while (0);
126
127 close(fd);
128 return rc;
129 }
130
FsDmSwitchToLinearDevice(const char * devName,DmLinearTarget * target,uint32_t targetNum)131 int FsDmSwitchToLinearDevice(const char *devName, DmLinearTarget *target, uint32_t targetNum)
132 {
133 if (devName == NULL || target == NULL) {
134 BEGET_LOGE("argc is null");
135 return -1;
136 }
137 if (targetNum == 0 || targetNum > MAX_TARGET_NUM) {
138 BEGET_LOGE("targetNum:%u is invalid", targetNum);
139 return -1;
140 }
141
142 int fd = open(DEVICE_MAPPER_PATH, O_RDWR | O_CLOEXEC);
143 if (fd < 0) {
144 BEGET_LOGE("open mapper path failed errno %d", errno);
145 return -1;
146 }
147
148 int rc = 0;
149
150 do {
151 rc = LoadDmLinearDeviceTable(fd, devName, target, targetNum);
152 if (rc != 0) {
153 BEGET_LOGE("load dm device name failed");
154 break;
155 }
156 rc = ActiveDmDevice(fd, devName);
157 if (rc != 0) {
158 BEGET_LOGE("active dm device name failed");
159 break;
160 }
161
162 BEGET_LOGI("fs switch linear device success, dev is [%s]", devName);
163 } while (0);
164
165 close(fd);
166 return rc;
167 }
168
169 #ifdef __cplusplus
170 #if __cplusplus
171 }
172 #endif
173 #endif