Hello community,

here is the log from the commit of package drbd for openSUSE:Factory checked in 
at 2018-05-03 12:34:44
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/drbd (Old)
 and      /work/SRC/openSUSE:Factory/.drbd.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "drbd"

Thu May  3 12:34:44 2018 rev:68 rq:603419 version:9.0.14+git.62f906cf

Changes:
--------
--- /work/SRC/openSUSE:Factory/drbd/drbd.changes        2018-04-19 
15:32:53.630661326 +0200
+++ /work/SRC/openSUSE:Factory/.drbd.new/drbd.changes   2018-05-03 
12:34:46.599162887 +0200
@@ -1,0 +2,24 @@
+Thu May  3 01:04:29 UTC 2018 - [email protected]
+
+- Update to 9.0.14-1
+* fix regression in 9.0.13: call after-split-brain-recovery
+  handlers no auto-recovery strategies (not even the default:
+  disconnect) would be applied, nodes would stay connected
+  and all nodes would try to become the source of the resync.
+* fix spurious temporary promotion failure: if after Primary
+  loss failover happened too quickly, transparently retry internally.
+* fixup recently introduced P_ZEROES to actually work as intended
+* fix online-verify to account for skipped blocks; otherwise,
+  it won't notice that it has finished, apparently being stuck
+  near "100% done"
+* expose more resync and online-verify statistics and details
+* improve accounting of "in-flight" data and resync requests
+* allow taking down an already useless minor device during "down",
+  even if it is (temporarily) opened by for example udev scanning
+* fix for a node staying "only" Consistent and not returning
+  to UpToDate in certain scenarios when fencing is enabled
+* fix data generation UUID propagate during resync
+* compat for upstream kernels up to v4.17
+ 
+
+-------------------------------------------------------------------

Old:
----
  drbd-9.0.13+git.b83ade31.tar.bz2

New:
----
  drbd-9.0.14+git.62f906cf.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ drbd.spec ++++++
--- /var/tmp/diff_new_pack.ldUjR8/_old  2018-05-03 12:34:47.423133530 +0200
+++ /var/tmp/diff_new_pack.ldUjR8/_new  2018-05-03 12:34:47.427133388 +0200
@@ -24,7 +24,7 @@
 %endif
 
 Name:           drbd
-Version:        9.0.13+git.b83ade31
+Version:        9.0.14+git.62f906cf
 Release:        0
 Summary:        DRBD driver for Linux
 License:        GPL-2.0+

++++++ _service ++++++
--- /var/tmp/diff_new_pack.ldUjR8/_old  2018-05-03 12:34:47.479131535 +0200
+++ /var/tmp/diff_new_pack.ldUjR8/_new  2018-05-03 12:34:47.479131535 +0200
@@ -7,10 +7,10 @@
     To update to a new release, change "revision" to the desired
     git commit hash and bump "version" if necessary
 
-    <param name="version">9.0.13</param>
+    <param name="version">9.0.14</param>
 -->
-    <param name="versionformat">9.0.13+git.%h</param>
-    <param name="revision">b83ade31e10925030206854027021eb4fc9f2563</param>
+    <param name="versionformat">9.0.14+git.%h</param>
+    <param name="revision">62f906cf44ef02a30ce0c148fec223b40c51c533</param>
   </service>
 
   <service name="recompress" mode="disabled">

++++++ drbd-9.0.13+git.b83ade31.tar.bz2 -> drbd-9.0.14+git.62f906cf.tar.bz2 
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/drbd-9.0.13+git.b83ade31/ChangeLog 
new/drbd-9.0.14+git.62f906cf/ChangeLog
--- old/drbd-9.0.13+git.b83ade31/ChangeLog      2018-04-17 12:04:10.000000000 
+0200
+++ new/drbd-9.0.14+git.62f906cf/ChangeLog      2018-05-01 00:15:21.000000000 
+0200
@@ -2,6 +2,25 @@
 ------
  For even more detail, use "git log" or visit http://git.drbd.org/.
 
+9.0.14-1 (api:genl2/proto:86-113/transport:14)
+ * fix regression in 9.0.13: call after-split-brain-recovery handlers
+   no auto-recovery strategies (not even the default: disconnect) would be
+   applied, nodes would stay connected and all nodes would try to become the
+   source of the resync.
+ * fix spurious temporary promotion failure: if after Primary loss
+   failover happened too quickly, transparently retry internally.
+ * fixup recently introduced P_ZEROES to actually work as intended
+ * fix online-verify to account for skipped blocks; otherwise, it won't
+   notice that it has finished, apparently being stuck near "100% done"
+ * expose more resync and online-verify statistics and details
+ * improve accounting of "in-flight" data and resync requests
+ * allow taking down an already useless minor device during "down",
+   even if it is (temporarily) opened by for example udev scanning
+ * fix for a node staying "only" Consistent and not returning to UpToDate
+   in certain scenarios when fencing is enabled
+ * fix data generation UUID propagate during resync
+ * compat for upstream kernels up to v4.17
+
 9.0.13-1 (api:genl2/proto:86-113/transport:14)
 --------
  * abort a resync if a resync source becomes weakly connected and the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/drbd-9.0.13+git.b83ade31/Makefile 
new/drbd-9.0.14+git.62f906cf/Makefile
--- old/drbd-9.0.13+git.b83ade31/Makefile       2018-04-17 12:04:10.000000000 
+0200
+++ new/drbd-9.0.14+git.62f906cf/Makefile       2018-05-01 00:15:21.000000000 
+0200
@@ -32,7 +32,12 @@
 KVER = `uname -r`
 KDIR = /lib/modules/$(KVER)/build
  else
-KVER := $(shell (make -s -C $(KDIR) kernelversion || make -s -C $(KDIR) 
kernelrelease) | tail -n1)
+# Aand sles is more special than rhel this time.
+# Others may be even more special than those two :-/
+# Try "kernelrelease" first, then try "kernelversion".
+# If the magic does not work out for you,
+# explicitly set both KVER and KDIR to matching values.
+KVER := $(shell (make -s -C $(KDIR) kernelrelease || make -s -C $(KDIR) 
kernelversion) | tail -n1)
 ifeq ($(KVER),)
        $(error could not guess kernel version string from kernel sources at 
"$(KDIR)")
 endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/drbd-9.0.13+git.b83ade31/README.drbd-utils 
new/drbd-9.0.14+git.62f906cf/README.drbd-utils
--- old/drbd-9.0.13+git.b83ade31/README.drbd-utils      2018-04-17 
12:04:10.000000000 +0200
+++ new/drbd-9.0.14+git.62f906cf/README.drbd-utils      2018-05-01 
00:15:21.000000000 +0200
@@ -4,9 +4,10 @@
   (tarball at http://links.linbit.com/drbd-download)
 
   That started out as "drbd-utils version 8.9.0",
+  has a different release cycle,
   and provides compatible drbdadm, drbdsetup and drbdmeta tools
   for DRBD module versions 8.3, 8.4 and 9.
 
   Again: to manage DRBD 9 kernel modules and above,
-  you want drbd-utils >= 8.9.11 from above url.
+  you want drbd-utils >= 9.3 from above url.
 =======================================================================
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/drbd-9.0.13+git.b83ade31/debian/changelog 
new/drbd-9.0.14+git.62f906cf/debian/changelog
--- old/drbd-9.0.13+git.b83ade31/debian/changelog       2018-04-17 
12:04:10.000000000 +0200
+++ new/drbd-9.0.14+git.62f906cf/debian/changelog       2018-05-01 
00:15:21.000000000 +0200
@@ -1,3 +1,9 @@
+drbd (9.0.14-1) unstable; urgency=medium
+
+  * New upstream release.
+
+ -- Lars Ellenberg <[email protected]>  Tue, 01 May 2018 00:12:39 +0200
+
 drbd (9.0.13-1) unstable; urgency=medium
 
   * New upstream release.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/drbd-9.0.13+git.b83ade31/drbd/drbd-kernel-compat/drbd_wrappers.h 
new/drbd-9.0.14+git.62f906cf/drbd/drbd-kernel-compat/drbd_wrappers.h
--- old/drbd-9.0.13+git.b83ade31/drbd/drbd-kernel-compat/drbd_wrappers.h        
2018-04-17 12:04:10.000000000 +0200
+++ new/drbd-9.0.14+git.62f906cf/drbd/drbd-kernel-compat/drbd_wrappers.h        
2018-05-01 00:15:21.000000000 +0200
@@ -60,6 +60,17 @@
 }
 #endif
 
