[DRBD-cvs] svn commit by phil - r3055 - in branches/drbd-8.2: drbd user - The first time the "data-integrity-alg" feature is work

drbd-cvs at lists.linbit.com drbd-cvs at lists.linbit.com
Thu Sep 6 17:31:52 CEST 2007


Author: phil
Date: 2007-09-06 17:31:41 +0200 (Thu, 06 Sep 2007)
New Revision: 3055

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_wrappers.h
   branches/drbd-8.2/user/drbdsetup.c
Log:
The first time the "data-integrity-alg" feature is working. 
* The 86 protocol seems to be broken somehow currently.
* More testing and debugging needed.


Modified: branches/drbd-8.2/drbd/drbd_int.h
===================================================================
--- branches/drbd-8.2/drbd/drbd_int.h	2007-09-06 15:25:55 UTC (rev 3054)
+++ branches/drbd-8.2/drbd/drbd_int.h	2007-09-06 15:31:41 UTC (rev 3055)
@@ -877,7 +877,9 @@
 	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;
+	void *int_dig_out;
+	void *int_dig_in;
+	void *int_dig_vv;
 	wait_queue_head_t seq_wait;
 	atomic_t packet_seq;
 	unsigned int peer_seq;
@@ -1336,6 +1338,7 @@
 /* maybe rather drbd_main.c ? */
 extern int drbd_md_sync_page_io(struct drbd_conf *mdev,
 		struct drbd_backing_dev *bdev, sector_t sector, int rw);
+void drbd_csum(struct drbd_conf *, struct crypto_hash *, struct bio *, void *);
 /* worker callbacks */
 extern int w_req_cancel_conflict(struct drbd_conf *, struct drbd_work *, int);
 extern int w_read_retry_remote(struct drbd_conf *, struct drbd_work *, int);

Modified: branches/drbd-8.2/drbd/drbd_main.c
===================================================================
--- branches/drbd-8.2/drbd/drbd_main.c	2007-09-06 15:25:55 UTC (rev 3054)
+++ branches/drbd-8.2/drbd/drbd_main.c	2007-09-06 15:31:41 UTC (rev 3055)
@@ -1762,7 +1762,7 @@
 	ok = (sizeof(p) ==
 		drbd_send(mdev, mdev->data.socket, &p, sizeof(p), MSG_MORE));
 	if (ok && dgs) {
-		dgb = mdev->integrity_digest;
+		dgb = mdev->int_dig_out;
 		drbd_csum(mdev, mdev->integrity_tfm, req->master_bio, dgb);
 		ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, MSG_MORE);
 	}
@@ -1812,7 +1812,7 @@
 	ok = sizeof(p) == drbd_send(mdev, mdev->data.socket, &p,
 					sizeof(p), MSG_MORE);
 	if (ok && dgs) {
-		dgb = mdev->integrity_digest;
+		dgb = mdev->int_dig_out;
 		drbd_csum(mdev, mdev->integrity_tfm, e->private_bio, dgb);
 		ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, MSG_MORE);
 	}
@@ -2371,7 +2371,9 @@
 			kfree(mdev->p_uuid);
 			mdev->p_uuid = NULL;
 
-			kfree(mdev->integrity_digest);
+			kfree(mdev->int_dig_out);
+			kfree(mdev->int_dig_in);
+			kfree(mdev->int_dig_vv);
 		}
 		drbd_destroy_mempools();
 	}

