MCPcopy
hub / github.com/google/gvisor / ReadInPages

Method ReadInPages

pkg/sentry/fsimpl/fuse/read_write.go:33–107  ·  view source on GitHub ↗

ReadInPages sends FUSE_READ requests for the size after round it up to a multiple of page size, blocks on it for reply, processes the reply and returns the payload (or joined payloads) as a byte slice. This is used for the general purpose reading. We do not support direct IO (which read the exact nu

(ctx context.Context, fd *regularFileFD, off uint64, size uint32)

Source from the content-addressed store, hash-verified

31// We do not support direct IO (which read the exact number of bytes)
32// at this moment.
33func (fs *filesystem) ReadInPages(ctx context.Context, fd *regularFileFD, off uint64, size uint32) ([][]byte, uint32, error) {
34 attributeVersion := fs.conn.attributeVersion.Load()
35
36 // Round up to a multiple of page size.
37 readSize, _ := hostarch.PageRoundUp(uint64(size))
38
39 // One request cannot exceed either maxRead or maxPages.
40 maxPages := fs.conn.maxRead >> hostarch.PageShift
41 if maxPages > uint32(fs.conn.maxPages) {
42 maxPages = uint32(fs.conn.maxPages)
43 }
44
45 var outs [][]byte
46 var sizeRead uint32
47
48 // readSize is a multiple of hostarch.PageSize.
49 // Always request bytes as a multiple of pages.
50 pagesRead, pagesToRead := uint32(0), uint32(readSize>>hostarch.PageShift)
51
52 // Reuse the same struct for unmarshalling to avoid unnecessary memory allocation.
53 in := linux.FUSEReadIn{
54 Fh: fd.Fh,
55 LockOwner: 0, // TODO(gvisor.dev/issue/3245): file lock
56 ReadFlags: 0, // TODO(gvisor.dev/issue/3245): |= linux.FUSE_READ_LOCKOWNER
57 Flags: fd.statusFlags(),
58 }
59
60 // This loop is intended for fragmented read where the bytes to read is
61 // larger than either the maxPages or maxRead.
62 // For the majority of reads with normal size, this loop should only
63 // execute once.
64 for pagesRead < pagesToRead {
65 pagesCanRead := pagesToRead - pagesRead
66 if pagesCanRead > maxPages {
67 pagesCanRead = maxPages
68 }
69
70 in.Offset = off + (uint64(pagesRead) << hostarch.PageShift)
71 in.Size = pagesCanRead << hostarch.PageShift
72
73 // TODO(gvisor.dev/issue/3247): support async read.
74 res, err := fd.inode().callRaw(ctx, linux.FUSE_READ, &in)
75 if err != nil {
76 return nil, 0, err
77 }
78
79 // Not enough bytes in response,
80 // either we reached EOF,
81 // or the FUSE server sends back a response
82 // that cannot even fit the hdr.
83 if len(res.data) <= res.hdr.SizeBytes() {
84 // We treat both case as EOF here for now
85 // since there is no reliable way to detect
86 // the over-short hdr case.
87 break
88 }
89
90 // Directly using the slice to avoid extra copy.

Callers 1

PReadMethod · 0.80

Calls 7

ReadCallbackMethod · 0.95
PageRoundUpFunction · 0.92
statusFlagsMethod · 0.80
callRawMethod · 0.80
LoadMethod · 0.65
SizeBytesMethod · 0.65
inodeMethod · 0.45

Tested by

no test coverage detected