[DRBD-cvs] DRBD CVS: drbd by phil from

drbd-cvs@linbit.com drbd-cvs@linbit.com
Mon, 12 Jan 2004 10:31:36 +0100 (CET)


DRBD CVS committal

Author  : phil
Host    : 
Module  : drbd

Dir     : drbd/drbd


Modified Files:
      Tag: rel-0_7-branch
	drbd_actlog.c drbd_fs.c drbd_int.h drbd_main.c lru_cache.c 
	lru_cache.h 


Log Message:
[Patch by Lars] 
Removes the callback of the LRU cache. Makes it a bit easier to read
and understand the code. 

===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/Attic/drbd_actlog.c,v
retrieving revision 1.1.2.43
retrieving revision 1.1.2.44
diff -u -3 -r1.1.2.43 -r1.1.2.44
--- drbd_actlog.c	10 Jan 2004 19:24:00 -0000	1.1.2.43
+++ drbd_actlog.c	12 Jan 2004 09:31:36 -0000	1.1.2.44
@@ -48,37 +48,6 @@
 STATIC void drbd_al_write_transaction(struct Drbd_Conf *,struct lc_element *);
 STATIC void drbd_update_on_disk_bm(struct Drbd_Conf *,unsigned int ,int);
 
-
-int drbd_al_changing(struct lru_cache* lc, struct lc_element *e,
-		     unsigned int enr)
-{
-	// This callback is called by lc_get().
-	// WRITE transaction....
-	// async:  do lc->flags &= ~LC_DIRTY and  wake_up(&mdev->al_wait);
-	// in end of IO hander. Return 0 here.
-	// sync: do everything here and return 1.
-
-	struct Drbd_Conf *mdev = (struct Drbd_Conf *) lc->lc_private;
-	unsigned long evicted;
-
-	evicted = e->lc_number;
-	e->lc_number = enr;
-	spin_unlock_irq(&mdev->al_lock);
-
-	if(mdev->cstate < Connected && evicted != LC_FREE ) {
-		drbd_update_on_disk_bm(mdev,evicted,1);
-	}
-	drbd_al_write_transaction(mdev,e);
-	mdev->al_writ_cnt++;
-
-	spin_lock_irq(&mdev->al_lock);
-	clear_bit(__LC_DIRTY,&lc->flags);
-	smp_mb__after_clear_bit();
-	wake_up(&mdev->al_wait);
-
-	return 1;
-}
-
 #define SM (BM_EXTENT_SIZE / AL_EXTENT_SIZE)
 
 static inline
@@ -97,15 +66,15 @@
 			return 0;
 		}
 	}
-	al_ext = lc_get(mdev->act_log,enr);
-	if (!al_ext) al_flags=mdev->act_log->flags;
+	al_ext   = lc_get(mdev->act_log,enr);
+	al_flags = mdev->act_log->flags;
 	spin_unlock_irq(&mdev->al_lock);
 
