(ctx context.Context, d *dentry, offset int64, src usermem.IOSequence)
| 280 | } |
| 281 | |
| 282 | func (fd *regularFileFD) writeCache(ctx context.Context, d *dentry, offset int64, src usermem.IOSequence) error { |
| 283 | // Write dirty cached pages that will be touched by the write back to |
| 284 | // the remote file. |
| 285 | if err := d.writeback(ctx, offset, src.NumBytes()); err != nil { |
| 286 | return err |
| 287 | } |
| 288 | |
| 289 | // Remove touched pages from the cache. |
| 290 | pgstart := hostarch.PageRoundDown(uint64(offset)) |
| 291 | pgend, ok := hostarch.PageRoundUp(uint64(offset + src.NumBytes())) |
| 292 | if !ok { |
| 293 | return linuxerr.EINVAL |
| 294 | } |
| 295 | mr := memmap.MappableRange{pgstart, pgend} |
| 296 | var freed []memmap.FileRange |
| 297 | |
| 298 | d.inode.dataMu.Lock() |
| 299 | d.inode.cache.RemoveRangeWith(mr, func(cseg fsutil.FileRangeIterator) { |
| 300 | freed = append(freed, memmap.FileRange{cseg.Value(), cseg.Value() + cseg.Range().Length()}) |
| 301 | }) |
| 302 | d.inode.dataMu.Unlock() |
| 303 | |
| 304 | // Invalidate mappings of removed pages. |
| 305 | d.inode.mapsMu.Lock() |
| 306 | d.inode.mappings.Invalidate(mr, memmap.InvalidateOpts{}) |
| 307 | d.inode.mapsMu.Unlock() |
| 308 | |
| 309 | // Finally free pages removed from the cache. |
| 310 | mf := d.inode.fs.mf |
| 311 | for _, freedFR := range freed { |
| 312 | mf.DecRef(freedFR) |
| 313 | } |
| 314 | return nil |
| 315 | } |
| 316 | |
| 317 | // Write implements vfs.FileDescriptionImpl.Write. |
| 318 | func (fd *regularFileFD) Write(ctx context.Context, src usermem.IOSequence, opts vfs.WriteOptions) (int64, error) { |
no test coverage detected