From: NeilBrown Date: Mon, 12 Jul 2010 02:21:34 +0000 (+1000) Subject: Some updates to rules.doc X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=1398d77fa3f968d92815b8df3fc76cfbd2421d5e;p=LaFS.git Some updates to rules.doc Too asleep to do much more Signed-off-by: NeilBrown --- diff --git a/block.c b/block.c index ac67508..089cb55 100644 --- a/block.c +++ b/block.c @@ -524,7 +524,7 @@ lafs_erase_dblock(struct datablock *b) spin_lock(&b->b.inode->i_data.private_lock); ib = LAFSI(b->b.inode)->iblock; if (ib) - getiref_locked(ib, MKREF("erasedblock")); + getiref_locked(ib, MKREF(erasedblock)); spin_unlock(&b->b.inode->i_data.private_lock); if (ib) { lafs_iolock_written(&ib->b); @@ -535,7 +535,7 @@ lafs_erase_dblock(struct datablock *b) clear_bit(B_PhysValid, &b->b.flags); } lafs_iounlock_block(&ib->b); - putiref(ib, MKREF("erasedblock")); + putiref(ib, MKREF(erasedblock)); } } diff --git a/index.c b/index.c index f7e2194..ffa6100 100644 --- a/index.c +++ b/index.c @@ -570,7 +570,6 @@ void lafs_phase_flip(struct fs *fs, struct indexblock *ib) * phase but unpin. */ if (test_bit(B_Pinned, &ib->b.flags) && - !test_bit(B_PinPending, &ib->b.flags) && !test_bit(B_Dirty, &ib->b.flags) && !test_bit(B_Realloc, &ib->b.flags) && atomic_read(&ib->b.refcnt) == 1 && /* This is us */ @@ -829,7 +828,7 @@ void lafs_refile(struct block *b, int dec) /* To (mostly) avoid recursion, we have a loop which may * walk up to the parent. * The main reason for holding lafs_hash_lock is that it protects - * ->lru - i.e. all the lists. + * ->lru - i.e. all the lists. FIXME that should be fs->lock */ LAFS_BUG(atomic_read(&b->refcnt) == 0, b); while (b) { @@ -1981,11 +1980,11 @@ int lafs_add_block_address(struct fs *fs, struct block *blk) /* We own a ref through blk->parent now, but * after lafs_incorporate, we might not */ - getiref(p,MKREF("addblock")); + getiref(p,MKREF(addblock)); lafs_iolock_written(&p->b); lafs_incorporate(fs, p); lafs_iounlock_block(&p->b); - putiref(p,MKREF("addblock")); + putiref(p,MKREF(addblock)); return 0; } } diff --git a/rules.doc b/rules.doc index cc2a1be..acc9159 100644 --- a/rules.doc +++ b/rules.doc @@ -5,10 +5,16 @@ b->refcnt counts the references to a block. These include: - transient references - ->parent references from children - - The flags: Dirty, Pinned, Alloc, Realloc, Uninc - - presence on an ->orphans list (is that B_Orphan?) + - The flags: Async, Uninc + - presence on an ->orphans list + - orphan block which needs to be held on to - The presence of inode->iblock implies a counted reference through inode->dblock + - presence on lists: leaf (phase,clean,account), cleaning, cluster + - ref from sibling with PrimaryRef set + - reference from segment summary record + - if a block has SegRef set, then it owns a reference on a segsum + - every segment in 'table' owns reference on segsum block If you have a reference to a block, you can always get another reference. Without a reference: @@ -46,17 +52,20 @@ blk->siblings inode->dblock Set or cleared under ->private_lock. refcounted when ->iblock set. + So if we hold a ref on iblock - possible indirect - then can access + directly. inode->iblock - Can be set from NULL under ->private_lock, and otherwise can only - be changed under i_mutex. - FIXME what do I need to read this given index tree can shrink and grow?? + Can be set to or from NULL under ->private_lock, otherwise need to be + IOLocked to change it. + If we hold a ref to a child with parent, then we can access iblock with + rcu_dereference Note that this reference isn't counted. It is similar to a reference held by the index hash table. ->lru is used for the global list of free indexblocks, and for - phase_leafs, clean_leafs and a cluster list. - Membership on the last three is a counted reference. + phase_leafs, clean_leafs, account_leaf, cluster list, pending io list + Membership on all but first is a counted reference. So if ->lru is not empty then checking the refcnt can determing if the block is on the freelist (0) or another list (non-zero). @@ -79,6 +88,35 @@ blk->peers If we "know" we hold a reference to all possible entries (as cleaner might) we can safely walk the list, else use private_lock. +Block flags + + B_Index - never changes, distinguished index block from data blocks + B_Root - is root block - there is no parent. + B_InoIdx - flags the inodes index block. Can be changed when ->iblock can + B_Valid - has been loaded or initialised. Never cleared + B_Dirty - For data block, the content has changed and not been written out + For index blocks this is set as soon as an address is ready to be + incorporated. + B_Realloc - as above for cleaning. Should change that to use dirty and have + a flag for 'new data' which isn't set by cleaner. + B_UnincCredit - have a credit to be passed to parent on incorporation + B_Uninc - on an uninc list, so phys addr shouldn't change + B_Pinned - pinned to the phase determined by B_Phase1. + will be considerred for writing in that phase. + must be on leaf list unless has children. or not dirty + B_Async - cleaner thread wants this when it is unlocked or written + B_Segref - own a refernce on the segsum for physaddr + B_Credit B_ICredit B_NCredit B_NICredit + B_IOLock - used for various locking. + + B_PinPending - data block should stay pinned even if not dirty. + Some thread is working on changing it. + Cleaner will just dirty it to clean. writepage will skip + should need iolock to set this. + + For index blocks we don't need this and just use refcnt. + but there are more refs held on data blocks. + I think we mainly need this for writepage and cleaner to ignore ------------------------ Phase filp: