kernel - Fix missing lock in pbuf update (minor)
authorMatthew Dillon <dillon@apollo.backplane.com>
Wed, 11 Jul 2012 03:15:37 +0000 (20:15 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Wed, 11 Jul 2012 03:15:37 +0000 (20:15 -0700)
* Fix a small timing window in an update of a counter.

* This bug is not known to have been hit by anyone, due to default
  settings for asynchronous I/O.

sys/sys/buf.h
sys/vm/swap_pager.c
sys/vm/vm_pager.c

index ba033c6..aa5af8c 100644 (file)
@@ -439,6 +439,7 @@ int biowait_timeout (struct bio *, const char *, int);
 void   bpdone (struct buf *, int);
 void   biodone (struct bio *);
 void   biodone_sync (struct bio *);
+void   pbuf_adjcount(int *pfreecnt, int n);
 
 void   cluster_append(struct bio *, struct buf *);
 int    cluster_readx (struct vnode *, off_t, off_t, int,
index 93f5bd4..2ecedeb 100644 (file)
@@ -1494,7 +1494,6 @@ swap_pager_putpages(vm_object_t object, vm_page_t *m, int count,
         * Update nsw parameters from swap_async_max sysctl values.  
         * Do not let the sysop crash the machine with bogus numbers.
         */
-
        if (swap_async_max != nsw_wcount_async_max) {
                int n;
 
@@ -1517,9 +1516,8 @@ swap_pager_putpages(vm_object_t object, vm_page_t *m, int count,
                lwkt_gettoken(&vm_token);
                n -= nsw_wcount_async_max;
                if (nsw_wcount_async + n >= 0) {
-                       nsw_wcount_async += n;
                        nsw_wcount_async_max += n;
-                       wakeup(&nsw_wcount_async);
+                       pbuf_adjcount(&nsw_wcount_async, n);
                }
                lwkt_reltoken(&vm_token);
        }
index 0002ef1..720e636 100644 (file)
@@ -509,3 +509,14 @@ relpbuf(struct buf *bp, int *pfreecnt)
        if (wake_freecnt)
                wakeup(pfreecnt);
 }
+
+void
+pbuf_adjcount(int *pfreecnt, int n)
+{
+       if (n) {
+               spin_lock(&bswspin);
+               *pfreecnt += n;
+               spin_unlock(&bswspin);
+               wakeup(pfreecnt);
+       }
+}