@cryptotaxi247 / kubo / commits / d39cb7f57

Ivan386/filestore fix (#7474)

* ipfs filestore fix [<obj>]... - Verify objects in filestore and remove bad links * Option --remove-bad-blocks for 'ipfs filestore verify' * fix call to DeleteBlock * action of --remove-bad-blocks in output only when option specified * Add sharness test for removing bad blocks --------- Co-authored-by: Andrew Gillis <11790789+gammazero@users.noreply.github.com>

Ivan committed Jun 5, 2025 at 00:04 UTC d39cb7f57554e2a41506b6022fa27dd58cb6215d
3 files changed +90 -9
core/commands/filestore.go
+41 -8
@@ -27,7 +27,8 @@ var FileStoreCmd = &cmds.Command{
27 }
28
29 const (
30 - fileOrderOptionName = "file-order"
30 + fileOrderOptionName = "file-order"
31 + removeBadBlocksOptionName = "remove-bad-blocks"
32 )
33
34 var lsFileStore = &cmds.Command{
@@ -57,7 +58,7 @@ The output is:
58 }
59 args := req.Arguments
60 if len(args) > 0 {
60 - return listByArgs(req.Context, res, fs, args)
61 + return listByArgs(req.Context, res, fs, args, false)
62 }
63
64 fileOrder, _ := req.Options[fileOrderOptionName].(bool)
@@ -108,7 +109,7 @@ otherwise verify all objects.
109
110 The output is:
111
111 -<status> <hash> <size> <path> <offset>
112 +<status> <hash> <size> <path> <offset> [<action>]
113
114 Where <status> is one of:
115 ok: the block can be reconstructed
@@ -118,6 +119,10 @@ error: there was some other problem reading the file
119 missing: <obj> could not be found in the filestore
120 ERROR: internal error, most likely due to a corrupt database
121
122 +Where <action> is present only when removing bad blocks and is one of:
123 +remove: link to the block will be removed from datastore
124 +keep: keep link, nothing to do
125 +
126 For ERROR entries the error will also be printed to stderr.
127 `,
128 },
@@ -126,15 +131,18 @@ For ERROR entries the error will also be printed to stderr.
131 },
132 Options: []cmds.Option{
133 cmds.BoolOption(fileOrderOptionName, "verify the objects based on the order of the backing file"),
134 + cmds.BoolOption(removeBadBlocksOptionName, "remove bad blocks. WARNING: This may remove pinned data. You should run 'ipfs pin verify' after running this command and correct any issues."),
135 },
136 Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
137 _, fs, err := getFilestore(env)
138 if err != nil {
139 return err
140 }
141 +
142 + removeBadBlocks, _ := req.Options[removeBadBlocksOptionName].(bool)
143 args := req.Arguments
144 if len(args) > 0 {
137 - return listByArgs(req.Context, res, fs, args)
145 + return listByArgs(req.Context, res, fs, args, removeBadBlocks)
146 }
147
148 fileOrder, _ := req.Options[fileOrderOptionName].(bool)
@@ -148,7 +156,14 @@ For ERROR entries the error will also be printed to stderr.
156 if r == nil {
157 break
158 }
151 - if err := res.Emit(r); err != nil {
159 +
160 + if removeBadBlocks && (r.Status != filestore.StatusOk) && (r.Status != filestore.StatusOtherError) {
161 + if err = fs.FileManager().DeleteBlock(req.Context, r.Key); err != nil {
162 + return err
163 + }
164 + }
165 +
166 + if err = res.Emit(r); err != nil {
167 return err
168 }
169 }
@@ -162,6 +177,8 @@ For ERROR entries the error will also be printed to stderr.
177 return err
178 }
179
180 + req := res.Request()
181 + removeBadBlocks, _ := req.Options[removeBadBlocksOptionName].(bool)
182 for {
183 v, err := res.Next()
184 if err != nil {
@@ -179,7 +196,16 @@ For ERROR entries the error will also be printed to stderr.
196 if list.Status == filestore.StatusOtherError {
197 fmt.Fprintf(os.Stderr, "%s\n", list.ErrorMsg)
198 }
182 - fmt.Fprintf(os.Stdout, "%s %s\n", list.Status.Format(), list.FormatLong(enc.Encode))
199 +
200 + if removeBadBlocks {
201 + action := "keep"
202 + if removeBadBlocks && (list.Status != filestore.StatusOk) && (list.Status != filestore.StatusOtherError) {
203 + action = "remove"
204 + }
205 + fmt.Fprintf(os.Stdout, "%s %s %s\n", list.Status.Format(), list.FormatLong(enc.Encode), action)
206 + } else {
207 + fmt.Fprintf(os.Stdout, "%s %s\n", list.Status.Format(), list.FormatLong(enc.Encode))
208 + }
209 }
210 },
211 },
@@ -236,7 +262,7 @@ func getFilestore(env cmds.Environment) (*core.IpfsNode, *filestore.Filestore, e
262 return n, fs, err
263 }
264
239 -func listByArgs(ctx context.Context, res cmds.ResponseEmitter, fs *filestore.Filestore, args []string) error {
265 +func listByArgs(ctx context.Context, res cmds.ResponseEmitter, fs *filestore.Filestore, args []string, removeBadBlocks bool) error {
266 for _, arg := range args {
267 c, err := cid.Decode(arg)
268 if err != nil {
@@ -250,7 +276,14 @@ func listByArgs(ctx context.Context, res cmds.ResponseEmitter, fs *filestore.Fil
276 continue
277 }
278 r := filestore.Verify(ctx, fs, c)
253 - if err := res.Emit(r); err != nil {
279 +
280 + if removeBadBlocks && (r.Status != filestore.StatusOk) && (r.Status != filestore.StatusOtherError) {
281 + if err = fs.FileManager().DeleteBlock(ctx, r.Key); err != nil {
282 + return err
283 + }
284 + }
285 +
286 + if err = res.Emit(r); err != nil {
287 return err
288 }
289 }
docs/changelogs/v0.36.md
+6 -1
@@ -10,7 +10,8 @@ This release was brought to you by the [Shipyard](http://ipshipyard.com/) team.
10
11 - [Overview](#overview)
12 - [🔦 Highlights](#-highlights)
13 - - [Update go-log to v2](#update-go-log-to-v2)
13 + - [Update go-log to v2](#update-go-log-to-v2
14 + - [Option for filestore command to remove bad blocks](#option-for-filestore-command-to-remove-bad-blocks)
15 - [📦️ Important dependency updates](#-important-dependency-updates)
16 - [📝 Changelog](#-changelog)
17 - [👨‍👩‍👧‍👦 Contributors](#-contributors)
@@ -28,6 +29,10 @@ go-log v2 has been out for quite a while now and it is time to deprecate v1.
29 - Fixes `ipfs log tail`
30 - Removes support for `ContextWithLoggable` as this is not needed for tracing-like functionality
31
32 +#### Option for filestore command to remove bad blocks
33 +
34 +The `filestore` command has a new option, `--remove-bad-blocks`, to verify objects in the filestore and remove those that fail verification.
35 +
36 #### 📦️ Important dependency updates
37
38 - update `go-libp2p-kad-dht` to [v0.33.0](https://github.com/libp2p/go-libp2p-kad-dht/releases/tag/v0.33.0)
test/sharness/t0271-filestore-utils.sh
+43
@@ -63,6 +63,20 @@ EOF
63
64 sort < verify_expect_file_order > verify_expect_key_order
65
66 +cat <<EOF > verify_rm_expect
67 +ok bafkreic2wqrsyr3y3qgzbvufen2w25r3p3zljckqyxkpcagsxz3zdcosd4 10000 somedir/file2 0 keep
68 +ok bafkreidx7ivgllulfkzyoo4oa7dfrg4mjmudg2qgdivoooj4s7lh3m5nqu 1000 somedir/file1 0 keep
69 +changed bafkreiemzfmzws23c2po4m6deiueknqfty7r3voes3e3zujmobrooc2ngm 262144 somedir/file3 0 remove
70 +changed bafkreifjcthslybjizk36xffcsb32fsbguxz3ptkl7723wz4u3qikttmam 213568 somedir/file3 786432 remove
71 +changed bafkreigl2pjptgxz6cexcnua56zc5dwsyrc4ph2eulmcb634oes6gzvmuy 262144 somedir/file3 524288 remove
72 +changed bafkreihgm53yhxn427lnfdwhqgpawc62qejog7gega5kqb6uwbyhjm47hu 262144 somedir/file3 262144 remove
73 +EOF
74 +
75 +cat <<EOF > verify_after_rm_expect
76 +ok bafkreic2wqrsyr3y3qgzbvufen2w25r3p3zljckqyxkpcagsxz3zdcosd4 10000 somedir/file2 0
77 +ok bafkreidx7ivgllulfkzyoo4oa7dfrg4mjmudg2qgdivoooj4s7lh3m5nqu 1000 somedir/file1 0
78 +EOF
79 +
80 IPFS_CMD="ipfs"
81
82 test_filestore_adds() {
@@ -155,6 +169,27 @@ test_filestore_verify() {
169 test_init_dataset
170 }
171
172 +test_filestore_rm_bad_blocks() {
173 + test_filestore_state
174 +
175 + test_expect_success "change first bit of file" '
176 + dd if=/dev/zero of=somedir/file3 bs=1024 count=1
177 + '
178 +
179 + test_expect_success "'$IPFS_CMD filestore verify --remove-bad-blocks' shows changed file removed" '
180 + $IPFS_CMD filestore verify --remove-bad-blocks > verify_rm_actual &&
181 + test_cmp verify_rm_expect verify_rm_actual
182 + '
183 +
184 + test_expect_success "'$IPFS_CMD filestore verify' shows only files that were not removed" '
185 + $IPFS_CMD filestore verify > verify_after &&
186 + test_cmp verify_after_rm_expect verify_after
187 + '
188 +
189 + # reset the state for the next test
190 + test_init_dataset
191 +}
192 +
193 test_filestore_dups() {
194 # make sure the filestore is in a clean state
195 test_filestore_state
@@ -179,6 +214,8 @@ test_filestore_verify
214
215 test_filestore_dups
216
217 +test_filestore_rm_bad_blocks
218 +
219 #
220 # With daemon
221 #
@@ -197,6 +234,8 @@ test_filestore_dups
234
235 test_kill_ipfs_daemon
236
237 +test_filestore_rm_bad_blocks
238 +
239 ##
240 ## base32
241 ##
@@ -243,6 +282,8 @@ test_filestore_verify
282
283 test_filestore_dups
284
285 +test_filestore_rm_bad_blocks
286 +
287 #
288 # With daemon
289 #
@@ -263,6 +304,8 @@ test_kill_ipfs_daemon
304
305 test_done
306
307 +test_filestore_rm_bad_blocks
308 +
309 ##
310
311 test_done