@@ -205,20 +205,54 @@ func insertBuffer(buffers []*FileBuffer, pos int, add ...*FileBuffer) []*FileBuf
205205}
206206
207207func (inode * Inode ) addBuffer (offset uint64 , data []byte , state int16 , copyData bool ) int64 {
208- allocated := int64 (0 )
209-
210- start := locateBuffer (inode .buffers , offset )
211208 dataLen := uint64 (len (data ))
212209 endOffset := offset + dataLen
213210
214211 // Remove intersecting parts as they're being overwritten
215- // If we're inserting a clean buffer, don't remove dirty ones
212+ allocated := inode .removeRange (offset , dataLen , state )
213+
214+ // Insert non-overlapping parts of the buffer
215+ curOffset := offset
216+ dataPtr := & BufferPointer {
217+ mem : data ,
218+ refs : 0 ,
219+ }
220+ start := locateBuffer (inode .buffers , offset )
221+ pos := start
222+ for ; pos < len (inode .buffers ) && curOffset < endOffset ; pos ++ {
223+ b := inode .buffers [pos ]
224+ if b .offset + b .length <= offset {
225+ continue
226+ }
227+ if b .offset > curOffset {
228+ // insert curOffset->min(b.offset,endOffset)
229+ nextEnd := b .offset
230+ if nextEnd > endOffset {
231+ nextEnd = endOffset
232+ }
233+ allocated += inode .insertBuffer (pos , curOffset , data [curOffset - offset : nextEnd - offset ], state , copyData , dataPtr )
234+ }
235+ curOffset = b .offset + b .length
236+ }
237+ if curOffset < endOffset {
238+ // Insert curOffset->endOffset
239+ allocated += inode .insertBuffer (pos , curOffset , data [curOffset - offset : ], state , copyData , dataPtr )
240+ }
241+
242+ return allocated
243+ }
244+
245+ // Remove buffers in range (offset..size)
246+ func (inode * Inode ) removeRange (offset , size uint64 , state int16 ) (allocated int64 ) {
247+ start := locateBuffer (inode .buffers , offset )
248+ endOffset := offset + size
216249 for pos := start ; pos < len (inode .buffers ); pos ++ {
217250 b := inode .buffers [pos ]
218251 if b .offset >= endOffset {
219252 break
220253 }
221254 bufEnd := b .offset + b .length
255+ // If we're inserting a clean buffer, don't remove dirty ones
222256 if (state >= BUF_DIRTY || b .state < BUF_DIRTY ) && bufEnd > offset && endOffset > b .offset {
223257 if offset <= b .offset {
224258 if endOffset >= bufEnd {
@@ -284,35 +318,35 @@ func (inode *Inode) addBuffer(offset uint64, data []byte, state int16, copyData
284318 }
285319 }
286320 }
321+ return
322+ }
287323
288- // Insert non-overlapping parts of the buffer
289- curOffset := offset
290- dataPtr := & BufferPointer {
291- mem : data ,
292- refs : 0 ,
293- }
294- pos := start
295- for ; pos < len (inode .buffers ) && curOffset < endOffset ; pos ++ {
296- b := inode .buffers [pos ]
297- if b .offset + b .length <= offset {
298- continue
299- }
300- if b .offset > curOffset {
301- // insert curOffset->min(b.offset,endOffset)
302- nextEnd := b .offset
303- if nextEnd > endOffset {
304- nextEnd = endOffset
305- }
306- allocated += inode .insertBuffer (pos , curOffset , data [curOffset - offset : nextEnd - offset ], state , copyData , dataPtr )
307- }
308- curOffset = b .offset + b .length
309- }
310- if curOffset < endOffset {
311- // Insert curOffset->endOffset
312- allocated += inode .insertBuffer (pos , curOffset , data [curOffset - offset : ], state , copyData , dataPtr )
324+ func (inode * Inode ) zeroRange (offset , size uint64 ) (bool , int64 ) {
325+ // Check if it's already zeroed
326+ pos := locateBuffer (inode .buffers , offset )
327+ if pos < len (inode .buffers ) && inode .buffers [pos ].zero &&
328+ inode .buffers [pos ].offset == offset && inode .buffers [pos ].length == size {
329+ return false , 0
313330 }
314331
315- return allocated
332+ // Remove intersecting parts as they're being overwritten
333+ allocated := inode .removeRange (offset , size , BUF_DIRTY )
334+
335+ // Insert a zero buffer
336+ pos = locateBuffer (inode .buffers , offset )
337+ inode .buffers = insertBuffer (inode .buffers , pos , & FileBuffer {
338+ offset : offset ,
339+ dirtyID : atomic .AddUint64 (& inode .fs .bufferPool .curDirtyID , 1 ),
340+ state : BUF_DIRTY ,
341+ onDisk : false ,
342+ zero : true ,
343+ recency : 0 ,
344+ length : size ,
345+ data : nil ,
346+ ptr : nil ,
347+ })
348+
349+ return true , allocated
316350}
317351
318352func (inode * Inode ) ResizeUnlocked (newSize uint64 , zeroFill bool , finalizeFlushed bool ) {
0 commit comments