@@ -11,7 +11,9 @@ import (
11
11
// ClearBlock fully resets a block device or disk file using the most efficient mechanism available.
12
12
// For files, it will truncate them down to zero and back to their original size.
13
13
// For blocks, it will attempt a variety of discard options, validating the result with marker files and eventually fallback to full zero-ing.
14
- func ClearBlock (blockPath string ) error {
14
+ //
15
+ // An offset can be specified to only reset a part of a device.
16
+ func ClearBlock (blockPath string , blockOffset int64 ) error {
15
17
// Open the block device for checking.
16
18
fd , err := os .OpenFile (blockPath , os .O_RDWR , 0644 )
17
19
if err != nil {
@@ -39,7 +41,7 @@ func ClearBlock(blockPath string) error {
39
41
40
42
if ! IsBlockdev (st .Mode ()) {
41
43
// For files, truncate them.
42
- err := fd .Truncate (0 )
44
+ err := fd .Truncate (blockOffset )
43
45
if err != nil {
44
46
return err
45
47
}
@@ -55,20 +57,47 @@ func ClearBlock(blockPath string) error {
55
57
// Blocks are trickier to reset with options varying based on disk features.
56
58
// We use a set of 3 markers to validate whether it was reset.
57
59
marker := []byte ("INCUS" )
58
- markerOffsetStart := int64 (0 )
59
- markerOffsetMiddle := size / 2
60
- markerOffsetEnd := size - 10
60
+ markerLength := int64 (len (marker ))
61
+ markerOffsetStart := blockOffset
62
+ markerOffsetMiddle := blockOffset + ((size - blockOffset ) / 2 )
63
+ markerOffsetEnd := size - markerLength
64
+
65
+ if markerOffsetStart + markerLength > size {
66
+ // No markers can fit.
67
+ markerOffsetStart = - 1
68
+ markerOffsetMiddle = - 1
69
+ markerOffsetEnd = - 1
70
+ } else {
71
+ if markerOffsetMiddle <= markerOffsetStart + markerLength {
72
+ // Middle marker goes over start marker.
73
+ markerOffsetMiddle = - 1
74
+ }
75
+
76
+ if markerOffsetEnd <= markerOffsetMiddle + markerLength {
77
+ // End marker goes over middle marker.
78
+ markerOffsetEnd = - 1
79
+ }
80
+
81
+ if markerOffsetEnd <= markerOffsetStart + markerLength {
82
+ // End marker goes over start marker.
83
+ markerOffsetEnd = - 1
84
+ }
85
+ }
61
86
62
87
writeMarkers := func (fd * os.File ) error {
63
88
for _ , offset := range []int64 {markerOffsetStart , markerOffsetMiddle , markerOffsetEnd } {
89
+ if offset < 0 {
90
+ continue
91
+ }
92
+
64
93
// Write the marker at the set offset.
65
94
n , err := fd .WriteAt (marker , offset )
66
95
if err != nil {
67
96
return err
68
97
}
69
98
70
- if n != len ( marker ) {
71
- return fmt .Errorf ("Only managed to write %d bytes out of %d of the %d offset marker" , n , len ( marker ) , offset )
99
+ if n != int ( markerLength ) {
100
+ return fmt .Errorf ("Only managed to write %d bytes out of %d of the %d offset marker" , n , markerLength , offset )
72
101
}
73
102
}
74
103
@@ -79,17 +108,21 @@ func ClearBlock(blockPath string) error {
79
108
found := 0
80
109
81
110
for _ , offset := range []int64 {markerOffsetStart , markerOffsetMiddle , markerOffsetEnd } {
82
- fmt .Printf ("offset=%d\n " , offset )
83
- buf := make ([]byte , 5 )
111
+ if offset < 0 {
112
+ found ++
113
+ continue
114
+ }
115
+
116
+ buf := make ([]byte , markerLength )
84
117
85
118
// Read the marker from the offset.
86
119
n , err := fd .ReadAt (buf , offset )
87
120
if err != nil {
88
121
return found , err
89
122
}
90
123
91
- if n != len ( marker ) {
92
- return found , fmt .Errorf ("Only managed to read %d bytes out of %d of the %d offset marker" , n , len ( marker ) , offset )
124
+ if n != int ( markerLength ) {
125
+ return found , fmt .Errorf ("Only managed to read %d bytes out of %d of the %d offset marker" , n , markerLength , offset )
93
126
}
94
127
95
128
// Check if we found it.
@@ -120,7 +153,7 @@ func ClearBlock(blockPath string) error {
120
153
_ = fd .Close ()
121
154
122
155
// Attempt a secure discard run.
123
- _ , err = subprocess .RunCommand ("blkdiscard" , "-f" , "-s" , blockPath )
156
+ _ , err = subprocess .RunCommand ("blkdiscard" , "-f" , "-o" , fmt . Sprintf ( "%d" , blockOffset ), "- s" , blockPath )
124
157
if err == nil {
125
158
// Check if the markers are gone.
126
159
fd , err := os .Open (blockPath )
@@ -145,7 +178,7 @@ func ClearBlock(blockPath string) error {
145
178
}
146
179
147
180
// Attempt a regular discard run.
148
- _ , err = subprocess .RunCommand ("blkdiscard" , "-f" , blockPath )
181
+ _ , err = subprocess .RunCommand ("blkdiscard" , "-f" , "-o" , fmt . Sprintf ( "%d" , blockOffset ), blockPath )
149
182
if err == nil {
150
183
// Check if the markers are gone.
151
184
fd , err := os .Open (blockPath )
@@ -170,7 +203,7 @@ func ClearBlock(blockPath string) error {
170
203
}
171
204
172
205
// Attempt device zero-ing.
173
- _ , err = subprocess .RunCommand ("blkdiscard" , "-f" , "-z" , blockPath )
206
+ _ , err = subprocess .RunCommand ("blkdiscard" , "-f" , "-o" , fmt . Sprintf ( "%d" , blockOffset ), "- z" , blockPath )
174
207
if err == nil {
175
208
// Check if the markers are gone.
176
209
fd , err := os .Open (blockPath )
@@ -209,12 +242,17 @@ func ClearBlock(blockPath string) error {
209
242
210
243
defer fd .Close ()
211
244
212
- n , err := io .CopyN (fd , zero , size )
245
+ _ , err = fd .Seek (blockOffset , 0 )
246
+ if err != nil {
247
+ return err
248
+ }
249
+
250
+ n , err := io .CopyN (fd , zero , size - blockOffset )
213
251
if err != nil {
214
252
return err
215
253
}
216
254
217
- if n != size {
255
+ if n != ( size - blockOffset ) {
218
256
return fmt .Errorf ("Only managed to reset %d bytes out of %d" , n , size )
219
257
}
220
258
0 commit comments