Modified: branches/drbd-8.2/drbd/drbd_nl.c
===================================================================
--- branches/drbd-8.2/drbd/drbd_nl.c	2007-09-06 15:25:55 UTC (rev 3054)
+++ branches/drbd-8.2/drbd/drbd_nl.c	2007-09-06 15:31:41 UTC (rev 3055)
@@ -1218,14 +1218,26 @@
 
 	if (mdev->integrity_tfm) {
 		crypto_free_hash(mdev->integrity_tfm);
-		kfree(mdev->integrity_digest);
+		kfree(mdev->int_dig_out);
+		kfree(mdev->int_dig_in);
+		kfree(mdev->int_dig_vv);
 		if (integrity_tfm) {
 			i = crypto_hash_digestsize(integrity_tfm);
-			mdev->integrity_digest = kmalloc(i, GFP_KERNEL);
-			if (!mdev->integrity_digest) {
+			mdev->int_dig_out = kmalloc(i, GFP_KERNEL);
+			if (!mdev->int_dig_out) {
 				retcode = KMallocFailed;
 				goto fail;
 			}
+			mdev->int_dig_in = kmalloc(i, GFP_KERNEL);
+			if (!mdev->int_dig_in) {
+				retcode = KMallocFailed;
+				goto fail;
+			}
+			mdev->int_dig_vv = kmalloc(i, GFP_KERNEL);
+			if (!mdev->int_dig_vv) {
+				retcode = KMallocFailed;
+				goto fail;
+			}
 		}
 	}
 	mdev->cram_hmac_tfm = integrity_tfm;

Modified: branches/drbd-8.2/drbd/drbd_receiver.c
===================================================================
--- branches/drbd-8.2/drbd/drbd_receiver.c	2007-09-06 15:25:55 UTC (rev 3054)
+++ branches/drbd-8.2/drbd/drbd_receiver.c	2007-09-06 15:31:41 UTC (rev 3055)
@@ -876,8 +876,27 @@
 	struct bio_vec *bvec;
 	struct page *page;
 	struct bio *bio;
-	int ds, i, rr;
+	int dgs, ds, i, rr;
+	void *dig_in = mdev->int_dig_in;
+	void *dig_vv = mdev->int_dig_vv;
 
+	dgs = (mdev->agreed_pro_version >= 87 && mdev->integrity_tfm) ? 
+		crypto_hash_digestsize(mdev->integrity_tfm) : 0;
+
+	if (dgs) {
+		rr = drbd_recv(mdev, dig_in, dgs);
+		if ( rr != dgs ) {
+			WARN("short read receiving data: read %d expected %d\n",
+			     rr, dgs);
+			return NULL;
+		}
+	}
+
+	data_size -= dgs;
+
+	ERR_IF(data_size &  0x1ff) return NULL;
+	ERR_IF(data_size >  DRBD_MAX_SEGMENT_SIZE) return NULL;
+
 	e = drbd_alloc_ee(mdev, id, sector, data_size, GFP_KERNEL);
 	if (!e)
 		return 0;
@@ -896,6 +915,13 @@
 		ds -= rr;
 	}
 
+	if (dgs) {
+		drbd_csum(mdev, mdev->integrity_tfm, bio, dig_vv);
+		if (memcmp(dig_in,dig_vv,dgs)) {
+			ERR("Digest integrity check failed. Broken NICs?\n");
+			return 0;
+		}
+	}
 	mdev->recv_cnt += data_size>>9;
 	return e;
 }
@@ -945,8 +971,24 @@
 {
 	struct bio_vec *bvec;
 	struct bio *bio;
-	int rr, i, expect;
+	int dgs, rr, i, expect;
+	void *dig_in = mdev->int_dig_in;
+	void *dig_vv = mdev->int_dig_vv;
 
+	dgs = (mdev->agreed_pro_version >= 87 && mdev->integrity_tfm) ? 
+		crypto_hash_digestsize(mdev->integrity_tfm) : 0;
+
+	if (dgs) {
+		rr = drbd_recv(mdev, dig_in, dgs);
+		if ( rr != dgs ) {
+			WARN("short read receiving data: read %d expected %d\n",
+			     rr, dgs);
+			return 0;
+		}
+	}
+
+	data_size -= dgs;
+
 	bio = req->master_bio;
 	D_ASSERT( sector == bio->bi_sector );
 
@@ -965,6 +1007,14 @@
 		data_size -= rr;
 	}
 
+	if (dgs) {
+		drbd_csum(mdev, mdev->integrity_tfm, bio, dig_vv);
+		if (memcmp(dig_in,dig_vv,dgs)) {
+			ERR("Digest integrity check failed. Broken NICs?\n");
+			return 0;
+		}
+	}
+
 	D_ASSERT(data_size == 0);
 	/* FIXME recv_cnt accounting ?? */
 	return 1;
@@ -1043,8 +1093,6 @@
 	 * and no more than DRBD_MAX_SEGMENT_SIZE.
 	 * is this too restrictive?  */
 	ERR_IF(data_size == 0) return FALSE;
