* Do clustered write for FFS. * * Three cases: * 1. Write is not sequential (write asynchronously) * Write is sequential: * 2. beginning of cluster - begin cluster * 3. middle of a cluster - add to cluster * 4. end of a cluster - asynchronously write cluster */
| 651 | * 4. end of a cluster - asynchronously write cluster |
| 652 | */ |
| 653 | void |
| 654 | cluster_write(struct vnode *vp, struct buf *bp, u_quad_t filesize, int seqcount, |
| 655 | int gbflags) |
| 656 | { |
| 657 | daddr_t lbn; |
| 658 | int maxclen, cursize; |
| 659 | int lblocksize; |
| 660 | int async; |
| 661 | |
| 662 | if (!unmapped_buf_allowed) |
| 663 | gbflags &= ~GB_UNMAPPED; |
| 664 | |
| 665 | if (vp->v_type == VREG) { |
| 666 | async = DOINGASYNC(vp); |
| 667 | lblocksize = vp->v_mount->mnt_stat.f_iosize; |
| 668 | } else { |
| 669 | async = 0; |
| 670 | lblocksize = bp->b_bufsize; |
| 671 | } |
| 672 | lbn = bp->b_lblkno; |
| 673 | KASSERT(bp->b_offset != NOOFFSET, ("cluster_write: no buffer offset")); |
| 674 | |
| 675 | /* Initialize vnode to beginning of file. */ |
| 676 | if (lbn == 0) |
| 677 | vp->v_lasta = vp->v_clen = vp->v_cstart = vp->v_lastw = 0; |
| 678 | |
| 679 | if (vp->v_clen == 0 || lbn != vp->v_lastw + 1 || |
| 680 | (bp->b_blkno != vp->v_lasta + btodb(lblocksize))) { |
| 681 | maxclen = vp->v_mount->mnt_iosize_max / lblocksize - 1; |
| 682 | if (vp->v_clen != 0) { |
| 683 | /* |
| 684 | * Next block is not sequential. |
| 685 | * |
| 686 | * If we are not writing at end of file, the process |
| 687 | * seeked to another point in the file since its last |
| 688 | * write, or we have reached our maximum cluster size, |
| 689 | * then push the previous cluster. Otherwise try |
| 690 | * reallocating to make it sequential. |
| 691 | * |
| 692 | * Change to algorithm: only push previous cluster if |
| 693 | * it was sequential from the point of view of the |
| 694 | * seqcount heuristic, otherwise leave the buffer |
| 695 | * intact so we can potentially optimize the I/O |
| 696 | * later on in the buf_daemon or update daemon |
| 697 | * flush. |
| 698 | */ |
| 699 | cursize = vp->v_lastw - vp->v_cstart + 1; |
| 700 | if (((u_quad_t) bp->b_offset + lblocksize) != filesize || |
| 701 | lbn != vp->v_lastw + 1 || vp->v_clen <= cursize) { |
| 702 | if (!async && seqcount > 0) { |
| 703 | cluster_wbuild_wb(vp, lblocksize, |
| 704 | vp->v_cstart, cursize, gbflags); |
| 705 | } |
| 706 | } else { |
| 707 | struct buf **bpp, **endbp; |
| 708 | struct cluster_save *buflist; |
| 709 | |
| 710 | buflist = cluster_collectbufs(vp, bp, gbflags); |
nothing calls this directly
no test coverage detected