[DRBD-cvs] drbd by phil; Merged LGE's make_request_take_4.diff. [...
drbd-user@lists.linbit.com
drbd-user@lists.linbit.com
Mon, 16 Feb 2004 21:39:05 +0100 (CET)
DRBD CVS committal
Author : phil
Module : drbd
Dir : drbd/drbd
Modified Files:
Tag: rel-0_7-branch
drbd_compat_wrappers.h drbd_dsender.c drbd_int.h drbd_main.c
drbd_receiver.c drbd_req-2.4.c
Log Message:
Merged LGE's make_request_take_4.diff.
[No testing done so far by me...]
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/Attic/drbd_compat_wrappers.h,v
retrieving revision 1.1.2.22
retrieving revision 1.1.2.23
diff -u -3 -r1.1.2.22 -r1.1.2.23
--- drbd_compat_wrappers.h 9 Feb 2004 10:36:54 -0000 1.1.2.22
+++ drbd_compat_wrappers.h 16 Feb 2004 20:39:00 -0000 1.1.2.23
@@ -8,6 +8,7 @@
extern void enslaved_read_bi_end_io (struct buffer_head *bh, int uptodate);
extern void drbd_dio_end_sec (struct buffer_head *bh, int uptodate);
extern void drbd_dio_end (struct buffer_head *bh, int uptodate);
+extern void drbd_read_bi_end_io (struct buffer_head *bh, int uptodate);
/*
* because in 2.6.x [sg]et_capacity operate on gendisk->capacity, which is in
@@ -196,7 +197,8 @@
// D_ASSERT(buffer_dirty(bh)); // It is not true ?!?
D_ASSERT(buffer_uptodate(bh));
- // FIXME should not be necessary
+ // FIXME should not be necessary;
+ // remove if the assertions above do not trigger.
bh->b_state = (1 << BH_Uptodate)
|(1 << BH_Dirty)
|(1 << BH_Lock)
@@ -206,9 +208,6 @@
req->rq_status = RQ_DRBD_NOTHING;
}
-#if 0
-/* not yet used
- */
static inline void
drbd_req_prepare_read(drbd_dev *mdev, struct drbd_request *req)
{
@@ -218,7 +217,7 @@
drbd_bh_clone(bh,bh_src);
bh->b_rdev = mdev->backing_bdev;
bh->b_private = mdev;
- bh->b_end_io = drbd_read_end_io;
+ bh->b_end_io = drbd_read_bi_end_io;
D_ASSERT(buffer_req(bh));
D_ASSERT(buffer_launder(bh));
@@ -226,14 +225,14 @@
D_ASSERT(buffer_mapped(bh));
D_ASSERT(!buffer_uptodate(bh));
- // FIXME should not be necessary
+ // FIXME should not be necessary;
+ // remove if the assertions above do not trigger.
bh->b_state = (1 << BH_Lock)
|(1 << BH_Req)
|(1 << BH_Mapped) ;
req->rq_status = RQ_DRBD_NOTHING;
}
-#endif
static inline struct page* drbd_bio_get_page(struct buffer_head *bh)
{
@@ -250,6 +249,13 @@
run_task_queue(&tq_disk);
}
+static inline void drbd_plug_device(drbd_dev *mdev)
+{
+ if(!test_and_set_bit(WRITE_HINT_QUEUED,&mdev->flags)) {
+ queue_task(&mdev->write_hint_tq, &tq_disk); // IO HINT
+ }
+}
+
static inline int _drbd_send_zc_bio(drbd_dev *mdev, struct buffer_head *bh)
{
struct page *page = bh->b_page;
@@ -282,6 +288,7 @@
extern int enslaved_read_bi_end_io (struct bio *bio, unsigned int bytes_done, int error);
extern int drbd_dio_end_sec (struct bio *bio, unsigned int bytes_done, int error);
extern int drbd_dio_end (struct bio *bio, unsigned int bytes_done, int error);
+extern int drbd_read_bi_end_io (struct bio *bio, unsigned int bytes_done, int error);
// we should not accept bios crossing our extent boundaries!
extern int drbd_merge_bvec_fn(request_queue_t *q, struct bio *bio, struct bio_vec *bv);
@@ -487,12 +494,20 @@
req->rq_status = RQ_DRBD_NOTHING;
}
-#if 0
static inline void
drbd_req_prepare_read(drbd_dev *mdev, struct drbd_request *req)
{
+ struct bio * const bio = &req->private_bio;
+ struct bio * const bio_src = req->master_bio;
+
+ __bio_clone(bio,bio_src);
+ bio->bi_bdev = mdev->backing_bdev;
+ bio->bi_private = mdev;
+ bio->bi_end_io = drbd_read_bi_end_io; // <- only difference
+ bio->bi_next = 0;
+
+ req->rq_status = RQ_DRBD_NOTHING;
}
-#endif
static inline struct page* drbd_bio_get_page(struct bio *bio)
{
@@ -500,6 +515,9 @@
return bvec->bv_page;
}
+/*
+ * used to submit our private bio
+ */
static inline void drbd_generic_make_request(int rw, struct bio *bio)
{
bio->bi_rw = rw; //??
@@ -509,6 +527,19 @@
static inline void drbd_kick_lo(drbd_dev *mdev)
{
blk_run_queue(bdev_get_queue(mdev->backing_bdev));
+}
+
+static inline void drbd_plug_device(drbd_dev *mdev)
+{
+ request_queue_t *q = bdev_get_queue(mdev->this_bdev);
+
+ spin_lock_irq(q->queue_lock);
+ if(!blk_queue_plugged(q)) {
+ blk_plug_device(q);
+ del_timer(&q->unplug_timer);
+ // unplugging should not happen automatically...
+ }
+ spin_unlock_irq(q->queue_lock);
}
static inline int _drbd_send_zc_bio(drbd_dev *mdev, struct bio *bio)
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/Attic/drbd_dsender.c,v
retrieving revision 1.1.2.75
retrieving revision 1.1.2.76
diff -u -3 -r1.1.2.75 -r1.1.2.76
--- drbd_dsender.c 15 Feb 2004 14:40:11 -0000 1.1.2.75
+++ drbd_dsender.c 16 Feb 2004 20:39:00 -0000 1.1.2.76
@@ -148,11 +148,41 @@
PARANOIA_BUG_ON(!VALID_POINTER(req));
drbd_chk_io_error(mdev,!uptodate);
- drbd_end_req(req, RQ_DRBD_WRITTEN, uptodate, drbd_req_get_sector(req));
+ drbd_end_req(req, RQ_DRBD_LOCAL, uptodate, drbd_req_get_sector(req));
drbd_al_complete_io(mdev,drbd_req_get_sector(req));
dec_local(mdev);
}
+/* reads on Primary comming from drbd_make_request
+ */
+void drbd_read_bi_end_io(struct buffer_head *bh, int uptodate)
+{
+ struct Drbd_Conf* mdev;
+ drbd_request_t *req;
+
+ mdev = bh->b_private;
+ PARANOIA_BUG_ON(!IS_VALID_MDEV(mdev));
+
+ req = container_of(bh,struct drbd_request,private_bio);
+ PARANOIA_BUG_ON(!VALID_POINTER(req));
+
+ if (!uptodate) {
+ // for the panic:
+ drbd_chk_io_error(mdev,!uptodate);
+ // ok, if we survived this, retry:
+ // FIXME sector ...
+ ERR("local read failed, retrying remotely\n");
+ req->w.cb = w_read_retry_remote;
+ drbd_queue_work(mdev,&mdev->data.work,&req->w);
+ } else {
+ bh->b_end_io(bh,uptodate);
+
+ INVALIDATE_MAGIC(req);
+ mempool_free(req,drbd_request_mempool);
+ }
+ dec_local(mdev);
+}
+
#else
/* used for synchronous meta data and bitmap IO
@@ -267,19 +297,91 @@
PARANOIA_BUG_ON(!VALID_POINTER(req));
drbd_chk_io_error(mdev,error);
- drbd_end_req(req, RQ_DRBD_WRITTEN, (error == 0), drbd_req_get_sector(req));
+ drbd_end_req(req, RQ_DRBD_LOCAL, (error == 0), drbd_req_get_sector(req));
drbd_al_complete_io(mdev,drbd_req_get_sector(req));
dec_local(mdev);
return 0;
}
+
+/* reads on Primary comming from drbd_make_request
+ */
+int drbd_read_bi_end_io(struct bio *bio, unsigned int bytes_done, int error)
+{
+ struct Drbd_Conf* mdev;
+ drbd_request_t *req;
+
+ // see above
+ if (bio->bi_size)
+ return 1;
+
+ mdev = bio->bi_private;
+ PARANOIA_BUG_ON(!IS_VALID_MDEV(mdev));
+
+ req = container_of(bio,struct drbd_request,private_bio);
+ PARANOIA_BUG_ON(!VALID_POINTER(req));
+
+ if (error) {
+ // for the panic:
+ drbd_chk_io_error(mdev,error);
+ // ok, if we survived this, retry:
+ // FIXME sector ...
+ ERR("local read failed, retrying remotely\n");
+ req->w.cb = w_read_retry_remote;
+ drbd_queue_work(mdev,&mdev->data.work,&req->w);
+ } else {
+ bio_endio(bio,bio->bi_size,error);
+
+ INVALIDATE_MAGIC(req);
+ mempool_free(req,drbd_request_mempool);
+ }
+ return 0;
+}
#endif
+int w_read_retry_remote(drbd_dev* mdev, struct drbd_work* w)
+{
+ drbd_request_t *req = (drbd_request_t*)w;
+
+ if ( mdev->cstate <= Connected ||
+ test_bit(PARTNER_DISKLESS,&mdev->flags) ) {
+
+ // FIXME
+ // local read failed, and we cannot retry.
+ // drbd_chk_io_error has already been called.
+ // what now: PANIC ??
+
+ // propagate, cannot do anything about it.
+ drbd_bio_endio(req->master_bio,0);
+ return 0; // worker will abort.
+ }
+
+ // FIXME: what if partner was SyncTarget, and is out of sync for
+ // this area ?? ... should be handled in the receiver.
+ drbd_read_remote(mdev,req);
+ return 1;
+}
+
int w_resync_inactive(drbd_dev *mdev, struct drbd_work *w)
{
ERR("resync inactive, but callback triggered??\n");
return 0;
}
+int w_is_resync_read(drbd_dev *mdev, struct drbd_work *w)
+{
+ ERR("%s: Typecheck only, should never be called!\n", __FUNCTION__ );
+ return 0;
+}
+
+/* in case we need it. currently unused,
+ * since should be assigned to "w_read_retry_remote"
+ */
+int w_is_app_read(drbd_dev *mdev, struct drbd_work *w)
+{
+ ERR("%s: Typecheck only, should never be called!\n", __FUNCTION__ );
+ return 0;
+}
+
void resync_timer_fn(unsigned long data)
{
drbd_dev* mdev = (drbd_dev*) data;
@@ -317,6 +419,7 @@
pr = mempool_alloc(drbd_pr_mempool, GFP_USER);
if (unlikely(pr == NULL)) goto requeue;
SET_MAGIC(pr);
+ pr->w.cb = w_is_resync_read;
next_sector:
size = BM_BLOCK_SIZE;
@@ -367,7 +470,7 @@
dt = (jiffies - mdev->rs_start) / HZ + 1;
n = mdev->rs_total>>1;
sector_div(n,dt);
- INFO("Resync done (total %lu sec; %u K/sec)\n",
+ INFO("Resync done (total %lu sec; %lu K/sec)\n",
dt,(unsigned long)n);
if (mdev->cstate == SyncTarget) {
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/drbd_int.h,v
retrieving revision 1.58.2.125
retrieving revision 1.58.2.126
diff -u -3 -r1.58.2.125 -r1.58.2.126
--- drbd_int.h 15 Feb 2004 14:40:11 -0000 1.58.2.125
+++ drbd_int.h 16 Feb 2004 20:39:00 -0000 1.58.2.126
@@ -232,10 +232,9 @@
/* these defines should go into blkdev.h
(if it will be ever includet into linus' linux) */
#define RQ_DRBD_NOTHING 0x0001
-#define RQ_DRBD_SENT 0x0010
-#define RQ_DRBD_WRITTEN 0x0020
+#define RQ_DRBD_SENT 0x0010
+#define RQ_DRBD_LOCAL 0x0020
#define RQ_DRBD_DONE 0x0030
-#define RQ_DRBD_READ 0x0040
enum MetaDataFlags {
MDF_Consistent = 1,
@@ -671,7 +670,8 @@
struct list_head read_ee; // IO in progress
// struct list_head rdone_ee; // send result or CondRequest
spinlock_t pr_lock;
- struct list_head app_reads;
+ // struct list_head app_reads; // FIXME broken on purpose by lge
+ struct list_head new_app_reads;
struct list_head resync_reads;
int ee_vacant;
int ee_in_use;
@@ -803,10 +803,11 @@
#define ERF_NOTLD 2 /* do not call tl_dependence */
extern void drbd_end_req(drbd_request_t *, int, int, sector_t);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-extern int drbd_make_request(request_queue_t *q, int rw, struct buffer_head *bio);
+extern int drbd_make_request_24(request_queue_t *q, int rw, struct buffer_head *bio);
#else
-extern int drbd_make_request(request_queue_t *q, struct bio *bio);
+extern int drbd_make_request_26(request_queue_t *q, struct bio *bio);
#endif
+extern void drbd_read_remote(drbd_dev *mdev, drbd_request_t *req);
// drbd_fs.c
extern int drbd_determin_dev_size(drbd_dev*);
@@ -821,11 +822,14 @@
// maybe rather drbd_main.c ?
extern int drbd_md_sync_page_io(drbd_dev *mdev, sector_t sector, int rw);
// worker callbacks
+extern int w_is_app_read (drbd_dev *mdev, struct drbd_work *w);
+extern int w_is_resync_read (drbd_dev *mdev, struct drbd_work *w);
+extern int w_read_retry_remote (drbd_dev *mdev, struct drbd_work *w);
extern int w_e_end_data_req (drbd_dev *mdev, struct drbd_work *w);
extern int w_e_end_rsdata_req (drbd_dev *mdev, struct drbd_work *w);
extern int w_resync_finished (drbd_dev *mdev, struct drbd_work *w);
extern int w_resync_inactive (drbd_dev *mdev, struct drbd_work *w);
-extern int w_resume_next_sg (drbd_dev* mdev, struct drbd_work *w);
+extern int w_resume_next_sg (drbd_dev *mdev, struct drbd_work *w);
// drbd_receiver.c
@@ -835,7 +839,7 @@
extern struct Tl_epoch_entry* drbd_get_ee(drbd_dev* mdev);
extern int recv_resync_read(drbd_dev* mdev, struct Pending_read *pr,
sector_t sector, int data_size);
-extern int recv_dless_read(drbd_dev* mdev, struct Pending_read *pr,
+extern int recv_dless_read(drbd_dev *mdev, drbd_request_t *req,
sector_t sector, int data_size);
// drbd_proc.c
@@ -934,7 +938,7 @@
break;
case Panic:
set_bit(DISKLESS,&mdev->flags);
- smp_mb();
+ smp_mb(); // but why is there smp_mb__after_clear_bit() ?
panic(DEVICE_NAME" : IO error on backing device!\n");
break;
case Detach:
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/drbd_main.c,v
retrieving revision 1.73.2.129
retrieving revision 1.73.2.130
diff -u -3 -r1.73.2.129 -r1.73.2.130
--- drbd_main.c 12 Feb 2004 18:27:06 -0000 1.73.2.129
+++ drbd_main.c 16 Feb 2004 20:39:00 -0000 1.73.2.130
@@ -1097,7 +1097,7 @@
INIT_LIST_HEAD(&mdev->done_ee);
INIT_LIST_HEAD(&mdev->read_ee);
INIT_LIST_HEAD(&mdev->busy_blocks);
- INIT_LIST_HEAD(&mdev->app_reads);
+ INIT_LIST_HEAD(&mdev->new_app_reads);
INIT_LIST_HEAD(&mdev->resync_reads);
INIT_LIST_HEAD(&mdev->data.work.q);
INIT_LIST_HEAD(&mdev->meta.work.q);
@@ -1342,7 +1342,7 @@
WARN("Could not bd_claim() myself.");
}
- blk_queue_make_request(q,drbd_make_request);
+ blk_queue_make_request(q,drbd_make_request_26);
q->unplug_fn = drbd_send_write_hint;
}
#endif
@@ -1405,7 +1405,7 @@
&drbd_ops, NULL);
#endif
- NOT_IN_26(blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR),drbd_make_request);)
+ NOT_IN_26(blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR),drbd_make_request_24);)
#if defined(CONFIG_PPC64) || defined(CONFIG_SPARC64) || defined(CONFIG_X86_64)
// tell the kernel that we think our ioctls are 64bit clean
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/drbd_receiver.c,v
retrieving revision 1.97.2.111
retrieving revision 1.97.2.112
diff -u -3 -r1.97.2.111 -r1.97.2.112
--- drbd_receiver.c 15 Feb 2004 14:40:11 -0000 1.97.2.111
+++ drbd_receiver.c 16 Feb 2004 20:39:00 -0000 1.97.2.112
@@ -742,17 +742,15 @@
mdev->writ_cnt+=data_size>>9;
}
-int recv_dless_read(drbd_dev *mdev, struct Pending_read *pr,
+int recv_dless_read(drbd_dev *mdev, drbd_request_t *req,
sector_t sector, int data_size)
{
drbd_bio_t *bio;
int ok,rr;
- // DBG("%s\n", __func__);
+ bio = req->master_bio;
- bio = pr->d.master_bio;
-
- D_ASSERT( sector == drbd_pr_get_sector(pr) );
+ D_ASSERT( sector == drbd_req_get_sector(req) );
rr=drbd_recv(mdev,drbd_bio_kmap(bio),data_size);
drbd_bio_kunmap(bio);
@@ -882,6 +880,7 @@
STATIC int receive_DataReply(drbd_dev *mdev,Drbd_Header* h)
{
struct Pending_read *pr;
+ drbd_request_t *req;
sector_t sector;
unsigned int header_size,data_size;
int ok;
@@ -889,7 +888,7 @@
static int (*funcs[])(struct Drbd_Conf* , struct Pending_read*,
sector_t,int) = {
- [Application] = recv_dless_read,
+ [Application] = NULL, /* recv_dless_read, */
[Resync] = recv_resync_read,
[AppAndResync] = recv_both_read
};
@@ -909,26 +908,47 @@
sector = be64_to_cpu(p->sector);
- pr = (struct Pending_read *)(long)p->block_id;
+ /* FIXME funny runtime type check.
+ * probably should be distinct packet types!
+ */
+ req = (drbd_request_t *)(long)p->block_id;
+ if (req->w.cb == w_is_resync_read) {
+ pr = (struct Pending_read *)(long)p->block_id;
+ req = NULL;
+ ERR_IF(!VALID_POINTER(pr)) return FALSE;
+ // XXX are enums unsigned by default?
+ ERR_IF((unsigned)pr->cause > AppAndResync) {
+ return FALSE;
+ }
+ } else {
+ pr = NULL;
+ ERR_IF(!VALID_POINTER(req)) return FALSE;
+ }
- // these would be BUG()s ...
- ERR_IF(!VALID_POINTER(pr)) return FALSE;
- // XXX are enums unsigned by default?
- ERR_IF((unsigned)pr->cause > AppAndResync) {
- return FALSE;
- }
+ if (pr) {
+ /* RESYNC request
+ */
+ /* Take it out of the list before calling the handler, since the
+ handler could be changed by make_req as long as it is on the list
+ */
+ spin_lock(&mdev->pr_lock);
+ list_del(&pr->w.list);
+ spin_unlock(&mdev->pr_lock);
- /* Take it out of the list before calling the handler, since the
- handler could be changed by make_req as long as it is on the list
- */
- spin_lock(&mdev->pr_lock);
- list_del(&pr->w.list);
- spin_unlock(&mdev->pr_lock);
+ // FIXME get rid of pr (at least its cause field) completely!
+ D_ASSERT(pr->cause == Resync);
- ok = funcs[pr->cause](mdev,pr,sector,data_size);
- INVALIDATE_MAGIC(pr);
- mempool_free(pr,drbd_pr_mempool);
+ ok = funcs[pr->cause](mdev,pr,sector,data_size);
+ INVALIDATE_MAGIC(pr);
+ mempool_free(pr,drbd_pr_mempool);
+ } else {
+ /* "diskless" application READ request
+ */
+ ok = recv_dless_read(mdev,req,sector,data_size);
+ INVALIDATE_MAGIC(req);
+ mempool_free(req,drbd_request_mempool);
+ }
return ok;
}
@@ -1314,23 +1334,27 @@
STATIC void drbd_fail_pending_reads(drbd_dev *mdev)
{
- struct Pending_read *pr;
struct list_head workset,*le;
drbd_bio_t *bio;
+ /*
+ * Application READ requests
+ */
spin_lock(&mdev->pr_lock);
- list_add(&workset,&mdev->app_reads);
- list_del(&mdev->app_reads);
- INIT_LIST_HEAD(&mdev->app_reads);
+ list_add(&workset,&mdev->new_app_reads);
+ list_del(&mdev->new_app_reads);
+ INIT_LIST_HEAD(&mdev->new_app_reads);
spin_unlock(&mdev->pr_lock);
while(!list_empty(&workset)) {
+ drbd_request_t *req;
le = workset.next;
- pr = list_entry(le, struct Pending_read, w.list);
+ req = list_entry(le, drbd_request_t, w.list);
list_del(le);
- bio = pr->d.master_bio;
+ bio = req->master_bio;
+#if 0
switch(pr->cause) {
case Application:
dec_ap_pending(mdev,HERE);
@@ -1345,13 +1369,18 @@
break;
case Discard:;
}
+#endif
drbd_bio_IO_error(bio);
+ dec_ap_pending(mdev,HERE);
- INVALIDATE_MAGIC(pr);
- mempool_free(pr,drbd_pr_mempool);
+ INVALIDATE_MAGIC(req);
+ mempool_free(req,drbd_request_mempool);
}
+ /*
+ * Resync READ requests
+ */
spin_lock(&mdev->pr_lock);
list_add(&workset,&mdev->resync_reads);
list_del(&mdev->resync_reads);
@@ -1359,6 +1388,7 @@
spin_unlock(&mdev->pr_lock);
while(!list_empty(&workset)) {
+ struct Pending_read *pr;
le = workset.next;
list_del(le);
pr = list_entry(le, struct Pending_read, w.list);
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/drbd_req-2.4.c,v
retrieving revision 1.33.2.54
retrieving revision 1.33.2.55
diff -u -3 -r1.33.2.54 -r1.33.2.55
--- drbd_req-2.4.c 11 Feb 2004 13:25:20 -0000 1.33.2.54
+++ drbd_req-2.4.c 16 Feb 2004 20:39:00 -0000 1.33.2.55
@@ -94,6 +94,7 @@
wake_asender(mdev);
}
+#if 0
STATIC struct Pending_read*
drbd_find_read(sector_t sector, struct list_head *in)
{
@@ -107,8 +108,10 @@
return NULL;
}
+#endif
-STATIC void drbd_issue_drequest(struct Drbd_Conf* mdev,drbd_bio_t *bio)
+#if 0
+STATIC void drbd_issue_drequest___FIXME_broken_on_purpose_by_lge(struct Drbd_Conf* mdev,drbd_bio_t *bio)
{
struct Pending_read *pr;
pr = mempool_alloc(drbd_pr_mempool, GFP_DRBD);
@@ -134,6 +137,24 @@
(unsigned long)pr);
#endif
}
+#endif
+
+void drbd_read_remote(drbd_dev *mdev, drbd_request_t *req)
+{
+ drbd_bio_t *bio = req->master_bio;
+
+ spin_lock(&mdev->pr_lock);
+ list_add(&req->w.list,&mdev->new_app_reads);
+ spin_unlock(&mdev->pr_lock);
+ inc_ap_pending(mdev);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ drbd_send_drequest(mdev, DataRequest, bio->b_rsector, bio->b_size,
+ (unsigned long)req);
+#else
+ drbd_send_drequest(mdev, DataRequest, bio->bi_sector, bio->bi_size,
+ (unsigned long)req);
+#endif
+}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
@@ -158,110 +179,103 @@
}
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-int drbd_make_request(request_queue_t *q, int rw, struct buffer_head *bio)
-#else
-int drbd_make_request(request_queue_t *q, struct bio *bio)
-#endif
+STATIC int
+drbd_make_request_common(drbd_dev *mdev, int rw, int size,
+ sector_t sector, drbd_bio_t *bio)
{
- struct Drbd_Conf* mdev =
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- drbd_conf + MINOR(bio->b_rdev);
-#else
- (drbd_dev*) q->queuedata;
-#endif
drbd_request_t *req;
- int send_ok;
- int sector, size;
- ONLY_IN_26(int rw = bio_rw(bio);)
+ int local, remote;
+ int target_area_out_of_sync = FALSE; // only relevant for reads
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- if (MINOR(bio->b_rdev) >= minor_count || mdev->cstate < StandAlone) {
- buffer_IO_error(bio);
+ /* allocate outside of all locks
+ */
+ req = mempool_alloc(drbd_request_mempool, GFP_DRBD);
+ if (!req) {
+ ERR("could not kmalloc() req\n");
+ drbd_bio_IO_error(bio);
return 0;
}
+ SET_MAGIC(req);
+ req->master_bio = bio;
-#else
- //#warning "FIXME"
-#endif
+ // XXX maybe merge both variants into one
+ if (rw == WRITE) drbd_req_prepare_write(mdev,req);
+ else drbd_req_prepare_read(mdev,req);
- /* what do we know?
+ /* XXX req->w.cb = something; drbd_queue_work() ....
+ * Not yet.
*/
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- sector = bio->b_rsector;
- size = bio->b_size;
-#else
- // rw = bio->bi_rw & RW_MASK;
- // ra = bio->bi_rw & RWA_MASK;
- size = bio->bi_size;
- sector = bio->bi_sector;
- /* barrier = bio_barrier(bio);
- nr_sectors = bio_sectors(bio); */
-#endif
-
- if( !inc_local(mdev) ) {
- if( mdev->cstate < Connected ) {
- drbd_bio_IO_error(bio);
- return 0;
- }
+ // down_read(mdev->device_lock);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- if(!test_and_set_bit(WRITE_HINT_QUEUED,&mdev->flags)) {
- queue_task(&mdev->write_hint_tq, &tq_disk); // IO HINT
- }
-#else
- spin_lock_irq(q->queue_lock);
- if(!blk_queue_plugged(q)) {
- blk_plug_device(q);
- del_timer(&q->unplug_timer);
- // unplugging should not happen automatically...
+ local = inc_local(mdev);
+ // FIXME special case handling of READA ??
+ if (rw == READ || rw == READA) {
+ if (local) {
+ target_area_out_of_sync =
+ (mdev->cstate == SyncTarget) &&
+ bm_get_bit(mdev->mbds_id,sector,size);
+ if (target_area_out_of_sync) {
+ /* whe could kick the syncer to
+ * sync this extent asap, wait for
+ * it, then continue locally.
+ * Or just issue the request remotely.
+ */
+ local = 0;
+ dec_local(mdev);
+ }
}
- spin_unlock_irq(q->queue_lock);
-#endif
-
+ remote = !local;
+ } else {
+ remote = 1;
+ }
+ remote = remote && (mdev->cstate >= Connected)
+ && !test_bit(PARTNER_DISKLESS,&mdev->flags);
+
+ if (!(local || remote)) {
+ ERR("IO ERROR: neither local nor remote disk\n");
+ // PANIC ??
+ drbd_bio_IO_error(bio);
+ return 0;
+ }
- // Fail READA ??
- if( rw == WRITE ) {
- req = mempool_alloc(drbd_request_mempool, GFP_DRBD);
-
- if (!req) {
- ERR("could not kmalloc() req\n");
- drbd_bio_IO_error(bio);
- return 0;
- }
- SET_MAGIC(req);
+ /* THINK
+ * maybe we need to
+ * if (rw == WRITE) drbd_al_begin_io(mdev, sector);
+ * right here already?
+ */
- //WORK_HERE
- /* FIXME the drbd_make_request function will be
- * restructured soon.
- * until that is the case,
- * at least put the mdev and sector number into the
- * private bh!
+ /* do this first, so I do not need to call drbd_end_req,
+ * but can set the rq_status directly.
+ */
+ if (!local)
+ req->rq_status |= RQ_DRBD_LOCAL;
+ if (!remote)
+ req->rq_status |= RQ_DRBD_SENT;
+
+ if (remote) {
+ /* either WRITE and Connected,
+ * or READ, and no local disk,
+ * or READ, but not in sync.
+ */
+ drbd_plug_device(mdev);
+ if (rw == WRITE) {
+ /* Syncronization with the syncer is done
+ * via drbd_[rs|al]_[begin|end]_io()
*/
- req->master_bio = bio;
- drbd_req_prepare_write(mdev,req);
- req->rq_status = RQ_DRBD_WRITTEN | 1;
-
if(mdev->conf.wire_protocol != DRBD_PROT_A) {
inc_ap_pending(mdev);
}
- drbd_send_dblock(mdev,req); // FIXME error check?
- } else { // rw == READ || rw == READA
- drbd_issue_drequest(mdev,bio);
- }
- return 0; // Ok everything arranged
- }
-
- if ( mdev->cstate == SyncTarget &&
- bm_get_bit(mdev->mbds_id,sector,size) ) {
- struct Pending_read *pr;
- if( rw == WRITE ) {
- // Actually nothing special to do.
- // Just do a mirrored write.
- // Syncronization with the syncer is done
- // via drbd_[rs|al]_[begin|end]_io()
- } else { // rw == READ || rw == READA
+ /* THINK drbd_send_dblock has a return value,
+ * but we ignore it here. Is it actually void,
+ * because error handling takes place elsewhere?
+ */
+ drbd_send_dblock(mdev,req);
+ } else if (target_area_out_of_sync) {
+ #if 0
+ /* lge: I do not like this branch,
+ * and it currently does not work anyways...
+ */
spin_lock(&mdev->pr_lock);
pr=drbd_find_read(sector,&mdev->resync_reads);
if(pr) {
@@ -273,84 +287,63 @@
list_del(&pr->w.list);
list_add(&pr->w.list,&mdev->app_reads);
spin_unlock(&mdev->pr_lock);
- return 0; // Ok everything arranged
+ /* Ok, everything arranged.
+ * since reads are never done
+ * on both nodes at the same time,
+ * we just:
+ */
+ // up_read(mdev->device_lock);
+ return 0;
}
-
spin_unlock(&mdev->pr_lock);
- drbd_issue_drequest(mdev,bio);
- return 0;
+ #endif
+ drbd_read_remote(mdev,req);
+ } else {
+ // this node is diskless ...
+ drbd_read_remote(mdev,req);
}
}
- if( rw == READ || rw == READA ) {
- mdev->read_cnt += size >> 9;
- dec_local(mdev); // FIXME TODO -> completion handler
- /// TODO FIXME shoulbe be able to reissue the request to
- /// the peer in case it fails locally.
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- bio->b_rdev = mdev->backing_bdev;
-#else
- bio->bi_bdev = mdev->backing_bdev;
-#endif
- return 1; // Not arranged for transfer ( but remapped :)
+ if (local) {
+ if (rw == WRITE) {
+ drbd_al_begin_io(mdev, sector);
+ if (!remote) drbd_set_out_of_sync(mdev,sector,size);
+ } else {
+ D_ASSERT(!remote);
+ }
+ /* FIXME
+ * Should we add even local reads to some list, so
+ * they can be grabbed and freed somewhen?
+ *
+ * They already have a reference count (sort of...)
+ * on mdev via inc_local()
+ */
+ drbd_generic_make_request(rw,&req->private_bio);
}
- mdev->writ_cnt += size >> 9;
-
- if(mdev->cstate<Connected || test_bit(PARTNER_DISKLESS,&mdev->flags)) {
- drbd_set_out_of_sync(mdev,sector,size);
+ // up_read(mdev->device_lock);
+ return 0;
+}
- /* This should be changed. We should not remap in this
- case !!!!! FIXME TODO FIXME TODO
- */
- drbd_al_begin_io(mdev, sector);
- drbd_al_complete_io(mdev, sector); // FIXME TODO -> completion handler
- dec_local(mdev); // FIXME TODO -> completion handler
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- bio->b_rdev = mdev->backing_bdev;
-#else
- bio->bi_bdev = mdev->backing_bdev;
-#endif
- return 1; // Not arranged for transfer ( but remapped :)
+int drbd_make_request_24(request_queue_t *q, int rw, struct buffer_head *bh)
+{
+ struct Drbd_Conf* mdev = drbd_conf + MINOR(bh->b_rdev);
+ if (MINOR(bh->b_rdev) >= minor_count || mdev->cstate < StandAlone) {
+ buffer_IO_error(bh);
+ return 0;
}
- // Now its clear that we have to do a mirrored write:
-
- req = mempool_alloc(drbd_request_mempool, GFP_DRBD);
-
- if (!req) {
- ERR("could not kmalloc() req\n");
+ return drbd_make_request_common(mdev,rw,bh->b_size,bh->b_rsector,bh);
+}
+#else
+int drbd_make_request_26(request_queue_t *q, struct bio *bio)
+{
+ struct Drbd_Conf* mdev = (drbd_dev*) q->queuedata;
+ if (mdev->cstate < StandAlone) {
drbd_bio_IO_error(bio);
- dec_local(mdev);
return 0;
}
- SET_MAGIC(req);
-
- req->master_bio = bio;
- drbd_req_prepare_write(mdev,req);
-
- send_ok=drbd_send_dblock(mdev,req);
-
- // FIXME we could remove the send_ok cases, the are redundant to tl_clear()
- if(send_ok && mdev->conf.wire_protocol!=DRBD_PROT_A) inc_ap_pending(mdev);
- if(mdev->conf.wire_protocol==DRBD_PROT_A || (!send_ok) ) {
- /* If sending failed, we can not expect
- an ack packet. */
- drbd_end_req(req, RQ_DRBD_SENT, 1, drbd_req_get_sector(req));
- }
- if(!send_ok) drbd_set_out_of_sync(mdev,sector,size);
-
-NOT_IN_26(
- if(!test_and_set_bit(WRITE_HINT_QUEUED,&mdev->flags)) {
- queue_task(&mdev->write_hint_tq, &tq_disk);
- }
-)
-
- drbd_al_begin_io(mdev, drbd_req_get_sector(req));
-
- drbd_generic_make_request(rw,&req->private_bio);
-
- return 0; /* Ok, bh arranged for transfer */
-
+ return drbd_make_request_common(mdev,bio_rw(bio),bio->bi_size,bio->bi_sector,bio);
}
-
+#endif