-	ERR_IF(data_size &  0x1ff) return FALSE;
-	ERR_IF(data_size >  DRBD_MAX_SEGMENT_SIZE) return FALSE;
 
 	if (drbd_recv(mdev, h->payload, header_size) != header_size)
 		return FALSE;
@@ -1255,8 +1303,6 @@
 	data_size   = h->length  - header_size;
 
 	ERR_IF(data_size == 0) return FALSE;
-	ERR_IF(data_size &  0x1ff) return FALSE;
-	ERR_IF(data_size >  DRBD_MAX_SEGMENT_SIZE) return FALSE;
 
 	if (drbd_recv(mdev, h->payload, header_size) != header_size)
 		return FALSE;

Modified: branches/drbd-8.2/drbd/drbd_wrappers.h
===================================================================
--- branches/drbd-8.2/drbd/drbd_wrappers.h	2007-09-06 15:25:55 UTC (rev 3054)
+++ branches/drbd-8.2/drbd/drbd_wrappers.h	2007-09-06 15:31:41 UTC (rev 3055)
@@ -289,11 +289,20 @@
 
 	// "hmac(xxx)" is in alg_name we need that xxx.
 	closing_bracket = strchr(alg_name,')');
-	if(!closing_bracket) return NULL;
-	if(closing_bracket-alg_name < 6) return NULL;
+	if(!closing_bracket) {
+		ch = kmalloc(sizeof(struct crypto_hash),GFP_KERNEL);
+		if(!ch) return ERR_PTR(-ENOMEM);
+		ch->base = crypto_alloc_tfm(alg_name, 0);
+		if (ch->base == NULL) {
+			kfree(ch);
+			return ERR_PTR(-ENOMEM);
+		}
+		return ch;
+	}
+	if(closing_bracket-alg_name < 6) return ERR_PTR(-ENOENT);
 
 	ch = kmalloc(sizeof(struct crypto_hash),GFP_KERNEL);
-	if(!ch) return NULL;
+	if(!ch) return ERR_PTR(-ENOMEM);
 
 	*closing_bracket = 0;
 	ch->base = crypto_alloc_tfm(alg_name + 5, 0);
@@ -301,7 +310,7 @@
 
 	if (ch->base == NULL) {
 		kfree(ch);
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 	}
 
 	return ch;
@@ -344,6 +353,28 @@
         return tfm->base;
 }
 
+static inline int crypto_hash_init(struct hash_desc *desc)
+{
+	crypto_digest_init(desc->tfm->base);
+	return 0;
+}
+
+static inline int crypto_hash_update(struct hash_desc *desc,
+                                     struct scatterlist *sg,
+                                     unsigned int nbytes)
+{
+        crypto_digest_update(desc->tfm->base,sg,1 /* ! */ );
+	/* ! this is not generic. Would need to convert nbytes -> nsg */
+
+	return 0;
+}
+
+static inline int crypto_hash_final(struct hash_desc *desc, u8 *out)
+{
+	crypto_digest_final(desc->tfm->base, out);
+	return 0;
+}
+
 #endif
 
 #ifdef NEED_BACKPORT_OF_KZALLOC

Modified: branches/drbd-8.2/user/drbdsetup.c
===================================================================
--- branches/drbd-8.2/user/drbdsetup.c	2007-09-06 15:25:55 UTC (rev 3054)
+++ branches/drbd-8.2/user/drbdsetup.c	2007-09-06 15:31:41 UTC (rev 3055)
@@ -309,7 +309,7 @@
 		 { "rr-conflict",'R',	T_rr_conflict,EH(rrcf_n,RR_CONFLICT) },
 		 { "ping-timeout",'p',  T_ping_timeo,	   EN(PING_TIMEO,1,"1/10 seconds") },
 		 { "discard-my-data",'D', T_want_lose,     EB },
-		 { "data-integrity-alg",'d', T_want_lose,     EB },
+		 { "data-integrity-alg",'d', T_integrity_alg,     ES },
 		 CLOSE_OPTIONS }} }, },
 
 	{"disconnect", P_disconnect, F_CONFIG_CMD, {{NULL, NULL}} },



More information about the drbd-cvs mailing list