svn commit: r285993 - in head/sys: kern sys ufs/ffs vm
Conrad Meyer
cse.cem at gmail.com
Wed Jul 29 05:53:50 UTC 2015
On Tue, Jul 28, 2015 at 7:26 PM, Jeff Roberson <jeff at freebsd.org> wrote:
> Author: jeff
> Date: Wed Jul 29 02:26:57 2015
> New Revision: 285993
> URL: https://svnweb.freebsd.org/changeset/base/285993
>
> Log:
> - Make 'struct buf *buf' private to vfs_bio.c. Having a global variable
> 'buf' is inconvenient and has lead me to some irritating to discover
> bugs over the years. It also makes it more challenging to refactor
> the buf allocation system.
> - Move swbuf and declare it as an extern in vfs_bio.c. This is still
> not perfect but better than it was before.
> - Eliminate the unused ffs function that relied on knowledge of the buf
> array.
> - Move the shutdown code that iterates over the buf array into vfs_bio.c.
>
> Reviewed by: kib
> Sponsored by: EMC / Isilon Storage Division
>
> Modified:
> head/sys/kern/kern_shutdown.c
> head/sys/kern/subr_param.c
> head/sys/kern/vfs_bio.c
> head/sys/sys/buf.h
> head/sys/ufs/ffs/ffs_subr.c
> head/sys/vm/vm_pager.c
>
> ...
>
> Modified: head/sys/kern/vfs_bio.c
> ==============================================================================
> --- head/sys/kern/vfs_bio.c Wed Jul 29 02:21:35 2015 (r285992)
> +++ head/sys/kern/vfs_bio.c Wed Jul 29 02:26:57 2015 (r285993)
> ...
This section is #ifdef INVARIANTS, breaking build on non-INVARIANTS
kernels (missing bufshutdown):
> @@ -958,6 +958,134 @@ vfs_buf_check_mapped(struct buf *bp)
> KASSERT(bp->b_data < unmapped_buf || bp->b_data > unmapped_buf +
> MAXPHYS, ("b_data + b_offset unmapped %p", bp));
> }
> +static int
> +isbufbusy(struct buf *bp)
> +{
> + if (((bp->b_flags & (B_INVAL | B_PERSISTENT)) == 0 &&
> + BUF_ISLOCKED(bp)) ||
> + ((bp->b_flags & (B_DELWRI | B_INVAL)) == B_DELWRI))
> + return (1);
> + return (0);
> +}
> +
> +/*
> + * Shutdown the system cleanly to prepare for reboot, halt, or power off.
> + */
> +void
> +bufshutdown(int show_busybufs)
> +{
> + static int first_buf_printf = 1;
> + struct buf *bp;
> + int iter, nbusy, pbusy;
> +#ifndef PREEMPTION
> + int subiter;
> +#endif
> +
> + /*
> + * Sync filesystems for shutdown
> + */
> + wdog_kern_pat(WD_LASTVAL);
> + sys_sync(curthread, NULL);
> +
> + /*
> + * With soft updates, some buffers that are
> + * written will be remarked as dirty until other
> + * buffers are written.
> + */
> + for (iter = pbusy = 0; iter < 20; iter++) {
> + nbusy = 0;
> + for (bp = &buf[nbuf]; --bp >= buf; )
> + if (isbufbusy(bp))
> + nbusy++;
> + if (nbusy == 0) {
> + if (first_buf_printf)
> + printf("All buffers synced.");
> + break;
> + }
> + if (first_buf_printf) {
> + printf("Syncing disks, buffers remaining... ");
> + first_buf_printf = 0;
> + }
> + printf("%d ", nbusy);
> + if (nbusy < pbusy)
> + iter = 0;
> + pbusy = nbusy;
> +
> + wdog_kern_pat(WD_LASTVAL);
> + sys_sync(curthread, NULL);
> +
> +#ifdef PREEMPTION
> + /*
> + * Drop Giant and spin for a while to allow
> + * interrupt threads to run.
> + */
> + DROP_GIANT();
> + DELAY(50000 * iter);
> + PICKUP_GIANT();
> +#else
> + /*
> + * Drop Giant and context switch several times to
> + * allow interrupt threads to run.
> + */
> + DROP_GIANT();
> + for (subiter = 0; subiter < 50 * iter; subiter++) {
> + thread_lock(curthread);
> + mi_switch(SW_VOL, NULL);
> + thread_unlock(curthread);
> + DELAY(1000);
> + }
> + PICKUP_GIANT();
> +#endif
> + }
> + printf("\n");
> + /*
> + * Count only busy local buffers to prevent forcing
> + * a fsck if we're just a client of a wedged NFS server
> + */
> + nbusy = 0;
> + for (bp = &buf[nbuf]; --bp >= buf; ) {
> + if (isbufbusy(bp)) {
> +#if 0
> +/* XXX: This is bogus. We should probably have a BO_REMOTE flag instead */
> + if (bp->b_dev == NULL) {
> + TAILQ_REMOVE(&mountlist,
> + bp->b_vp->v_mount, mnt_list);
> + continue;
> + }
> +#endif
> + nbusy++;
> + if (show_busybufs > 0) {
> + printf(
> + "%d: buf:%p, vnode:%p, flags:%0x, blkno:%jd, lblkno:%jd, buflock:",
> + nbusy, bp, bp->b_vp, bp->b_flags,
> + (intmax_t)bp->b_blkno,
> + (intmax_t)bp->b_lblkno);
> + BUF_LOCKPRINTINFO(bp);
> + if (show_busybufs > 1)
> + vn_printf(bp->b_vp,
> + "vnode content: ");
> + }
> + }
> + }
> + if (nbusy) {
> + /*
> + * Failed to sync all blocks. Indicate this and don't
> + * unmount filesystems (thus forcing an fsck on reboot).
> + */
> + printf("Giving up on %d buffers\n", nbusy);
> + DELAY(5000000); /* 5 seconds */
> + } else {
> + if (!first_buf_printf)
> + printf("Final sync complete\n");
> + /*
> + * Unmount filesystems
> + */
> + if (panicstr == 0)
> + vfs_unmountall();
> + }
> + swapoff_all();
> + DELAY(100000); /* wait for console output to finish */
> +}
Thanks,
Conrad
More information about the svn-src-head
mailing list