@@ -33,14 +33,35 @@ func NewBlockDeviceBackedFilePool(blockDevice blockdevice.BlockDevice, sectorAll
33
33
}
34
34
}
35
35
36
+ type zeroReaderAt struct {}
37
+
38
+ func (zeroReaderAt ) ReadAt (p []byte , off int64 ) (int , error ) {
39
+ for i := range p {
40
+ p [i ] = 0
41
+ }
42
+ return len (p ), nil
43
+ }
44
+
36
45
func (fp * blockDeviceBackedFilePool ) NewFile () (filesystem.FileReadWriter , error ) {
37
- return & blockDeviceBackedFile {
46
+ readLayer := NewReadLayer (& zeroReaderAt {}, 0 )
47
+ return fp .NewFileWithReadLayer (readLayer , 0 )
48
+ }
49
+
50
+ func (fp * blockDeviceBackedFilePool ) NewFileWithReadLayer (readLayer ReadLayer , sizeBytes uint64 ) (filesystem.FileReadWriter , error ) {
51
+ file := & blockDeviceBackedFile {
38
52
fp : fp ,
39
- }, nil
53
+ rl : readLayer ,
54
+ }
55
+ err := file .Truncate (int64 (sizeBytes ))
56
+ if err != nil {
57
+ return nil , err
58
+ }
59
+ return file , nil
40
60
}
41
61
42
62
type blockDeviceBackedFile struct {
43
63
fp * blockDeviceBackedFilePool
64
+ rl ReadLayer
44
65
sizeBytes uint64
45
66
sectors []uint32
46
67
}
@@ -172,23 +193,17 @@ func (f *blockDeviceBackedFile) GetNextRegionOffset(off int64, regionType filesy
172
193
func (f * blockDeviceBackedFile ) readFromSectors (p []byte , sectorIndex , lastSectorIndex , offsetWithinSector int ) (int , error ) {
173
194
if sectorIndex >= len (f .sectors ) {
174
195
// Attempted to read from a hole located at the
175
- // end of the file. Fill up all of the remaining
176
- // space with zero bytes.
177
- for i := 0 ; i < len (p ); i ++ {
178
- p [i ] = 0
179
- }
180
- return len (p ), nil
196
+ // end of the file. Delegate to ReadLayer.
197
+ offset := f .fp .sectorSizeBytes * sectorIndex + offsetWithinSector
198
+ return f .rl .ReadAt (p , int64 (offset ))
181
199
}
182
200
183
201
sector , sectorsToRead := f .getSectorsContiguous (sectorIndex , lastSectorIndex )
184
202
p = f .limitBufferToSectorBoundary (p , sectorsToRead , offsetWithinSector )
185
203
if sector == 0 {
186
204
// Attempted to read from a sparse region of the file.
187
- // Fill in zero bytes.
188
- for i := 0 ; i < len (p ); i ++ {
189
- p [i ] = 0
190
- }
191
- return len (p ), nil
205
+ offset := f .fp .sectorSizeBytes * sectorIndex + offsetWithinSector
206
+ return f .rl .ReadAt (p , int64 (offset ))
192
207
}
193
208
194
209
// Attempted to read from a region of the file that contains
@@ -267,6 +282,9 @@ func (f *blockDeviceBackedFile) Truncate(size int64) error {
267
282
if size < 0 {
268
283
return status .Errorf (codes .InvalidArgument , "Negative truncation size: %d" , size )
269
284
}
285
+ if err := f .rl .Truncate (size ); err != nil {
286
+ return fmt .Errorf ("read layer truncate failed: %w" , err )
287
+ }
270
288
271
289
sectorIndex := int (size / int64 (f .fp .sectorSizeBytes ))
272
290
offsetWithinSector := int (size % int64 (f .fp .sectorSizeBytes ))
@@ -299,7 +317,7 @@ func (f *blockDeviceBackedFile) Truncate(size int64) error {
299
317
// writeToNewSectors is used to write data into new sectors. This
300
318
// function is called when holes in a sparse file are filled up or when
301
319
// data is appended to the end of a file.
302
- func (f * blockDeviceBackedFile ) writeToNewSectors (p []byte , offsetWithinSector int ) (int , uint32 , int , error ) {
320
+ func (f * blockDeviceBackedFile ) writeToNewSectors (p []byte , fromSector int , offsetWithinSector int ) (int , uint32 , int , error ) {
303
321
// Allocate space to store the data.
304
322
sectorsToAllocate := int ((uint64 (offsetWithinSector ) + uint64 (len (p )) + uint64 (f .fp .sectorSizeBytes ) - 1 ) / uint64 (f .fp .sectorSizeBytes ))
305
323
firstSector , sectorsAllocated , err := f .fp .sectorAllocator .AllocateContiguous (sectorsToAllocate )
@@ -314,10 +332,15 @@ func (f *blockDeviceBackedFile) writeToNewSectors(p []byte, offsetWithinSector i
314
332
nWritten := len (p )
315
333
316
334
// Write the first sector separately when we need to introduce
317
- // leading zero padding.
335
+ // leading read layer padding.
318
336
sector := firstSector
319
337
if offsetWithinSector > 0 {
320
338
buf := make ([]byte , f .fp .sectorSizeBytes )
339
+ logicalOffset := fromSector * f .fp .sectorSizeBytes
340
+ if _ , err := f .rl .ReadAt (buf [:offsetWithinSector ], int64 (logicalOffset )); err != nil {
341
+ f .fp .sectorAllocator .FreeContiguous (firstSector , sectorsAllocated )
342
+ return 0 , 0 , 0 , err
343
+ }
321
344
nWritten := copy (buf [offsetWithinSector :], p )
322
345
if _ , err := f .fp .blockDevice .WriteAt (buf , f .toDeviceOffset (sector , 0 )); err != nil {
323
346
f .fp .sectorAllocator .FreeContiguous (firstSector , sectorsAllocated )
@@ -340,9 +363,14 @@ func (f *blockDeviceBackedFile) writeToNewSectors(p []byte, offsetWithinSector i
340
363
}
341
364
342
365
// Write the last sector separately when we need to introduce
343
- // trailing zero padding.
366
+ // trailing read layer padding.
344
367
if len (p ) > 0 {
345
368
buf := make ([]byte , f .fp .sectorSizeBytes )
369
+ logicalOffset := uint32 (len (p )) + (sector - firstSector )* uint32 (f .fp .sectorSizeBytes )
370
+ if _ , err := f .rl .ReadAt (buf [len (p ):], int64 (logicalOffset )); err != nil {
371
+ f .fp .sectorAllocator .FreeContiguous (firstSector , sectorsAllocated )
372
+ return 0 , 0 , 0 , err
373
+ }
346
374
copy (buf , p )
347
375
if _ , err := f .fp .blockDevice .WriteAt (buf , f .toDeviceOffset (sector , 0 )); err != nil {
348
376
f .fp .sectorAllocator .FreeContiguous (firstSector , sectorsAllocated )
@@ -375,7 +403,7 @@ func (f *blockDeviceBackedFile) writeToSectors(p []byte, sectorIndex, lastSector
375
403
// Attempted to write past the end-of-file or within a
376
404
// hole located at the end of a sparse file. Allocate
377
405
// space and grow the file.
378
- bytesWritten , firstSector , sectorsAllocated , err := f .writeToNewSectors (p , offsetWithinSector )
406
+ bytesWritten , firstSector , sectorsAllocated , err := f .writeToNewSectors (p , sectorIndex , offsetWithinSector )
379
407
if err != nil {
380
408
return 0 , err
381
409
}
@@ -389,7 +417,7 @@ func (f *blockDeviceBackedFile) writeToSectors(p []byte, sectorIndex, lastSector
389
417
if sector == 0 {
390
418
// Attempted to write to a hole within a sparse file.
391
419
// Allocate space and insert sectors into the file.
392
- bytesWritten , firstSector , sectorsAllocated , err := f .writeToNewSectors (p , offsetWithinSector )
420
+ bytesWritten , firstSector , sectorsAllocated , err := f .writeToNewSectors (p , sectorIndex , offsetWithinSector )
393
421
if err != nil {
394
422
return 0 , err
395
423
}
0 commit comments