1 // SPDX-License-Identifier: BSD-3-Clause
2 /* Copyright 2018-2020, Intel Corporation */
5 * set_badblocks.c - common part of implementation of bad blocks API
16 #include "set_badblocks.h"
17 #include "badblocks.h"
19 /* helper structure for badblocks_check_file_cb() */
20 struct check_file_cb
{
21 int n_files_bbs
; /* number of files with bad blocks */
22 int create
; /* poolset is just being created */
26 * badblocks_check_file_cb -- (internal) callback checking bad blocks
30 badblocks_check_file_cb(struct part_file
*pf
, void *arg
)
32 LOG(3, "part_file %p arg %p", pf
, arg
);
34 struct check_file_cb
*pcfcb
= arg
;
38 * Remote replicas are checked for bad blocks
39 * while opening in util_pool_open_remote().
44 int exists
= util_file_exists(pf
->part
->path
);
49 /* the part does not exist, so it has no bad blocks */
52 int ret
= badblocks_check_file(pf
->part
->path
);
54 ERR("checking the pool file for bad blocks failed -- '%s'",
60 ERR("part file contains bad blocks -- '%s'", pf
->part
->path
);
62 pf
->part
->has_bad_blocks
= 1;
69 * badblocks_check_poolset -- checks if the pool set contains bad blocks
73 * 0 pool set does not contain bad blocks
74 * 1 pool set contains bad blocks
77 badblocks_check_poolset(struct pool_set
*set
, int create
)
79 LOG(3, "set %p create %i", set
, create
);
81 struct check_file_cb cfcb
;
86 if (util_poolset_foreach_part_struct(set
, badblocks_check_file_cb
,
91 if (cfcb
.n_files_bbs
) {
92 LOG(1, "%i pool file(s) contain bad blocks", cfcb
.n_files_bbs
);
93 set
->has_bad_blocks
= 1;
96 return (cfcb
.n_files_bbs
> 0);
100 * badblocks_clear_poolset_cb -- (internal) callback clearing bad blocks
104 badblocks_clear_poolset_cb(struct part_file
*pf
, void *arg
)
106 LOG(3, "part_file %p arg %p", pf
, arg
);
110 if (pf
->is_remote
) { /* XXX not supported yet */
112 "WARNING: clearing bad blocks in remote replicas is not supported yet -- '%s:%s'",
113 pf
->remote
->node_addr
, pf
->remote
->pool_desc
);
119 * Poolset is just being created - check if file exists
120 * and if we can read it.
122 int exists
= util_file_exists(pf
->part
->path
);
130 int ret
= badblocks_clear_all(pf
->part
->path
);
132 ERR("clearing bad blocks in the pool file failed -- '%s'",
138 pf
->part
->has_bad_blocks
= 0;
144 * badblocks_clear_poolset -- clears bad blocks in the pool set
147 badblocks_clear_poolset(struct pool_set
*set
, int create
)
149 LOG(3, "set %p create %i", set
, create
);
151 if (util_poolset_foreach_part_struct(set
, badblocks_clear_poolset_cb
,
156 set
->has_bad_blocks
= 0;
162 * badblocks_recovery_file_alloc -- allocate name of bad block recovery file,
163 * the allocated name has to be freed
167 badblocks_recovery_file_alloc(const char *file
, unsigned rep
, unsigned part
)
169 LOG(3, "file %s rep %u part %u", file
, rep
, part
);
174 sprintf(bbs_suffix
, "_r%u_p%u_badblocks.txt", rep
, part
);
176 size_t len_file
= strlen(file
);
177 size_t len_bbs_suffix
= strlen(bbs_suffix
);
178 size_t len_path
= len_file
+ len_bbs_suffix
;
180 path
= Malloc(len_path
+ 1);
187 strcat(path
, bbs_suffix
);
193 * badblocks_recovery_file_exists -- check if any bad block recovery file exists
196 * 0 when there are no bad block recovery files and
197 * 1 when there is at least one bad block recovery file.
200 badblocks_recovery_file_exists(struct pool_set
*set
)
202 LOG(3, "set %p", set
);
204 int recovery_file_exists
= 0;
206 for (unsigned r
= 0; r
< set
->nreplicas
; ++r
) {
207 struct pool_replica
*rep
= set
->replica
[r
];
209 /* XXX: not supported yet */
213 for (unsigned p
= 0; p
< rep
->nparts
; ++p
) {
214 const char *path
= PART(rep
, p
)->path
;
216 int exists
= util_file_exists(path
);
221 /* part file does not exist - skip it */
226 badblocks_recovery_file_alloc(set
->path
, r
, p
);
227 if (rec_file
== NULL
) {
229 "allocating name of bad block recovery file failed");
233 exists
= util_file_exists(rec_file
);
240 LOG(3, "bad block recovery file exists: %s",
243 recovery_file_exists
= 1;
248 if (recovery_file_exists
)