-	if(al_flags & LC_STARVING) {
-		WARN("Have to wait for LRU element (AL too small?)\n");
-	}
-	if(al_flags & LC_DIRTY) {
-		WARN("Ongoing AL update (AL device too slow?)\n");
+	if (!al_ext) {
+		if (al_flags & LC_STARVING)
+			WARN("Have to wait for LRU element (AL too small?)\n");
+		if (al_flags & LC_DIRTY)
+			WARN("Ongoing AL update (AL device too slow?)\n");
 	}
 
 	return al_ext;
@@ -114,9 +83,28 @@
 void drbd_al_begin_io(struct Drbd_Conf *mdev, sector_t sector)
 {
 	unsigned int enr = (sector >> (AL_EXTENT_SIZE_B-9));
-	struct lc_element *extent;
+	struct lc_element *al_ext;
+
+	wait_event(mdev->al_wait, (al_ext = _al_get(mdev,enr)) );
+
+	if (al_ext->lc_number != enr) {
+		// We have to do write an transaction to AL.
+		unsigned long evicted;
 
-	wait_event(mdev->al_wait, (extent = _al_get(mdev,enr)) );
+		evicted = al_ext->lc_number;
+		al_ext->lc_number = enr;
+
+		if(mdev->cstate < Connected && evicted != LC_FREE ) {
+			drbd_update_on_disk_bm(mdev,evicted,1);
+		}
+		drbd_al_write_transaction(mdev,al_ext);
+		mdev->al_writ_cnt++;
+
+		spin_lock_irq(&mdev->al_lock);
+		lc_changed(mdev->act_log,al_ext);
+		spin_unlock_irq(&mdev->al_lock);
+		wake_up(&mdev->al_wait);
+	}
 }
 
 void drbd_al_complete_io(struct Drbd_Conf *mdev, sector_t sector)
@@ -520,13 +508,13 @@
 
 	spin_lock_irqsave(&mdev->al_lock,flags);
 	ext = (struct bm_extent *) lc_get(mdev->resync,enr);
-	if(ext) {
+	if (ext) {
 		if( ext->lce.lc_number == enr) {
 			ext->rs_left -= cleared;
 			D_ASSERT((long)ext->rs_left >= 0);
 		} else {
 			WARN("Recounting sectors (resync LRU too small?)\n");
-			ext->lce.lc_number = enr;
+			lc_changed(mdev->resync,(struct lc_element*)ext);
 			ext->rs_left = bm_count_sectors(mdev->mbds_id,enr);
 		}
 		lc_put(mdev->resync,(struct lc_element*)ext);
@@ -595,24 +583,25 @@
 struct bm_extent* _bme_get(struct Drbd_Conf *mdev, unsigned int enr)
 {
 	struct bm_extent  *bm_ext;
-	unsigned long     rs_flags=0;
+	unsigned long     rs_flags;
 
 	spin_lock_irq(&mdev->al_lock);
 	bm_ext = (struct bm_extent*) lc_get(mdev->resync,enr);
-	if(bm_ext) {
+	if (bm_ext) {
 		if(bm_ext->lce.lc_number != enr) {
-			bm_ext->lce.lc_number = enr;
+			lc_changed(mdev->resync,(struct lc_element*)bm_ext);
 			bm_ext->rs_left = bm_count_sectors(mdev->mbds_id,enr);
+			wake_up(&mdev->al_wait);
 		}
 		set_bit(BME_NO_WRITES,&bm_ext->flags); // within the lock
 	}
-	if(bm_ext == 0)	rs_flags=mdev->resync->flags;
+	rs_flags=mdev->resync->flags;
 	spin_unlock_irq(&mdev->al_lock);
 
-	if(rs_flags & LC_STARVING) {
+	if (rs_flags & LC_STARVING) {
 		WARN("Have to wait for element (resync LRU too small?)\n");
 	}
-	if(rs_flags & LC_DIRTY) {
+	if (rs_flags & LC_DIRTY) {
 		BUG(); // WARN("Ongoing RS update (???)\n");
 	}
 
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/drbd_fs.c,v
retrieving revision 1.28.2.42
retrieving revision 1.28.2.43
diff -u -3 -r1.28.2.42 -r1.28.2.43
--- drbd_fs.c	9 Jan 2004 08:48:04 -0000	1.28.2.42
+++ drbd_fs.c	12 Jan 2004 09:31:36 -0000	1.28.2.43
@@ -242,8 +242,7 @@
 	{
 		struct lru_cache *n,*t;
 		n = lc_alloc(mdev->sync_conf.al_extents,
-			     sizeof(struct lc_element),
-			     drbd_al_changing, mdev);
+			     sizeof(struct lc_element), mdev);
 		// FIXME if (n==NULL) scream out loud ...
 		// FIXME if (still_in_use) BUG();
 		spin_lock_irq(&mdev->al_lock);
@@ -572,8 +571,7 @@
 		{
 			struct lru_cache *n,*t;
 			n = lc_alloc(mdev->sync_conf.al_extents,
-				     sizeof(struct lc_element),
-				     drbd_al_changing, NULL);
+				     sizeof(struct lc_element), mdev);
 			// FIXME if (n==NULL) scream out loud ...
 			// FIXME if (still_in_use) BUG();
 			spin_lock_irq(&mdev->al_lock);
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/drbd_int.h,v
retrieving revision 1.58.2.81
retrieving revision 1.58.2.82
diff -u -3 -r1.58.2.81 -r1.58.2.82
--- drbd_int.h	11 Jan 2004 08:56:40 -0000	1.58.2.81
+++ drbd_int.h	12 Jan 2004 09:31:36 -0000	1.58.2.82
@@ -774,8 +774,6 @@
 extern int drbd_proc_get_info(char *, char **, off_t, int, int *, void *);
 
 // drbd_actlog.c
-extern int drbd_al_changing(struct lru_cache* lc, struct lc_element *e,
-			    unsigned int enr);
 extern void drbd_al_begin_io(struct Drbd_Conf *mdev, sector_t sector);
 extern void drbd_al_complete_io(struct Drbd_Conf *mdev, sector_t sector);
 extern void drbd_rs_complete_io(struct Drbd_Conf *mdev, sector_t sector);
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/drbd_main.c,v
retrieving revision 1.73.2.89
retrieving revision 1.73.2.90
diff -u -3 -r1.73.2.89 -r1.73.2.90
--- drbd_main.c	11 Jan 2004 08:56:40 -0000	1.73.2.89
+++ drbd_main.c	12 Jan 2004 09:31:36 -0000	1.73.2.90
@@ -1209,11 +1209,10 @@
 		mdev->mbds_id = bm_init(0);
 		if (!mdev->mbds_id) goto Enomem;
 		// no need to lock access, we are still initializing the module.
-		mdev->resync = lc_alloc(7, sizeof(struct bm_extent),NULL,NULL);
+		mdev->resync = lc_alloc(7, sizeof(struct bm_extent),mdev);
 		if (!mdev->resync) goto Enomem;
 		mdev->act_log = lc_alloc(mdev->sync_conf.al_extents,
-					 sizeof(struct lc_element),
-					 drbd_al_changing, mdev);
+					 sizeof(struct lc_element), mdev);
 		if (!mdev->act_log) goto Enomem;
 
 		drbd_init_set_defaults(mdev);
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/Attic/lru_cache.c,v
retrieving revision 1.1.2.19
retrieving revision 1.1.2.20
diff -u -3 -r1.1.2.19 -r1.1.2.20
--- lru_cache.c	10 Jan 2004 21:39:56 -0000	1.1.2.19
+++ lru_cache.c	12 Jan 2004 09:31:36 -0000	1.1.2.20
@@ -47,7 +47,7 @@
  * returns pointer to a newly initialized lru_cache object with said parameters.
  */
 struct lru_cache* lc_alloc(unsigned int e_count, unsigned int e_size,
-			   lc_notify_on_change_fn fn, void *private_p)
+			   void *private_p)
 {
 	unsigned long bytes;
 	struct lru_cache   *lc;
@@ -65,7 +65,7 @@
 		INIT_LIST_HEAD(&lc->free);
 		lc->element_size     = e_size;
 		lc->nr_elements      = e_count;
-		lc->notify_on_change = fn;
+		lc->new_number	     = -1;
 		lc->lc_private       = private_p;
 		for(i=0;i<e_count;i++) {
 			e = lc_entry(lc,i);
@@ -179,21 +179,34 @@
  * the cache. In either case, the user is notified so he is able to e.g. keep
  * a persistent log of the cache changes, and therefore the objects in use.
  *
+ * Return values:
+ *  NULL    if the requested element number was not in the cache, and no unused
+ *          element could be recycled
+ *  pointer to the element with the REQUESTED element number
+ *          In this case, it can be used right away
+ *
+ *  pointer to an UNUSED element with some different element number.
+ *          In this case, the cache is marked dirty, and the returned element
+ *          pointer is removed from the lru list and hash collision chains.
+ *          The user now should do whatever houskeeping is necessary. Then he
+ *          needs to call lc_element_changed(lc,element_pointer), to finish the
+ *          change.
+ *
+ * NOTE: The user needs to check the lc_number on EACH use, so he recognizes
+ *       any cache set change.
+ *
  * @lc: The lru_cache object
  * @enr: element number
  */
 struct lc_element* lc_get(struct lru_cache* lc, unsigned int enr)
 {
 	struct lc_element *e;
-	int sync;
 
 	BUG_ON(!lc);
 	BUG_ON(!lc->nr_elements);
 
 	PARANOIA_ENTRY();
-	// maybe this should be test_bit, but access needs be serialized
-	// anyways, so this should be ok.
-	if ( lc->flags & (LC_STARVING|LC_LOCKED) ) RETURN(NULL);
+	if ( lc->flags & LC_STARVING ) RETURN(NULL);
 
 	e = lc_find(lc, enr);
 	if (e) {
@@ -203,7 +216,7 @@
 	}
 
 	/* In case there is nothing available and we can not kick out
-	   the LRU element, we have to wait ...
+	 * the LRU element, we have to wait ...
 	 */
 	if(!lc_unused_element_available(lc)) {
 		__set_bit(__LC_STARVING,&lc->flags);
@@ -219,42 +232,29 @@
 	e = lc_get_unused_element(lc);
 	BUG_ON(!e);
 
-	list_add(&e->list,&lc->lru);
+	clear_bit(__LC_STARVING,&lc->flags);
+	BUG_ON(++e->refcnt != 1);
 
-	if(lc->notify_on_change) {
-		PARANOIA_LEAVE();
-		sync = lc->notify_on_change(lc,e,enr);
-		PARANOIA_ENTRY();
-		/* we set the STARVING bit when we try to evict the lru
-		 * element, but it is still in use, to avoid usage patterns
-		 * where we never can evict.
-		 * as soon as we have successfully changed an element,
-		 * we need to clear this flag again.
-		 */
-		clear_bit(__LC_STARVING,&lc->flags);
-		smp_mb__after_clear_bit();
-		BUG_ON( sync && (e->lc_number != enr) );
-	} else {
-		/* ok, user does not want to be notified.
-		 * He sets lc_number we he gets the extent...
-		 */
-		// I'd like to use __clear_bit, but 2.4.23 does not have it.
-		clear_bit(__LC_DIRTY,&lc->flags);
-		clear_bit(__LC_STARVING,&lc->flags);
-		smp_mb__after_clear_bit();
-		sync = 1;
-	}
+	lc->changing_element = e;
+	lc->new_number = enr;
 
-	hlist_add_head( &e->colision, lc->slot + lc_hash_fn(lc, enr) );
+	RETURN(e);
+}
 
-	if (sync) {
-		BUG_ON(++e->refcnt != 1);
-		BUG_ON(lc->flags & LC_DIRTY);
-		RETURN(e);
-	} else {
-		RETURN(NULL);
-	}
+void lc_changed(struct lru_cache* lc, struct lc_element* e)
+{
+	PARANOIA_ENTRY();
+	BUG_ON(e != lc->changing_element);
+	e->lc_number = lc->new_number;
+	list_add(&e->list,&lc->lru);
+	hlist_add_head( &e->colision, lc->slot + lc_hash_fn(lc, lc->new_number) );
+	lc->changing_element = NULL;
+	lc->new_number = -1;
+	clear_bit(__LC_DIRTY,&lc->flags);
+	smp_mb__after_clear_bit();
+	PARANOIA_LEAVE();
 }
+
 
 unsigned int lc_put(struct lru_cache* lc, struct lc_element* e)
 {
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/Attic/lru_cache.h,v
retrieving revision 1.1.2.13
retrieving revision 1.1.2.14
diff -u -3 -r1.1.2.13 -r1.1.2.14
--- lru_cache.h	10 Jan 2004 08:24:10 -0000	1.1.2.13
+++ lru_cache.h	12 Jan 2004 09:31:36 -0000	1.1.2.14
@@ -58,20 +58,19 @@
 	unsigned int lc_number;
 };
 
-struct lru_cache;
-typedef int (*lc_notify_on_change_fn)(struct lru_cache*,struct lc_element*,unsigned int);
-
 struct lru_cache {
 	struct list_head lru;
 	struct list_head free;
 	size_t element_size;
 	unsigned int  nr_elements;
+	unsigned int  new_number;
 	unsigned long flags;
+	struct lc_element *changing_element; // just for paranoia
 
-	lc_notify_on_change_fn notify_on_change;
 	void  *lc_private;
 
 	struct hlist_head slot[0];
+	// hash colision chains here, then element storage.
 };
 
 
@@ -80,15 +79,13 @@
 	__LC_PARANOIA,
 	__LC_DIRTY,
 	__LC_STARVING,
-	__LC_LOCKED
 };
 #define LC_PARANOIA (1<<__LC_PARANOIA)
 #define LC_DIRTY    (1<<__LC_DIRTY)
 #define LC_STARVING (1<<__LC_STARVING)
-#define LC_LOCKED   (1<<__LC_LOCKED)
 
 extern struct lru_cache* lc_alloc(unsigned int e_count, unsigned int e_size,
-				  lc_notify_on_change_fn fn, void *private_p);
+				  void *private_p);
 extern void lc_free(struct lru_cache* lc);
 extern void lc_set (struct lru_cache* lc, unsigned int enr, int index);
 extern void lc_del (struct lru_cache* lc, struct lc_element *element);
@@ -96,10 +93,12 @@
 extern struct lc_element* lc_find(struct lru_cache* lc, unsigned int enr);
 extern struct lc_element* lc_get (struct lru_cache* lc, unsigned int enr);
 extern unsigned int       lc_put (struct lru_cache* lc, struct lc_element* e);
+extern void            lc_changed(struct lru_cache* lc, struct lc_element* e);
 
 
-/* this can be used to "disables" lc_get.
- * lc_put still accesses and changes the elements, though.
+/* This can be used to stop lc_get from changing the set of active elements.
+ * Note that the reference counts and order on the lru list may still change.
+ * returns true if we aquired the lock.
  */
 static inline int lc_try_lock(struct lru_cache* lc)
 {