Skip to content

Commit d39cb7f

Browse files
ivan386gammazero
andauthored
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 <[email protected]>
1 parent 78ef5e9 commit d39cb7f

File tree

3 files changed

+90
-9
lines changed

3 files changed

+90
-9
lines changed

core/commands/filestore.go

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ var FileStoreCmd = &cmds.Command{
2727
}
2828

2929
const (
30-
fileOrderOptionName = "file-order"
30+
fileOrderOptionName = "file-order"
31+
removeBadBlocksOptionName = "remove-bad-blocks"
3132
)
3233

3334
var lsFileStore = &cmds.Command{
@@ -57,7 +58,7 @@ The output is:
5758
}
5859
args := req.Arguments
5960
if len(args) > 0 {
60-
return listByArgs(req.Context, res, fs, args)
61+
return listByArgs(req.Context, res, fs, args, false)
6162
}
6263

6364
fileOrder, _ := req.Options[fileOrderOptionName].(bool)
@@ -108,7 +109,7 @@ otherwise verify all objects.
108109
109110
The output is:
110111
111-
<status> <hash> <size> <path> <offset>
112+
<status> <hash> <size> <path> <offset> [<action>]
112113
113114
Where <status> is one of:
114115
ok: the block can be reconstructed
@@ -118,6 +119,10 @@ error: there was some other problem reading the file
118119
missing: <obj> could not be found in the filestore
119120
ERROR: internal error, most likely due to a corrupt database
120121
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+
121126
For ERROR entries the error will also be printed to stderr.
122127
`,
123128
},
@@ -126,15 +131,18 @@ For ERROR entries the error will also be printed to stderr.
126131
},
127132
Options: []cmds.Option{
128133
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."),
129135
},
130136
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
131137
_, fs, err := getFilestore(env)
132138
if err != nil {
133139
return err
134140
}
141+
142+
removeBadBlocks, _ := req.Options[removeBadBlocksOptionName].(bool)
135143
args := req.Arguments
136144
if len(args) > 0 {
137-
return listByArgs(req.Context, res, fs, args)
145+
return listByArgs(req.Context, res, fs, args, removeBadBlocks)
138146
}
139147

140148
fileOrder, _ := req.Options[fileOrderOptionName].(bool)
@@ -148,7 +156,14 @@ For ERROR entries the error will also be printed to stderr.
148156
if r == nil {
149157
break
150158
}
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 {
152167
return err
153168
}
154169
}
@@ -162,6 +177,8 @@ For ERROR entries the error will also be printed to stderr.
162177
return err
163178
}
164179

180+
req := res.Request()
181+
removeBadBlocks, _ := req.Options[removeBadBlocksOptionName].(bool)
165182
for {
166183
v, err := res.Next()
167184
if err != nil {
@@ -179,7 +196,16 @@ For ERROR entries the error will also be printed to stderr.
179196
if list.Status == filestore.StatusOtherError {
180197
fmt.Fprintf(os.Stderr, "%s\n", list.ErrorMsg)
181198
}
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+
}
183209
}
184210
},
185211
},
@@ -236,7 +262,7 @@ func getFilestore(env cmds.Environment) (*core.IpfsNode, *filestore.Filestore, e
236262
return n, fs, err
237263
}
238264

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 {
240266
for _, arg := range args {
241267
c, err := cid.Decode(arg)
242268
if err != nil {
@@ -250,7 +276,14 @@ func listByArgs(ctx context.Context, res cmds.ResponseEmitter, fs *filestore.Fil
250276
continue
251277
}
252278
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 {
254287
return err
255288
}
256289
}

docs/changelogs/v0.36.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ This release was brought to you by the [Shipyard](http://ipshipyard.com/) team.
1010

1111
- [Overview](#overview)
1212
- [🔦 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)
1415
- [📦️ Important dependency updates](#-important-dependency-updates)
1516
- [📝 Changelog](#-changelog)
1617
- [👨‍👩‍👧‍👦 Contributors](#-contributors)
@@ -28,6 +29,10 @@ go-log v2 has been out for quite a while now and it is time to deprecate v1.
2829
- Fixes `ipfs log tail`
2930
- Removes support for `ContextWithLoggable` as this is not needed for tracing-like functionality
3031

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+
3136
#### 📦️ Important dependency updates
3237

3338
- 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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,20 @@ EOF
6363

6464
sort < verify_expect_file_order > verify_expect_key_order
6565

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+
6680
IPFS_CMD="ipfs"
6781

6882
test_filestore_adds() {
@@ -155,6 +169,27 @@ test_filestore_verify() {
155169
test_init_dataset
156170
}
157171

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+
158193
test_filestore_dups() {
159194
# make sure the filestore is in a clean state
160195
test_filestore_state
@@ -179,6 +214,8 @@ test_filestore_verify
179214

180215
test_filestore_dups
181216

217+
test_filestore_rm_bad_blocks
218+
182219
#
183220
# With daemon
184221
#
@@ -197,6 +234,8 @@ test_filestore_dups
197234

198235
test_kill_ipfs_daemon
199236

237+
test_filestore_rm_bad_blocks
238+
200239
##
201240
## base32
202241
##
@@ -243,6 +282,8 @@ test_filestore_verify
243282

244283
test_filestore_dups
245284

285+
test_filestore_rm_bad_blocks
286+
246287
#
247288
# With daemon
248289
#
@@ -263,6 +304,8 @@ test_kill_ipfs_daemon
263304

264305
test_done
265306

307+
test_filestore_rm_bad_blocks
308+
266309
##
267310

268311
test_done

0 commit comments

Comments
 (0)