Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 29 Jul 2015 02:26:58 +0000 (UTC)
From:      Jeff Roberson <jeff@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r285993 - in head/sys: kern sys ufs/ffs vm
Message-ID:  <201507290226.t6T2Qwp7072379@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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/kern_shutdown.c
==============================================================================
--- head/sys/kern/kern_shutdown.c	Wed Jul 29 02:21:35 2015	(r285992)
+++ head/sys/kern/kern_shutdown.c	Wed Jul 29 02:26:57 2015	(r285993)
@@ -275,24 +275,13 @@ doadump(boolean_t textdump)
 	return (error);
 }
 
-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
 kern_reboot(int howto)
 {
-	static int first_buf_printf = 1;
-	static int waittime = -1;
+	static int once = 0;
 
 #if defined(SMP)
 	/*
@@ -321,116 +310,9 @@ kern_reboot(int howto)
 	/* 
 	 * Now sync filesystems
 	 */
-	if (!cold && (howto & RB_NOSYNC) == 0 && waittime < 0) {
-		register struct buf *bp;
-		int iter, nbusy, pbusy;
-#ifndef PREEMPTION
-		int subiter;
-#endif
-
-		waittime = 0;
-
-		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 */
+	if (!cold && (howto & RB_NOSYNC) == 0 && once == 0) {
+		once = 1;
+		bufshutdown(show_busybufs);
 	}
 
 	print_uptime();

Modified: head/sys/kern/subr_param.c
==============================================================================
--- head/sys/kern/subr_param.c	Wed Jul 29 02:21:35 2015	(r285992)
+++ head/sys/kern/subr_param.c	Wed Jul 29 02:26:57 2015	(r285993)
@@ -139,13 +139,6 @@ SYSCTL_PROC(_kern, OID_AUTO, vm_guest, C
     "Virtual machine guest detected?");
 
 /*
- * These have to be allocated somewhere; allocating
- * them here forces loader errors if this file is omitted
- * (if they've been externed everywhere else; hah!).
- */
-struct	buf *swbuf;
-
-/*
  * The elements of this array are ordered based upon the values of the
  * corresponding enum VM_GUEST members.
  */

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)
@@ -64,9 +64,11 @@ __FBSDID("$FreeBSD$");
 #include <sys/resourcevar.h>
 #include <sys/rwlock.h>
 #include <sys/sysctl.h>
+#include <sys/sysproto.h>
 #include <sys/vmem.h>
 #include <sys/vmmeter.h>
 #include <sys/vnode.h>
+#include <sys/watchdog.h>
 #include <geom/geom.h>
 #include <vm/vm.h>
 #include <vm/vm_param.h>
@@ -76,6 +78,7 @@ __FBSDID("$FreeBSD$");
 #include <vm/vm_object.h>
 #include <vm/vm_extern.h>
 #include <vm/vm_map.h>
+#include <vm/swap_pager.h>
 #include "opt_compat.h"
 #include "opt_swap.h"
 
@@ -91,11 +94,8 @@ struct	buf_ops buf_ops_bio = {
 	.bop_bdflush	=	bufbdflush,
 };
 
-/*
- * XXX buf is global because kern_shutdown.c and ffs_checkoverlap has
- * carnal knowledge of buffers.  This knowledge should be moved to vfs_bio.c.
- */
-struct buf *buf;		/* buffer header pool */
+static struct buf *buf;		/* buffer header pool */
+extern struct buf *swbuf;	/* Swap buffer header pool. */
 caddr_t unmapped_buf;
 
 /* Used below and for softdep flushing threads in ufs/ffs/ffs_softdep.c */
@@ -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 */
+}
 
 static inline void
 vfs_buf_check_unmapped(struct buf *bp)

Modified: head/sys/sys/buf.h
==============================================================================
--- head/sys/sys/buf.h	Wed Jul 29 02:21:35 2015	(r285992)
+++ head/sys/sys/buf.h	Wed Jul 29 02:26:57 2015	(r285993)
@@ -465,8 +465,6 @@ extern int	dirtybufthresh;
 extern int	bdwriteskip;
 extern int	dirtybufferflushes;
 extern int	altbufferflushes;
