static int ffs_rawread_sync(struct vnode *vp) { int error; /* * Check for dirty mmap, pending writes and dirty buffers */ lwkt_gettoken(&vp->v_token); if (bio_track_active(&vp->v_track_write) || !RB_EMPTY(&vp->v_rbdirty_tree) || (vp->v_flag & VOBJDIRTY) != 0) { /* Attempt to msync mmap() regions to clean dirty mmap */ if ((vp->v_flag & VOBJDIRTY) != 0) { struct vm_object *obj; if ((obj = vp->v_object) != NULL) vm_object_page_clean(obj, 0, 0, OBJPC_SYNC); } /* Wait for pending writes to complete */ error = bio_track_wait(&vp->v_track_write, 0, 0); if (error != 0) { goto done; } /* Flush dirty buffers */ if (!RB_EMPTY(&vp->v_rbdirty_tree)) { if ((error = VOP_FSYNC(vp, MNT_WAIT, 0)) != 0) { goto done; } if (bio_track_active(&vp->v_track_write) || !RB_EMPTY(&vp->v_rbdirty_tree)) panic("ffs_rawread_sync: dirty bufs"); } } else { error = 0; } done: lwkt_reltoken(&vp->v_token); return error; }
/* * Pass 2 - only run after pass 1 has completed or has given up * * We ignore TMPFS, NFS, MFS, and SMBFS mounts in this pass. */ static int shutdown_busycount2(struct buf *bp, void *info) { struct vnode *vp; /* * Ignore tmpfs and nfs mounts */ if ((vp = bp->b_vp) != NULL) { if (vp->v_tag == VT_TMPFS) return (0); if (vp->v_tag == VT_NFS) return (0); if (vp->v_tag == VT_MFS) return (0); if (vp->v_tag == VT_SMBFS) return (0); } /* * Only count buffers stuck on I/O, ignore everything else */ if (((bp->b_flags & B_INVAL) == 0 && BUF_REFCNT(bp)) || ((bp->b_flags & (B_DELWRI|B_INVAL)) == B_DELWRI)) { /* * Only count buffers undergoing write I/O * on the related vnode. */ if (bp->b_vp == NULL || bio_track_active(&bp->b_vp->v_track_write) == 0) { return (0); } #if defined(SHOW_BUSYBUFS) || defined(DIAGNOSTIC) kprintf( "%p dev:?, flags:%08x, loffset:%jd, doffset:%jd\n", bp, bp->b_flags, (intmax_t)bp->b_loffset, (intmax_t)bp->b_bio2.bio_offset); #endif return(1); } return(0); }