[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)
{