[DRBD-cvs] svn commit by phil - r3052 - in branches/drbd-8.2/drbd: . linux - More unfinished work on the integrity check sum feature

drbd-cvs at lists.linbit.com drbd-cvs at lists.linbit.com
Wed Sep 5 17:04:02 CEST 2007


Author: phil
Date: 2007-09-05 17:03:58 +0200 (Wed, 05 Sep 2007)
New Revision: 3052

Modified:
   branches/drbd-8.2/drbd/drbd_int.h
   branches/drbd-8.2/drbd/drbd_main.c
   branches/drbd-8.2/drbd/drbd_nl.c
   branches/drbd-8.2/drbd/drbd_receiver.c
   branches/drbd-8.2/drbd/drbd_worker.c
   branches/drbd-8.2/drbd/linux/drbd.h
Log:
More unfinished work on the integrity check sum feature...


Modified: branches/drbd-8.2/drbd/drbd_int.h
===================================================================
--- branches/drbd-8.2/drbd/drbd_int.h	2007-09-05 12:29:47 UTC (rev 3051)
+++ branches/drbd-8.2/drbd/drbd_int.h	2007-09-05 15:03:58 UTC (rev 3052)
@@ -347,7 +347,6 @@
 		[BarrierAck]	   = "BarrierAck",
 		[StateChgRequest]  = "StateChgRequest",
 		[StateChgReply]    = "StateChgReply",
