[DRBD-cvs] r1758 - in trunk/drbd: . linux
svn at svn.drbd.org
svn at svn.drbd.org
Sat Feb 12 18:48:22 CET 2005
Author: phil
Date: 2005-02-12 18:48:17 +0100 (Sat, 12 Feb 2005)
New Revision: 1758
Modified:
trunk/drbd/drbd_fs.c
trunk/drbd/drbd_int.h
trunk/drbd/drbd_main.c
trunk/drbd/drbd_receiver.c
trunk/drbd/drbd_sizeof_sanity_check.c
trunk/drbd/linux/drbd.h
Log:
The implementation of the "allow-two-primaries" option
is now complete, but untested... might crash everywhere...
Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c 2005-02-11 15:59:06 UTC (rev 1757)
+++ trunk/drbd/drbd_fs.c 2005-02-12 17:48:17 UTC (rev 1758)
@@ -569,18 +569,18 @@
if (mdev->tl_hash_s != new_conf.max_epoch_size/8 ) {
- new_tl_hash = kmalloc(mdev->tl_hash_s * sizeof(void*),
- GFP_KERNEL);
+ new_tl_hash=kmalloc((new_conf.max_epoch_size/8)*sizeof(void*),
+ GFP_KERNEL);
if(!new_tl_hash) {
retcode=KMallocFailed;
goto fail_ioctl;
}
}
- if (mdev->conf.two_primaries &&
+ if (new_conf.two_primaries &&
( mdev->ee_hash_s != new_conf.max_buffers/8 ) ) {
- new_ee_hash = kmalloc(mdev->ee_hash_s * sizeof(void*),
- GFP_KERNEL);
+ new_ee_hash=kmalloc((new_conf.max_buffers/8)*sizeof(void*),
+ GFP_KERNEL);
if(!new_ee_hash) {
retcode=KMallocFailed;
goto fail_ioctl;
Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h 2005-02-11 15:59:06 UTC (rev 1757)
+++ trunk/drbd/drbd_int.h 2005-02-12 17:48:17 UTC (rev 1758)
@@ -307,6 +307,7 @@
NegDReply, // Local disk is broken...
NegRSDReply, // Local disk is broken...
BarrierAck,
+ DiscardNote,
MAX_CMD,
MayIgnore = 0x100, // Flag only to test if (cmd > MayIgnore) ...
@@ -345,7 +346,8 @@
[NegAck] = "NegAck",
[NegDReply] = "NegDReply",
[NegRSDReply] = "NegRSDReply",
- [BarrierAck] = "BarrierAck"
+ [BarrierAck] = "BarrierAck",
+ [DiscardNote] = "DiscardNote"
};
if (cmd == HandShake) return "HandShake";
@@ -490,6 +492,13 @@
u32 bit_map_gen[5];
} __attribute((packed)) Drbd06_Parameter_P;
+typedef struct {
+ Drbd_Header head;
+ u64 block_id;
+ u32 seq_num;
+ u32 pad;
+} __attribute((packed)) Drbd_Discard_Packet;
+
typedef union {
Drbd_Header head;
Drbd_HandShake_Packet HandShake;
@@ -560,13 +569,14 @@
struct drbd_barrier;
struct drbd_request {
struct drbd_work w;
- long magic;
- int rq_status;
struct drbd_barrier *barrier; // The next barrier.
struct bio *master_bio; // master bio pointer
struct bio *private_bio;
struct hlist_node colision;
drbd_dev *mdev;
+ long magic;
+ int rq_status;
+ int seq_num;
};
struct drbd_barrier {
@@ -790,9 +800,7 @@
extern void tl_clear(drbd_dev *mdev);
extern int tl_dependence(drbd_dev *mdev, drbd_request_t * item);
extern int tl_verify(drbd_dev *mdev, drbd_request_t * item, sector_t sector);
-#define TLHW_FLAG_SENT 0x10000000
-#define TLHW_FLAG_RECVW 0x20000000
-extern int req_have_write(drbd_dev *mdev, struct Tl_epoch_entry *e, int flags);
+extern drbd_request_t * req_have_write(drbd_dev *, struct Tl_epoch_entry *);
extern void drbd_free_sock(drbd_dev *mdev);
extern int drbd_send(drbd_dev *mdev, struct socket *sock,
void* buf, size_t size, unsigned msg_flags);
@@ -822,6 +830,7 @@
sector_t sector,int size, u64 block_id);
extern int drbd_send_bitmap(drbd_dev *mdev);
extern int _drbd_send_bitmap(drbd_dev *mdev);
+extern int drbd_send_discard(drbd_dev *mdev, drbd_request_t *req);
extern void drbd_free_ll_dev(drbd_dev *mdev);
extern int drbd_io_error(drbd_dev* mdev);
extern void drbd_mdev_cleanup(drbd_dev *mdev);
Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c 2005-02-11 15:59:06 UTC (rev 1757)
+++ trunk/drbd/drbd_main.c 2005-02-12 17:48:17 UTC (rev 1758)
@@ -375,20 +375,14 @@
return !( ( s1 + (l1>>9) <= s2 ) || ( s1 >= s2 + (l2>>9) ) );
}
-/* Return values:
- *
- * 0 ... no conflicting write
- * 1 ... a conflicting write, have not got ack by now.
- * 2 ... a conflicting write, have got also got ack.
- */
-int req_have_write(drbd_dev *mdev, struct Tl_epoch_entry *e, int flags)
+drbd_request_t * req_have_write(drbd_dev *mdev, struct Tl_epoch_entry *e)
{
struct hlist_head *slot;
struct hlist_node *n;
drbd_request_t * req;
sector_t sector = drbd_ee_get_sector(e);
int size = drbd_ee_get_size(e);
- int i, rv=0;
+ int i;
D_ASSERT(size <= 1<<(HT_SHIFT+9) );
@@ -401,20 +395,10 @@
if( overlaps(drbd_req_get_sector(req),
drbd_req_get_size(req),
sector,
- size) ) {
- rv=1;
- if( req->rq_status & RQ_DRBD_SENT ) rv++;
- if( flags & TLHW_FLAG_SENT ) {
- req->rq_status |= RQ_DRBD_SENT;
- }
- if( flags & TLHW_FLAG_RECVW ) {
- req->rq_status |= RQ_DRBD_RECVW;
- }
- goto out;
- } //overlaps()
+ size) ) goto out;
} // hlist_for_each_entry()
}
-
+ req = NULL;
// Good, no conflict found
INIT_HLIST_NODE(&e->colision);
hlist_add_head( &e->colision, mdev->ee_hash +
@@ -422,17 +406,18 @@
out:
spin_unlock_irq(&mdev->tl_lock);
- return rv;
+ return req;
}
-STATIC int ee_have_write(drbd_dev *mdev, drbd_request_t * req)
+STATIC struct Tl_epoch_entry * ee_have_write(drbd_dev *mdev,
+ drbd_request_t * req)
{
struct hlist_head *slot;
struct hlist_node *n;
struct Tl_epoch_entry *ee;
sector_t sector = drbd_req_get_sector(req);
int size = drbd_req_get_size(req);
- int i, rv=0;
+ int i;
D_ASSERT(size <= 1<<(HT_SHIFT+9) );
@@ -445,19 +430,16 @@
if( overlaps(drbd_ee_get_sector(ee),
drbd_ee_get_size(ee),
sector,
- size) ) {
- rv=1;
- goto out;
- } //overlaps()
+ size) ) goto out;
} // hlist_for_each_entry()
}
-
+ ee = NULL;
// Good, no conflict found
_tl_add(mdev,req);
out:
spin_unlock_irq(&mdev->tl_lock);
- return rv;
+ return ee;
}
/**
@@ -1000,7 +982,17 @@
return ok;
}
+int drbd_send_discard(drbd_dev *mdev, drbd_request_t *req)
+{
+ Drbd_Discard_Packet p;
+ p.block_id = (unsigned long)req;
+ p.seq_num = cpu_to_be32(req->seq_num);
+
+ return drbd_send_cmd(mdev,mdev->meta.socket,DiscardNote,
+ (Drbd_Header*)&p,sizeof(p));
+}
+
int drbd_send_state(drbd_dev *mdev)
{
Drbd_State_Packet p;
@@ -1307,7 +1299,8 @@
p.sector = cpu_to_be64(drbd_req_get_sector(req));
p.block_id = (unsigned long)req;
- p.seq_num = cpu_to_be32(atomic_add_return(1,&mdev->packet_seq));
+ p.seq_num = cpu_to_be32( req->seq_num =
+ atomic_add_return(1,&mdev->packet_seq) );
/* About tl_add():
1. This must be within the semaphor,
Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c 2005-02-11 15:59:06 UTC (rev 1757)
+++ trunk/drbd/drbd_receiver.c 2005-02-12 17:48:17 UTC (rev 1758)
@@ -1011,21 +1011,26 @@
return ok;
}
-STATIC int drbd_chk_discard(drbd_dev *mdev,u64 block_id,int seq_num)
+STATIC int drbd_chk_discard(drbd_dev *mdev,struct Tl_epoch_entry *e)
{
struct drbd_discard_note *dn;
struct list_head *le;
MUST_HOLD(&mdev->peer_seq_lock);
-
+ start_over:
list_for_each(le,&mdev->discard) {
dn = list_entry(le, struct drbd_discard_note, list);
- if( dn->seq_num == seq_num ) {
- D_ASSERT( dn->block_id == block_id );
+ if( dn->seq_num == mdev->peer_seq ) {
+ D_ASSERT( dn->block_id == e->block_id );
list_del(le);
kfree(dn);
return 1;
- }
+ }
+ if( dn->seq_num < mdev->peer_seq ) {
+ list_del(le);
+ kfree(dn);
+ goto start_over;
+ }
}
return 0;
}
@@ -1035,8 +1040,9 @@
{
sector_t sector;
struct Tl_epoch_entry *e;
+ drbd_request_t * req;
Drbd_Data_Packet *p = (Drbd_Data_Packet*)h;
- int header_size,data_size, packet_seq,discard=0;
+ int header_size, data_size, packet_seq, discard;
// FIXME merge this code dups into some helper function
header_size = sizeof(*p) - sizeof(*h);
@@ -1052,6 +1058,20 @@
if (drbd_recv(mdev, h->payload, header_size) != header_size)
return FALSE;
+ sector = be64_to_cpu(p->sector);
+ e = read_in_block(mdev,data_size);
+ if (!e) return FALSE;
+
+ if(!inc_local(mdev)) {
+ if (DRBD_ratelimit(5*HZ,5))
+ ERR("Can not write mirrored data block to local disk.\n");
+ drbd_send_ack(mdev,NegAck,e);
+ spin_lock_irq(&mdev->ee_lock);
+ drbd_put_ee(mdev,e);
+ spin_unlock_irq(&mdev->ee_lock);
+ return TRUE;
+ }
+
/* This wait_event is here to make sure that never ever an
DATA packet traveling via sock can overtake an ACK packet
traveling on msock
@@ -1066,68 +1086,58 @@
spin_lock(&mdev->peer_seq_lock);
mdev->peer_seq = max(mdev->peer_seq, packet_seq);
/* is update_peer_seq(mdev,packet_seq); */
- discard = drbd_chk_discard(mdev,p->block_id,packet_seq);
+ discard = drbd_chk_discard(mdev,e);
spin_unlock(&mdev->peer_seq_lock);
- }
- sector = be64_to_cpu(p->sector);
- e = read_in_block(mdev,data_size);
- if (!e) return FALSE;
-
- if(!inc_local(mdev)) {
- if (DRBD_ratelimit(5*HZ,5))
- ERR("Can not write mirrored data block to local disk.\n");
- drbd_send_ack(mdev,NegAck,e);
- spin_lock_irq(&mdev->ee_lock);
- drbd_put_ee(mdev,e);
- spin_unlock_irq(&mdev->ee_lock);
- return TRUE;
- }
-
- if(discard) {
- spin_lock_irq(&mdev->ee_lock);
- drbd_put_ee(mdev,e);
- spin_unlock_irq(&mdev->ee_lock);
- WARN("Concurrent write! [DISCARD BY LIST] sec=%lu\n",
- (unsigned long)sector);
- return TRUE;
- }
-
- switch( req_have_write(mdev, e, 0) ) {
- case 2: /* Conflicting write, got ACK */
- /* write afterwards ...*/
- WARN("Concurrent write! [W AFTERWARDS] sec=%lu\n",
- (unsigned long)sector);
- if( wait_event_interruptible(mdev->cstate_wait,
- !req_have_write(mdev,e,TLHW_FLAG_RECVW))) {
+ if(discard) {
spin_lock_irq(&mdev->ee_lock);
drbd_put_ee(mdev,e);
spin_unlock_irq(&mdev->ee_lock);
- return FALSE;
- }
- case 1: /* Conflicting write, no ACK by now*/
- if (test_bit(UNIQUE,&mdev->flags)) {
- spin_lock_irq(&mdev->ee_lock);
- drbd_put_ee(mdev,e);
- spin_unlock_irq(&mdev->ee_lock);
- WARN("Concurrent write! [DISCARD BY FLAG] sec=%lu\n",
+ WARN("Concurrent write! [DISCARD BY LIST] sec=%lu\n",
(unsigned long)sector);
return TRUE;
- } else {
- /* write afterwards, do not expect ACK */
- WARN("Concurrent write! [W AFTERWARDS] sec=%lu\n",
- (unsigned long)sector);
- if( wait_event_interruptible(mdev->cstate_wait,
- !req_have_write(mdev,e,
- TLHW_FLAG_RECVW|TLHW_FLAG_SENT))) {
- spin_lock_irq(&mdev->ee_lock);
- drbd_put_ee(mdev,e);
- spin_unlock_irq(&mdev->ee_lock);
- return FALSE;
+ }
+
+ req = req_have_write(mdev, e);
+
+ if(req) {
+ if( req->rq_status & RQ_DRBD_SENT ) {
+ /* Conflicting write, got ACK */
+ /* write afterwards ...*/
+ WARN("Concurrent write! [W AFTERWARDS] "
+ "sec=%lu\n",(unsigned long)sector);
+ if( wait_event_interruptible(mdev->cstate_wait,
+ !req_have_write(mdev,e))) {
+ spin_lock_irq(&mdev->ee_lock);
+ drbd_put_ee(mdev,e);
+ spin_unlock_irq(&mdev->ee_lock);
+ return FALSE;
+ }
+ } else {
+ /* Conflicting write, no ACK by now*/
+ if (test_bit(UNIQUE,&mdev->flags)) {
+ spin_lock_irq(&mdev->ee_lock);
+ drbd_put_ee(mdev,e);
+ spin_unlock_irq(&mdev->ee_lock);
+ WARN("Concurrent write! [DISCARD BY FLAG] sec=%lu\n",
+ (unsigned long)sector);
+ return TRUE;
+ } else {
+ /* write afterwards do not exp ACK */
+ WARN("Concurrent write! [W AFTERWARDS] sec=%lu\n",
+ (unsigned long)sector);
+ drbd_send_discard(mdev,req);
+ drbd_end_req(req, RQ_DRBD_SENT, 1, sector);
+ if( wait_event_interruptible(mdev->cstate_wait,
+ !req_have_write(mdev,e))) {
+ spin_lock_irq(&mdev->ee_lock);
+ drbd_put_ee(mdev,e);
+ spin_unlock_irq(&mdev->ee_lock);
+ return FALSE;
+ }
+ }
}
}
- /* case 0: no conflicting write. */
- /* write it to disk now... */
}
e->block_id = p->block_id; // no meaning on this side, e* on partner
@@ -2265,6 +2275,27 @@
return TRUE;
}
+STATIC int got_Discard(drbd_dev *mdev, Drbd_Header* h)
+{
+ Drbd_Discard_Packet *p = (Drbd_Discard_Packet*)h;
+ struct drbd_discard_note *dn;
+
+ dn = kmalloc(sizeof(struct drbd_discard_note),GFP_KERNEL);
+ if(!dn) {
+ ERR("kmalloc(drbd_discard_note) failed.");
+ return FALSE;
+ }
+
+ dn->block_id = (long)p->block_id;
+ dn->seq_num = be32_to_cpu(p->seq_num);
+
+ spin_lock(&mdev->peer_seq_lock);
+ list_add(&dn->list,&mdev->discard);
+ spin_unlock(&mdev->peer_seq_lock);
+
+ return TRUE;
+}
+
struct asender_cmd {
size_t pkt_size;
int (*process)(drbd_dev *mdev, Drbd_Header* h);
@@ -2290,6 +2321,7 @@
[NegDReply] ={ sizeof(Drbd_BlockAck_Packet), got_NegDReply },
[NegRSDReply]={sizeof(Drbd_BlockAck_Packet), got_NegRSDReply},
[BarrierAck]={ sizeof(Drbd_BarrierAck_Packet),got_BarrierAck },
+ [DiscardNote]={sizeof(Drbd_Discard_Packet), got_Discard },
};
sprintf(current->comm, "drbd%d_asender", (int)(mdev-drbd_conf));
Modified: trunk/drbd/drbd_sizeof_sanity_check.c
===================================================================
--- trunk/drbd/drbd_sizeof_sanity_check.c 2005-02-11 15:59:06 UTC (rev 1757)
+++ trunk/drbd/drbd_sizeof_sanity_check.c 2005-02-12 17:48:17 UTC (rev 1758)
@@ -15,10 +15,10 @@
int sizeof_drbd_structs_sanity_check(void)
{
int err = 0, s = 0;
- SZO(struct disk_config, 24)
+ SZO(struct disk_config, 32)
SZO(struct net_config, 432)
SZO(struct syncer_config, 24)
- SZO(struct ioctl_disk_config, 32)
+ SZO(struct ioctl_disk_config, 40)
SZO(struct ioctl_net_config, 440)
SZO(struct ioctl_syncer_config, 32)
SZO(struct ioctl_wait, 16)
Modified: trunk/drbd/linux/drbd.h
===================================================================
--- trunk/drbd/linux/drbd.h 2005-02-11 15:59:06 UTC (rev 1757)
+++ trunk/drbd/linux/drbd.h 2005-02-12 17:48:17 UTC (rev 1758)
@@ -77,6 +77,7 @@
IN int meta_device;
IN int meta_index;
IN int split_brain_fix;
+ const int _pad;
};
enum disconnect_handler {
More information about the drbd-cvs
mailing list