+static inline int drbd_always_getpeername(struct socket *sock, struct sockaddr 
*uaddr)
+{
+#ifdef COMPAT_SOCK_OPS_RETURNS_ADDR_LEN
+       return sock->ops->getname(sock, uaddr, 2);
+#else
+       int len = 0;
+       int err = sock->ops->getname(sock, uaddr, &len, 2);
+       return err ?: len;
+#endif
+}
+
 #ifdef COMPAT_HAVE_BLK_QC_T_MAKE_REQUEST
 /* in Commit dece16353ef47d8d33f5302bc158072a9d65e26f
  * make_request() becomes type blk_qc_t. */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/drbd-9.0.13+git.b83ade31/drbd/drbd-kernel-compat/tests/have_blk_queue_flag_set.c
 
new/drbd-9.0.14+git.62f906cf/drbd/drbd-kernel-compat/tests/have_blk_queue_flag_set.c
--- 
old/drbd-9.0.13+git.b83ade31/drbd/drbd-kernel-compat/tests/have_blk_queue_flag_set.c
        1970-01-01 01:00:00.000000000 +0100
+++ 
new/drbd-9.0.14+git.62f906cf/drbd/drbd-kernel-compat/tests/have_blk_queue_flag_set.c
        2018-05-01 00:15:21.000000000 +0200
@@ -0,0 +1,6 @@
+#include <linux/blkdev.h>
+
+void dummy(struct request_queue *q)
+{
+       blk_queue_flag_set(QUEUE_FLAG_DISCARD, q); 
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/drbd-9.0.13+git.b83ade31/drbd/drbd-kernel-compat/tests/sock_ops_returns_addr_len.c
 
new/drbd-9.0.14+git.62f906cf/drbd/drbd-kernel-compat/tests/sock_ops_returns_addr_len.c
--- 
old/drbd-9.0.13+git.b83ade31/drbd/drbd-kernel-compat/tests/sock_ops_returns_addr_len.c
      1970-01-01 01:00:00.000000000 +0100
+++ 
new/drbd-9.0.14+git.62f906cf/drbd/drbd-kernel-compat/tests/sock_ops_returns_addr_len.c
      2018-05-01 00:15:21.000000000 +0200
@@ -0,0 +1,5 @@
+#include <linux/net.h>
+int always_getpeername(struct socket *sock, struct sockaddr *addr)
+{
+       return sock->ops->getname(sock, addr, 2);
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/drbd-9.0.13+git.b83ade31/drbd/drbd_debugfs.c 
new/drbd-9.0.14+git.62f906cf/drbd/drbd_debugfs.c
--- old/drbd-9.0.13+git.b83ade31/drbd/drbd_debugfs.c    2018-04-17 
12:04:10.000000000 +0200
+++ new/drbd-9.0.14+git.62f906cf/drbd/drbd_debugfs.c    2018-05-01 
00:15:21.000000000 +0200
@@ -829,6 +829,8 @@
        pretty_print_bit(C_UNREGISTERED);
        pretty_print_bit(RECONNECT);
        pretty_print_bit(CONN_DISCARD_MY_DATA);
+       pretty_print_bit(SEND_STATE_AFTER_AHEAD_C);
+       pretty_print_bit(NOTIFY_PEERS_LOST_PRIMARY);
 #undef pretty_print_bit
        seq_putc(m, '\n');
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/drbd-9.0.13+git.b83ade31/drbd/drbd_int.h 
new/drbd-9.0.14+git.62f906cf/drbd/drbd_int.h
--- old/drbd-9.0.13+git.b83ade31/drbd/drbd_int.h        2018-04-17 
12:04:10.000000000 +0200
+++ new/drbd-9.0.14+git.62f906cf/drbd/drbd_int.h        2018-05-01 
00:15:21.000000000 +0200
@@ -550,6 +550,7 @@
        STABLE_RESYNC,          /* One peer_device finished the resync stable! 
*/
        READ_BALANCE_RR,
        PRIMARY_LOST_QUORUM,
+       DESTROYING_DEV,
 };
 
 /* flag bits per peer device */
@@ -1143,6 +1144,10 @@
        sector_t ov_last_oos_start;
        /* size of out-of-sync range in sectors. */
        sector_t ov_last_oos_size;
+       /* Start sector of skipped range (to merge printk reporting). */
+       sector_t ov_last_skipped_start;
+       /* size of skipped range in sectors. */
+       sector_t ov_last_skipped_size;
        int c_sync_rate; /* current resync rate after syncer throttle magic */
        struct fifo_buffer *rs_plan_s; /* correction values of resync planer 
(RCU, connection->conn_update) */
        atomic_t rs_sect_in; /* for incoming resync data rate, SyncTarget */
@@ -1151,6 +1156,7 @@
                              * on the lower level device when we last looked. 
*/
        int rs_in_flight; /* resync sectors in flight (to proxy, in proxy and 
from proxy) */
        unsigned long ov_left; /* in bits */
+       unsigned long ov_skipped; /* in bits */
 
        u64 current_uuid;
        u64 bitmap_uuids[DRBD_PEERS_MAX];
@@ -1849,6 +1855,8 @@
 extern void resume_next_sg(struct drbd_device *device);
 extern void suspend_other_sg(struct drbd_device *device);
 extern int drbd_resync_finished(struct drbd_peer_device *, enum 
drbd_disk_state);
+extern void verify_progress(struct drbd_peer_device *peer_device,
+               const sector_t sector, const unsigned int size);
 /* maybe rather drbd_main.c ? */
 extern void *drbd_md_get_buffer(struct drbd_device *device, const char 
*intent);
 extern void drbd_md_put_buffer(struct drbd_device *device);
@@ -1872,6 +1880,15 @@
        peer_device->ov_last_oos_size = 0;
 }
 
+static inline void ov_skipped_print(struct drbd_peer_device *peer_device)
+{
+       if (peer_device->ov_last_skipped_size) {
+               drbd_info(peer_device, "Skipped verify, too busy: start=%llu, 
size=%lu (sectors)\n",
+                    (unsigned long long)peer_device->ov_last_skipped_start,
+                    (unsigned long)peer_device->ov_last_skipped_size);
+       }
+       peer_device->ov_last_skipped_size = 0;
+}
 
 extern void drbd_csum_bio(struct crypto_ahash *, struct bio *, void *);
 extern void drbd_csum_pages(struct crypto_ahash *, struct page *, void *);