-		[IntegrityAlg]     = "IntegrityAlg"
 	};
 
 	if (Data > cmd || cmd >= MAX_CMD) {
@@ -489,6 +488,7 @@
 	u32 after_sb_2p;
 	u32 want_lose;
 	u32 two_primaries;
+	char integrity_alg[0]; /* Since protocol version 87 and higher. */
 } __attribute((packed));
 
 struct Drbd_GenCnt_Packet {
@@ -876,6 +876,8 @@
 	int al_tr_cycle;
 	int al_tr_pos;   /* position of the next transaction in the journal */
 	struct crypto_hash *cram_hmac_tfm;
+	struct crypto_hash *integrity_tfm;
+	void *integrity_digest;
 	wait_queue_head_t seq_wait;
 	atomic_t packet_seq;
 	unsigned int peer_seq;

Modified: branches/drbd-8.2/drbd/drbd_main.c
===================================================================
--- branches/drbd-8.2/drbd/drbd_main.c	2007-09-05 12:29:47 UTC (rev 3051)
+++ branches/drbd-8.2/drbd/drbd_main.c	2007-09-05 15:03:58 UTC (rev 3052)
@@ -1312,25 +1312,30 @@
 
 int drbd_send_protocol(struct drbd_conf *mdev)
 {
-	int rv;
-	struct Drbd_Protocol_Packet p;
+	struct Drbd_Protocol_Packet *p;
+	int size,rv;
 
-	p.protocol      = cpu_to_be32(mdev->net_conf->wire_protocol);
-	p.after_sb_0p   = cpu_to_be32(mdev->net_conf->after_sb_0p);
-	p.after_sb_1p   = cpu_to_be32(mdev->net_conf->after_sb_1p);
-	p.after_sb_2p   = cpu_to_be32(mdev->net_conf->after_sb_2p);
-	p.want_lose     = cpu_to_be32(mdev->net_conf->want_lose);
-	p.two_primaries = cpu_to_be32(mdev->net_conf->two_primaries);
+	size = sizeof(struct Drbd_Protocol_Packet);
 
-	if (mdev->agreed_pro_version >= 87) {
-		rv = drbd_send_cmd2(mdev, USE_DATA_SOCKET, ReportProtocol,
-				    (struct Drbd_Header *)&p, sizeof(p),
-				    mdev->net_conf->integrity_alg,
-				    strlen(mdev->net_conf->integrity_alg));
-	} else { 
-		rv = drbd_send_cmd(mdev, USE_DATA_SOCKET, ReportProtocol,
-				   (struct Drbd_Header *)&p, sizeof(p));
-	}
+	if (mdev->agreed_pro_version >= 87)
+		size += strlen(mdev->net_conf->integrity_alg) + 1;
+
+	if ((p = kmalloc(size, GFP_KERNEL)) == NULL)
+		return 0;
+
+	p->protocol      = cpu_to_be32(mdev->net_conf->wire_protocol);
+	p->after_sb_0p   = cpu_to_be32(mdev->net_conf->after_sb_0p);
+	p->after_sb_1p   = cpu_to_be32(mdev->net_conf->after_sb_1p);
+	p->after_sb_2p   = cpu_to_be32(mdev->net_conf->after_sb_2p);
+	p->want_lose     = cpu_to_be32(mdev->net_conf->want_lose);
+	p->two_primaries = cpu_to_be32(mdev->net_conf->two_primaries);
+
+	if (mdev->agreed_pro_version >= 87)
+		strcpy(p->integrity_alg,mdev->net_conf->integrity_alg);
+
+	rv = drbd_send_cmd(mdev, USE_DATA_SOCKET, ReportProtocol,
+			   (struct Drbd_Header *)p, size);
+	kfree(p);
 	return rv;
 }
 
@@ -1724,14 +1729,19 @@
 	int ok = 1;
 	struct Drbd_Data_Packet p;
 	unsigned int dp_flags = 0;
+	void *dgb;
+	int dgs;
 
 	if (!drbd_get_data_sock(mdev))
 		return 0;
 
+	dgs = (mdev->agreed_pro_version >= 87 && mdev->integrity_tfm) ? 
+		crypto_hash_digestsize(mdev->integrity_tfm) : 0;
+
 	p.head.magic   = BE_DRBD_MAGIC;
 	p.head.command = cpu_to_be16(Data);
-	p.head.length  = cpu_to_be16(sizeof(p)
-			-sizeof(struct Drbd_Header)+req->size);
+	p.head.length  = cpu_to_be16( sizeof(p)
+			-sizeof(struct Drbd_Header)+dgs+req->size);
 
 	p.sector   = cpu_to_be64(req->sector);
 	p.block_id = (unsigned long)req;
@@ -1751,6 +1761,11 @@
 	set_bit(UNPLUG_REMOTE, &mdev->flags);
 	ok = (sizeof(p) ==
 		drbd_send(mdev, mdev->data.socket, &p, sizeof(p), MSG_MORE));
+	if (ok && dgs) {
+		dgb = mdev->integrity_digest;
+		drbd_csum(mdev, mdev->integrity_tfm, req->master_bio, dgb);
+		ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, MSG_MORE);
+	}
 	if (ok) {
 		if (mdev->net_conf->wire_protocol == DRBD_PROT_A)
 			ok = _drbd_send_bio(mdev, req->master_bio);
@@ -1771,11 +1786,16 @@
 {
 	int ok;
 	struct Drbd_Data_Packet p;
+	void *dgb;
+	int dgs;
 
+	dgs = (mdev->agreed_pro_version >= 87 && mdev->integrity_tfm) ? 
+		crypto_hash_digestsize(mdev->integrity_tfm) : 0;
+
 	p.head.magic   = BE_DRBD_MAGIC;
 	p.head.command = cpu_to_be16(cmd);
 	p.head.length  = cpu_to_be16( sizeof(p)
-			-sizeof(struct Drbd_Header) + e->size);
+			-sizeof(struct Drbd_Header) + dgs + e->size);
 
 	p.sector   = cpu_to_be64(e->sector);
 	p.block_id = e->block_id;
@@ -1791,6 +1811,11 @@
 	dump_packet(mdev, mdev->data.socket, 0, (void *)&p, __FILE__, __LINE__);
 	ok = sizeof(p) == drbd_send(mdev, mdev->data.socket, &p,
 					sizeof(p), MSG_MORE);
+	if (ok && dgs) {
+		dgb = mdev->integrity_digest;
+		drbd_csum(mdev, mdev->integrity_tfm, e->private_bio, dgb);
+		ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, MSG_MORE);
+	}
 	if (ok)
 		ok = _drbd_send_zc_bio(mdev, e->private_bio);
 
