(t *kernel.Task, file *vfs.FileDescription, src usermem.IOSequence, offset int64, opts vfs.WriteOptions)
| 480 | } |
| 481 | |
| 482 | func pwrite(t *kernel.Task, file *vfs.FileDescription, src usermem.IOSequence, offset int64, opts vfs.WriteOptions) (int64, error) { |
| 483 | n, err := file.PWrite(t, src, offset, opts) |
| 484 | if !linuxerr.Equals(linuxerr.ErrWouldBlock, err) { |
| 485 | return n, err |
| 486 | } |
| 487 | |
| 488 | allowBlock, deadline, hasDeadline := blockPolicy(t, file) |
| 489 | if !allowBlock { |
| 490 | return n, err |
| 491 | } |
| 492 | |
| 493 | // Register for notifications. |
| 494 | w, ch := waiter.NewChannelEntry(eventMaskWrite) |
| 495 | if err := file.EventRegister(&w); err != nil { |
| 496 | return n, err |
| 497 | } |
| 498 | |
| 499 | total := n |
| 500 | for { |
| 501 | // Shorten src to reflect bytes previously written. |
| 502 | src = src.DropFirst(int(n)) |
| 503 | |
| 504 | // Issue the request and break out if it completes with anything other than |
| 505 | // "would block". |
| 506 | n, err = file.PWrite(t, src, offset+total, opts) |
| 507 | total += n |
| 508 | if !linuxerr.Equals(linuxerr.ErrWouldBlock, err) { |
| 509 | break |
| 510 | } |
| 511 | |
| 512 | // Wait for a notification that we should retry. |
| 513 | if err = t.BlockWithDeadline(ch, hasDeadline, deadline); err != nil { |
| 514 | if linuxerr.Equals(linuxerr.ETIMEDOUT, err) { |
| 515 | err = linuxerr.ErrWouldBlock |
| 516 | } |
| 517 | break |
| 518 | } |
| 519 | } |
| 520 | file.EventUnregister(&w) |
| 521 | return total, err |
| 522 | } |
| 523 | |
| 524 | func blockPolicy(t *kernel.Task, file *vfs.FileDescription) (allowBlock bool, deadline ktime.Time, hasDeadline bool) { |
| 525 | if file.StatusFlags()&linux.O_NONBLOCK != 0 { |
no test coverage detected
searching dependent graphs…