@@ -1881,7 +1898,6 @@
 extern int w_e_end_csum_rs_req(struct drbd_work *, int);
 extern int w_e_end_ov_reply(struct drbd_work *, int);
 extern int w_e_end_ov_req(struct drbd_work *, int);
-extern int w_ov_finished(struct drbd_work *, int);
 extern int w_resync_timer(struct drbd_work *, int);
 extern int w_send_dblock(struct drbd_work *, int);
 extern int w_send_read_req(struct drbd_work *, int);
@@ -2491,6 +2507,13 @@
                is_sync_target_state(peer_device, which);
 }
 
+static inline bool is_verify_state(struct drbd_peer_device *peer_device,
+                                  enum which_state which)
+{
+       enum drbd_repl_state repl_state = peer_device->repl_state[which];
+       return repl_state == L_VERIFY_S || repl_state == L_VERIFY_T;
+}
+
 /**
  * get_ldev() - Increase the ref count on device->ldev. Returns 0 if there is 
no ldev
  * @_device:           DRBD device.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/drbd-9.0.13+git.b83ade31/drbd/drbd_main.c 
new/drbd-9.0.14+git.62f906cf/drbd/drbd_main.c
--- old/drbd-9.0.13+git.b83ade31/drbd/drbd_main.c       2018-04-17 
12:04:10.000000000 +0200
+++ new/drbd-9.0.14+git.62f906cf/drbd/drbd_main.c       2018-05-01 
00:15:21.000000000 +0200
@@ -2511,7 +2511,9 @@
                return IOC_ABORT;
 
        spin_lock_irq(&resource->req_lock);
-       if (!resource->remote_state_change) {
+       if (test_bit(UNREGISTERED, &device->flags))
+               r = IOC_ABORT;
+       else if (!resource->remote_state_change) {
                r = IOC_OK;
                if (mode & FMODE_WRITE)
                        device->open_rw_cnt++;
@@ -2620,6 +2622,11 @@
        if (open_ro_cnt == 0)
                wake_up_all(&resource->state_wait);
 
+       if (test_bit(UNREGISTERED, &device->flags) &&
+           device->open_rw_cnt == 0 && device->open_ro_cnt == 0 &&
+           !test_and_set_bit(DESTROYING_DEV, &device->flags))
+               call_rcu(&device->rcu, drbd_reclaim_device);
+
        if (resource->res_opts.auto_promote) {
                enum drbd_state_rv rv;
 
@@ -4654,7 +4661,7 @@
 {
        struct drbd_device *device = peer_device->device;
        u64 dagtag = peer_device->connection->last_dagtag_sector;
-       u64 got_new_bitmap_uuid = 0;
+       u64 receipients = 0;
        bool set_current = true;
 
        spin_lock_irq(&device->ldev->md.uuid_lock);
@@ -4665,16 +4672,21 @@
                        peer_device->current_uuid = val;
                        set_current = false;
                }
+               if (peer_device->repl_state[NOW] == L_SYNC_SOURCE ||
+                   peer_device->repl_state[NOW] == L_PAUSED_SYNC_S)
+                       receipients |= NODE_MASK(peer_device->node_id);
+
        }
 
        if (set_current) {
                if (device->disk_state[NOW] == D_UP_TO_DATE)
-                       got_new_bitmap_uuid = 
rotate_current_into_bitmap(device, weak_nodes, dagtag);
+                       receipients |= rotate_current_into_bitmap(device, 
weak_nodes, dagtag);
                __drbd_uuid_set_current(device, val);
        }
 
        spin_unlock_irq(&device->ldev->md.uuid_lock);
-       drbd_propagate_uuids(device, got_new_bitmap_uuid);
+       if (set_current)
+               drbd_propagate_uuids(device, receipients);
 }
 
 static u64 __set_bitmap_slots(struct drbd_device *device, u64 bitmap_uuid, u64 
do_nodes) __must_hold(local)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/drbd-9.0.13+git.b83ade31/drbd/drbd_nl.c 
new/drbd-9.0.14+git.62f906cf/drbd/drbd_nl.c
--- old/drbd-9.0.13+git.b83ade31/drbd/drbd_nl.c 2018-04-17 12:04:10.000000000 
+0200
+++ new/drbd-9.0.14+git.62f906cf/drbd/drbd_nl.c 2018-05-01 00:15:21.000000000 
+0200
@@ -928,6 +928,29 @@
        rcu_read_unlock();
 }
 
+static bool wait_up_to_date(struct drbd_resource *resource)
+{
+       long timeout = resource->res_opts.auto_promote_timeout * HZ / 10;
+       struct drbd_device *device;
+       int vnr;
+
+       rcu_read_lock();
+       idr_for_each_entry(&resource->devices, device, vnr) {
+               if (device->disk_state[NOW] == D_CONSISTENT)
+                       break;
+       }
+       rcu_read_unlock();
+
+       if (!device)
+               return false;
+
+       timeout = wait_event_interruptible_timeout(resource->state_wait,
+                                                  device->disk_state[NOW] != 
D_CONSISTENT,
+                                                  timeout);
+       return device->disk_state[NOW] == D_UP_TO_DATE;
+}
+
+
 enum drbd_state_rv
 drbd_set_role(struct drbd_resource *resource, enum drbd_role role, bool force, 
struct sk_buff *reply_skb)
 {
@@ -936,6 +959,7 @@
        const int max_tries = 4;
        enum drbd_state_rv rv = SS_UNKNOWN_ERROR;
        int try = 0;
+       bool retried_ss_two_primaries = false;
        int forced = 0;
        bool with_force = false;
        const char *err_str = NULL;
@@ -1017,6 +1041,19 @@
                        continue;
                }
 
+               if (rv == SS_NO_UP_TO_DATE_DISK) {
+                       bool a_disk_became_up_to_date;
+
+                       /* need to give up state_sem, see 
try_become_up_to_date(); */
+                       up(&resource->state_sem);
+                       drbd_flush_workqueue(&resource->work);
+                       a_disk_became_up_to_date = wait_up_to_date(resource);
+                       down(&resource->state_sem);
+                       if (a_disk_became_up_to_date)
+                               continue;
+                       /* fall through into possible fence-peer or even force 
cases */
+               }
+
                if (rv == SS_NO_UP_TO_DATE_DISK && !with_force) {
                        struct drbd_connection *connection;
                        u64 im;
@@ -1067,6 +1104,10 @@
                        struct net_conf *nc;
                        int timeout = 0;
 
+                       if (try >= max_tries || retried_ss_two_primaries)
+                               break;
+                       retried_ss_two_primaries = true;
+
                        /*
                         * Catch the case where we discover that the other
                         * primary has died soon after the state change
@@ -1085,8 +1126,6 @@
                                timeout = 1;
 
                        schedule_timeout_interruptible(timeout);
-                       if (try < max_tries)
-                               try = max_tries - 1;
                        continue;
                }
 
@@ -1819,6 +1858,26 @@
        return s;
 }
 
+#ifndef COMPAT_HAVE_BLK_QUEUE_FLAG_SET
+static void blk_queue_flag_set(unsigned int flag, struct request_queue *q)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(q->queue_lock, flags);
+       queue_flag_set(flag, q);
+       spin_unlock_irqrestore(q->queue_lock, flags);
+}
+
+static void blk_queue_flag_clear(unsigned int flag, struct request_queue *q)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(q->queue_lock, flags);
+       queue_flag_clear(flag, q);
+       spin_unlock_irqrestore(q->queue_lock, flags);
+}
+#endif
+
 static void decide_on_discard_support(struct drbd_device *device,
                        struct request_queue *q,
                        struct request_queue *b,
@@ -1847,17 +1906,11 @@
                 * topology on all peers. */
                blk_queue_discard_granularity(q, 512);
                q->limits.max_discard_sectors = 
drbd_max_discard_sectors(device->resource);
-               queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
-#ifdef COMPAT_HAVE_REQ_OP_WRITE_ZEROES
-               q->limits.max_write_zeroes_sectors = 
drbd_max_discard_sectors(device->resource);
-#endif
+               blk_queue_flag_set(QUEUE_FLAG_DISCARD, q);
        } else {
-               queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q);
+               blk_queue_flag_clear(QUEUE_FLAG_DISCARD, q);
                blk_queue_discard_granularity(q, 0);
                q->limits.max_discard_sectors = 0;
