1 // SPDX-License-Identifier: BSD-3-Clause
2 /* Copyright 2016-2018, Intel Corporation */
5 * check_backup.c -- pre-check backup
15 #include "libpmempool.h"
18 #include "check_util.h"
21 Q_OVERWRITE_EXISTING_FILE
,
22 Q_OVERWRITE_EXISTING_PARTS
26 * location_release -- (internal) release poolset structure
29 location_release(location
*loc
)
32 util_poolset_free(loc
->set
);
38 * backup_nonpoolset_requirements -- (internal) check backup requirements
41 backup_nonpoolset_requirements(PMEMpoolcheck
*ppc
, location
*loc
)
43 LOG(3, "backup_path %s", ppc
->backup_path
);
45 int exists
= util_file_exists(ppc
->backup_path
);
48 "unable to access the backup destination: %s",
57 if ((size_t)util_file_get_size(ppc
->backup_path
) !=
58 ppc
->pool
->set_file
->size
) {
59 ppc
->result
= CHECK_RESULT_ERROR
;
61 "destination of the backup does not match the size of the source pool file: %s",
65 if (CHECK_WITHOUT_FIXING(ppc
)) {
66 location_release(loc
);
67 loc
->step
= CHECK_STEP_COMPLETE
;
71 CHECK_ASK(ppc
, Q_OVERWRITE_EXISTING_FILE
,
72 "destination of the backup already exists.|Do you want to overwrite it?");
74 return check_questions_sequence_validate(ppc
);
78 * backup_nonpoolset_overwrite -- (internal) overwrite pool
81 backup_nonpoolset_overwrite(PMEMpoolcheck
*ppc
, location
*loc
,
82 uint32_t question
, void *context
)
89 case Q_OVERWRITE_EXISTING_FILE
:
90 if (pool_copy(ppc
->pool
, ppc
->backup_path
, 1 /* overwrite */)) {
91 location_release(loc
);
92 ppc
->result
= CHECK_RESULT_ERROR
;
93 return CHECK_ERR(ppc
, "cannot perform backup");
96 location_release(loc
);
97 loc
->step
= CHECK_STEP_COMPLETE
;
100 ERR("not implemented question id: %u", question
);
107 * backup_nonpoolset_create -- (internal) create backup
110 backup_nonpoolset_create(PMEMpoolcheck
*ppc
, location
*loc
)
112 CHECK_INFO(ppc
, "creating backup file: %s", ppc
->backup_path
);
114 if (pool_copy(ppc
->pool
, ppc
->backup_path
, 0)) {
115 location_release(loc
);
116 ppc
->result
= CHECK_RESULT_ERROR
;
117 return CHECK_ERR(ppc
, "cannot perform backup");
120 location_release(loc
);
121 loc
->step
= CHECK_STEP_COMPLETE
;
126 * backup_poolset_requirements -- (internal) check backup requirements
129 backup_poolset_requirements(PMEMpoolcheck
*ppc
, location
*loc
)
131 LOG(3, "backup_path %s", ppc
->backup_path
);
133 if (ppc
->pool
->set_file
->poolset
->nreplicas
> 1) {
135 "backup of a poolset with multiple replicas is not supported");
139 if (pool_set_parse(&loc
->set
, ppc
->backup_path
)) {
140 CHECK_INFO_ERRNO(ppc
, "invalid poolset backup file: %s",
145 if (loc
->set
->nreplicas
> 1) {
147 "backup to a poolset with multiple replicas is not supported");
151 ASSERTeq(loc
->set
->nreplicas
, 1);
152 struct pool_replica
*srep
= ppc
->pool
->set_file
->poolset
->replica
[0];
153 struct pool_replica
*drep
= loc
->set
->replica
[0];
154 if (srep
->nparts
!= drep
->nparts
) {
156 "number of part files in the backup poolset must match number of part files in the source poolset");
160 int overwrite_required
= 0;
161 for (unsigned p
= 0; p
< srep
->nparts
; p
++) {
162 int exists
= util_file_exists(drep
->part
[p
].path
);
165 "unable to access the part of the destination poolset: %s",
170 if (srep
->part
[p
].filesize
!= drep
->part
[p
].filesize
) {
172 "size of the part %u of the backup poolset does not match source poolset",
182 overwrite_required
= true;
184 if ((size_t)util_file_get_size(drep
->part
[p
].path
) !=
185 srep
->part
[p
].filesize
) {
187 "destination of the backup part does not match size of the source part file: %s",
193 if (CHECK_WITHOUT_FIXING(ppc
)) {
194 location_release(loc
);
195 loc
->step
= CHECK_STEP_COMPLETE
;
199 if (overwrite_required
) {
200 CHECK_ASK(ppc
, Q_OVERWRITE_EXISTING_PARTS
,
201 "part files of the destination poolset of the backup already exist.|"
202 "Do you want to overwrite them?");
205 return check_questions_sequence_validate(ppc
);
208 location_release(loc
);
210 ppc
->result
= CHECK_RESULT_ERROR
;
211 return CHECK_ERR(ppc
, "unable to backup poolset");
215 * backup_poolset -- (internal) backup the poolset
218 backup_poolset(PMEMpoolcheck
*ppc
, location
*loc
, int overwrite
)
220 struct pool_replica
*srep
= ppc
->pool
->set_file
->poolset
->replica
[0];
221 struct pool_replica
*drep
= loc
->set
->replica
[0];
222 for (unsigned p
= 0; p
< srep
->nparts
; p
++) {
223 if (overwrite
== 0) {
224 CHECK_INFO(ppc
, "creating backup file: %s",
227 if (pool_set_part_copy(&drep
->part
[p
], &srep
->part
[p
],
229 location_release(loc
);
230 ppc
->result
= CHECK_RESULT_ERROR
;
231 CHECK_INFO(ppc
, "unable to create backup file");
232 return CHECK_ERR(ppc
, "unable to backup poolset");
240 * backup_poolset_overwrite -- (internal) backup poolset with overwrite
243 backup_poolset_overwrite(PMEMpoolcheck
*ppc
, location
*loc
,
244 uint32_t question
, void *context
)
251 case Q_OVERWRITE_EXISTING_PARTS
:
252 if (backup_poolset(ppc
, loc
, 1 /* overwrite */)) {
253 location_release(loc
);
254 ppc
->result
= CHECK_RESULT_ERROR
;
255 return CHECK_ERR(ppc
, "cannot perform backup");
258 location_release(loc
);
259 loc
->step
= CHECK_STEP_COMPLETE
;
262 ERR("not implemented question id: %u", question
);
269 * backup_poolset_create -- (internal) backup poolset
272 backup_poolset_create(PMEMpoolcheck
*ppc
, location
*loc
)
274 if (backup_poolset(ppc
, loc
, 0)) {
275 location_release(loc
);
276 ppc
->result
= CHECK_RESULT_ERROR
;
277 return CHECK_ERR(ppc
, "cannot perform backup");
280 location_release(loc
);
281 loc
->step
= CHECK_STEP_COMPLETE
;
286 int (*check
)(PMEMpoolcheck
*, location
*);
287 int (*fix
)(PMEMpoolcheck
*, location
*, uint32_t, void *);
291 static const struct step steps
[] = {
293 .check
= backup_nonpoolset_requirements
,
297 .fix
= backup_nonpoolset_overwrite
,
301 .check
= backup_nonpoolset_create
,
305 .check
= backup_poolset_requirements
,
309 .fix
= backup_poolset_overwrite
,
313 .check
= backup_poolset_create
,
323 * step_exe -- (internal) perform single step according to its parameters
326 step_exe(PMEMpoolcheck
*ppc
, location
*loc
)
328 ASSERT(loc
->step
< ARRAY_SIZE(steps
));
330 const struct step
*step
= &steps
[loc
->step
++];
332 if (step
->poolset
== 0 && ppc
->pool
->params
.is_poolset
== 1)
336 return step
->check(ppc
, loc
);
338 if (!check_has_answer(ppc
->data
))
341 if (check_answer_loop(ppc
, loc
, NULL
, 1, step
->fix
))
344 ppc
->result
= CHECK_RESULT_CONSISTENT
;
350 * check_backup -- perform backup if requested and needed
353 check_backup(PMEMpoolcheck
*ppc
)
355 LOG(3, "backup_path %s", ppc
->backup_path
);
357 if (ppc
->backup_path
== NULL
)
360 location
*loc
= check_get_step_data(ppc
->data
);
363 while (CHECK_NOT_COMPLETE(loc
, steps
)) {
364 if (step_exe(ppc
, loc
))