Merge branch 'drbd-8.4_ed6' into for-3.8-drivers-drbd-8.4_ed6
[firefly-linux-kernel-4.4.55.git] / drivers / block / drbd / drbd_int.h
index 2ecee6cd2bdb5c1bb8dff5b4c0d2352b6a7197fd..ef72a72814c76087e8ec978f8cff82cb5e2afbd2 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
-#include <linux/version.h>
 #include <linux/list.h>
 #include <linux/sched.h>
 #include <linux/bitops.h>
@@ -64,8 +63,8 @@
 
 /* module parameter, defined in drbd_main.c */
 extern unsigned int minor_count;
-extern int disable_sendpage;
-extern int allow_oos;
+extern bool disable_sendpage;
+extern bool allow_oos;
 
 #ifdef CONFIG_DRBD_FAULT_INJECTION
 extern int enable_faults;
@@ -164,16 +163,9 @@ drbd_insert_fault(struct drbd_conf *mdev, unsigned int type) {
 /* usual integer division */
 #define div_floor(A, B) ((A)/(B))
 
-/* drbd_meta-data.c (still in drbd_main.c) */
-/* 4th incarnation of the disk layout. */
-#define DRBD_MD_MAGIC (DRBD_MAGIC+4)
-
 extern struct ratelimit_state drbd_ratelimit_state;
-extern struct idr minors;
-extern struct list_head drbd_tconns;
-extern struct rw_semaphore drbd_cfg_rwsem;
-/* drbd_cfg_rwsem protects: drbd_tconns list, minors idr, tconn->volumes idr 
-   note: non sleeping iterations over the idrs are protoected by RCU */
+extern struct idr minors; /* RCU, updates: genl_lock() */
+extern struct list_head drbd_tconns; /* RCU, updates: genl_lock() */
 
 /* on the wire */
 enum drbd_packet {
@@ -204,7 +196,7 @@ enum drbd_packet {
        P_RECV_ACK            = 0x15, /* Used in protocol B */
        P_WRITE_ACK           = 0x16, /* Used in protocol C */
        P_RS_WRITE_ACK        = 0x17, /* Is a P_WRITE_ACK, additionally call set_in_sync(). */
-       P_DISCARD_WRITE       = 0x18, /* Used in proto C, two-primaries conflict detection */
+       P_SUPERSEDED          = 0x18, /* Used in proto C, two-primaries conflict detection */
        P_NEG_ACK             = 0x19, /* Sent if local disk is unusable */
        P_NEG_DREPLY          = 0x1a, /* Local disk is broken... */
        P_NEG_RS_DREPLY       = 0x1b, /* Local disk is broken... */
@@ -228,6 +220,7 @@ enum drbd_packet {
        P_CONN_ST_CHG_REQ     = 0x2a, /* data sock: Connection wide state request */
        P_CONN_ST_CHG_REPLY   = 0x2b, /* meta sock: Connection side state req reply */
        P_RETRY_WRITE         = 0x2c, /* Protocol C: retry conflicting write request */
+       P_PROTOCOL_UPDATE     = 0x2d, /* data sock: is used in established connections */
 
        P_MAY_IGNORE          = 0x100, /* Flag to test if (cmd > P_MAY_IGNORE) ... */
        P_MAX_OPT_CMD         = 0x101,
@@ -341,7 +334,7 @@ struct p_data {
  * commands which share a struct:
  *  p_block_ack:
  *   P_RECV_ACK (proto B), P_WRITE_ACK (proto C),
- *   P_DISCARD_WRITE (proto C, two-primaries conflict detection)
+ *   P_SUPERSEDED (proto C, two-primaries conflict detection)
  *  p_block_req:
  *   P_DATA_REQUEST, P_RS_DATA_REQUEST
  */
@@ -374,11 +367,11 @@ struct p_connection_features {
        u32 protocol_max;
 
        /* should be more than enough for future enhancements
-        * for now, feature_flags and the reserverd array shall be zero.
+        * for now, feature_flags and the reserved array shall be zero.
         */
 
        u32 _pad;
-       u64 reserverd[7];
+       u64 reserved[7];
 } __packed;
 
 struct p_barrier {
@@ -392,21 +385,21 @@ struct p_barrier_ack {
 } __packed;
 
 struct p_rs_param {
-       u32 rate;
+       u32 resync_rate;
 
              /* Since protocol version 88 and higher. */
        char verify_alg[0];
 } __packed;
 
 struct p_rs_param_89 {
-       u32 rate;
+       u32 resync_rate;
         /* protocol version 89: */
        char verify_alg[SHARED_SECRET_MAX];
        char csums_alg[SHARED_SECRET_MAX];
 } __packed;
 
 struct p_rs_param_95 {
-       u32 rate;
+       u32 resync_rate;
        char verify_alg[SHARED_SECRET_MAX];
        char csums_alg[SHARED_SECRET_MAX];
        u32 c_plan_ahead;
@@ -416,7 +409,7 @@ struct p_rs_param_95 {
 } __packed;
 
 enum drbd_conn_flags {
-       CF_WANT_LOSE = 1,
+       CF_DISCARD_MY_DATA = 1,
        CF_DRY_RUN = 2,
 };
 
@@ -473,12 +466,6 @@ struct p_drbd06_param {
        u32       bit_map_gen[5];
 } __packed;
 
-struct p_discard {
-       u64         block_id;
-       u32         seq_num;
-       u32         pad;
-} __packed;
-
 struct p_block_desc {
        u64 sector;
        u32 blksize;
@@ -568,29 +555,31 @@ struct drbd_request {
        struct bio *private_bio;
 
        struct drbd_interval i;
-       unsigned int epoch; /* barrier_nr */
 
-       /* barrier_nr: used to check on "completion" whether this req was in
+       /* epoch: used to check on "completion" whether this req was in
         * the current epoch, and we therefore have to close it,
-        * starting a new epoch...
+        * causing a p_barrier packet to be send, starting a new epoch.
+        *
+        * This corresponds to "barrier" in struct p_barrier[_ack],
+        * and to "barrier_nr" in struct drbd_epoch (and various
+        * comments/function parameters/local variable names).
         */
+       unsigned int epoch;
 
        struct list_head tl_requests; /* ring list in the transfer log */
        struct bio *master_bio;       /* master bio pointer */
-       unsigned long rq_state; /* see comments above _req_mod() */
-       int seq_num;
        unsigned long start_time;
-};
 
-struct drbd_tl_epoch {
-       struct drbd_work w;
-       struct list_head requests; /* requests before */
-       struct drbd_tl_epoch *next; /* pointer to the next barrier */
-       unsigned int br_number;  /* the barriers identifier. */
-       int n_writes;   /* number of requests attached before this barrier */
+       /* once it hits 0, we may complete the master_bio */
+       atomic_t completion_ref;
+       /* once it hits 0, we may destroy this drbd_request object */
+       struct kref kref;
+
+       unsigned rq_state; /* see comments above _req_mod() */
 };
 
 struct drbd_epoch {
+       struct drbd_tconn *tconn;
        struct list_head list;
        unsigned int barrier_nr;
        atomic_t epoch_size; /* increased on every request added. */
@@ -676,8 +665,6 @@ enum {
 
 /* flag bits per mdev */
 enum {
-       CREATE_BARRIER,         /* next P_DATA is preceded by a P_BARRIER */
-       UNPLUG_QUEUED,          /* only relevant with kernel 2.4 */
        UNPLUG_REMOTE,          /* sending a "UnplugRemote" could help */
        MD_DIRTY,               /* current uuids and flags not yet on disk */
        USE_DEGR_WFC_T,         /* degr-wfc-timeout instead of wfc-timeout. */
@@ -686,7 +673,6 @@ enum {
        CRASHED_PRIMARY,        /* This node was a crashed primary.
                                 * Gets cleared when the state.conn
                                 * goes into C_CONNECTED state. */
-       NO_BARRIER_SUPP,        /* underlying block device doesn't implement barriers */
        CONSIDER_RESYNC,
 
        MD_NO_FUA,              /* Users wants us to not use FUA/FLUSH on meta data dev */
@@ -695,7 +681,9 @@ enum {
                                   once no more io in flight, start bitmap io */
        BITMAP_IO_QUEUED,       /* Started bitmap IO */
        GO_DISKLESS,            /* Disk is being detached, on io-error or admin request. */
-       WAS_IO_ERROR,           /* Local disk failed returned IO error */
+       WAS_IO_ERROR,           /* Local disk failed, returned IO error */
+       WAS_READ_ERROR,         /* Local disk READ failed (set additionally to the above) */
+       FORCE_DETACH,           /* Force-detach from local disk, aborting any pending local IO */
        RESYNC_AFTER_NEG,       /* Resync after online grow after the attach&negotiate finished. */
        RESIZE_PENDING,         /* Size change detected locally, waiting for the response from
                                 * the peer, if it changed there as well. */
@@ -703,6 +691,8 @@ enum {
        AL_SUSPENDED,           /* Activity logging is currently suspended. */
        AHEAD_TO_SYNC_SOURCE,   /* Ahead -> SyncSource queued */
        B_RS_H_DONE,            /* Before resync handler done (already executed) */
+       DISCARD_MY_DATA,        /* discard_my_data flag per volume */
+       READ_BALANCE_RR,
 };
 
 struct drbd_bitmap; /* opaque for drbd_conf */
@@ -714,39 +704,37 @@ enum bm_flag {
        BM_P_VMALLOCED = 0x10000, /* internal use only, will be masked out */
 
        /* currently locked for bulk operation */
-       BM_LOCKED_MASK = 0x7,
+       BM_LOCKED_MASK = 0xf,
 
        /* in detail, that is: */
        BM_DONT_CLEAR = 0x1,
        BM_DONT_SET   = 0x2,
        BM_DONT_TEST  = 0x4,
 
+       /* so we can mark it locked for bulk operation,
+        * and still allow all non-bulk operations */
+       BM_IS_LOCKED  = 0x8,
+
        /* (test bit, count bit) allowed (common case) */
-       BM_LOCKED_TEST_ALLOWED = 0x3,
+       BM_LOCKED_TEST_ALLOWED = BM_DONT_CLEAR | BM_DONT_SET | BM_IS_LOCKED,
 
        /* testing bits, as well as setting new bits allowed, but clearing bits
         * would be unexpected.  Used during bitmap receive.  Setting new bits
         * requires sending of "out-of-sync" information, though. */
-       BM_LOCKED_SET_ALLOWED = 0x1,
+       BM_LOCKED_SET_ALLOWED = BM_DONT_CLEAR | BM_IS_LOCKED,
 
-       /* clear is not expected while bitmap is locked for bulk operation */
+       /* for drbd_bm_write_copy_pages, everything is allowed,
+        * only concurrent bulk operations are locked out. */
+       BM_LOCKED_CHANGE_ALLOWED = BM_IS_LOCKED,
 };
 
-
-/* TODO sort members for performance
- * MAYBE group them further */
-
-/* THINK maybe we actually want to use the default "event/%s" worker threads
- * or similar in linux 2.6, which uses per cpu data and threads.
- */
 struct drbd_work_queue {
        struct list_head q;
-       struct semaphore s; /* producers up it, worker down()s it */
        spinlock_t q_lock;  /* to protect the list. */
+       wait_queue_head_t q_wait;
 };
 
 struct drbd_socket {
-       struct drbd_work_queue work;
        struct mutex mutex;
        struct socket    *socket;
        /* this way we get our
@@ -759,6 +747,7 @@ struct drbd_md {
        u64 md_offset;          /* sector offset to 'super' block */
 
        u64 la_size_sect;       /* last agreed size, unit sectors */
+       spinlock_t uuid_lock;
        u64 uuid[UI_SIZE];
        u64 device_uuid;
        u32 flags;
@@ -782,8 +771,7 @@ struct drbd_backing_dev {
 };
 
 struct drbd_md_io {
-       struct drbd_conf *mdev;
-       struct completion event;
+       unsigned int done;
        int error;
 };
 
@@ -812,13 +800,23 @@ extern struct fifo_buffer *fifo_alloc(int fifo_size);
 /* flag bits per tconn */
 enum {
        NET_CONGESTED,          /* The data socket is congested */
-       DISCARD_CONCURRENT,     /* Set on one node, cleared on the peer! */
+       RESOLVE_CONFLICTS,      /* Set on one node, cleared on the peer! */
        SEND_PING,              /* whether asender should send a ping asap */
        SIGNAL_ASENDER,         /* whether asender wants to be interrupted */
        GOT_PING_ACK,           /* set when we receive a ping_ack packet, ping_wait gets woken */
+       CONN_WD_ST_CHG_REQ,     /* A cluster wide state change on the connection is active */
        CONN_WD_ST_CHG_OKAY,
        CONN_WD_ST_CHG_FAIL,
        CONN_DRY_RUN,           /* Expect disconnect after resync handshake. */
+       CREATE_BARRIER,         /* next P_DATA is preceded by a P_BARRIER */
+       STATE_SENT,             /* Do not change state/UUIDs while this is set */
+       CALLBACK_PENDING,       /* Whether we have a call_usermodehelper(, UMH_WAIT_PROC)
+                                * pending, from drbd worker context.
+                                * If set, bdi_write_congested() returns true,
+                                * so shrink_page_list() would not recurse into,
+                                * and potentially deadlock on, this drbd worker.
+                                */
+       DISCONNECT_SENT,
 };
 
 struct drbd_tconn {                    /* is a resource from the config file */
@@ -838,6 +836,11 @@ struct drbd_tconn {                        /* is a resource from the config file */
        wait_queue_head_t ping_wait;    /* Woken upon reception of a ping, and a state change */
        struct res_opts res_opts;
 
+       struct sockaddr_storage my_addr;
+       int my_addr_len;
+       struct sockaddr_storage peer_addr;
+       int peer_addr_len;
+
        struct drbd_socket data;        /* data/barrier/cstate/parameter packets */
        struct drbd_socket meta;        /* ping/ack (metadata) packets */
        int agreed_pro_version;         /* actually used protocol version */
@@ -845,28 +848,53 @@ struct drbd_tconn {                       /* is a resource from the config file */
        unsigned int ko_count;
 
        spinlock_t req_lock;
-       struct drbd_tl_epoch *unused_spare_tle; /* for pre-allocation */
-       struct drbd_tl_epoch *newest_tle;
-       struct drbd_tl_epoch *oldest_tle;
-       struct list_head out_of_sequence_requests;
+
+       struct list_head transfer_log;  /* all requests not yet fully processed */
 
        struct crypto_hash *cram_hmac_tfm;
-       struct crypto_hash *integrity_tfm;  /* checksums we compute */
-       struct crypto_hash *peer_integrity_tfm;  /* checksums we verify */
+       struct crypto_hash *integrity_tfm;  /* checksums we compute, updates protected by tconn->data->mutex */
+       struct crypto_hash *peer_integrity_tfm;  /* checksums we verify, only accessed from receiver thread  */
        struct crypto_hash *csums_tfm;
        struct crypto_hash *verify_tfm;
        void *int_dig_in;
        void *int_dig_vv;
 
+       /* receiver side */
+       struct drbd_epoch *current_epoch;
+       spinlock_t epoch_lock;
+       unsigned int epochs;
+       enum write_ordering_e write_ordering;
+       atomic_t current_tle_nr;        /* transfer log epoch number */
+       unsigned current_tle_writes;    /* writes seen within this tl epoch */
+
+       unsigned long last_reconnect_jif;
        struct drbd_thread receiver;
        struct drbd_thread worker;
        struct drbd_thread asender;
        cpumask_var_t cpu_mask;
+
+       /* sender side */
+       struct drbd_work_queue sender_work;
+
+       struct {
+               /* whether this sender thread
+                * has processed a single write yet. */
+               bool seen_any_write_yet;
+
+               /* Which barrier number to send with the next P_BARRIER */
+               int current_epoch_nr;
+
+               /* how many write requests have been sent
+                * with req->epoch == current_epoch_nr.
+                * If none, no P_BARRIER will be sent. */
+               unsigned current_epoch_writes;
+       } send;
 };
 
 struct drbd_conf {
        struct drbd_tconn *tconn;
        int vnr;                        /* volume number within the connection */
+       struct kref kref;
 
        /* things that are stored as / read from meta data on disk */
        unsigned long flags;
@@ -879,6 +907,7 @@ struct drbd_conf {
        struct block_device *this_bdev;
        struct gendisk      *vdisk;
 
+       unsigned long last_reattach_jif;
        struct drbd_work  resync_work,
                          unplug_work,
                          go_diskless,
@@ -910,7 +939,7 @@ struct drbd_conf {
        atomic_t ap_bio_cnt;     /* Requests we need to complete */
        atomic_t ap_pending_cnt; /* AP data packets on the wire, ack expected */
        atomic_t rs_pending_cnt; /* RS request/data packets on the wire */
-       atomic_t unacked_cnt;    /* Need to send replys for */
+       atomic_t unacked_cnt;    /* Need to send replies for */
        atomic_t local_cnt;      /* Waiting for local completion */
 
        /* Interval tree of pending local requests */
@@ -935,9 +964,11 @@ struct drbd_conf {
        unsigned long rs_mark_time[DRBD_SYNC_MARKS];
        /* current index into rs_mark_{left,time} */
        int rs_last_mark;
+       unsigned long rs_last_bcast; /* [unit jiffies] */
 
        /* where does the admin want us to start? (sector) */
        sector_t ov_start_sector;
+       sector_t ov_stop_sector;
        /* where are we now? (sector) */
        sector_t ov_position;
        /* Start sector of out of sync range (to merge printk reporting). */
@@ -958,10 +989,7 @@ struct drbd_conf {
 
        int open_cnt;
        u64 *p_uuid;
-       struct drbd_epoch *current_epoch;
-       spinlock_t epoch_lock;
-       unsigned int epochs;
-       enum write_ordering_e write_ordering;
+
        struct list_head active_ee; /* IO in progress (P_DATA gets written to disk) */
        struct list_head sync_ee;   /* IO in progress (P_RS_DATA_REPLY gets written to disk) */
        struct list_head done_ee;   /* need to send P_WRITE_ACK */
@@ -974,7 +1002,8 @@ struct drbd_conf {
        atomic_t pp_in_use_by_net;      /* sendpage()d, still referenced by tcp */
        wait_queue_head_t ee_wait;
        struct page *md_io_page;        /* one page buffer for md_io */
-       struct mutex md_io_mutex;       /* protects the md_io_buffer */
+       struct drbd_md_io md_io;
+       atomic_t md_io_in_use;          /* protects the md_io, md_io_page and md_io_tmpp */
        spinlock_t al_lock;
        wait_queue_head_t al_wait;
        struct lru_cache *act_log;      /* activity log */
@@ -998,11 +1027,11 @@ struct drbd_conf {
        int rs_last_events;  /* counter of read or write "events" (unit sectors)
                              * on the lower level device when we last looked. */
        int c_sync_rate; /* current resync rate after syncer throttle magic */
-       struct fifo_buffer *rs_plan_s; /* correction values of resync planer */
+       struct fifo_buffer *rs_plan_s; /* correction values of resync planer (RCU, tconn->conn_update) */
        int rs_in_flight; /* resync sectors in flight (to proxy, in proxy and from proxy) */
        atomic_t ap_in_flight; /* App sectors in flight (waiting for ack) */
-       int peer_max_bio_size;
-       int local_max_bio_size;
+       unsigned int peer_max_bio_size;
+       unsigned int local_max_bio_size;
 };
 
 static inline struct drbd_conf *minor_to_mdev(unsigned int minor)
@@ -1045,25 +1074,22 @@ extern void drbd_calc_cpu_mask(struct drbd_tconn *tconn);
 extern void tl_release(struct drbd_tconn *, unsigned int barrier_nr,
                       unsigned int set_size);
 extern void tl_clear(struct drbd_tconn *);
-extern void _tl_add_barrier(struct drbd_tconn *, struct drbd_tl_epoch *);
 extern void drbd_free_sock(struct drbd_tconn *tconn);
 extern int drbd_send(struct drbd_tconn *tconn, struct socket *sock,
                     void *buf, size_t size, unsigned msg_flags);
 extern int drbd_send_all(struct drbd_tconn *, struct socket *, void *, size_t,
                         unsigned);
 
-extern int __drbd_send_protocol(struct drbd_tconn *tconn);
+extern int __drbd_send_protocol(struct drbd_tconn *tconn, enum drbd_packet cmd);
 extern int drbd_send_protocol(struct drbd_tconn *tconn);
 extern int drbd_send_uuids(struct drbd_conf *mdev);
 extern int drbd_send_uuids_skip_initial_sync(struct drbd_conf *mdev);
 extern void drbd_gen_and_send_sync_uuid(struct drbd_conf *mdev);
 extern int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags flags);
-extern int _conn_send_state_req(struct drbd_tconn *, int vnr, enum drbd_packet cmd,
-                               union drbd_state, union drbd_state);
-extern int _drbd_send_state(struct drbd_conf *mdev);
-extern int drbd_send_state(struct drbd_conf *mdev);
+extern int drbd_send_state(struct drbd_conf *mdev, union drbd_state s);
+extern int drbd_send_current_state(struct drbd_conf *mdev);
 extern int drbd_send_sync_param(struct drbd_conf *mdev);
-extern void drbd_send_b_ack(struct drbd_conf *mdev, u32 barrier_nr,
+extern void drbd_send_b_ack(struct drbd_tconn *tconn, u32 barrier_nr,
                            u32 set_size);
 extern int drbd_send_ack(struct drbd_conf *, enum drbd_packet,
                         struct drbd_peer_request *);
@@ -1091,13 +1117,15 @@ extern void drbd_free_bc(struct drbd_backing_dev *ldev);
 extern void drbd_mdev_cleanup(struct drbd_conf *mdev);
 void drbd_print_uuids(struct drbd_conf *mdev, const char *text);
 
+extern void conn_md_sync(struct drbd_tconn *tconn);
 extern void drbd_md_sync(struct drbd_conf *mdev);
 extern int  drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev);
 extern void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local);
 extern void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local);
 extern void drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local);
-extern void _drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local);
 extern void drbd_uuid_set_bm(struct drbd_conf *mdev, u64 val) __must_hold(local);
+extern void drbd_uuid_move_history(struct drbd_conf *mdev) __must_hold(local);
+extern void __drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local);
 extern void drbd_md_set_flag(struct drbd_conf *mdev, int flags) __must_hold(local);
 extern void drbd_md_clear_flag(struct drbd_conf *mdev, int flags)__must_hold(local);
 extern int drbd_md_test_flag(struct drbd_backing_dev *, int);
@@ -1115,6 +1143,9 @@ extern void drbd_queue_bitmap_io(struct drbd_conf *mdev,
 extern int drbd_bitmap_io(struct drbd_conf *mdev,
                int (*io_fn)(struct drbd_conf *),
                char *why, enum bm_flag flags);
+extern int drbd_bitmap_io_from_worker(struct drbd_conf *mdev,
+               int (*io_fn)(struct drbd_conf *),
+               char *why, enum bm_flag flags);
 extern int drbd_bmio_set_n_write(struct drbd_conf *mdev);
 extern int drbd_bmio_clear_n_write(struct drbd_conf *mdev);
 extern void drbd_go_diskless(struct drbd_conf *mdev);
@@ -1274,13 +1305,14 @@ struct bm_extent {
  * we limit us to a platform agnostic constant here for now.
  * A followup commit may allow even bigger BIO sizes,
  * once we thought that through. */
-#define DRBD_MAX_BIO_SIZE (1 << 20)
+#define DRBD_MAX_BIO_SIZE (1U << 20)
 #if DRBD_MAX_BIO_SIZE > BIO_MAX_SIZE
 #error Architecture not supported: DRBD_MAX_BIO_SIZE > BIO_MAX_SIZE
 #endif
-#define DRBD_MAX_BIO_SIZE_SAFE (1 << 12)       /* Works always = 4k */
+#define DRBD_MAX_BIO_SIZE_SAFE (1U << 12)       /* Works always = 4k */
 
-#define DRBD_MAX_SIZE_H80_PACKET (1 << 15) /* The old header only allows packets up to 32Kib data */
+#define DRBD_MAX_SIZE_H80_PACKET (1U << 15) /* Header 80 only allows packets up to 32KiB data */
+#define DRBD_MAX_BIO_SIZE_P95    (1U << 17) /* Protocol 95 to 99 allows bios up to 128KiB */
 
 extern int  drbd_bm_init(struct drbd_conf *mdev);
 extern int  drbd_bm_resize(struct drbd_conf *mdev, sector_t sectors, int set_new_bits);
@@ -1305,8 +1337,8 @@ extern int  drbd_bm_read(struct drbd_conf *mdev) __must_hold(local);
 extern void drbd_bm_mark_for_writeout(struct drbd_conf *mdev, int page_nr);
 extern int  drbd_bm_write(struct drbd_conf *mdev) __must_hold(local);
 extern int  drbd_bm_write_hinted(struct drbd_conf *mdev) __must_hold(local);
-extern unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev,
-               unsigned long al_enr);
+extern int drbd_bm_write_all(struct drbd_conf *mdev) __must_hold(local);
+extern int  drbd_bm_write_copy_pages(struct drbd_conf *mdev) __must_hold(local);
 extern size_t       drbd_bm_words(struct drbd_conf *mdev);
 extern unsigned long drbd_bm_bits(struct drbd_conf *mdev);
 extern sector_t      drbd_bm_capacity(struct drbd_conf *mdev);
@@ -1373,25 +1405,27 @@ extern rwlock_t global_state_lock;
 
 extern int conn_lowest_minor(struct drbd_tconn *tconn);
 enum drbd_ret_code conn_new_minor(struct drbd_tconn *tconn, unsigned int minor, int vnr);
-extern void drbd_delete_device(struct drbd_conf *mdev);
+extern void drbd_minor_destroy(struct kref *kref);
 
-struct drbd_tconn *conn_create(const char *name);
+extern int set_resource_options(struct drbd_tconn *tconn, struct res_opts *res_opts);
+extern struct drbd_tconn *conn_create(const char *name, struct res_opts *res_opts);
 extern void conn_destroy(struct kref *kref);
 struct drbd_tconn *conn_get_by_name(const char *name);
+extern struct drbd_tconn *conn_get_by_addrs(void *my_addr, int my_addr_len,
+                                           void *peer_addr, int peer_addr_len);
 extern void conn_free_crypto(struct drbd_tconn *tconn);
 
 extern int proc_details;
 
 /* drbd_req */
-extern int __drbd_make_request(struct drbd_conf *, struct bio *, unsigned long);
-extern int drbd_make_request(struct request_queue *q, struct bio *bio);
+extern void __drbd_make_request(struct drbd_conf *, struct bio *, unsigned long);
+extern void drbd_make_request(struct request_queue *q, struct bio *bio);
 extern int drbd_read_remote(struct drbd_conf *mdev, struct drbd_request *req);
 extern int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct bio_vec *bvec);
 extern int is_valid_ar_handle(struct drbd_request *, sector_t);
 
 
 /* drbd_nl.c */
-extern void drbd_set_res_opts_defaults(struct res_opts *r);
 extern int drbd_msg_put_info(const char *info);
 extern void drbd_suspend_io(struct drbd_conf *mdev);
 extern void drbd_resume_io(struct drbd_conf *mdev);
@@ -1410,16 +1444,20 @@ extern int drbd_khelper(struct drbd_conf *mdev, char *cmd);
 
 /* drbd_worker.c */
 extern int drbd_worker(struct drbd_thread *thi);
-enum drbd_ret_code drbd_sync_after_valid(struct drbd_conf *mdev, int o_minor);
-void drbd_sync_after_changed(struct drbd_conf *mdev);
+enum drbd_ret_code drbd_resync_after_valid(struct drbd_conf *mdev, int o_minor);
+void drbd_resync_after_changed(struct drbd_conf *mdev);
 extern void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side);
 extern void resume_next_sg(struct drbd_conf *mdev);
 extern void suspend_other_sg(struct drbd_conf *mdev);
 extern int drbd_resync_finished(struct drbd_conf *mdev);
 /* maybe rather drbd_main.c ? */
+extern void *drbd_md_get_buffer(struct drbd_conf *mdev);
+extern void drbd_md_put_buffer(struct drbd_conf *mdev);
 extern int drbd_md_sync_page_io(struct drbd_conf *mdev,
                struct drbd_backing_dev *bdev, sector_t sector, int rw);
 extern void drbd_ov_out_of_sync_found(struct drbd_conf *, sector_t, int);
+extern void wait_until_done_or_force_detached(struct drbd_conf *mdev,
+               struct drbd_backing_dev *bdev, unsigned int *done);
 extern void drbd_rs_controller_reset(struct drbd_conf *mdev);
 
 static inline void ov_out_of_sync_print(struct drbd_conf *mdev)
@@ -1437,7 +1475,6 @@ extern void drbd_csum_bio(struct drbd_conf *, struct crypto_hash *, struct bio *
 extern void drbd_csum_ee(struct drbd_conf *, struct crypto_hash *,
                         struct drbd_peer_request *, void *);
 /* worker callbacks */
-extern int w_read_retry_remote(struct drbd_work *, int);
 extern int w_e_end_data_req(struct drbd_work *, int);
 extern int w_e_end_rsdata_req(struct drbd_work *, int);
 extern int w_e_end_csum_rs_req(struct drbd_work *, int);
@@ -1448,7 +1485,6 @@ extern int w_resync_timer(struct drbd_work *, int);
 extern int w_send_write_hint(struct drbd_work *, int);
 extern int w_make_resync_request(struct drbd_work *, int);
 extern int w_send_dblock(struct drbd_work *, int);
-extern int w_send_barrier(struct drbd_work *, int);
 extern int w_send_read_req(struct drbd_work *, int);
 extern int w_prev_work_done(struct drbd_work *, int);
 extern int w_e_reissue(struct drbd_work *, int);
@@ -1476,7 +1512,7 @@ extern struct page *drbd_alloc_pages(struct drbd_conf *, unsigned int, bool);
 extern void drbd_set_recv_tcq(struct drbd_conf *mdev, int tcq_enabled);
 extern void _drbd_clear_done_ee(struct drbd_conf *mdev, struct list_head *to_be_freed);
 extern void conn_flush_workqueue(struct drbd_tconn *tconn);
-extern int drbd_connected(int vnr, void *p, void *data);
+extern int drbd_connected(struct drbd_conf *mdev);
 static inline void drbd_flush_workqueue(struct drbd_conf *mdev)
 {
        conn_flush_workqueue(mdev->tconn);
@@ -1531,7 +1567,7 @@ static inline void drbd_tcp_quickack(struct socket *sock)
                        (char*)&val, sizeof(val));
 }
 
-void drbd_bump_write_ordering(struct drbd_conf *mdev, enum write_ordering_e wo);
+void drbd_bump_write_ordering(struct drbd_tconn *tconn, enum write_ordering_e wo);
 
 /* drbd_proc.c */
 extern struct proc_dir_entry *drbd_proc;
@@ -1549,7 +1585,6 @@ extern void drbd_rs_cancel_all(struct drbd_conf *mdev);
 extern int drbd_rs_del_all(struct drbd_conf *mdev);
 extern void drbd_rs_failed_io(struct drbd_conf *mdev,
                sector_t sector, int size);
-extern int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *);
 extern void drbd_advance_rs_marks(struct drbd_conf *mdev, unsigned long still_to_go);
 extern void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector,
                int size, const char *file, const unsigned int line);
@@ -1559,7 +1594,6 @@ extern int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector,
                int size, const char *file, const unsigned int line);
 #define drbd_set_out_of_sync(mdev, sector, size) \
        __drbd_set_out_of_sync(mdev, sector, size, __FILE__, __LINE__)
-extern void drbd_al_apply_to_bm(struct drbd_conf *mdev);
 extern void drbd_al_shrink(struct drbd_conf *mdev);
 
 /* drbd_nl.c */
@@ -1594,18 +1628,6 @@ static inline struct page *page_chain_next(struct page *page)
 #define page_chain_for_each_safe(page, n) \
        for (; page && ({ n = page_chain_next(page); 1; }); page = n)
 
-static inline int drbd_bio_has_active_page(struct bio *bio)
-{
-       struct bio_vec *bvec;
-       int i;
-
-       __bio_for_each_segment(bvec, bio, i, 0) {
-               if (page_count(bvec->bv_page) > 1)
-                       return 1;
-       }
-
-       return 0;
-}
 
 static inline int drbd_peer_req_has_active_page(struct drbd_peer_request *peer_req)
 {
@@ -1642,8 +1664,17 @@ static inline union drbd_state drbd_read_state(struct drbd_conf *mdev)
        return rv;
 }
 
+enum drbd_force_detach_flags {
+       DRBD_READ_ERROR,
+       DRBD_WRITE_ERROR,
+       DRBD_META_IO_ERROR,
+       DRBD_FORCE_DETACH,
+};
+
 #define __drbd_chk_io_error(m,f) __drbd_chk_io_error_(m,f, __func__)
-static inline void __drbd_chk_io_error_(struct drbd_conf *mdev, int forcedetach, const char *where)
+static inline void __drbd_chk_io_error_(struct drbd_conf *mdev,
+               enum drbd_force_detach_flags df,
+               const char *where)
 {
        enum drbd_io_error_p ep;
 
@@ -1652,17 +1683,41 @@ static inline void __drbd_chk_io_error_(struct drbd_conf *mdev, int forcedetach,
        rcu_read_unlock();
        switch (ep) {
        case EP_PASS_ON: /* FIXME would this be better named "Ignore"? */
-               if (!forcedetach) {
+               if (df == DRBD_READ_ERROR || df == DRBD_WRITE_ERROR) {
                        if (__ratelimit(&drbd_ratelimit_state))
                                dev_err(DEV, "Local IO failed in %s.\n", where);
                        if (mdev->state.disk > D_INCONSISTENT)
                                _drbd_set_state(_NS(mdev, disk, D_INCONSISTENT), CS_HARD, NULL);
                        break;
                }
-               /* NOTE fall through to detach case if forcedetach set */
+               /* NOTE fall through for DRBD_META_IO_ERROR or DRBD_FORCE_DETACH */
        case EP_DETACH:
        case EP_CALL_HELPER:
+               /* Remember whether we saw a READ or WRITE error.
+                *
+                * Recovery of the affected area for WRITE failure is covered
+                * by the activity log.
+                * READ errors may fall outside that area though. Certain READ
+                * errors can be "healed" by writing good data to the affected
+                * blocks, which triggers block re-allocation in lower layers.
+                *
+                * If we can not write the bitmap after a READ error,
+                * we may need to trigger a full sync (see w_go_diskless()).
+                *
+                * Force-detach is not really an IO error, but rather a
+                * desperate measure to try to deal with a completely
+                * unresponsive lower level IO stack.
+                * Still it should be treated as a WRITE error.
+                *
+                * Meta IO error is always WRITE error:
+                * we read meta data only once during attach,
+                * which will fail in case of errors.
+                */
                set_bit(WAS_IO_ERROR, &mdev->flags);
+               if (df == DRBD_READ_ERROR)
+                       set_bit(WAS_READ_ERROR, &mdev->flags);
+               if (df == DRBD_FORCE_DETACH)
+                       set_bit(FORCE_DETACH, &mdev->flags);
                if (mdev->state.disk > D_FAILED) {
                        _drbd_set_state(_NS(mdev, disk, D_FAILED), CS_HARD, NULL);
                        dev_err(DEV,
@@ -1682,7 +1737,7 @@ static inline void __drbd_chk_io_error_(struct drbd_conf *mdev, int forcedetach,
  */
 #define drbd_chk_io_error(m,e,f) drbd_chk_io_error_(m,e,f, __func__)
 static inline void drbd_chk_io_error_(struct drbd_conf *mdev,
-       int error, int forcedetach, const char *where)
+       int error, enum drbd_force_detach_flags forcedetach, const char *where)
 {
        if (error) {
                unsigned long flags;
@@ -1834,9 +1889,8 @@ drbd_queue_work_front(struct drbd_work_queue *q, struct drbd_work *w)
        unsigned long flags;
        spin_lock_irqsave(&q->q_lock, flags);
        list_add(&w->list, &q->q);
-       up(&q->s); /* within the spinlock,
-                     see comment near end of drbd_worker() */
        spin_unlock_irqrestore(&q->q_lock, flags);
+       wake_up(&q->q_wait);
 }
 
 static inline void
@@ -1845,9 +1899,8 @@ drbd_queue_work(struct drbd_work_queue *q, struct drbd_work *w)
        unsigned long flags;
        spin_lock_irqsave(&q->q_lock, flags);
        list_add_tail(&w->list, &q->q);
-       up(&q->s); /* within the spinlock,
-                     see comment near end of drbd_worker() */
        spin_unlock_irqrestore(&q->q_lock, flags);
+       wake_up(&q->q_wait);
 }
 
 static inline void wake_asender(struct drbd_tconn *tconn)
@@ -2065,7 +2118,7 @@ static inline void drbd_get_syncer_progress(struct drbd_conf *mdev,
                 * Note: currently we don't support such large bitmaps on 32bit
                 * arch anyways, but no harm done to be prepared for it here.
                 */
-               unsigned int shift = mdev->rs_total >= (1ULL << 32) ? 16 : 10;
+               unsigned int shift = mdev->rs_total > UINT_MAX ? 16 : 10;
                unsigned long left = *bits_left >> shift;
                unsigned long total = 1UL + (mdev->rs_total >> shift);
                unsigned long tmp = 1000UL - left * 1000UL/total;
@@ -2144,12 +2197,12 @@ static inline int drbd_state_is_stable(struct drbd_conf *mdev)
        case D_OUTDATED:
        case D_CONSISTENT:
        case D_UP_TO_DATE:
+       case D_FAILED:
                /* disk state is stable as well. */
                break;
 
-       /* no new io accepted during tansitional states */
+       /* no new io accepted during transitional states */
        case D_ATTACHING:
-       case D_FAILED:
        case D_NEGOTIATING:
        case D_UNKNOWN:
        case D_MASK:
@@ -2211,7 +2264,7 @@ static inline void inc_ap_bio(struct drbd_conf *mdev)
        /* we wait here
         *    as long as the device is suspended
         *    until the bitmap is no longer on the fly during connection
-        *    handshake as long as we would exeed the max_buffer limit.
+        *    handshake as long as we would exceed the max_buffer limit.
         *
         * to avoid races with the reconnect code,
         * we need to atomic_inc within the spinlock. */
@@ -2225,15 +2278,23 @@ static inline void dec_ap_bio(struct drbd_conf *mdev)
        int ap_bio = atomic_dec_return(&mdev->ap_bio_cnt);
 
        D_ASSERT(ap_bio >= 0);
+
+       if (ap_bio == 0 && test_bit(BITMAP_IO, &mdev->flags)) {
+               if (!test_and_set_bit(BITMAP_IO_QUEUED, &mdev->flags))
+                       drbd_queue_work(&mdev->tconn->sender_work, &mdev->bm_io_work.w);
+       }
+
        /* this currently does wake_up for every dec_ap_bio!
         * maybe rather introduce some type of hysteresis?
         * e.g. (ap_bio == mxb/2 || ap_bio == 0) ? */
        if (ap_bio < mxb)
                wake_up(&mdev->misc_wait);
-       if (ap_bio == 0 && test_bit(BITMAP_IO, &mdev->flags)) {
-               if (!test_and_set_bit(BITMAP_IO_QUEUED, &mdev->flags))
-                       drbd_queue_work(&mdev->tconn->data.work, &mdev->bm_io_work.w);
-       }
+}
+
+static inline bool verify_can_do_stop_sector(struct drbd_conf *mdev)
+{
+       return mdev->tconn->agreed_pro_version >= 97 &&
+               mdev->tconn->agreed_pro_version != 100;
 }
 
 static inline int drbd_set_ed_uuid(struct drbd_conf *mdev, u64 val)
@@ -2257,10 +2318,15 @@ static inline void drbd_md_flush(struct drbd_conf *mdev)
 {
        int r;
 
+       if (mdev->ldev == NULL) {
+               dev_warn(DEV, "mdev->ldev == NULL in drbd_md_flush\n");
+               return;
+       }
+
        if (test_bit(MD_NO_FUA, &mdev->flags))
                return;
 
-       r = blkdev_issue_flush(mdev->ldev->md_bdev, GFP_KERNEL, NULL);
+       r = blkdev_issue_flush(mdev->ldev->md_bdev, GFP_NOIO, NULL);
        if (r) {
                set_bit(MD_NO_FUA, &mdev->flags);
                dev_err(DEV, "meta data flush failed with status %d, disabling md-flushes\n", r);
@@ -2268,3 +2334,30 @@ static inline void drbd_md_flush(struct drbd_conf *mdev)
 }
 
 #endif
+
+/* This is defined in drivers/md/md.h as well. Should go into wait.h */
+#define __wait_event_lock_irq(wq, condition, lock, cmd)                \
+do {                                                                   \
+       wait_queue_t __wait;                                            \
+       init_waitqueue_entry(&__wait, current);                         \
+                                                                       \
+       add_wait_queue(&wq, &__wait);                                   \
+       for (;;) {                                                      \
+               set_current_state(TASK_UNINTERRUPTIBLE);                \
+               if (condition)                                          \
+                       break;                                          \
+               spin_unlock_irq(&lock);                                 \
+               cmd;                                                    \
+               schedule();                                             \
+               spin_lock_irq(&lock);                                   \
+       }                                                               \
+       current->state = TASK_RUNNING;                                  \
+       remove_wait_queue(&wq, &__wait);                                \
+} while (0)
+
+#define wait_event_lock_irq(wq, condition, lock, cmd)                  \
+do {                                                                   \
+       if (condition)                                                  \
+               break;                                                  \
+       __wait_event_lock_irq(wq, condition, lock, cmd);                \
+} while (0)