-#ifdef COMPAT_HAVE_REQ_OP_WRITE_ZEROES
-               q->limits.max_write_zeroes_sectors = 0;
-#endif
        }
 }
 
@@ -1873,6 +1926,23 @@
        }
 }
 
+static void fixup_write_zeroes(struct drbd_device *device, struct 
request_queue *q)
+{
+#ifdef COMPAT_HAVE_REQ_OP_WRITE_ZEROES
+       /* Fixup max_write_zeroes_sectors after blk_queue_stack_limits():
+        * if we can handle "zeroes" efficiently on the protocol,
+        * we want to do that, even if our backend does not announce
+        * max_write_zeroes_sectors itself. */
+
+       /* If all peers announce WZEROES support, use it.  Otherwise, rather
+        * send explicit zeroes than rely on some discard-zeroes-data magic. */
+       if (common_connection_features(device->resource) & DRBD_FF_WZEROES)
+               q->limits.max_write_zeroes_sectors = DRBD_MAX_BBIO_SECTORS;
+       else
+               q->limits.max_write_zeroes_sectors = 0;
+#endif
+}
+
 static void decide_on_write_same_support(struct drbd_device *device,
                        struct request_queue *q,
                        struct request_queue *b, struct o_qlim *o,
@@ -1974,6 +2044,7 @@
                adjust_ra_pages(q, b);
        }
        fixup_discard_if_not_supported(q);
+       fixup_write_zeroes(device, q);
 }
 
 void drbd_reconsider_queue_parameters(struct drbd_device *device, struct 
drbd_backing_dev *bdev, struct o_qlim *o)
@@ -4949,6 +5020,13 @@
        return -EMSGSIZE;
 }
 
+static void connection_to_statistics(struct connection_statistics *s, struct 
drbd_connection *connection)
+{
+       s->conn_congested = test_bit(NET_CONGESTED, 
&connection->transport.flags);
+       s->ap_in_flight = atomic_read(&connection->ap_in_flight);
+       s->rs_in_flight = atomic_read(&connection->rs_in_flight);
+}
+
 enum { SINGLE_RESOURCE, ITERATE_RESOURCES };
 
 int drbd_adm_dump_connections(struct sk_buff *skb, struct netlink_callback *cb)
@@ -5054,7 +5132,7 @@
                err = connection_info_to_skb(skb, &connection_info, 
!capable(CAP_SYS_ADMIN));
                if (err)
                        goto out;
-               connection_statistics.conn_congested = test_bit(NET_CONGESTED, 
&connection->transport.flags);
+               connection_to_statistics(&connection_statistics, connection);
                err = connection_statistics_to_skb(skb, &connection_statistics, 
!capable(CAP_SYS_ADMIN));
                if (err)
                        goto out;
@@ -5073,21 +5151,65 @@
 }
 
 static void peer_device_to_statistics(struct peer_device_statistics *s,
-                                     struct drbd_peer_device *peer_device)
+                                     struct drbd_peer_device *pd)
 {
-       struct drbd_device *device = peer_device->device;
+       struct drbd_device *device = pd->device;
+       unsigned long now = jiffies;
+       unsigned long rs_left = 0;
+       int i;
+
+       /* userspace should get "future proof" units,
+        * convert to sectors or milli seconds as appropriate */
 
        memset(s, 0, sizeof(*s));
-       s->peer_dev_received = peer_device->recv_cnt;
-       s->peer_dev_sent = peer_device->send_cnt;
-       s->peer_dev_pending = atomic_read(&peer_device->ap_pending_cnt) +
-                             atomic_read(&peer_device->rs_pending_cnt);
-       s->peer_dev_unacked = atomic_read(&peer_device->unacked_cnt);
-       s->peer_dev_out_of_sync = drbd_bm_total_weight(peer_device) << 
(BM_BLOCK_SHIFT - 9);
-       s->peer_dev_resync_failed = peer_device->rs_failed << (BM_BLOCK_SHIFT - 
9);
+       s->peer_dev_received = pd->recv_cnt;
+       s->peer_dev_sent = pd->send_cnt;
+       s->peer_dev_pending = atomic_read(&pd->ap_pending_cnt) +
+                             atomic_read(&pd->rs_pending_cnt);
+       s->peer_dev_unacked = atomic_read(&pd->unacked_cnt);
+       s->peer_dev_out_of_sync = BM_BIT_TO_SECT(drbd_bm_total_weight(pd));
+
+       if (is_verify_state(pd, NOW)) {
+               rs_left = BM_BIT_TO_SECT(pd->ov_left);
+               s->peer_dev_ov_start_sector = pd->ov_start_sector;
+               s->peer_dev_ov_stop_sector = pd->ov_stop_sector;
+               s->peer_dev_ov_position = pd->ov_position;
+               s->peer_dev_ov_left = BM_BIT_TO_SECT(pd->ov_left);
+               s->peer_dev_ov_skipped = BM_BIT_TO_SECT(pd->ov_skipped);
+       } else if (is_sync_state(pd, NOW)) {
+               rs_left = s->peer_dev_out_of_sync - 
BM_BIT_TO_SECT(pd->rs_failed);
+               s->peer_dev_resync_failed = BM_BIT_TO_SECT(pd->rs_failed);
+               s->peer_dev_rs_same_csum = BM_BIT_TO_SECT(pd->rs_same_csum);
+       }
+
+       if (rs_left) {
+               enum drbd_repl_state repl_state = pd->repl_state[NOW];
+               if (repl_state == L_SYNC_TARGET || repl_state == L_VERIFY_S)
+                       s->peer_dev_rs_c_sync_rate = pd->c_sync_rate;
+
+               s->peer_dev_rs_total = BM_BIT_TO_SECT(pd->rs_total);
+
+               s->peer_dev_rs_dt_start_ms = jiffies_to_msecs(now - 
pd->rs_start);
+               s->peer_dev_rs_paused_ms = jiffies_to_msecs(pd->rs_paused);
+
+               i = (pd->rs_last_mark + 2) % DRBD_SYNC_MARKS;
+               s->peer_dev_rs_dt0_ms = jiffies_to_msecs(now - 
pd->rs_mark_time[i]);
+               s->peer_dev_rs_db0_sectors = 
BM_BIT_TO_SECT(pd->rs_mark_left[i]) - rs_left;
+
+               i = (pd->rs_last_mark + DRBD_SYNC_MARKS-1) % DRBD_SYNC_MARKS;
+               s->peer_dev_rs_dt1_ms = jiffies_to_msecs(now - 
pd->rs_mark_time[i]);
+               s->peer_dev_rs_db1_sectors = 
BM_BIT_TO_SECT(pd->rs_mark_left[i]) - rs_left;
+
+               /* long term average:
+                * dt = rs_dt_start_ms - rs_paused_ms;
+                * db = rs_total - rs_left, which is
+                *   rs_total - (ov_left? ov_left : out_of_sync - rs_failed)
+                */
+       }
+
        if (get_ldev(device)) {
                struct drbd_md *md = &device->ldev->md;
-               struct drbd_peer_md *peer_md = &md->peers[peer_device->node_id];
+               struct drbd_peer_md *peer_md = &md->peers[pd->node_id];
 
                spin_lock_irq(&md->uuid_lock);
                s->peer_dev_bitmap_uuid = peer_md->bitmap_uuid;
@@ -5556,8 +5678,7 @@
                return ERR_MINOR_INVALID;
 
        spin_lock_irq(&resource->req_lock);
-       if (device->disk_state[NOW] == D_DISKLESS &&
-           device->open_ro_cnt == 0 && device->open_rw_cnt == 0) {
+       if (device->disk_state[NOW] == D_DISKLESS) {
                set_bit(UNREGISTERED, &device->flags);
                ret = NO_ERROR;
        } else {
@@ -5587,7 +5708,10 @@
                                         NOTIFY_DESTROY | NOTIFY_CONTINUES);
        notify_device_state(NULL, 0, device, NULL, NOTIFY_DESTROY);
        mutex_unlock(&notification_mutex);
-       call_rcu(&device->rcu, drbd_reclaim_device);
+
+       if (device->open_ro_cnt == 0 && device->open_rw_cnt == 0 &&
+           !test_and_set_bit(DESTROYING_DEV, &device->flags))
+               call_rcu(&device->rcu, drbd_reclaim_device);
 
        return ret;
 }
@@ -5888,7 +6012,7 @@
             connection_info_to_skb(skb, connection_info, true)))
                goto nla_put_failure;
        connection_paths_to_skb(skb, connection);
