diff --git a/_service b/_service
index 64d86d5..176cd31 100644
--- a/_service
+++ b/_service
@@ -10,7 +10,7 @@
9.0.12
-->
9.0.12+git.%h
- 7eb4aef4abbfba8ebb1afbcc30574df74db0063e
+ 969e477dcfdf31c8b0462b7c725dda56b70371b2
diff --git a/drbd-9.0.12+git.7eb4aef.tar.bz2 b/drbd-9.0.12+git.7eb4aef.tar.bz2
deleted file mode 100644
index 5c5e8f5..0000000
--- a/drbd-9.0.12+git.7eb4aef.tar.bz2
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:2a7ed60b42b41a893dd1cff93907fd618bca31c780e7b21be6871f5e5b32262c
-size 314006
diff --git a/drbd-9.0.12+git.969e477d.tar.bz2 b/drbd-9.0.12+git.969e477d.tar.bz2
new file mode 100644
index 0000000..8ccc641
--- /dev/null
+++ b/drbd-9.0.12+git.969e477d.tar.bz2
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6f99f1b06eae6dcbe56374171fcafc9cbd6db979e2e7b679ac81f4d9e4018272
+size 313765
diff --git a/drbd.changes b/drbd.changes
index 9b9090b..3039ae9 100644
--- a/drbd.changes
+++ b/drbd.changes
@@ -1,3 +1,11 @@
+-------------------------------------------------------------------
+Sun Feb 11 06:39:19 UTC 2018 - nwang@suse.com
+
+- bsc#1080458, enable build with kernel-rt on x86_64.
+- bsc#1080459, support build against 4.15.0.
+ setup_timer() change to timer_setup()
+- Add patch support-timer-setup.patch
+
-------------------------------------------------------------------
Wed Jan 24 03:44:56 UTC 2018 - nwang@suse.com
diff --git a/drbd.spec b/drbd.spec
index 0c36c14..cc382f4 100644
--- a/drbd.spec
+++ b/drbd.spec
@@ -19,12 +19,12 @@
%if ! 0%{?is_opensuse}
%ifarch x86_64
-%define buildrt 0
+%define buildrt 1
%endif
%endif
Name: drbd
-Version: 9.0.12+git.7eb4aef
+Version: 9.0.12+git.969e477d
Release: 0
Summary: DRBD driver for Linux
License: GPL-2.0+
@@ -36,6 +36,7 @@ Source1: preamble
Source2: Module.supported
Source3: drbd_git_revision
Patch1: fix-resync-finished-with-syncs-have-bits-set.patch
+Patch2: support-timer-setup.patch
BuildRequires: kernel-source
BuildRequires: kernel-syms
BuildRequires: libelf-devel
@@ -69,6 +70,7 @@ installed kernel.
%prep
%setup -q -n drbd-%{version}
%patch1 -p1
+%patch2 -p1
mkdir source
cp -a drbd/. source/. || :
diff --git a/drbd_git_revision b/drbd_git_revision
index e98e210..99011ce 100644
--- a/drbd_git_revision
+++ b/drbd_git_revision
@@ -1 +1 @@
-GIT-hash: 7eb4aef4abbfba8ebb1afbcc30574df74db0063e
+GIT-hash: 969e477dcfdf31c8b0462b7c725dda56b70371b2
diff --git a/support-timer-setup.patch b/support-timer-setup.patch
new file mode 100644
index 0000000..cca9e91
--- /dev/null
+++ b/support-timer-setup.patch
@@ -0,0 +1,382 @@
+diff -Naur drbd-9.0.12+git.969e477d.orig/drbd/drbd_int.h drbd-9.0.12+git.969e477d/drbd/drbd_int.h
+--- drbd-9.0.12+git.969e477d.orig/drbd/drbd_int.h 2018-02-11 17:28:38.748598711 +0800
++++ drbd-9.0.12+git.969e477d/drbd/drbd_int.h 2018-02-11 17:28:50.168678009 +0800
+@@ -1860,7 +1860,11 @@
+ extern void drbd_rs_controller_reset(struct drbd_peer_device *);
+ extern void drbd_ping_peer(struct drbd_connection *connection);
+ extern struct drbd_peer_device *peer_device_by_node_id(struct drbd_device *, int);
++#ifndef COMPAT_HAVE_SETUP_TIMER
++extern void repost_up_to_date_fn(struct timer_list *t);
++#else
+ extern void repost_up_to_date_fn(unsigned long data);
++#endif
+
+ static inline void ov_out_of_sync_print(struct drbd_peer_device *peer_device)
+ {
+@@ -1890,8 +1894,13 @@
+ extern int w_start_resync(struct drbd_work *, int);
+ extern int w_send_uuids(struct drbd_work *, int);
+
++#ifndef COMPAT_HAVE_SETUP_TIMER
++extern void resync_timer_fn(struct timer_list *);
++extern void start_resync_timer_fn(struct timer_list *);
++#else
+ extern void resync_timer_fn(unsigned long data);
+ extern void start_resync_timer_fn(unsigned long data);
++#endif
+
+ extern void drbd_endio_write_sec_final(struct drbd_peer_request *peer_req);
+
+@@ -1974,7 +1983,11 @@
+ extern struct drbd_connection *drbd_connection_by_node_id(struct drbd_resource *, int);
+ extern struct drbd_connection *drbd_get_connection_by_node_id(struct drbd_resource *, int);
+ extern void queue_queued_twopc(struct drbd_resource *resource);
++#ifndef COMPAT_HAVE_SETUP_TIMER
++extern void queued_twopc_timer_fn(struct timer_list *);
++#else
+ extern void queued_twopc_timer_fn(unsigned long data);
++#endif
+ extern bool drbd_have_local_disk(struct drbd_resource *resource);
+ extern enum drbd_state_rv drbd_support_2pc_resize(struct drbd_resource *resource);
+ extern enum determine_dev_size
+@@ -2021,8 +2034,13 @@
+ void drbd_bump_write_ordering(struct drbd_resource *resource, struct drbd_backing_dev *bdev,
+ enum write_ordering_e wo);
+
++#ifndef COMPAT_HAVE_SETUP_TIMER
++extern void twopc_timer_fn(struct timer_list *);
++extern void connect_timer_fn(struct timer_list *);
++#else
+ extern void twopc_timer_fn(unsigned long);
+ extern void connect_timer_fn(unsigned long);
++#endif
+
+ /* drbd_proc.c */
+ extern struct proc_dir_entry *drbd_proc;
+diff -Naur drbd-9.0.12+git.969e477d.orig/drbd/drbd-kernel-compat/tests/have_setup_timer.c drbd-9.0.12+git.969e477d/drbd/drbd-kernel-compat/tests/have_setup_timer.c
+--- drbd-9.0.12+git.969e477d.orig/drbd/drbd-kernel-compat/tests/have_setup_timer.c 1970-01-01 08:00:00.000000000 +0800
++++ drbd-9.0.12+git.969e477d/drbd/drbd-kernel-compat/tests/have_setup_timer.c 2018-02-11 17:28:50.168678009 +0800
+@@ -0,0 +1,7 @@
++#include
++
++void dummy(struct timer_list *timer, void (*function)(unsigned long), unsigned long data)
++{
++ setup_timer(timer, function, data);
++ return;
++}
+diff -Naur drbd-9.0.12+git.969e477d.orig/drbd/drbd_main.c drbd-9.0.12+git.969e477d/drbd/drbd_main.c
+--- drbd-9.0.12+git.969e477d.orig/drbd/drbd_main.c 2018-02-11 17:28:38.748598711 +0800
++++ drbd-9.0.12+git.969e477d/drbd/drbd_main.c 2018-02-11 17:34:37.499091262 +0800
+@@ -76,7 +76,11 @@
+
+ static int drbd_open(struct block_device *bdev, fmode_t mode);
+ static DRBD_RELEASE_RETURN drbd_release(struct gendisk *gd, fmode_t mode);
++#ifndef COMPAT_HAVE_SETUP_TIMER
++static void md_sync_timer_fn(struct timer_list *t);
++#else
+ static void md_sync_timer_fn(unsigned long data);
++#endif
+ static int w_bitmap_io(struct drbd_work *w, int unused);
+ static int flush_send_buffer(struct drbd_connection *connection, enum drbd_stream drbd_stream);
+
+@@ -3192,9 +3196,15 @@
+ spin_unlock_irq(&resource->req_lock);
+ }
+
++#ifndef COMPAT_HAVE_SETUP_TIMER
++static void peer_ack_timer_fn(struct timer_list *t)
++{
++ struct drbd_resource *resource = from_timer(resource, t, peer_ack_timer);
++#else
+ static void peer_ack_timer_fn(unsigned long data)
+ {
+ struct drbd_resource *resource = (struct drbd_resource *) data;
++#endif
+
+ drbd_flush_peer_acks(resource);
+ }
+@@ -3309,8 +3319,13 @@
+ INIT_LIST_HEAD(&resource->connections);
+ INIT_LIST_HEAD(&resource->transfer_log);
+ INIT_LIST_HEAD(&resource->peer_ack_list);
++#ifndef COMPAT_HAVE_SETUP_TIMER
++ timer_setup(&resource->peer_ack_timer, peer_ack_timer_fn, 0);
++ timer_setup(&resource->repost_up_to_date_timer, repost_up_to_date_fn, 0);
++#else
+ setup_timer(&resource->peer_ack_timer, peer_ack_timer_fn, (unsigned long) resource);
+ setup_timer(&resource->repost_up_to_date_timer, repost_up_to_date_fn, (unsigned long) resource);
++#endif
+ sema_init(&resource->state_sem, 1);
+ resource->role[NOW] = R_SECONDARY;
+ if (set_resource_options(resource, res_opts))
+@@ -3327,11 +3342,19 @@
+ init_waitqueue_head(&resource->twopc_wait);
+ init_waitqueue_head(&resource->barrier_wait);
+ INIT_LIST_HEAD(&resource->twopc_parents);
++#ifndef COMPAT_HAVE_SETUP_TIMER
++ timer_setup(&resource->twopc_timer, twopc_timer_fn, 0);
++#else
+ setup_timer(&resource->twopc_timer, twopc_timer_fn, (unsigned long) resource);
++#endif
+ INIT_LIST_HEAD(&resource->twopc_work.list);
+ INIT_LIST_HEAD(&resource->queued_twopc);
+ spin_lock_init(&resource->queued_twopc_lock);
++#ifndef COMPAT_HAVE_SETUP_TIMER
++ timer_setup(&resource->queued_twopc_timer, queued_twopc_timer_fn, 0);
++#else
+ setup_timer(&resource->queued_twopc_timer, queued_twopc_timer_fn, (unsigned long) resource);
++#endif
+ drbd_init_workqueue(&resource->work);
+ drbd_thread_init(resource, &resource->worker, drbd_worker, "worker");
+ drbd_thread_start(&resource->worker);
+@@ -3391,9 +3414,15 @@
+ mutex_init(&connection->mutex[CONTROL_STREAM]);
+
+ INIT_LIST_HEAD(&connection->connect_timer_work.list);
++#ifndef COMPAT_HAVE_SETUP_TIMER
++ timer_setup(&connection->connect_timer,
++ connect_timer_fn,
++ 0);
++#else
+ setup_timer(&connection->connect_timer,
+ connect_timer_fn,
+ (unsigned long) connection);
++#endif
+
+ drbd_thread_init(resource, &connection->receiver, drbd_receiver, "receiver");
+ connection->receiver.connection = connection;
+@@ -3504,16 +3533,26 @@
+ kfree(peer_device);
+ return NULL;
+ }
+-
++#ifndef COMPAT_HAVE_SETUP_TIMER
++ timer_setup(&peer_device->start_resync_timer,
++ start_resync_timer_fn,
++ 0);
++#else
+ setup_timer(&peer_device->start_resync_timer,
+ start_resync_timer_fn,
+ (unsigned long) peer_device);
+-
++#endif
+ INIT_LIST_HEAD(&peer_device->resync_work.list);
+ peer_device->resync_work.cb = w_resync_timer;
++#ifndef COMPAT_HAVE_SETUP_TIMER
++ timer_setup(&peer_device->resync_timer,
++ resync_timer_fn,
++ 0);
++#else
+ setup_timer(&peer_device->resync_timer,
+ resync_timer_fn,
+ (unsigned long) peer_device);
++#endif
+
+ INIT_LIST_HEAD(&peer_device->propagate_uuids_work.list);
+ peer_device->propagate_uuids_work.cb = w_send_uuids;
+@@ -3609,12 +3648,21 @@
+ spin_lock_init(&device->pending_bitmap_work.q_lock);
+ INIT_LIST_HEAD(&device->pending_bitmap_work.q);
+
++#ifndef COMPAT_HAVE_SETUP_TIMER
++ timer_setup(&device->md_sync_timer,
++ md_sync_timer_fn,
++ 0);
++ timer_setup(&device->request_timer,
++ request_timer_fn,
++ 0);
++#else
+ setup_timer(&device->md_sync_timer,
+ md_sync_timer_fn,
+ (unsigned long) device);
+ setup_timer(&device->request_timer,
+ request_timer_fn,
+ (unsigned long) device);
++#endif
+
+ init_waitqueue_head(&device->misc_wait);
+ init_waitqueue_head(&device->al_wait);
+@@ -5191,9 +5239,15 @@
+ return md->peers[peer_device->node_id].flags & flag;
+ }
+
++#ifndef COMPAT_HAVE_SETUP_TIMER
++static void md_sync_timer_fn(struct timer_list *t)
++{
++ struct drbd_device *device = from_timer(device, t, md_sync_timer);
++#else
+ static void md_sync_timer_fn(unsigned long data)
+ {
+ struct drbd_device *device = (struct drbd_device *) data;
++#endif
+ drbd_device_post_work(device, MD_SYNC);
+ }
+
+diff -Naur drbd-9.0.12+git.969e477d.orig/drbd/drbd_receiver.c drbd-9.0.12+git.969e477d/drbd/drbd_receiver.c
+--- drbd-9.0.12+git.969e477d.orig/drbd/drbd_receiver.c 2018-02-11 17:28:38.748598711 +0800
++++ drbd-9.0.12+git.969e477d/drbd/drbd_receiver.c 2018-02-11 17:28:50.172678024 +0800
+@@ -596,9 +596,15 @@
+ return err;
+ }
+
++#ifndef COMPAT_HAVE_SETUP_TIMER
++void connect_timer_fn(struct timer_list *t)
++{
++ struct drbd_connection *connection = from_timer(connection, t, connect_timer);
++#else
+ void connect_timer_fn(unsigned long data)
+ {
+ struct drbd_connection *connection = (struct drbd_connection *) data;
++#endif
+ struct drbd_resource *resource = connection->resource;
+ unsigned long irq_flags;
+
+@@ -5327,10 +5333,17 @@
+ return 0;
+ }
+
++#ifndef COMPAT_HAVE_SETUP_TIMER
++void twopc_timer_fn(struct timer_list *t)
++{
++ unsigned long irq_flags;
++ struct drbd_resource *resource = from_timer(resource, t, twopc_timer);
++#else
+ void twopc_timer_fn(unsigned long data)
+ {
+ struct drbd_resource *resource = (struct drbd_resource *) data;
+ unsigned long irq_flags;
++#endif
+
+ spin_lock_irqsave(&resource->req_lock, irq_flags);
+ if (resource->twopc_work.cb == NULL) {
+@@ -5582,12 +5595,21 @@
+ return 0;
+ }
+
++#ifndef COMPAT_HAVE_SETUP_TIMER
++void queued_twopc_timer_fn(struct timer_list *time)
++{
++ struct queued_twopc *q;
++ unsigned long irq_flags;
++ struct drbd_resource *resource = from_timer(resource, time, queued_twopc_timer);
++ unsigned long t = twopc_timeout(resource) / 4;
++#else
+ void queued_twopc_timer_fn(unsigned long data)
+ {
+ struct drbd_resource *resource = (struct drbd_resource *) data;
+ struct queued_twopc *q;
+ unsigned long irq_flags;
+ unsigned long t = twopc_timeout(resource) / 4;
++#endif
+
+ spin_lock_irqsave(&resource->queued_twopc_lock, irq_flags);
+ q = list_first_entry_or_null(&resource->queued_twopc, struct queued_twopc, w.list);
+@@ -7262,7 +7284,11 @@
+ wake_up(&peer_device->device->misc_wait);
+
+ del_timer_sync(&peer_device->resync_timer);
++#ifndef COMPAT_HAVE_SETUP_TIMER
++ resync_timer_fn(&peer_device->resync_timer);
++#else
+ resync_timer_fn((unsigned long)peer_device);
++#endif
+ del_timer_sync(&peer_device->start_resync_timer);
+ }
+
+diff -Naur drbd-9.0.12+git.969e477d.orig/drbd/drbd_req.c drbd-9.0.12+git.969e477d/drbd/drbd_req.c
+--- drbd-9.0.12+git.969e477d.orig/drbd/drbd_req.c 2018-02-11 17:28:38.748598711 +0800
++++ drbd-9.0.12+git.969e477d/drbd/drbd_req.c 2018-02-11 17:28:50.172678024 +0800
+@@ -2309,6 +2309,19 @@
+ * to expire twice (worst case) to become effective. Good enough.
+ */
+
++#ifndef COMPAT_HAVE_SETUP_TIMER
++void request_timer_fn(struct timer_list *t)
++{
++ struct drbd_connection *connection;
++ struct drbd_request *req_read, *req_write;
++ unsigned long oldest_submit_jif;
++ unsigned long dt = 0;
++ unsigned long et = 0;
++ unsigned long now = jiffies;
++ unsigned long next_trigger_time = now;
++ bool restart_timer = false;
++ struct drbd_device *device = from_timer(device, t, request_timer);
++#else
+ void request_timer_fn(unsigned long data)
+ {
+ struct drbd_device *device = (struct drbd_device *) data;
+@@ -2320,6 +2333,7 @@
+ unsigned long now = jiffies;
+ unsigned long next_trigger_time = now;
+ bool restart_timer = false;
++#endif
+
+ rcu_read_lock();
+ if (get_ldev(device)) { /* implicit state.disk >= D_INCONSISTENT */
+diff -Naur drbd-9.0.12+git.969e477d.orig/drbd/drbd_req.h drbd-9.0.12+git.969e477d/drbd/drbd_req.h
+--- drbd-9.0.12+git.969e477d.orig/drbd/drbd_req.h 2018-02-11 17:28:38.748598711 +0800
++++ drbd-9.0.12+git.969e477d/drbd/drbd_req.h 2018-02-11 17:28:50.172678024 +0800
+@@ -319,7 +319,11 @@
+ struct bio_and_error *m);
+ extern void complete_master_bio(struct drbd_device *device,
+ struct bio_and_error *m);
++#ifndef COMPAT_HAVE_SETUP_TIMER
++extern void request_timer_fn(struct timer_list *);
++#else
+ extern void request_timer_fn(unsigned long data);
++#endif
+ extern void tl_restart(struct drbd_connection *connection, enum drbd_req_event what);
+ extern void _tl_restart(struct drbd_connection *connection, enum drbd_req_event what);
+ extern void drbd_queue_peer_ack(struct drbd_resource *resource, struct drbd_request *req);
+diff -Naur drbd-9.0.12+git.969e477d.orig/drbd/drbd_sender.c drbd-9.0.12+git.969e477d/drbd/drbd_sender.c
+--- drbd-9.0.12+git.969e477d.orig/drbd/drbd_sender.c 2018-02-11 17:28:38.748598711 +0800
++++ drbd-9.0.12+git.969e477d/drbd/drbd_sender.c 2018-02-11 17:28:50.172678024 +0800
+@@ -498,9 +498,15 @@
+ return 0;
+ }
+
++#ifndef COMPAT_HAVE_SETUP_TIMER
++void resync_timer_fn(struct timer_list *t)
++{
++ struct drbd_peer_device *peer_device = from_timer(peer_device, t, resync_timer);
++#else
+ void resync_timer_fn(unsigned long data)
+ {
+ struct drbd_peer_device *peer_device = (struct drbd_peer_device *) data;
++#endif
+
+ drbd_queue_work_if_unqueued(
+ &peer_device->connection->sender_work,
+@@ -1809,9 +1815,15 @@
+ rcu_read_unlock();
+ }
+
++#ifndef COMPAT_HAVE_SETUP_TIMER
++void start_resync_timer_fn(struct timer_list *t)
++{
++ struct drbd_peer_device *peer_device = from_timer(peer_device, t, start_resync_timer);
++#else
+ void start_resync_timer_fn(unsigned long data)
+ {
+ struct drbd_peer_device *peer_device = (struct drbd_peer_device *) data;
++#endif
+ drbd_peer_device_post_work(peer_device, RS_START);
+ }
+
+@@ -2153,9 +2165,15 @@
+ return 0;
+ }
+
++#ifndef COMPAT_HAVE_SETUP_TIMER
++void repost_up_to_date_fn(struct timer_list *t)
++{
++ struct drbd_resource *resource = from_timer(resource, t, repost_up_to_date_timer);
++#else
+ void repost_up_to_date_fn(unsigned long data)
+ {
+ struct drbd_resource *resource = (struct drbd_resource *) data;
++#endif
+ drbd_post_work(resource, TRY_BECOME_UP_TO_DATE);
+ }
+