@@ -2345,6 +2370,8 @@
 
 			kfree(mdev->p_uuid);
 			mdev->p_uuid = NULL;
+
+			kfree(mdev->integrity_digest);
 		}
 		drbd_destroy_mempools();
 	}
@@ -2502,8 +2529,8 @@
 #endif
 
 	printk(KERN_INFO "drbd: initialised. "
-	       "Version: " REL_VERSION " (api:%d/proto:%d)\n",
-	       API_VERSION, PRO_VERSION);
+	       "Version: " REL_VERSION " (api:%d/proto:%d-%d)\n",
+	       API_VERSION, PRO_VERSION_MIN, PRO_VERSION_MAX);
 	printk(KERN_INFO "drbd: %s\n", drbd_buildtag());
 	printk(KERN_INFO "drbd: registered as block device major %d\n",
 		DRBD_MAJOR);

Modified: branches/drbd-8.2/drbd/drbd_nl.c
===================================================================
--- branches/drbd-8.2/drbd/drbd_nl.c	2007-09-05 12:29:47 UTC (rev 3051)
+++ branches/drbd-8.2/drbd/drbd_nl.c	2007-09-05 15:03:58 UTC (rev 3052)
@@ -1036,6 +1036,7 @@
 	enum ret_codes retcode;
 	struct net_conf *new_conf = NULL;
 	struct crypto_hash *tfm = NULL;
+	struct crypto_hash *integrity_tfm = NULL;
 	struct hlist_head *new_tl_hash = NULL;
 	struct hlist_head *new_ee_hash = NULL;
 	struct drbd_conf *odev;
@@ -1136,7 +1137,19 @@
 		}
 	}
 