-       connection_statistics.conn_congested = test_bit(NET_CONGESTED, 
&connection->transport.flags);
+       connection_to_statistics(&connection_statistics, connection);
        connection_statistics_to_skb(skb, &connection_statistics, 
!capable(CAP_SYS_ADMIN));
        genlmsg_end(skb, dh);
        if (multicast) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/drbd-9.0.13+git.b83ade31/drbd/drbd_receiver.c 
new/drbd-9.0.14+git.62f906cf/drbd/drbd_receiver.c
--- old/drbd-9.0.13+git.b83ade31/drbd/drbd_receiver.c   2018-04-17 
12:04:10.000000000 +0200
+++ new/drbd-9.0.14+git.62f906cf/drbd/drbd_receiver.c   2018-05-01 
00:15:21.000000000 +0200
@@ -1786,7 +1786,7 @@
                struct drbd_peer_request_details *d, struct packet_info *pi)
 {
        struct p_trim *p = pi->data;
-       bool is_trim_or_wsame = pi->cmd == P_TRIM || pi->cmd == P_WSAME;
+       bool is_trim_or_wsame = pi->cmd == P_TRIM || pi->cmd == P_WSAME || 
pi->cmd == P_ZEROES;
        unsigned int digest_size =
                pi->cmd != P_TRIM && connection->peer_integrity_tfm ?
                crypto_ahash_digestsize(connection->peer_integrity_tfm) : 0;
@@ -2944,6 +2944,20 @@
        return false;
 }
 
