seaweedfs/weed/mount/weedfs_file_lseek.go
Chris Lu d4566d4aaa
more solid weed mount (#4089)
* compare chunks by timestamp

* fix slab clearing error

* fix test compilation

* move oldest chunk to sealed, instead of by fullness

* lock on fh.entryViewCache

* remove verbose logs

* revert slat clearing

* less logs

* less logs

* track write and read by timestamp

* remove useless logic

* add entry lock on file handle release

* use mem chunk only, swap file chunk has problems

* comment out code that maybe used later

* add debug mode to compare data read and write

* more efficient readResolvedChunks with linked list

* small optimization

* fix test compilation

* minor fix on writer

* add SeparateGarbageChunks

* group chunks into sections

* turn off debug mode

* fix tests

* fix tests

* tmp enable swap file chunk

* Revert "tmp enable swap file chunk"

This reverts commit 985137ec47.

* simple refactoring

* simple refactoring

* do not re-use swap file chunk. Sealed chunks should not be re-used.

* comment out debugging facilities

* either mem chunk or swap file chunk is fine now

* remove orderedMutex  as *semaphore.Weighted

not found impactful

* optimize size calculation for changing large files

* optimize performance to avoid going through the long list of chunks

* still problems with swap file chunk

* rename

* tiny optimization

* swap file chunk save only successfully read data

* fix

* enable both mem and swap file chunk

* resolve chunks with range

* rename

* fix chunk interval list

* also change file handle chunk group when adding chunks

* pick in-active chunk with time-decayed counter

* fix compilation

* avoid nil with empty fh.entry

* refactoring

* rename

* rename

* refactor visible intervals to *list.List

* refactor chunkViews to *list.List

* add IntervalList for generic interval list

* change visible interval to use IntervalList in generics

* cahnge chunkViews to *IntervalList[*ChunkView]

* use NewFileChunkSection to create

* rename variables

* refactor

* fix renaming leftover

* renaming

* renaming

* add insert interval

* interval list adds lock

* incrementally add chunks to readers

Fixes:
1. set start and stop offset for the value object
2. clone the value object
3. use pointer instead of copy-by-value when passing to interval.Value
4. use insert interval since adding chunk could be out of order

* fix tests compilation

* fix tests compilation
2023-01-02 23:20:45 -08:00

75 lines
1.8 KiB
Go

package mount
import (
"syscall"
"github.com/hanwen/go-fuse/v2/fuse"
"github.com/seaweedfs/seaweedfs/weed/filer"
"github.com/seaweedfs/seaweedfs/weed/glog"
)
// These are non-POSIX extensions
const (
SEEK_DATA uint32 = 3 // seek to next data after the offset
SEEK_HOLE uint32 = 4 // seek to next hole after the offset
ENXIO = fuse.Status(syscall.ENXIO)
)
// Lseek finds next data or hole segments after the specified offset
// See https://man7.org/linux/man-pages/man2/lseek.2.html
func (wfs *WFS) Lseek(cancel <-chan struct{}, in *fuse.LseekIn, out *fuse.LseekOut) fuse.Status {
// not a documented feature
if in.Padding != 0 {
return fuse.EINVAL
}
if in.Whence != SEEK_DATA && in.Whence != SEEK_HOLE {
return fuse.EINVAL
}
// file must exist
fh := wfs.GetHandle(FileHandleId(in.Fh))
if fh == nil {
return fuse.EBADF
}
// lock the file until the proper offset was calculated
fh.Lock()
defer fh.Unlock()
fh.entryLock.Lock()
defer fh.entryLock.Unlock()
fileSize := int64(filer.FileSize(fh.GetEntry()))
offset := max(int64(in.Offset), 0)
glog.V(4).Infof(
"Lseek %s fh %d in [%d,%d], whence %d",
fh.FullPath(), fh.fh, offset, fileSize, in.Whence,
)
// can neither seek beyond file nor seek to a hole at the end of the file with SEEK_DATA
if offset > fileSize {
return ENXIO
} else if in.Whence == SEEK_DATA && offset == fileSize {
return ENXIO
}
// search chunks for the offset
found, offset := fh.entryChunkGroup.SearchChunks(offset, fileSize, in.Whence)
if found {
out.Offset = uint64(offset)
return fuse.OK
}
// in case we found no exact matches, we return the recommended fallbacks, that is:
// original offset for SEEK_DATA or end of file for an implicit hole
if in.Whence == SEEK_DATA {
out.Offset = in.Offset
} else {
out.Offset = uint64(fileSize)
}
return fuse.OK
}