drbd: cleanup, drop unused struct
[cascardo/linux.git] / drivers / block / drbd / drbd_int.h
index 6035784..e5c9853 100644 (file)
@@ -164,10 +164,6 @@ 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; /* RCU, updates: genl_lock() */
 extern struct list_head drbd_tconns; /* RCU, updates: genl_lock() */
@@ -471,12 +467,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;
@@ -566,29 +556,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. */
@@ -674,8 +666,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. */
@@ -684,7 +674,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 */
@@ -694,6 +683,7 @@ enum {
        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 */
+       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. */
@@ -701,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 */
@@ -712,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
@@ -780,8 +770,7 @@ struct drbd_backing_dev {
 };
 
 struct drbd_md_io {
-       struct drbd_conf *mdev;
-       struct completion event;
+       unsigned int done;
        int error;
 };
 
@@ -814,9 +803,18 @@ enum {
        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.
+                                */
 };
 
 struct drbd_tconn {                    /* is a resource from the config file */
@@ -848,10 +846,8 @@ 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, updates protected by tconn->data->mutex */
@@ -861,10 +857,36 @@ struct drbd_tconn {                       /* is a resource from the config file */
        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 {
@@ -883,6 +905,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,
@@ -942,6 +965,7 @@ struct drbd_conf {
 
        /* 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). */
@@ -962,10 +986,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 */
@@ -978,7 +999,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 */
@@ -1049,7 +1071,6 @@ 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);
@@ -1062,12 +1083,10 @@ 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 *);
@@ -1310,8 +1329,7 @@ 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_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);
@@ -1391,7 +1409,7 @@ 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 void __drbd_make_request(struct drbd_conf *, struct bio *, unsigned long);
 extern int 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);
@@ -1424,9 +1442,13 @@ 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_disk_failure(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)
@@ -1444,7 +1466,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);
@@ -1455,7 +1476,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);
@@ -1538,7 +1558,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;
@@ -1556,7 +1576,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);
@@ -1566,7 +1585,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 */
@@ -1601,18 +1619,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)
 {
@@ -1649,8 +1655,16 @@ static inline union drbd_state drbd_read_state(struct drbd_conf *mdev)
        return rv;
 }
 
+enum drbd_force_detach_flags {
+       DRBD_IO_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 forcedetach,
+               const char *where)
 {
        enum drbd_io_error_p ep;
 
@@ -1659,7 +1673,7 @@ 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 (forcedetach == DRBD_IO_ERROR) {
                        if (__ratelimit(&drbd_ratelimit_state))
                                dev_err(DEV, "Local IO failed in %s.\n", where);
                        if (mdev->state.disk > D_INCONSISTENT)
@@ -1670,6 +1684,8 @@ static inline void __drbd_chk_io_error_(struct drbd_conf *mdev, int forcedetach,
        case EP_DETACH:
        case EP_CALL_HELPER:
                set_bit(WAS_IO_ERROR, &mdev->flags);
+               if (forcedetach == 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,
@@ -1689,7 +1705,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;
@@ -1841,9 +1857,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
@@ -1852,9 +1867,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)
@@ -2151,12 +2165,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 transitional states */
        case D_ATTACHING:
-       case D_FAILED:
        case D_NEGOTIATING:
        case D_UNKNOWN:
        case D_MASK:
@@ -2232,15 +2246,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)