+static void verify_skipped_block(struct drbd_peer_device *peer_device,
+               const sector_t sector, const unsigned int size)
+{
+       ++peer_device->ov_skipped;
+       if (peer_device->ov_last_skipped_start + 
peer_device->ov_last_skipped_size == sector) {
+               peer_device->ov_last_skipped_size += size>>9;
+       } else {
+               ov_skipped_print(peer_device);
+               peer_device->ov_last_skipped_start = sector;
+               peer_device->ov_last_skipped_size = size>>9;
+       }
+       verify_progress(peer_device, sector, size);
+}
+
 static int receive_DataRequest(struct drbd_connection *connection, struct 
packet_info *pi)
 {
        struct drbd_peer_device *peer_device;
@@ -2985,10 +2999,11 @@
                case P_DATA_REQUEST:
                        drbd_send_ack_rp(peer_device, P_NEG_DREPLY, p);
                        break;
+               case P_OV_REQUEST:
+                       verify_skipped_block(peer_device, sector, size);
                case P_RS_THIN_REQ:
                case P_RS_DATA_REQUEST:
                case P_CSUM_RS_REQUEST:
-               case P_OV_REQUEST:
                        drbd_send_ack_rp(peer_device, P_NEG_RS_DREPLY , p);
                        break;
                case P_OV_REPLY:
@@ -3084,6 +3099,7 @@
                        peer_device->ov_start_sector = sector;
                        peer_device->ov_position = sector;
                        peer_device->ov_left = drbd_bm_bits(device) - 
BM_SECT_TO_BIT(sector);
+                       peer_device->ov_skipped = 0;
                        peer_device->rs_total = peer_device->ov_left;
                        for (i = 0; i < DRBD_SYNC_MARKS; i++) {
                                peer_device->rs_mark_left[i] = 
peer_device->ov_left;
@@ -3141,6 +3157,8 @@
                   Instruct the SyncSource to retry */
                err = drbd_try_rs_begin_io(peer_device, sector, false);
                if (err) {
+                       if (pi->cmd == P_OV_REQUEST)
+                               verify_skipped_block(peer_device, sector, size);
                        err = drbd_send_ack(peer_device, P_RS_CANCEL, peer_req);
                        /* If err is set, we will drop the connection... */
                        goto fail3;
@@ -3963,7 +3981,7 @@
                        else if (!device->have_quorum[NOW] && peer_state.quorum)
                                hg = -2;
                }
-               if (hg > 2 && hg < -2) {
+               if (abs(hg) > 2) {
                        switch (pcount) {
                        case 0:
                                hg = drbd_asb_recover_0p(peer_device);
@@ -6580,7 +6598,7 @@
                                new_disk_state = D_CONSISTENT;
                                /* This is a "safety net"; it can only happen 
if fencing and quorum
                                   are both disabled. This alone would be racy, 
look for
-                                  "Do not trust this guy!" */
+                                  "Do not trust this guy!" (see also 
may_return_to_up_to_date()) */
                        }
                }
        } else if (resource->role[NOW] == R_PRIMARY && device->disk_state[NOW] 
== D_DISKLESS &&
@@ -7334,8 +7352,10 @@
        [P_CURRENT_UUID]    = { 0, sizeof(struct p_current_uuid), 
receive_current_uuid },
        [P_TWOPC_COMMIT]    = { 0, sizeof(struct p_twopc_request), 
receive_twopc },
        [P_TRIM]            = { 0, sizeof(struct p_trim), receive_Data },
+       [P_ZEROES]          = { 0, sizeof(struct p_trim), receive_Data },
        [P_RS_DEALLOCATED]  = { 0, sizeof(struct p_block_desc), 
receive_rs_deallocated },
        [P_WSAME]           = { 1, sizeof(struct p_wsame), receive_Data },
+       [P_ZEROES]          = { 0, sizeof(struct p_trim), receive_Data },
 };
 
 static void drbdd(struct drbd_connection *connection)
@@ -7715,11 +7735,11 @@
                        connection->peer_node_id,
                        connection->agreed_pro_version);
 
-       drbd_info(connection, "Feature flags enabled on protocol level: 
0x%x%s%s%s.\n",
+       drbd_info(connection, "Feature flags enabled on protocol level: 
0x%x%s%s%s%s.\n",
                  connection->agreed_features,
                  connection->agreed_features & DRBD_FF_TRIM ? " TRIM" : "",
                  connection->agreed_features & DRBD_FF_THIN_RESYNC ? " 
THIN_RESYNC" : "",
-                 connection->agreed_features & DRBD_FF_WSAME ? " WRITE_SAME" :
+                 connection->agreed_features & DRBD_FF_WSAME ? " WRITE_SAME" : 
"",
                  connection->agreed_features & DRBD_FF_WZEROES ? " 
WRITE_ZEROES" :
                  connection->agreed_features ? "" : " none");
 
@@ -7800,7 +7820,7 @@
        if (pi.cmd != P_AUTH_CHALLENGE) {
                drbd_err(connection, "expected AuthChallenge packet, received: 
%s (0x%04x)\n",
                         drbd_packet_name(pi.cmd), pi.cmd);
-               rv = 0;
+               rv = -1;
                goto fail;
        }
 
@@ -8318,10 +8338,14 @@
                        drbd_rs_failed_io(peer_device, sector, size);
                        break;
                case P_RS_CANCEL:
-                       bit = BM_SECT_TO_BIT(sector);
-                       mutex_lock(&device->bm_resync_fo_mutex);
-                       device->bm_resync_fo = min(device->bm_resync_fo, bit);
-                       mutex_unlock(&device->bm_resync_fo_mutex);
+                       if (peer_device->repl_state[NOW] == L_VERIFY_S) {
+                               verify_skipped_block(peer_device, sector, size);
+                       } else {
+                               bit = BM_SECT_TO_BIT(sector);
+                               mutex_lock(&device->bm_resync_fo_mutex);
+                               device->bm_resync_fo = 
min(device->bm_resync_fo, bit);
+                               mutex_unlock(&device->bm_resync_fo_mutex);
+                       }
 
                        atomic_add(size >> 9, &peer_device->rs_sect_in);
                        mod_timer(&peer_device->resync_timer, jiffies + 
SLEEP_TIME);
@@ -8373,24 +8397,8 @@
        drbd_rs_complete_io(peer_device, sector);
        dec_rs_pending(peer_device);
 
-       --peer_device->ov_left;
+       verify_progress(peer_device, sector, size);
 
-       /* let's advance progress step marks only for every other megabyte */
-       if ((peer_device->ov_left & 0x200) == 0x200)
-               drbd_advance_rs_marks(peer_device, peer_device->ov_left);
-
-       if (peer_device->ov_left == 0) {
-               struct drbd_peer_device_work *dw = kmalloc(sizeof(*dw), 
GFP_NOIO);
-               if (dw) {
-                       dw->w.cb = w_ov_finished;
-                       dw->peer_device = peer_device;
-                       drbd_queue_work(&connection->sender_work, &dw->w);
-               } else {
-                       drbd_err(device, "kmalloc(dw) failed.");
-                       ov_out_of_sync_print(peer_device);
-                       drbd_resync_finished(peer_device, D_MASK);
-               }
-       }
        put_ldev(device);
        return 0;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/drbd-9.0.13+git.b83ade31/drbd/drbd_req.c 
new/drbd-9.0.14+git.62f906cf/drbd/drbd_req.c
--- old/drbd-9.0.13+git.b83ade31/drbd/drbd_req.c        2018-04-17 
12:04:10.000000000 +0200
+++ new/drbd-9.0.14+git.62f906cf/drbd/drbd_req.c        2018-05-01 
00:15:21.000000000 +0200
@@ -623,6 +623,21 @@
        connection->req_not_net_done = req;
 }
 
+/* for wsame, discard, and zero-out requests, the payload (amount of data we
+ * need to send) is much smaller than the number of storage sectors affected */
+static unsigned int req_payload_sectors(struct drbd_request *req)
+{
+       /* actually: physical_block_size,
+        * but lets just hardcode 4k in sectors: */
+       if (unlikely(req->local_rq_state & RQ_WSAME))
+               return 8;
+       /* really only a few bytes, but let's pretend one sector */
+       if (unlikely(req->local_rq_state & (RQ_UNMAP|RQ_ZEROES)))
+               return 1;
+       /* other have all the data as payload on the wire */
+       return req->i.size >> 9;
+}
+
 /* I'd like this to be the only place that manipulates
  * req->completion_ref and req->kref. */
 static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
@@ -689,7 +704,7 @@
        if (!(old_net & RQ_NET_SENT) && (set & RQ_NET_SENT)) {
                /* potentially already completed in the ack_receiver thread */
                if (!(old_net & RQ_NET_DONE)) {
-                       atomic_add(req->i.size >> 9, 
&peer_device->connection->ap_in_flight);
+                       atomic_add(req_payload_sectors(req), 
&peer_device->connection->ap_in_flight);
                        set_if_null_req_not_net_done(peer_device, req);
                }
                if (req->net_rq_state[idx] & RQ_NET_PENDING)
@@ -733,7 +748,7 @@
                atomic_t *ap_in_flight = &peer_device->connection->ap_in_flight;
 
                if (old_net & RQ_NET_SENT)
-                       atomic_sub(req->i.size >> 9, ap_in_flight);
+                       atomic_sub(req_payload_sectors(req), ap_in_flight);
                if (old_net & RQ_EXP_BARR_ACK)
                        kref_put(&req->kref, drbd_req_destroy);
                req->net_done_kt[peer_device->node_id] = ktime_get();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/drbd-9.0.13+git.b83ade31/drbd/drbd_sender.c 
new/drbd-9.0.14+git.62f906cf/drbd/drbd_sender.c
--- old/drbd-9.0.13+git.b83ade31/drbd/drbd_sender.c     2018-04-17 
12:04:10.000000000 +0200
+++ new/drbd-9.0.14+git.62f906cf/drbd/drbd_sender.c     2018-05-01 
00:15:21.000000000 +0200
@@ -873,18 +873,6 @@
        return 1;
 }
 
-int w_ov_finished(struct drbd_work *w, int cancel)
-{
-       struct drbd_peer_device_work *dw =
-               container_of(w, struct drbd_peer_device_work, w);
-       struct drbd_peer_device *peer_device = dw->peer_device;
-       kfree(dw);
-       ov_out_of_sync_print(peer_device);
-       drbd_resync_finished(peer_device, D_MASK);
-
-       return 0;
-}
-
 struct resync_finished_work {
        struct drbd_peer_device_work pdw;
        enum drbd_disk_state new_peer_disk_state;
@@ -1091,17 +1079,22 @@
        __change_repl_state(peer_device, L_ESTABLISHED);
 
        aborted = device->disk_state[NOW] == D_OUTDATED && new_peer_disk_state 
== D_INCONSISTENT;
-
-       drbd_info(peer_device, "%s %s (total %lu sec; paused %lu sec; %lu 
K/sec)\n",
+       {
+       char tmp[sizeof(" but 01234567890123456789 4k blocks skipped")] = "";
+       if (verify_done && peer_device->ov_skipped)
+               snprintf(tmp, sizeof(tmp), " but %lu %dk blocks skipped",
+                       peer_device->ov_skipped, Bit2KB(1));
+       drbd_info(peer_device, "%s %s%s (total %lu sec; paused %lu sec; %lu 
K/sec)\n",
                  verify_done ? "Online verify" : "Resync",
-                 aborted ? "aborted" : "done",
+                 aborted ? "aborted" : "done", tmp,
                  dt + peer_device->rs_paused, peer_device->rs_paused, dbdt);
+       }
 
        n_oos = drbd_bm_total_weight(peer_device);
 
        if (repl_state[NOW] == L_VERIFY_S || repl_state[NOW] == L_VERIFY_T) {
                if (n_oos) {
-                       drbd_alert(peer_device, "Online verify found %lu %dk 
block out of sync!\n",
+                       drbd_alert(peer_device, "Online verify found %lu %dk 
blocks out of sync!\n",
                              n_oos, Bit2KB(1));
                        khelper_cmd = "out-of-sync";
                }
@@ -1340,10 +1333,15 @@
        } else if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) {
                if (likely(peer_device->disk_state[NOW] >= D_INCONSISTENT)) {
                        inc_rs_pending(peer_device);
+                       /* If we send back as P_RS_DATA_REPLY,
+                        * this is overestimating "in-flight" accounting.
+                        * But needed to be properly balanced with
+                        * the atomic_sub() in got_BlockAck.
+                        * TODO: to fix that, we'd need a protocol bump. */
+                       atomic_add(peer_req->i.size >> 9, 
&connection->rs_in_flight);
                        if (peer_req->flags & EE_RS_THIN_REQ && 
all_zero(peer_req)) {
                                err = drbd_send_rs_deallocated(peer_device, 
peer_req);
                        } else {
-                               atomic_add(peer_req->i.size >> 9, 
&connection->rs_in_flight);
                                err = drbd_send_block(peer_device, 
P_RS_DATA_REPLY, peer_req);
                        }
                } else {
@@ -1485,12 +1483,31 @@
        if (peer_device->ov_last_oos_start + peer_device->ov_last_oos_size == 
sector) {
                peer_device->ov_last_oos_size += size>>9;
        } else {
+               ov_out_of_sync_print(peer_device);
                peer_device->ov_last_oos_start = sector;
                peer_device->ov_last_oos_size = size>>9;
        }
        drbd_set_out_of_sync(peer_device, sector, size);
 }
 
+void verify_progress(struct drbd_peer_device *peer_device,
+               const sector_t sector, const unsigned int size)
+{
+       bool stop_sector_reached =
+               (peer_device->repl_state[NOW] == L_VERIFY_S) &&
+               verify_can_do_stop_sector(peer_device) &&
+               (sector + (size>>9)) >= peer_device->ov_stop_sector;
+
+       --peer_device->ov_left;
+
+       /* let's advance progress step marks only for every other megabyte */
+       if ((peer_device->ov_left & 0x1ff) == 0)
+               drbd_advance_rs_marks(peer_device, peer_device->ov_left);
+
+       if (peer_device->ov_left == 0 || stop_sector_reached)
+               drbd_peer_device_post_work(peer_device, RS_DONE);
+}
+
 int w_e_end_ov_reply(struct drbd_work *w, int cancel)
 {
        struct drbd_peer_request *peer_req = container_of(w, struct 
drbd_peer_request, w);
@@ -1502,7 +1519,6 @@
        unsigned int size = peer_req->i.size;
        int digest_size;
        int err, eq = 0;
-       bool stop_sector_reached = false;
 
        if (unlikely(cancel)) {
                drbd_free_peer_req(peer_req);
@@ -1547,19 +1563,7 @@
 
        dec_unacked(peer_device);
 
-       --peer_device->ov_left;
-
-       /* let's advance progress step marks only for every other megabyte */
-       if ((peer_device->ov_left & 0x200) == 0x200)
-               drbd_advance_rs_marks(peer_device, peer_device->ov_left);
-
-       stop_sector_reached = verify_can_do_stop_sector(peer_device) &&
-               (sector + (size>>9)) >= peer_device->ov_stop_sector;
-
-       if (peer_device->ov_left == 0 || stop_sector_reached) {
-               ov_out_of_sync_print(peer_device);
-               drbd_resync_finished(peer_device, D_MASK);
-       }
+       verify_progress(peer_device, sector, size);
 
        return err;
 }
@@ -2080,7 +2084,15 @@
 
        drbd_bm_write_lazy(device, 0);
 
-       if (resync_done && is_sync_state(peer_device, NOW))
+       if (resync_done) {
+               if (is_verify_state(peer_device, NOW)) {
+                       ov_out_of_sync_print(peer_device);
+                       ov_skipped_print(peer_device);
+               } else
+                       resync_done = is_sync_state(peer_device, NOW);
+       }
+
+       if (resync_done)
                drbd_resync_finished(peer_device, D_MASK);
 
        /* update timestamp, in case it took a while to write out stuff */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/drbd-9.0.13+git.b83ade31/drbd/drbd_state.c 
new/drbd-9.0.14+git.62f906cf/drbd/drbd_state.c
--- old/drbd-9.0.13+git.b83ade31/drbd/drbd_state.c      2018-04-17 
12:04:10.000000000 +0200
+++ new/drbd-9.0.14+git.62f906cf/drbd/drbd_state.c      2018-05-01 
00:15:21.000000000 +0200
@@ -91,30 +91,27 @@
 static enum drbd_state_rv change_peer_state(struct drbd_connection *, int, 
union drbd_state,
                                            union drbd_state, unsigned long *);
 
-static bool only_diskless_peers(struct drbd_device *device, enum which_state 
which)
+/* We need to stay consistent if we are neighbour of a diskless primary with
+   different UUID. This function should be used if the device was D_UP_TO_DATE
+   before.
+ */
+static bool may_return_to_up_to_date(struct drbd_device *device, enum 
which_state which)
 {
        struct drbd_peer_device *peer_device;
+       bool rv = true;
 
-       for_each_peer_device(peer_device, device) {
-               enum drbd_disk_state peer_disk_state = 
peer_device->disk_state[which];
-
-               if (peer_disk_state >= D_INCONSISTENT && peer_disk_state != 
D_UNKNOWN)
-                       return false;
-       }
-
-       for_each_peer_device(peer_device, device) {
-               if (peer_device->disk_state[which] != D_DISKLESS ||
-                   peer_device->connection->peer_role[which] != R_PRIMARY)
-                       continue;
-
-               if (peer_device->current_uuid != device->ldev->md.current_uuid) 
{
-                       /* Limit disk state get to D_CONSISTENT at max.
-                          That has the effect that the diskless peer can
-                          not read/write from/to this node. */
-                       return true;
+       rcu_read_lock();
+       for_each_peer_device_rcu(peer_device, device) {
+               if (peer_device->disk_state[which] == D_DISKLESS &&
+                   peer_device->connection->peer_role[which] == R_PRIMARY &&
+                   peer_device->current_uuid != drbd_current_uuid(device)) {
+                       rv = false;
+                       break;
                }
        }
-       return false;
+       rcu_read_unlock();
+
+       return rv;
 }
 
 /**
@@ -128,7 +125,7 @@
        bool all_peers_outdated = true;
        int node_id;
 
-       if (only_diskless_peers(device, which)) /* and one primary peer */
+       if (!may_return_to_up_to_date(device, which))
                return false;
 
        rcu_read_lock();
@@ -2040,6 +2037,7 @@
                peer_device->ov_position = peer_device->ov_start_sector;
        }
        peer_device->ov_left = peer_device->rs_total;
+       peer_device->ov_skipped = 0;
 }
 
 static void queue_after_state_change_work(struct drbd_resource *resource,
@@ -2252,6 +2250,8 @@
                                peer_device->rs_last_sect_ev = 0;
                                peer_device->ov_last_oos_size = 0;
                                peer_device->ov_last_oos_start = 0;
+                               peer_device->ov_last_skipped_size = 0;
+                               peer_device->ov_last_skipped_start = 0;
 
                                for (i = 0; i < DRBD_SYNC_MARKS; i++) {
                                        peer_device->rs_mark_left[i] = 
peer_device->ov_left;
@@ -3406,7 +3406,7 @@
                        send_new_state_to_all_peer_devices(state_change, 
n_device);
 
                if (disk_state[OLD] == D_UP_TO_DATE && disk_state[NEW] == 
D_CONSISTENT &&
-                   may_be_up_to_date(device, NOW))
+                   may_return_to_up_to_date(device, NOW))
                        try_become_up_to_date = true;
 
                drbd_md_sync_if_dirty(device);
@@ -4566,7 +4566,8 @@
                int vnr;
 
                idr_for_each_entry(&resource->devices, device, vnr) {
-                       if (device->disk_state[NOW] == D_CONSISTENT)
+                       if (device->disk_state[NOW] == D_CONSISTENT &&
+                           may_return_to_up_to_date(device, NOW))
                                __change_disk_state(device, D_UP_TO_DATE);
                }
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/drbd-9.0.13+git.b83ade31/drbd/drbd_transport_tcp.c 
new/drbd-9.0.14+git.62f906cf/drbd/drbd_transport_tcp.c
--- old/drbd-9.0.13+git.b83ade31/drbd/drbd_transport_tcp.c      2018-04-17 
12:04:10.000000000 +0200
+++ new/drbd-9.0.14+git.62f906cf/drbd/drbd_transport_tcp.c      2018-05-01 
00:15:21.000000000 +0200
@@ -607,7 +607,7 @@
 {
        struct dtt_socket_container *socket_c;
        struct sockaddr_storage peer_addr;
-       int connect_int, peer_addr_len, err = 0;
+       int connect_int, err = 0;
        long timeo;
        struct socket *s_estab = NULL;
        struct net_conf *nc;
@@ -653,7 +653,8 @@
                   from the listening socket. */
                unregister_state_change(s_estab->sk, listener);
 
-               s_estab->ops->getname(s_estab, (struct sockaddr *)&peer_addr, 
&peer_addr_len, 2);
+
+               drbd_always_getpeername(s_estab, (struct sockaddr *)&peer_addr);
 
                spin_lock_bh(&listener->listener.waiters_lock);
                drbd_path2 = drbd_find_path_by_addr(&listener->listener, 
&peer_addr);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/drbd-9.0.13+git.b83ade31/drbd/linux/drbd_config.h 
new/drbd-9.0.14+git.62f906cf/drbd/linux/drbd_config.h
--- old/drbd-9.0.13+git.b83ade31/drbd/linux/drbd_config.h       2018-04-17 
12:04:10.000000000 +0200
+++ new/drbd-9.0.14+git.62f906cf/drbd/linux/drbd_config.h       2018-05-01 
00:15:21.000000000 +0200
@@ -32,7 +32,7 @@
 
 /* End of external module for 2.6.33 stuff */
 
-#define REL_VERSION "9.0.13-1"
+#define REL_VERSION "9.0.14-1"
 #define PRO_VERSION_MIN 86
 #define PRO_VERSION_MAX 113
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/drbd-9.0.13+git.b83ade31/drbd-headers/linux/drbd_genl.h 
new/drbd-9.0.14+git.62f906cf/drbd-headers/linux/drbd_genl.h
--- old/drbd-9.0.13+git.b83ade31/drbd-headers/linux/drbd_genl.h 2018-04-17 
12:04:10.000000000 +0200
+++ new/drbd-9.0.14+git.62f906cf/drbd-headers/linux/drbd_genl.h 2018-05-01 
00:15:21.000000000 +0200
@@ -272,6 +272,8 @@
 
 GENL_struct(DRBD_NLA_CONNECTION_STATISTICS, 21, connection_statistics,
        __flg_field(1, 0, conn_congested)
+       __u64_field(2, 0, ap_in_flight) /* sectors */
+       __u64_field(3, 0, rs_in_flight) /* sectors */
 )
 
 GENL_struct(DRBD_NLA_PEER_DEVICE_STATISTICS, 22, peer_device_statistics,
@@ -283,6 +285,24 @@
        __u64_field(6, 0, peer_dev_resync_failed)  /* sectors */
        __u64_field(7, 0, peer_dev_bitmap_uuid)
        __u32_field(9, 0, peer_dev_flags)
+       /* you need the peer_repl_state from peer_device_info
+        * to properly interpret these stats for "progress"
+        * of syncer/verify */
+       __u64_field(10,0, peer_dev_rs_total)    /* sectors */
+       __u64_field(11,0, peer_dev_ov_start_sector)
+       __u64_field(12,0, peer_dev_ov_stop_sector)
+       __u64_field(13,0, peer_dev_ov_position) /* sectors */
+       __u64_field(14,0, peer_dev_ov_left)     /* sectors */
+       __u64_field(15,0, peer_dev_ov_skipped)  /* sectors */
+       __u64_field(16,0, peer_dev_rs_same_csum)
+       __u64_field(17,0, peer_dev_rs_dt_start_ms)
+       __u64_field(18,0, peer_dev_rs_paused_ms)
+       /* resync progress marks for "resync speed" guestimation */
+       __u64_field(19,0, peer_dev_rs_dt0_ms)
+       __u64_field(20,0, peer_dev_rs_db0_sectors)
+       __u64_field(21,0, peer_dev_rs_dt1_ms)
+       __u64_field(22,0, peer_dev_rs_db1_sectors)
+       __u32_field(23,0, peer_dev_rs_c_sync_rate)
 )
 
 GENL_struct(DRBD_NLA_NOTIFICATION_HEADER, 23, drbd_notification_header,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/drbd-9.0.13+git.b83ade31/drbd-kernel.spec 
new/drbd-9.0.14+git.62f906cf/drbd-kernel.spec
--- old/drbd-9.0.13+git.b83ade31/drbd-kernel.spec       2018-04-17 
12:04:10.000000000 +0200
+++ new/drbd-9.0.14+git.62f906cf/drbd-kernel.spec       2018-05-01 
00:15:21.000000000 +0200
@@ -1,6 +1,6 @@
 Name: drbd-kernel
 Summary: Kernel driver for DRBD
-Version: 9.0.13
+Version: 9.0.14
 Release: 1%{?dist}
 
 # always require a suitable userland
@@ -103,6 +103,9 @@
 rm -rf %{buildroot}
 
 %changelog
+* Tue May 01 2018 Lars Ellenberg <[email protected]> - 9.0.14-1
+- New upstream release.
+
 * Tue Apr 17 2018 Philipp Reisner <[email protected]> - 9.0.13-1
 - New upstream release.
 

++++++ drbd_git_revision ++++++
--- /var/tmp/diff_new_pack.ldUjR8/_old  2018-05-03 12:34:47.759121560 +0200
+++ /var/tmp/diff_new_pack.ldUjR8/_new  2018-05-03 12:34:47.759121560 +0200
@@ -1 +1 @@
-GIT-hash: b83ade31e10925030206854027021eb4fc9f2563
+GIT-hash: 62f906cf44ef02a30ce0c148fec223b40c51c533


Reply via email to