+	if (new_conf->integrity_alg[0]) {
+		integrity_tfm = crypto_alloc_hash(new_conf->integrity_alg, 0, CRYPTO_ALG_ASYNC);
+		if (IS_ERR(integrity_tfm)) {
+			retcode=IntegrityAlgNotAvail;
+			goto fail;
+		}
 
+		if (crypto_tfm_alg_type(crypto_hash_tfm(integrity_tfm)) != CRYPTO_ALG_TYPE_DIGEST) {
+			retcode=IntegrityAlgNotDigest;
+			goto fail;				
+		}
+	}
+
 	ns = new_conf->max_epoch_size/8;
 	if (mdev->tl_hash_s != ns) {
 		new_tl_hash = kzalloc(ns*sizeof(void *), GFP_KERNEL);
@@ -1203,6 +1216,20 @@
 		crypto_free_hash(mdev->cram_hmac_tfm);
 	mdev->cram_hmac_tfm = tfm;
 
+	if (mdev->integrity_tfm) {
+		crypto_free_hash(mdev->integrity_tfm);
+		kfree(mdev->integrity_digest);
+		if (integrity_tfm) {
+			i = crypto_hash_digestsize(integrity_tfm);
+			mdev->integrity_digest = kmalloc(i, GFP_KERNEL);
+			if (!mdev->integrity_digest) {
+				retcode = KMallocFailed;
+				goto fail;
+			}
+		}
+	}
+	mdev->cram_hmac_tfm = integrity_tfm;
+
 	retcode = drbd_request_state(mdev, NS(conn, Unconnected));
 
 	reply->ret_code = retcode;
@@ -1210,6 +1237,7 @@
 
 fail:
 	crypto_free_hash(tfm);
+	crypto_free_hash(integrity_tfm);
 	kfree(new_tl_hash);
 	kfree(new_ee_hash);
 	kfree(new_conf);

Modified: branches/drbd-8.2/drbd/drbd_receiver.c
===================================================================
--- branches/drbd-8.2/drbd/drbd_receiver.c	2007-09-05 12:29:47 UTC (rev 3051)
+++ branches/drbd-8.2/drbd/drbd_receiver.c	2007-09-05 15:03:58 UTC (rev 3052)
@@ -49,13 +49,6 @@
 #include "drbd_int.h"
 #include "drbd_req.h"
 
-#if defined(__arch_um__) && !defined(HAVE_UML_TO_VIRT)
-static inline void *to_virt(unsigned long phys)
-{
-	return((void *) uml_physmem + phys);
-}
-#endif
-
 #ifdef DBG_ASSERTS
 void drbd_assert_breakpoint(struct drbd_conf *mdev, char *exp,
 			    char *file, int line)
@@ -2101,14 +2094,15 @@
 	}
 
 	if (mdev->agreed_pro_version >= 87) {
-		if (drbd_recv(mdev, integrity_alg, data_size) != data_size)
+		if (drbd_recv(mdev, p_integrity_alg, data_size) != data_size)
 			return FALSE;
 
-		integrity_alg[SHARED_SECRET_MAX-1]=0;
-		if(strcmp(integrity_alg, mdev->net_conf->integrity_alg)) {
+		p_integrity_alg[SHARED_SECRET_MAX-1]=0;
+		if(strcmp(p_integrity_alg, mdev->net_conf->integrity_alg)) {
 			ERR("incompatible setting of the data-integrity-alg\n");
 			goto disconnect;
 		}
+		WARN("data-integrity-alg: %s\n",mdev->net_conf->integrity_alg);
 	}
 
 	return TRUE;
@@ -2840,7 +2834,7 @@
 	if (PRO_VERSION_MAX < p->protocol_min ) goto incompat;
 	if (PRO_VERSION_MIN > p->protocol_max ) goto incompat;
 
-	mdev->agreed_pro_version = min(PRO_VERSION_MAX,p->protocol_max);
+	mdev->agreed_pro_version = min_t(int,PRO_VERSION_MAX,p->protocol_max);
 
 	INFO("Handshake successful: "
 	     "Agreed network protocol version %d\n", mdev->agreed_pro_version);

Modified: branches/drbd-8.2/drbd/drbd_worker.c
===================================================================
--- branches/drbd-8.2/drbd/drbd_worker.c	2007-09-05 12:29:47 UTC (rev 3051)
+++ branches/drbd-8.2/drbd/drbd_worker.c	2007-09-05 15:03:58 UTC (rev 3052)
@@ -287,6 +287,29 @@
 	return 1; /* Simply ignore this! */
 }
 
+void drbd_csum(struct drbd_conf *mdev, struct crypto_hash *tfm, struct bio *bio, void *digest)
+{
+	struct hash_desc desc;
+	struct scatterlist sg;
+	struct bio_vec *bvec;
+	int i;
+
+	desc.tfm=tfm;
+	desc.flags=0;
+
+	// Improve in generic Kernel ?
+	// sg and bvec have exactly the same purpose 
+
+	crypto_hash_init(&desc);
+	__bio_for_each_segment(bvec, bio, i, 0) {
+		sg.page   = bvec->bv_page;
+		sg.offset = bvec->bv_offset;
+		sg.length = bvec->bv_len;
+		crypto_hash_update(&desc,&sg,sg.length);
+	}
+	crypto_hash_final(&desc,digest);
+}
+
 void resync_timer_fn(unsigned long data)
 {
 	unsigned long flags;

Modified: branches/drbd-8.2/drbd/linux/drbd.h
===================================================================
--- branches/drbd-8.2/drbd/linux/drbd.h	2007-09-05 12:29:47 UTC (rev 3051)
+++ branches/drbd-8.2/drbd/linux/drbd.h	2007-09-05 15:03:58 UTC (rev 3052)
@@ -112,6 +112,8 @@
 	UnknownNetLinkPacket,
 	HaveNoDiskConfig,
 	ProtocolCRequired,
+	IntegrityAlgNotAvail,
+	IntegrityAlgNotDigest,
 
 	/* insert new ones above this line */
 	AfterLastRetCode



More information about the drbd-cvs mailing list