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