PRead implements vfs.FileDescriptionImpl.PRead.
(ctx context.Context, dst usermem.IOSequence, offset int64, opts vfs.ReadOptions)
| 112 | |
| 113 | // PRead implements vfs.FileDescriptionImpl.PRead. |
| 114 | func (fd *regularFileFD) PRead(ctx context.Context, dst usermem.IOSequence, offset int64, opts vfs.ReadOptions) (int64, error) { |
| 115 | if offset < 0 { |
| 116 | return 0, linuxerr.EINVAL |
| 117 | } |
| 118 | |
| 119 | // Check that flags are supported. |
| 120 | // |
| 121 | // TODO(gvisor.dev/issue/2601): Support select preadv2 flags. |
| 122 | if opts.Flags&^linux.RWF_HIPRI != 0 { |
| 123 | return 0, linuxerr.EOPNOTSUPP |
| 124 | } |
| 125 | |
| 126 | size := dst.NumBytes() |
| 127 | if size == 0 { |
| 128 | // Early return if count is 0. |
| 129 | return 0, nil |
| 130 | } |
| 131 | if size > math.MaxUint32 { |
| 132 | // FUSE only supports uint32 for size. |
| 133 | // Overflow. |
| 134 | return 0, linuxerr.EINVAL |
| 135 | } |
| 136 | |
| 137 | // TODO(gvisor.dev/issue/3678): Add direct IO support. |
| 138 | |
| 139 | inode := fd.inode() |
| 140 | inode.attrMu.Lock() |
| 141 | defer inode.attrMu.Unlock() |
| 142 | |
| 143 | // Reading beyond EOF, update file size if outdated. |
| 144 | if uint64(offset+size) > inode.size.Load() { |
| 145 | if err := inode.reviseAttr(ctx, linux.FUSE_GETATTR_FH, fd.Fh); err != nil { |
| 146 | return 0, err |
| 147 | } |
| 148 | // If the offset after update is still too large, return error. |
| 149 | if uint64(offset) >= inode.size.Load() { |
| 150 | return 0, io.EOF |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | // Truncate the read with updated file size. |
| 155 | fileSize := inode.size.Load() |
| 156 | if uint64(offset+size) > fileSize { |
| 157 | size = int64(fileSize) - offset |
| 158 | } |
| 159 | |
| 160 | buffers, n, err := inode.fs.ReadInPages(ctx, fd, uint64(offset), uint32(size)) |
| 161 | if err != nil { |
| 162 | return 0, err |
| 163 | } |
| 164 | |
| 165 | // TODO(gvisor.dev/issue/3237): support indirect IO (e.g. caching), |
| 166 | // store the bytes that were read ahead. |
| 167 | |
| 168 | // Update the number of bytes to copy for short read. |
| 169 | if n < uint32(size) { |
| 170 | size = int64(n) |
| 171 | } |
no test coverage detected