@@ -560,7 +560,7 @@ func (inode *Inode) OpenCacheFD() error {
560560// Load some inode data into memory
561561// Must be called with inode.mu taken
562562// Loaded range should be guarded against eviction by adding it into inode.readRanges
563- func (inode * Inode ) LoadRange (offset uint64 , size uint64 , readAheadSize uint64 , ignoreMemoryLimit bool ) (requestErr error ) {
563+ func (inode * Inode ) LoadRange (offset uint64 , size uint64 , readAheadSize uint64 , ignoreMemoryLimit bool ) (miss bool , requestErr error ) {
564564
565565 end := offset + readAheadSize
566566 if size > readAheadSize {
@@ -606,7 +606,7 @@ func (inode *Inode) LoadRange(offset uint64, size uint64, readAheadSize uint64,
606606 } else if b .state == BUF_FL_CLEARED {
607607 // Buffer is saved as a part and then removed
608608 // We must complete multipart upload to be able to read it back
609- return syscall .ESPIPE
609+ return true , syscall .ESPIPE
610610 }
611611 pos = b .offset + b .length
612612 }
@@ -713,7 +713,7 @@ func (inode *Inode) LoadRange(offset uint64, size uint64, readAheadSize uint64,
713713
714714 if len (diskRequests ) > 0 {
715715 if err := inode .OpenCacheFD (); err != nil {
716- return err
716+ return true , err
717717 }
718718 loadedFromDisk := uint64 (0 )
719719 for i := 0 ; i < len (diskRequests ); i += 2 {
@@ -722,7 +722,7 @@ func (inode *Inode) LoadRange(offset uint64, size uint64, readAheadSize uint64,
722722 data := make ([]byte , requestSize )
723723 _ , err := inode .DiskCacheFD .ReadAt (data , int64 (requestOffset ))
724724 if err != nil {
725- return err
725+ return true , err
726726 }
727727 pos := locateBuffer (inode .buffers , requestOffset )
728728 var ib * FileBuffer
@@ -754,6 +754,7 @@ func (inode *Inode) LoadRange(offset uint64, size uint64, readAheadSize uint64,
754754 return
755755 }
756756
757+ miss = true
757758 end = offset + size
758759 for {
759760 // Check if all buffers are loaded or if there is a read error
@@ -910,8 +911,8 @@ func (inode *Inode) IsRangeLocked(offset uint64, size uint64, onlyFlushing bool)
910911 return false
911912}
912913
913- func (inode * Inode ) CheckLoadRange (offset , size , readAheadSize uint64 , ignoreMemoryLimit bool ) error {
914- err := inode .LoadRange (offset , size , readAheadSize , ignoreMemoryLimit )
914+ func (inode * Inode ) CheckLoadRange (offset , size , readAheadSize uint64 , ignoreMemoryLimit bool ) ( bool , error ) {
915+ miss , err := inode .LoadRange (offset , size , readAheadSize , ignoreMemoryLimit )
915916 if err == syscall .ESPIPE {
916917 // Finalize multipart upload to get some flushed data back
917918 // We have to flush all parts that extend the file up until the last flushed part
@@ -933,15 +934,15 @@ func (inode *Inode) CheckLoadRange(offset, size, readAheadSize uint64, ignoreMem
933934 err = inode .SyncFile ()
934935 inode .mu .Lock ()
935936 if err == nil {
936- err = inode .LoadRange (offset , size , readAheadSize , ignoreMemoryLimit )
937+ _ , err = inode .LoadRange (offset , size , readAheadSize , ignoreMemoryLimit )
937938 }
938939 }
939940 inode .pauseWriters --
940941 if inode .readCond != nil {
941942 inode .readCond .Broadcast ()
942943 }
943944 }
944- return err
945+ return miss , err
945946}
946947
947948func appendZero (data [][]byte , zeroBuf []byte , zeroLen int ) [][]byte {
@@ -1022,7 +1023,6 @@ func (fh *FileHandle) ReadFile(sOffset int64, sLen int64) (data [][]byte, bytesR
10221023 defer fh .inode .UnlockRange (offset , end - offset , false )
10231024
10241025 // Check if anything requires to be loaded from the server
1025- var requestErr error
10261026 ra := fh .inode .fs .flags .ReadAheadKB * 1024
10271027 if fh .seqReadSize >= fh .inode .fs .flags .LargeReadCutoffKB * 1024 {
10281028 // Use larger readahead with 'pipelining'
@@ -1038,7 +1038,10 @@ func (fh *FileHandle) ReadFile(sOffset int64, sLen int64) (data [][]byte, bytesR
10381038 if ra + end > maxFileSize {
10391039 ra = 0
10401040 }
1041- requestErr = fh .inode .CheckLoadRange (offset , end - offset , ra , false )
1041+ miss , requestErr := fh .inode .CheckLoadRange (offset , end - offset , ra , false )
1042+ if ! miss {
1043+ atomic .AddInt64 (& fh .inode .fs .stats .readHits , 1 )
1044+ }
10421045 mappedErr := mapAwsError (requestErr )
10431046 if requestErr != nil {
10441047 err = requestErr
@@ -1676,7 +1679,7 @@ func (inode *Inode) FlushSmallObject() {
16761679 inode .LockRange (0 , sz , true )
16771680
16781681 if inode .CacheState == ST_MODIFIED {
1679- err := inode .LoadRange (0 , sz , 0 , true )
1682+ _ , err := inode .LoadRange (0 , sz , 0 , true )
16801683 mappedErr := mapAwsError (err )
16811684 if mappedErr == fuse .ENOENT || mappedErr == syscall .ERANGE {
16821685 // Object is deleted or resized remotely (416). Discard local version
@@ -1873,7 +1876,7 @@ func (inode *Inode) FlushPart(part uint64) {
18731876 // Ignore memory limit to not produce a deadlock when we need to free some memory
18741877 // by flushing objects, but we can't flush a part without allocating more memory
18751878 // for read-modify-write...
1876- err := inode .LoadRange (partOffset , partSize , 0 , true )
1879+ _ , err := inode .LoadRange (partOffset , partSize , 0 , true )
18771880 if err == syscall .ESPIPE {
18781881 // Part is partly evicted, we can't flush it
18791882 return
0 commit comments