-extern struct	buf *buf;		/* The buffer headers. */
-extern struct	buf *swbuf;		/* Swap I/O buffer headers. */
 extern int	nswbuf;			/* Number of swap I/O buffer headers. */
 extern int	cluster_pbuf_freecnt;	/* Number of pbufs for clusters */
 extern int	vnode_pbuf_freecnt;	/* Number of pbufs for vnode pager */
@@ -485,6 +483,7 @@ void	runningbufwakeup(struct buf *);
 void	waitrunningbufspace(void);
 caddr_t	kern_vfs_bio_buffer_alloc(caddr_t v, long physmem_est);
 void	bufinit(void);
+void	bufshutdown(int);
 void	bdata2bio(struct buf *bp, struct bio *bip);
 void	bwillwrite(void);
 int	buf_dirty_count_severe(void);

Modified: head/sys/ufs/ffs/ffs_subr.c
==============================================================================
--- head/sys/ufs/ffs/ffs_subr.c	Wed Jul 29 02:21:35 2015	(r285992)
+++ head/sys/ufs/ffs/ffs_subr.c	Wed Jul 29 02:26:57 2015	(r285993)
@@ -55,10 +55,6 @@ __FBSDID("$FreeBSD$");
 #include <ufs/ffs/ffs_extern.h>
 #include <ufs/ffs/fs.h>
 
-#ifdef KDB
-void	ffs_checkoverlap(struct buf *, struct inode *);
-#endif
-
 /*
  * Return buffer with the contents of block "offset" from the beginning of
  * directory "ip".  If "res" is non-zero, fill it in with a pointer to the
@@ -165,37 +161,6 @@ ffs_fragacct(fs, fragmap, fraglist, cnt)
 	}
 }
 
-#ifdef KDB
-void
-ffs_checkoverlap(bp, ip)
-	struct buf *bp;
-	struct inode *ip;
-{
-	struct buf *ebp, *ep;
-	ufs2_daddr_t start, last;
-	struct vnode *vp;
-
-	ebp = &buf[nbuf];
-	start = bp->b_blkno;
-	last = start + btodb(bp->b_bcount) - 1;
-	for (ep = buf; ep < ebp; ep++) {
-		if (ep == bp || (ep->b_flags & B_INVAL) ||
-		    ep->b_vp == NULLVP)
-			continue;
-		vp = ip->i_devvp;
-		/* look for overlap */
-		if (ep->b_bcount == 0 || ep->b_blkno > last ||
-		    ep->b_blkno + btodb(ep->b_bcount) <= start)
-			continue;
-		vprint("Disk overlap", vp);
-		printf("\tstart %jd, end %jd overlap start %jd, end %jd\n",
-		    (intmax_t)start, (intmax_t)last, (intmax_t)ep->b_blkno,
-		    (intmax_t)(ep->b_blkno + btodb(ep->b_bcount) - 1));
-		panic("ffs_checkoverlap: Disk buffer overlap");
-	}
-}
-#endif /* KDB */
-
 /*
  * block operations
  *

Modified: head/sys/vm/vm_pager.c
==============================================================================
--- head/sys/vm/vm_pager.c	Wed Jul 29 02:21:35 2015	(r285992)
+++ head/sys/vm/vm_pager.c	Wed Jul 29 02:26:57 2015	(r285993)
@@ -86,6 +86,8 @@ __FBSDID("$FreeBSD$");
 
 int cluster_pbuf_freecnt = -1;	/* unlimited to begin with */
 
+struct buf *swbuf;
+
 static int dead_pager_getpages(vm_object_t, vm_page_t *, int, int);
 static vm_object_t dead_pager_alloc(void *, vm_ooffset_t, vm_prot_t,
     vm_ooffset_t, struct ucred *);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201507290226.t6T2Qwp7072379>