afs/fs/cachefs super.c,1.23,1.24 status.c,1.4,1.5 rootdir.c,1.7,1.8
recycling.c,1.15,1.16 kcachefsd.c,1.8,1.9 journal.c,1.28,1.29
index.c,1.12,1.13 dump-journal.c,1.7,1.8 cachefs-layout.h,1.19,1.20
cachefs-int.h,1.24,1.25 aops.c,1.23,1.24 Makefile,1.13,1.14
dwh at infradead.org
dwh at infradead.org
Wed Apr 2 11:12:34 BST 2003
Update of /home/cvs/afs/fs/cachefs
In directory phoenix.infradead.org:/tmp/cvs-serv29593/fs/cachefs
Modified Files:
super.c status.c rootdir.c recycling.c kcachefsd.c journal.c
index.c dump-journal.c cachefs-layout.h cachefs-int.h aops.c
Makefile
Log Message:
can now recycle index trees
Index: super.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/super.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- super.c 29 Mar 2003 11:13:47 -0000 1.23
+++ super.c 2 Apr 2003 09:12:31 -0000 1.24
@@ -244,6 +244,14 @@
memset(super,0,sizeof(*super));
+ super->rcm_imm_buf = (unsigned*) get_zeroed_page(GFP_KERNEL);
+ if (!super->rcm_imm_buf)
+ goto error;
+
+ super->rcm_atm_list = (struct cachefs_reclaimable *) get_zeroed_page(GFP_KERNEL);
+ if (!super->rcm_atm_list)
+ goto error;
+
/* fill in the superblock */
sb->s_magic = CACHEFS_FS_MAGIC;
sb->s_op = &cachefs_super_ops;
@@ -256,6 +264,8 @@
rwlock_init(&super->blk_tree_lock);
+ spin_lock_init(&super->rcm_lock);
+
init_MUTEX(&super->ujnl_alloc_sem);
init_waitqueue_head(&super->ujnl_alloc_wq);
init_waitqueue_head(&super->ujnl_sync_wq);
@@ -282,7 +292,6 @@
init_MUTEX(&super->alloc_sem);
init_waitqueue_head(&super->alloc_wq);
- INIT_LIST_HEAD(&super->recycleq);
init_completion(&super->dmn_alive);
init_completion(&super->dmn_dead);
@@ -392,17 +401,21 @@
return 0;
error:
- if (super->dmn_task) {
- super->dmn_die = 1;
- wake_up(&super->dmn_sleepq);
- wait_for_completion(&super->dmn_dead);
- }
+ if (super) {
+ if (super->dmn_task) {
+ super->dmn_die = 1;
+ wake_up(&super->dmn_sleepq);
+ wait_for_completion(&super->dmn_dead);
+ }
- if (super->fsdef_index) kfree(super->fsdef_index);
- if (super->alloc_node) page_cache_release(super->alloc_node);
- if (super->recycle_node) page_cache_release(super->recycle_node);
+ if (super->fsdef_index) kfree(super->fsdef_index);
+ if (super->alloc_node) page_cache_release(super->alloc_node);
+ if (super->recycle_node) page_cache_release(super->recycle_node);
+ if (super->rcm_atm_list) free_page((unsigned long)super->rcm_atm_list);
+ if (super->rcm_imm_buf) free_page((unsigned long)super->rcm_imm_buf);
- kcachefs_jnld_remove_super(super);
+ kcachefs_jnld_remove_super(super);
+ }
if (page) {
wait_on_page_locked(page);
@@ -413,8 +426,8 @@
if (inode) iput(&inode->vfs_inode);
if (super) {
- if (super->istorage) cachefs_iput(super->istorage);
- if (super->imisc) iput(super->imisc);
+ if (super->istorage) cachefs_iput(super->istorage);
+ if (super->imisc) iput(super->imisc);
dbgfree(super);
kfree(super);
}
@@ -710,6 +723,9 @@
if (super->recycle_block)
cachefs_block_put(super,super->recycle_block);
+
+ if (super->rcm_atm_list) free_page((unsigned long)super->rcm_atm_list);
+ if (super->rcm_imm_buf) free_page((unsigned long)super->rcm_imm_buf);
kcachefs_jnld_remove_super(super);
Index: status.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/status.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- status.c 21 Mar 2003 14:01:00 -0000 1.4
+++ status.c 2 Apr 2003 09:12:31 -0000 1.5
@@ -129,7 +129,9 @@
seq_printf(m,"Recyc Stk : TOS={%u} #%u NUM=%u\n",
super->recycle_cur,super->recycle_room,super->recycle_cur_n);
- seq_printf(m,"Recycler : {%u} %u-%u\n",super->rcyblock,super->rcynext,super->rcystop);
+ seq_printf(m,"Reclaimer : ino=%u indir=%u blk=%u:%hu-%hu\n",
+ super->rcm_ino,super->rcm_indirect,super->rcm_block,
+ super->rcm_ptrnext,super->rcm_ptrstop);
seq_printf(m,"uj disc : NEXT=%u ACK=%u\n",super->ujnl_head,super->ujnl_tail);
Index: rootdir.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/rootdir.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- rootdir.c 29 Mar 2003 11:13:47 -0000 1.7
+++ rootdir.c 2 Apr 2003 09:12:31 -0000 1.8
@@ -18,6 +18,7 @@
#include <linux/file.h>
#include <linux/pagemap.h>
#include <linux/ctype.h>
+#include <linux/circ_buf.h>
#include <asm/uaccess.h>
#include "cachefs-int.h"
@@ -604,6 +605,9 @@
struct cachefs_ondisc_storage *storage;
struct cachefs_transaction *trans;
struct cachefs_inode *inode;
+ struct cachefs_super *super = dir->i_sb->s_fs_info;
+ unsigned long flags;
+ int ret;
kenter("{%lx},{%s,%p}",dir->i_ino,dentry->d_name.name,dentry->d_inode);
@@ -616,17 +620,23 @@
inode = CACHEFS_FS_I(dentry->d_inode);
/* mark for reclamation under journalling */
- trans = cachefs_trans_alloc(dir->i_sb->s_fs_info,GFP_KERNEL);
+ trans = cachefs_trans_alloc(super,GFP_KERNEL);
if (!trans) {
kleave(" = -ENOMEM");
return -ENOMEM;
}
- trans->jentry->mark = CACHEFS_ONDISC_UJNL_INODE_RECLAIMING;
+ trans->jentry->mark = CACHEFS_ONDISC_UJNL_INODE_MARK_RECLAIM;
trans->jentry->ino = inode->vfs_inode.i_ino;
cachefs_trans_affects_inode(trans,inode);
- cachefs_trans_mark(trans);
+
+ ret = cachefs_trans_mark(trans);
+ if (ret<0) {
+ cachefs_trans_put(trans);
+ kleave(" = %d",ret);
+ return ret;
+ }
/* modify the inode storage entry */
storage = kmap(inode->storage) + inode->storage_offset;
@@ -634,6 +644,22 @@
kunmap(inode->storage);
cachefs_trans_commit(trans);
+
+ /* add to the immediate-reclaim table if possible */
+ spin_lock_irqsave(&super->rcm_lock,flags);
+
+ if (CIRC_SPACE(super->rcm_imm_head,super->rcm_imm_tail,CACHEFS_RCM_IMM_BUFSIZE)>0) {
+ super->rcm_imm_buf[super->rcm_imm_head] = inode->vfs_inode.i_ino;
+ super->rcm_imm_head = (super->rcm_imm_head+1) & (CACHEFS_RCM_IMM_BUFSIZE-1);
+ }
+ else {
+ set_bit(CACHEFS_SUPER_RCM_IMM_SCAN,&super->flags);
+ }
+
+ spin_unlock_irqrestore(&super->rcm_lock,flags);
+
+ set_bit(CACHEFS_SUPER_DO_RECLAIM,&super->flags);
+ wake_up(&super->dmn_sleepq);
kleave(" = 0");
return 0;
Index: recycling.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/recycling.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- recycling.c 21 Mar 2003 14:01:00 -0000 1.15
+++ recycling.c 2 Apr 2003 09:12:31 -0000 1.16
@@ -25,28 +25,15 @@
#include <linux/buffer_head.h>
#include "cachefs-int.h"
-static void cachefs_recycle_manage_advance_rcynext(struct cachefs_super *super)
-{
- super->rcynext++;
-}
-
-static void cachefs_recycle_manage_clear_rcyblock(struct cachefs_super *super)
-{
- super->rcyblock = 0;
- super->rcynext = 0;
- super->rcystop = 0;
-}
-
/*****************************************************************************/
/*
* begin a new recycling node
* - a block may be suggested as the target page
*/
-int cachefs_recycle_begin_new_node(struct cachefs_super *super,
- cachefs_blockix_t bix,
- cachefs_blockix_t upblock,
- unsigned short upentry,
- void (*manage)(struct cachefs_super *super))
+static int cachefs_recycle_begin_new_node(struct cachefs_super *super,
+ cachefs_blockix_t bix,
+ cachefs_blockix_t upblock,
+ unsigned short upentry)
{
struct cachefs_ondisc_free_node *node;
struct cachefs_transaction *trans;
@@ -114,8 +101,6 @@
page = xchg(&super->recycle_node,page);
block = xchg(&super->recycle_block,block);
- if (manage) manage(super);
-
if (used_unready_node)
super->layout->bix_unready++;
@@ -157,7 +142,7 @@
* block to set up a new one
*/
if (super->recycle_room==0)
- cachefs_recycle_begin_new_node(super,0,0,0,NULL);
+ cachefs_recycle_begin_new_node(super,0,0,0);
qty = super->layout->bix_end - super->layout->bix_unready;
if (qty==0) {
@@ -222,233 +207,6 @@
/*****************************************************************************/
/*
- * recycle the dependents of the block currently in the recycling bin and then recycle the block
- * itself
- */
-static int cachefs_recycle_pointer_array(struct cachefs_super *super)
-{
- struct cachefs_ondisc_free_node *node;
- struct cachefs_transaction *trans;
- cachefs_blockix_t *indirect, *jeptr;
- struct page *page;
- unsigned limit, count, src, dst, max;
- int ret;
-
- _enter("{room=%u block=%u:%hu-%hu},",
- super->recycle_room,super->rcyblock,super->rcynext,super->rcystop);
-
- max = super->sb->s_blocksize - sizeof(struct cachefs_ondisc_update_journal);
- max /= sizeof(cachefs_blockix_t);
-
- /* load the pointer block page */
- ret = cachefs_block_read(super,NULL,super->rcyblock,0,NULL,&page);
- if (ret<0) {
- _leave(" = %d",ret);
- return ret;
- }
-
- wait_on_page_locked(page);
-
- indirect = (cachefs_blockix_t*) kmap(page);
-
- ret = 0;
- for (;;) {
- /* find an occupied pointer */
- for (src=super->rcynext; src<super->rcystop; src++)
- if (indirect[src])
- goto found;
- break;
- found:
-
- /* make sure there's a recycling block with space available */
- if (super->recycle_room==0) {
- /* recycle the first dependent page as the new recycling node */
- super->rcynext = src;
- cachefs_recycle_begin_new_node(super,indirect[src],super->rcyblock,src,
- cachefs_recycle_manage_advance_rcynext);
- continue;
- }
-
- /* journal what we're going to do */
- trans = cachefs_trans_alloc(super,GFP_KERNEL);
- if (!trans)
- goto out;
-
- cachefs_trans_affects_block(trans,super->recycle_block,0,PAGE_SIZE);
-
- limit = min(super->recycle_room,max);
- dst = CACHEFS_ONDISC_LEAVES_PER_FREE_NODE - super->recycle_room;
-
- trans->jentry->mark = CACHEFS_ONDISC_UJNL_RECYC_SCAVENGE;
- trans->jentry->block = super->rcyblock;
- trans->jentry->entry = src;
- trans->jentry->auxblock = super->recycle_cur;
- trans->jentry->auxentry = dst;
-
- /* transfer the pointers into the journal entry first */
- jeptr = trans->jentry->rcyptrs;
- count = 0;
- while (count<limit && src<super->rcystop) {
- if (indirect[src]) {
- jeptr[count] = indirect[src];
- count++;
- }
-
- src++;
- }
-
- trans->jentry->count = count;
-
- ret = cachefs_trans_mark(trans);
- if (ret<0) {
- printk("kcachefsd: Failed to mark journal: %d\n",ret);
- cachefs_trans_put(trans);
- break;
- }
-
- super->recycle_room -= count;
- super->recycle_cur_n += count;
- if (super->recycle_room==0) super->recycle_cur_n++;
-
- /* transfer from the jentry to the recycling block */
- cachefs_block_modify(super,super->recycle_block,&super->recycle_node);
-
- node = (struct cachefs_ondisc_free_node*) kmap(super->recycle_node);
-
- memcpy(&node->leaves[dst],trans->jentry->rcyptrs,count*sizeof(cachefs_blockix_t));
-
- kunmap(node);
-
- super->rcynext = src;
- cachefs_trans_commit(trans);
- trans = NULL;
- }
-
- kunmap(page);
- dbgpgfree(page);
- page_cache_release(page);
-
- /* finally, the pointer block itself must be recycled */
- if (super->recycle_room==0) {
- /* reuse as new recycling node */
- super->rcyblock = 0;
- cachefs_recycle_begin_new_node(super,indirect[src],super->rcyblock,src,
- cachefs_recycle_manage_clear_rcyblock);
- }
- else {
- /* add to current recycling node */
- unsigned short slot = CACHEFS_ONDISC_LEAVES_PER_FREE_NODE - super->recycle_room;
-
- trans = cachefs_trans_alloc(super,GFP_KERNEL);
- if (!trans)
- goto out;
-
- cachefs_trans_affects_block(trans,super->recycle_block,0,PAGE_SIZE);
-
- trans->jentry->mark = CACHEFS_ONDISC_UJNL_RECYC_PTRBLK;
- trans->jentry->block = super->rcyblock;
- trans->jentry->auxblock = super->recycle_cur;
- trans->jentry->auxentry = slot;
-
- ret = cachefs_trans_mark(trans);
- if (ret<0) {
- printk("kcachefsd: Failed to mark journal: %d\n",ret);
- cachefs_trans_put(trans);
- goto out2;
- }
-
- node = (struct cachefs_ondisc_free_node*) kmap(super->recycle_node);
- node->leaves[slot] = super->rcyblock;
- kunmap(node);
-
- super->recycle_room--;
- super->recycle_cur_n++;
- if (super->recycle_room==0) super->recycle_cur_n++;
-
- super->rcyblock = 0;
- super->rcynext = 0;
- super->rcystop = 0;
- cachefs_trans_commit(trans);
- out2:
- trans = NULL;
- out:
- ;
- }
-
- _leave(" = %d",ret);
- return ret;
-} /* end cachefs_recycle_pointer_array() */
-
-/*****************************************************************************/
-/*
- * recycle an indirection block
- */
-static int cachefs_recycle_indirect_block(struct cachefs_super *super,
- ino_t ino,
- struct page **_parent,
- unsigned poffset,
- cachefs_blockix_t bix,
- unsigned short first,
- unsigned short count)
-{
- struct cachefs_transaction *trans;
- struct cachefs_block *pblock;
- int ret;
-
- _enter(",%lu,{bix=%u},%u,%u,%hu,%hu",
- ino,__cachefs_get_page_block(*_parent)->bix,poffset,
- bix,first,count);
-
- pblock = cachefs_block_get(__cachefs_get_page_block(*_parent));
-
- /* mark the journal to indicate the intended breaking of the pointer */
- ret = -ENOMEM;
- trans = cachefs_trans_alloc(super,GFP_KERNEL);
- if (!trans)
- goto error_rel_block;
-
- cachefs_trans_affects_block(trans,pblock,poffset,sizeof(cachefs_blockix_t));
-
- trans->jentry->ino = ino;
- trans->jentry->mark = CACHEFS_ONDISC_UJNL_INDIRECT_FREEING;
- trans->jentry->block = bix;
- trans->jentry->entry = first;
- trans->jentry->count = count;
- trans->jentry->upblock = pblock->bix;
- trans->jentry->upentry = poffset;
-
- ret = cachefs_trans_mark(trans);
- if (ret<0)
- goto error_rel_trans;
-
- super->rcyblock = bix;
- super->rcynext = first;
- super->rcystop = first + count;
-
- cachefs_block_modify(super,pblock,_parent);
- *(cachefs_blockix_t*) (kmap(*_parent) + poffset) = 0;
- kunmap(*_parent);
-
- cachefs_trans_commit(trans);
- cachefs_block_put(super,pblock);
-
- /* zap the contents */
- ret = cachefs_recycle_pointer_array(super);
-
- _leave(" = %d",ret);
- return ret;
-
- error_rel_trans:
- printk("kcachefsd: Failed to mark journal: %d\n",ret);
- cachefs_trans_put(trans);
- error_rel_block:
- cachefs_block_put(super,pblock);
- _leave(" = %d",ret);
- return ret;
-} /* end cachefs_recycle_indirect_block() */
-
-/*****************************************************************************/
-/*
* transfer the recycling stack to the allocation stack
*/
void cachefs_recycle_transfer_stack(struct cachefs_super *super)
@@ -569,111 +327,486 @@
_leave("");
} /* end cachefs_recycle_transfer_stack() */
-#if 1
/*****************************************************************************/
/*
- *
+ * recycle the dependents of the block currently in the recycling bin and then recycle the block
+ * itself
*/
-static int cachefs_recycle_test_write(struct bio *bio, unsigned int bytes_done, int err)
+static void cachefs_recycle_pointer_array(struct cachefs_super *super)
{
- _enter("{sz=%u rw=%lu},%u,%d",bio->bi_size,bio->bi_rw,bytes_done,err);
+ struct cachefs_ondisc_free_node *node;
+ struct cachefs_transaction *trans;
+ cachefs_blockix_t *indirect, *jeptr;
+ struct page *page;
+ unsigned limit, count, src, dst, max;
+ int ret;
+
+ kenter("{room=%u block=%u:%hu-%hu},",
+ super->recycle_room,super->rcm_block,super->rcm_ptrnext,super->rcm_ptrstop);
+
+ max = super->sb->s_blocksize - sizeof(struct cachefs_ondisc_update_journal);
+ max /= sizeof(cachefs_blockix_t);
- if (bio->bi_size)
- return 1;
+ /* load the pointer block page */
+ ret = cachefs_block_read(super,NULL,super->rcm_block,0,NULL,&page);
+ if (ret<0) {
+ kleave(" [error %d]",ret);
+ return;
+ }
- if (err<0)
- panic("test write failed: %d\n",err);
+ wait_on_page_locked(page);
+
+ indirect = (cachefs_blockix_t*) kmap(page);
- end_page_writeback(bio->bi_io_vec[0].bv_page);
+ /* find an occupied pointer */
+ for (src=super->rcm_ptrnext; src<super->rcm_ptrstop; src++)
+ if (indirect[src])
+ goto found;
- bio_put(bio);
- return 0;
-}
+ super->rcm_ptrnext = src;
+ goto out;
+
+ found:
+ /* make sure there's a recycling block with space available */
+ if (super->recycle_room==0) {
+ /* recycle the first dependent page as the new recycling node */
+ super->rcm_ptrnext = src;
+ ret = cachefs_recycle_begin_new_node(super,indirect[src],super->rcm_block,src);
+ goto out;
+ }
+
+ /* journal what we're going to do */
+ trans = cachefs_trans_alloc(super,GFP_KERNEL);
+ if (!trans)
+ goto out;
+
+ cachefs_trans_affects_block(trans,super->recycle_block,0,PAGE_SIZE);
+
+ limit = min(super->recycle_room,max);
+ dst = CACHEFS_ONDISC_LEAVES_PER_FREE_NODE - super->recycle_room;
+
+ trans->jentry->mark = CACHEFS_ONDISC_UJNL_RECYC_SCAVENGE;
+ trans->jentry->block = super->rcm_block;
+ trans->jentry->entry = src;
+ trans->jentry->auxblock = super->recycle_cur;
+ trans->jentry->auxentry = dst;
+
+ /* transfer the pointers into the journal entry first */
+ jeptr = trans->jentry->rcyptrs;
+ count = 0;
+ while (count<limit && src<super->rcm_ptrstop) {
+ if (indirect[src]) {
+ jeptr[count] = indirect[src];
+ count++;
+ }
+
+ src++;
+ }
+
+ trans->jentry->count = count;
+
+ ret = cachefs_trans_mark(trans);
+ if (ret<0) {
+ printk("kcachefsd: Failed to mark journal: %d\n",ret);
+ cachefs_trans_put(trans);
+ goto out;
+ }
+
+ super->recycle_room -= count;
+ super->recycle_cur_n += count;
+ if (super->recycle_room==0) super->recycle_cur_n++;
+
+ /* transfer from the jentry to the recycling block */
+ cachefs_block_modify(super,super->recycle_block,&super->recycle_node);
+
+ node = (struct cachefs_ondisc_free_node*) kmap(super->recycle_node);
+
+ memcpy(&node->leaves[dst],trans->jentry->rcyptrs,count*sizeof(cachefs_blockix_t));
+
+ kunmap(node);
-void cachefs_recycle_test(struct cachefs_super *super)
+ super->rcm_ptrnext = src;
+
+ cachefs_trans_commit(trans);
+ trans = NULL;
+
+ out:
+ kunmap(page);
+ dbgpgfree(page);
+ page_cache_release(page);
+
+ kleave(" [error %d]",ret);
+} /* end cachefs_recycle_pointer_array() */
+
+/*****************************************************************************/
+/*
+ * reclaim an inode storage entry
+ * - need to change four entities:
+ * - storage record of inode being reclaimed
+ * - storage record of storage inode (we've got a new free inode)
+ * - index entry pointing to inode being reclaimed
+ * - storage record of index (we've got a new free index entry)
+ */
+static int cachefs_recycle_reclaim_inode_storage(struct cachefs_super *super)
{
- struct cachefs_block *iblock, *pblock;
- cachefs_blockix_t block, *indirect;
- struct page *ipage, *ppage;
- struct bio *bio;
- ino_t ino;
- int loop, ret;
-
- printk("\n");
- _debug("________________________________________\n");
- _enter("{%u}",super->layout->bix_unready);
+ struct cachefs_ondisc_index_entry *xent;
+ struct cachefs_ondisc_storage *storage;
+ struct cachefs_transaction *trans = NULL;
+ struct cachefs_inode *iinode = NULL;
+ struct page *ixpage = NULL;
+ unsigned iino, ixentry, offset;
+ int ret;
- ino = 40000;
- block = super->layout->bix_unready++;
+ kenter("{%u}",super->rcm_ino);
- /* prepare a block with a full list of pointers to other blocks */
- ret = cachefs_block_read(super,NULL,block,1,&iblock,&ipage);
- if (ret<0)
- BUG();
+ /* find the parent index entry */
+ storage = kmap(super->rcm_inode->storage) + super->rcm_inode->storage_offset;
+ iino = storage->pindex;
+ ixentry = storage->pindex_entry;
+ kunmap(super->rcm_inode->storage);
+
+ if (iino) {
+ ret = cachefs_iget(super,iino,&iinode);
+ if (ret<0)
+ goto error;
+
+ ret = cachefs_get_page(iinode,ixentry/iinode->index_epp,&ixpage);
+ if (ret<0)
+ goto error;
+
+ offset = (ixentry % iinode->index_epp) * iinode->index_esize;
+ }
+ else {
+ ixentry = 0;
+ offset = 0;
+ }
+
+ /* do the release under journalling */
+ ret = -ENOMEM;
+ trans = cachefs_trans_alloc(super,GFP_KERNEL);
+ if (!trans)
+ goto error;
- indirect = (cachefs_blockix_t *) kmap(ipage);
+ trans->jentry->mark = CACHEFS_ONDISC_UJNL_INODE_DELETING;
+ trans->jentry->index = iino;
+ trans->jentry->ixentry = ixentry;
+ trans->jentry->ino = super->rcm_ino;
+ trans->jentry->size = iinode ? iinode->vfs_inode.i_size : 0;
+ trans->jentry->pgnum = ixpage ? ixpage->index : 0;
+ trans->jentry->block = ixpage ? __cachefs_get_page_block(ixpage)->bix : 0;
+ trans->jentry->entry = offset;
+ trans->jentry->count = iinode ? iinode->index_esize : 0;
+
+ storage = kmap(super->istorage->storage) + super->istorage->storage_offset;
+ trans->jentry->auxblock = storage->freelink;
+ kunmap(super->istorage->storage);
+
+ if (iinode) {
+ storage = kmap(iinode->storage) + iinode->storage_offset;
+ trans->jentry->upblock = storage->freelink;
+ kunmap(iinode->storage);
- for (loop=0; loop<PAGE_SIZE/sizeof(cachefs_blockix_t); loop++)
- indirect[loop] = super->layout->bix_unready++;
+ cachefs_trans_affects_page(trans,ixpage,offset,iinode->index_esize);
+ cachefs_trans_affects_inode(trans,iinode);
+ }
- kunmap(ipage);
- flush_dcache_page(ipage);
- SetPageWriteback(ipage);
-
- bio = bio_alloc(GFP_KERNEL,1);
- if (!bio) BUG();
- bio->bi_sector = __cachefs_get_page_block(ipage)->bix;
- bio->bi_sector <<= (PAGE_SHIFT - super->sb->s_blocksize_bits);
- bio->bi_bdev = super->sb->s_bdev;
- bio->bi_end_io = cachefs_recycle_test_write;
- if (!bio_add_page(bio,ipage,super->sb->s_blocksize,0))
- BUG();
- submit_bio(WRITE,bio);
- wait_on_page_writeback(ipage);
-
- cachefs_block_put(super,iblock);
- page_cache_release(ipage);
- dbgpgfree(ipage);
+ cachefs_trans_affects_inode(trans,super->rcm_inode);
+ cachefs_trans_affects_inode(trans,super->istorage);
- /* create a parent page for the indirection block */
- ret = cachefs_block_read(super,NULL,super->layout->bix_unready++,1,&pblock,&ppage);
+ ret = cachefs_trans_mark(trans);
if (ret<0)
- BUG();
+ goto error;
+
+ if (iinode)
+ cachefs_page_modify(super,&ixpage);
+
+ /* free up the parent index entry */
+ if (iinode) {
+ xent = kmap(ixpage) + offset;
+ xent->state = CACHEFS_ONDISC_INDEX_FREE;
+ xent->ino = 0;
+ xent->freelink[0] = trans->jentry->upblock;
+ memset(xent->data,0,iinode->index_dsize);
+ kunmap(ixpage);
+
+ /* modify the index inode storage entry */
+ storage = kmap(iinode->storage) + iinode->storage_offset;
+ storage->freelink = ixentry;
+ kunmap(iinode->storage);
+ }
+
+ /* clear the inode definition */
+ storage = kmap(super->rcm_inode->storage) + super->rcm_inode->storage_offset;
+ memset(storage,0,sizeof(super->istorage->index_esize));
+
+ storage->header.state = CACHEFS_ONDISC_INDEX_FREE;
+ storage->freelink = trans->jentry->auxblock;
+ storage->mtime = CURRENT_TIME.tv_sec;
+ storage->atime = CURRENT_TIME.tv_sec;
+ kunmap(super->rcm_inode->storage);
+
+ /* modify the storage inode storage entry */
+ storage = kmap(super->istorage->storage) + super->istorage->storage_offset;
+ storage->freelink = super->rcm_ino;
+ kunmap(super->istorage->storage);
+
+ /* do the writing */
+ cachefs_trans_commit(trans);
+ trans = NULL;
+
+ error:
+ if (trans) cachefs_trans_put(trans);
+ if (ixpage) put_page(ixpage);
+ if (iinode) cachefs_iput(iinode);
+
+ kleave(" = %d",ret);
+ return ret;
+} /* end cachefs_recycle_reclaim_inode_storage() */
+
+/*****************************************************************************/
+/*
+ * do next step in reclamation of a file
+ * - need to dispose of:
+ * (1) index entries in file content (if it's an index file)
+ * (2) data blocks and indirection blocks
+ * (3) parent index entry
+ * (4) inode storage entry
+ * - update journal keeps track of recycling point
+ * - rcm_ino, rcm_indirect, rcm_block, rcm_ptrnext & rcm_ptrstop
+ * - work out which block we're actually dealing with from rcm_indirect:
+ * FROM TO WHAT
+ * 0 - not started yet
+ * 1 - reclaiming index entries
+ * 2 - pointers in single indirect block
+ * 3 3+N-1 pointers in dblindirect subblocks 0...N-1
+ * 3+N - pointers in dblindirect block
+ * 3+N+1 - all pointers in inode struct
+ * 3+N+2 - inode itself
+ */
+static void cachefs_recycle_reclaim_inode(struct cachefs_super *super)
+{
+ struct cachefs_ondisc_storage *storage;
+ cachefs_blockix_t bix, *pbix;
+ struct page *page, *dpage;
+ unsigned indirect;
+ unsigned short next, stop;
+ int ret, loop;
+
+ const unsigned N = PAGE_SIZE / sizeof(cachefs_blockix_t);
+
+ kenter("{%u,%u,%u:%hu-%hu}",
+ super->rcm_ino,super->rcm_indirect,super->rcm_block,
+ super->rcm_ptrnext,super->rcm_ptrstop);
+
+ BUG_ON(!super->rcm_ino);
+
+ if (super->rcm_ptrnext==super->rcm_ptrstop && super->rcm_curpage) {
+ put_page(super->rcm_curpage);
+ super->rcm_curpage = NULL;
+ }
+
+ indirect = super->rcm_indirect;
+ bix = 0;
+ next = 0;
+ stop = PAGE_SIZE / sizeof(cachefs_blockix_t);
+
+ ret = 0;
+
+ again:
+ indirect++;
+
+ /* clear out then entries in an index */
+ if (indirect == 1) {
+ if (super->rcm_inode->index_dsize==0)
+ goto again;
+
+ if (cachefs_index_zap(super)<0)
+ goto error2;
+ goto again;
+ }
+
+ /* process the single indirect block */
+ if (indirect == 2) {
+ storage = kmap(super->rcm_inode->storage) + super->rcm_inode->storage_offset;
+ bix = storage->single_indirect;
+ kunmap(super->rcm_inode->storage);
+
+ if (!bix)
+ goto again;
+ goto pointer_array;
+ }
+
+ /* deal with double indirection */
+ if (indirect <= 3+N) {
+ storage = kmap(super->rcm_inode->storage) + super->rcm_inode->storage_offset;
+ bix = storage->double_indirect;
+ kunmap(super->rcm_inode->storage);
+
+ if (!bix) {
+ indirect = 3+N;
+ goto again;
+ }
+
+ ret = cachefs_block_read(super,NULL,bix,0,NULL,&dpage);
+ if (ret<0)
+ goto error;
+
+ /* start processing a double indirect subblock */
+ if (indirect <= 3+N-1) {
+ wait_on_page_locked(dpage);
+
+ bix = 0;
+ pbix = kmap(dpage);
+ for (loop=indirect-2; loop<N; loop++) {
+ bix = pbix[loop];
+ if (bix)
+ break;
+ }
+ kunmap(pbix);
+
+ indirect = loop + 3;
+ if (bix) {
+ put_page(dpage);
+ goto pointer_array;
+ }
+ }
- *(cachefs_blockix_t *) kmap(ppage) = block;
- kunmap(ppage);
- flush_dcache_page(ppage);
- SetPageWriteback(ppage);
-
- bio = bio_alloc(GFP_KERNEL,1);
- if (!bio) BUG();
- bio->bi_sector = __cachefs_get_page_block(ipage)->bix;
- bio->bi_sector <<= (PAGE_SHIFT - super->sb->s_blocksize_bits);
- bio->bi_bdev = super->sb->s_bdev;
- bio->bi_end_io = cachefs_recycle_test_write;
- if (!bio_add_page(bio,ppage,super->sb->s_blocksize,0))
- BUG();
- submit_bio(WRITE,bio);
- wait_on_page_writeback(ppage);
-
- /* now recycle it */
- _debug("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
- ret = cachefs_recycle_indirect_block(super,ino,&ppage,0,block,0,PAGE_SIZE/4);
- _debug("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+ /* start processing the double indirect block */
+ page = dpage;
+ bix = __cachefs_get_page_block(dpage)->bix;
+ goto pointer_array2;
+ }
+
+ /* reclaim all the block pointers in the inode storage record */
+ if (indirect == 3+N+1) {
+ bix = __cachefs_get_page_block(super->rcm_inode->storage)->bix;
+ next = super->rcm_inode->storage_offset;
+ next += offsetof(struct cachefs_ondisc_storage,triple_indirect);
+ next /= sizeof(cachefs_blockix_t);
+
+ stop = super->rcm_inode->storage_offset + super->layout->storage_size;
+ stop /= sizeof(cachefs_blockix_t);
+
+ page = super->rcm_inode->storage;
+ get_page(page);
+ goto pointer_array2;
+ }
+
+ /* reclaim the inode itself */
+ if (cachefs_recycle_reclaim_inode_storage(super)<0) {
+ indirect--;
+ bix = 0;
+ next = 0;
+ stop = 0;
+ page = NULL;
+ goto set;
+ }
+
+ /* finished this inode */
+ cachefs_iput(super->rcm_inode);
+ super->rcm_inode = NULL;
+ super->rcm_ino = 0;
+ super->rcm_indirect = 0;
+ super->rcm_block = 0;
+ super->rcm_ptrnext = 0;
+ super->rcm_ptrstop = 0;
+ kleave("");
+ return;
+
+ pointer_array:
+ ret = cachefs_block_read(super,NULL,bix,0,NULL,&page);
if (ret<0)
- panic("recycle indirect failed: %d\n",ret);
+ goto error;
- cachefs_block_put(super,pblock);
- dbgpgfree(ppage);
- page_cache_release(ppage);
+ pointer_array2:
+ cachefs_recycle_pointer_array(super);
- _debug("________________________________________\n");
- printk("\n");
- _leave("");
-} /* end cachefs_recycle_test() */
-#endif
+ set:
+ super->rcm_indirect = indirect;
+ super->rcm_block = bix;
+ super->rcm_ptrnext = next;
+ super->rcm_ptrstop = stop;
+ super->rcm_curpage = page;
+ kleave("");
+ return;
+
+ error:
+ if (ret==-EIO) {
+ /* just sweep any buggy block under the rug */
+ printk("CacheFS: discarding block %u due to I/O error\n",bix);
+ goto again;
+ }
+ error2:
+ kleave(" [error %d]",ret);
+ goto set;
+} /* end cachefs_recycle_reclaim_inode() */
-void cachefs_recycle_nodes(struct cachefs_super *super)
+/*****************************************************************************/
+/*
+ * do inode reclamation
+ */
+void cachefs_recycle_reclaim(struct cachefs_super *super)
{
- _enter("");
-}
+ struct cachefs_transaction *trans;
+ int ret;
+
+ kenter("{%u,%u,%u:%hu-%hu}",
+ super->rcm_ino,super->rcm_indirect,super->rcm_block,
+ super->rcm_ptrnext,super->rcm_ptrstop);
+
+ /* recycle the next chunk of an inode we're busy reclaiming */
+ if (super->rcm_ino) {
+ kdebug("do reclaim");
+ if (!super->rcm_inode) {
+ ret = cachefs_iget(super,super->rcm_ino,&super->rcm_inode);
+ if (ret<0) {
+ kleave(" [error %d]",ret);
+ return;
+ }
+ }
+
+ cachefs_recycle_reclaim_inode(super);
+
+ goto done;
+ }
+
+ /* see if there's an inode we can start reclaiming */
+ if (super->rcm_imm_head != super->rcm_imm_tail) {
+ kdebug("begin reclaim {%u-%u}",super->rcm_imm_tail,super->rcm_imm_head);
+ trans = cachefs_trans_alloc(super,GFP_KERNEL);
+ if (!trans) {
+ kdebug("[ENOMEM]");
+ goto done;
+ }
+
+ trans->jentry->ino = super->rcm_imm_buf[super->rcm_imm_tail];
+ trans->jentry->mark = CACHEFS_ONDISC_UJNL_INODE_RECLAIMING;
+
+ ret = cachefs_trans_mark(trans);
+ if (ret<0) {
+ kdebug("[error %d]",ret);
+ cachefs_trans_put(trans);
+ goto done;
+ }
+
+ super->rcm_ino = trans->jentry->ino;
+ super->rcm_indirect = 0;
+ super->rcm_block = 0;
+ super->rcm_ptrnext = 0;
+ super->rcm_ptrstop = 0;
+
+ cachefs_trans_commit(trans);
+
+ super->rcm_imm_tail = (super->rcm_imm_tail+1) & (CACHEFS_RCM_IMM_BUFSIZE-1);
+ goto done;
+ }
+
+
+ done:
+ if (super->rcm_ino ||
+ super->rcm_imm_head != super->rcm_imm_tail
+ )
+ set_bit(CACHEFS_SUPER_DO_RECLAIM,&super->flags);
+ kleave("");
+ return;
+} /* end cachefs_recycle_immediate_reclaim() */
Index: kcachefsd.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/kcachefsd.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- kcachefsd.c 21 Mar 2003 14:01:00 -0000 1.8
+++ kcachefsd.c 2 Apr 2003 09:12:31 -0000 1.9
@@ -79,9 +79,9 @@
/* see if there's work to be done */
if (!super->alloc_node ||
- !list_empty(&super->recycleq) ||
super->layout->bix_unready < super->layout->bix_end ||
- test_bit(CACHEFS_SUPER_BATCH_TIMER,&super->flags)
+ test_bit(CACHEFS_SUPER_BATCH_TIMER,&super->flags) ||
+ test_bit(CACHEFS_SUPER_DO_RECLAIM,&super->flags)
)
break;
@@ -101,8 +101,8 @@
_debug("@@@ Begin Cache Management");
/* decant the recycling queue */
- if (!list_empty(&super->recycleq))
- cachefs_recycle_nodes(super);
+ if (test_and_clear_bit(CACHEFS_SUPER_DO_RECLAIM,&super->flags))
+ cachefs_recycle_reclaim(super);
/* transfer blocks from the unready data if possible */
if (super->layout->bix_unready<super->layout->bix_end) {
@@ -115,13 +115,6 @@
yield();
}
}
-
-#if 0
- cachefs_recycle_test(super);
-#endif
-#if 0
- super->layout->bix_unready = super->layout->bix_end;
-#endif
/* if there's no next node, then get one */
if (!super->alloc_node)
Index: journal.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/journal.c,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -r1.28 -r1.29
--- journal.c 29 Mar 2003 11:13:47 -0000 1.28
+++ journal.c 2 Apr 2003 09:12:31 -0000 1.29
@@ -25,12 +25,12 @@
"RcycBegin",
"RcycXfer ",
"RcycScvng",
- "RcycPtrBk",
"RcycMkRdy",
"InoAlloc ",
"InoUpdate",
"InoDelete",
- "InoReclm ",
+ "InoMkRcm ",
+ "InoRcming",
"DataAlloc",
"DataWrite",
"IndrAlloc",
@@ -330,9 +330,11 @@
trans->jentry->alloc_leaf = super->alloc_leaf;
trans->jentry->alloc_cur = super->alloc_cur;
trans->jentry->recycle_cur = super->recycle_cur;
- trans->jentry->rcyblock = super->rcyblock;
- trans->jentry->rcynext = super->rcynext;
- trans->jentry->rcystop = super->rcystop;
+ trans->jentry->rcm_ino = super->rcm_ino;
+ trans->jentry->rcm_indirect = super->rcm_indirect;
+ trans->jentry->rcm_block = super->rcm_block;
+ trans->jentry->rcm_ptrnext = super->rcm_ptrnext;
+ trans->jentry->rcm_ptrstop = super->rcm_ptrstop;
/* transfer the journal entry to the page it's going to be written from */
offset = (trans->index << super->sb->s_blocksize_bits) & ~PAGE_MASK;
@@ -516,9 +518,11 @@
ajentry->alloc_leaf = super->alloc_leaf;
ajentry->alloc_cur = super->alloc_cur;
ajentry->recycle_cur = super->recycle_cur;
- ajentry->rcyblock = super->rcyblock;
- ajentry->rcynext = super->rcynext;
- ajentry->rcystop = super->rcystop;
+ ajentry->rcm_ino = super->rcm_ino;
+ ajentry->rcm_indirect = super->rcm_indirect;
+ ajentry->rcm_block = super->rcm_block;
+ ajentry->rcm_ptrnext = super->rcm_ptrnext;
+ ajentry->rcm_ptrstop = super->rcm_ptrstop;
up_write(&super->batch_ctrl_sem);
Index: index.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/index.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- index.c 29 Mar 2003 11:13:47 -0000 1.12
+++ index.c 2 Apr 2003 09:12:31 -0000 1.13
@@ -25,6 +25,7 @@
#include <linux/completion.h>
#include <linux/slab.h>
#include <linux/bio.h>
+#include <linux/circ_buf.h>
#include "cachefs-int.h"
struct cachefs_index_search_record {
@@ -356,7 +357,13 @@
cachefs_trans_affects_inode(trans,iinode);
cachefs_trans_affects_page(trans,inopage,ino_offset,super->layout->storage_size);
cachefs_trans_affects_inode(trans,super->istorage);
- cachefs_trans_mark(trans);
+
+ ret = cachefs_trans_mark(trans);
+ if (ret<0)
+ goto error;
+
+ cachefs_page_modify(super,&ixpage);
+ cachefs_page_modify(super,&inopage);
/* fill the index entry */
xent = kmap(ixpage) + offset;
@@ -446,4 +453,103 @@
error:
kleave(" = %d",ret);
return ret;
+} /* end cachefs_index_add() */
+
+/*****************************************************************************/
+/*
+ * mark the next inode pinned by an entry in the index currently being reclaimed as being obsolete
+ */
+int cachefs_index_zap(struct cachefs_super *super)
+{
+ struct cachefs_ondisc_index_entry *xent;
+ struct cachefs_ondisc_storage *storage;
+ struct cachefs_transaction *trans = NULL;
+ struct cachefs_inode *inode = NULL;
+ unsigned long flags;
+ struct page *page = NULL;
+ unsigned pgnum, offset, ino;
+ int ret;
+
+ kenter("{%u,%u}",super->rcm_ino,super->rcm_block);
+
+ pgnum = super->rcm_block / super->rcm_inode->index_epp;
+ offset = super->rcm_block % super->rcm_inode->index_epp;
+
+ if (pgnum >= (super->rcm_inode->vfs_inode.i_size >> PAGE_SHIFT)) {
+ kleave(" = 0");
+ return 0; /* done them all */
+ }
+
+ /* get the page holding the next index entry and extract the inode number from it */
+ ret = cachefs_get_page(super->rcm_inode,pgnum,&page);
+ if (ret<0) {
+ if (ret==-EIO) {
+ super->rcm_block = (pgnum+1) * super->rcm_inode->index_epp;
+ }
+ kleave(" = %d",ret);
+ return ret;
+ }
+
+ offset *= super->rcm_inode->index_esize;
+ xent = kmap(page) + offset;
+ ino = xent->ino;
+ kunmap(page);
+
+ /* open the inode */
+ ret = cachefs_iget(super,ino,&inode);
+ if (ret<0)
+ goto error_skip;
+
+ /* journal what we're going to do */
+ trans = cachefs_trans_alloc(super,GFP_KERNEL);
+ if (!trans) {
+ kleave(" = -ENOMEM");
+ return -ENOMEM;
+ }
+
+ trans->jentry->mark = CACHEFS_ONDISC_UJNL_INODE_MARK_RECLAIM;
+ trans->jentry->ino = inode->vfs_inode.i_ino;
+ trans->jentry->index = super->rcm_ino;
+ trans->jentry->ixentry = super->rcm_block;
+
+ cachefs_trans_affects_inode(trans,inode);
+
+ ret = cachefs_trans_mark(trans);
+ if (ret<0)
+ goto error_skip;
+
+ /* modify the inode storage entry */
+ storage = kmap(inode->storage) + inode->storage_offset;
+ storage->header.state = CACHEFS_ONDISC_INDEX_RECYCLE;
+ storage->pindex = 0;
+ storage->pindex_entry = 0;
+ kunmap(inode->storage);
+
+ cachefs_trans_commit(trans);
+ trans = NULL;
+
+ /* add to the immediate-reclaim table if possible */
+ spin_lock_irqsave(&super->rcm_lock,flags);
+
+ if (CIRC_SPACE(super->rcm_imm_head,super->rcm_imm_tail,CACHEFS_RCM_IMM_BUFSIZE)>0) {
+ super->rcm_imm_buf[super->rcm_imm_head] = inode->vfs_inode.i_ino;
+ super->rcm_imm_head = (super->rcm_imm_head+1) & (CACHEFS_RCM_IMM_BUFSIZE-1);
+ }
+ else {
+ set_bit(CACHEFS_SUPER_RCM_IMM_SCAN,&super->flags);
+ }
+
+ spin_unlock_irqrestore(&super->rcm_lock,flags);
+
+ super->rcm_block++;
+ ret = -EAGAIN;
+
+ error_skip:
+ if (inode) cachefs_iput(inode);
+ if (trans) cachefs_trans_put(trans);
+ if (page) put_page(page);
+ if (ret==-EIO) super->rcm_block++;
+ kleave(" = %d",ret);
+ return ret;
+
} /* end cachefs_index_add() */
Index: dump-journal.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/dump-journal.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- dump-journal.c 29 Mar 2003 11:13:47 -0000 1.7
+++ dump-journal.c 2 Apr 2003 09:12:31 -0000 1.8
@@ -48,12 +48,12 @@
BRIGHT "RcycBegin" NORMAL,
BRIGHT "RcycXfer " NORMAL,
BRIGHT "RcycScvng" NORMAL,
- BRIGHT "RcycPtrBk" NORMAL,
BRIGHT "RcycMkRdy" NORMAL,
BRIGHT "InoAlloc " NORMAL,
BRIGHT "InoUpdate" NORMAL,
BRIGHT "InoDelete" NORMAL,
- BRIGHT "InoReclm " NORMAL,
+ BRIGHT "InoMkRcm " NORMAL,
+ BRIGHT "InoRcming" NORMAL,
BRIGHT "DataAlloc" NORMAL,
BRIGHT "DataWrite" NORMAL,
BRIGHT "IndrAlloc" NORMAL,
@@ -184,7 +184,7 @@
jentry->count,
jentry->alloc_cur, jentry->alloc_leaf,
jentry->recycle_cur,
- jentry->rcyblock, jentry->rcynext, jentry->rcystop
+ jentry->rcm_block, jentry->rcm_ptrnext, jentry->rcm_ptrstop
);
}
Index: cachefs-layout.h
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/cachefs-layout.h,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- cachefs-layout.h 29 Mar 2003 11:13:47 -0000 1.19
+++ cachefs-layout.h 2 Apr 2003 09:12:31 -0000 1.20
@@ -122,7 +122,7 @@
u_int64_t version; /* current data version */
u_int64_t size; /* size of file */
- /* file contents */
+ /* file contents - recycling depends on triple_indirect being first */
cachefs_blockix_t triple_indirect; /* triple indirect block index */
cachefs_blockix_t double_indirect; /* double indirect block index */
cachefs_blockix_t single_indirect; /* single indirect block index */
@@ -250,13 +250,6 @@
*/
CACHEFS_ONDISC_UJNL_RECYC_SCAVENGE,
- /* scavenge the picked over corpse of a pointer block (super->rcyblock)
- * - block = block being scavenged
- * - auxblock = recycling node transferred to
- * - auxentry = index into auxblock[] of leaf attached to
- */
- CACHEFS_ONDISC_UJNL_RECYC_PTRBLK,
-
/* transfer bix_unready to recycle_stk
* - block = recycling node that blocks were pasted into
* - auxblock = first unready block transferred
@@ -273,8 +266,15 @@
/* inode being deleted */
CACHEFS_ONDISC_UJNL_INODE_DELETING,
+ /* inode being marked for reclamation
+ * - ino = target inode
+ */
+ CACHEFS_ONDISC_UJNL_INODE_MARK_RECLAIM,
+
/* inode being reclaimed
* - ino = target inode
+ * - index = inode's parent index
+ * - ixentry = inode's parent index entry
*/
CACHEFS_ONDISC_UJNL_INODE_RECLAIMING,
@@ -350,14 +350,16 @@
u_int16_t entry;
u_int16_t auxentry;
u_int16_t upentry;
- u_int16_t rcynext; /* next ptr in rcyblock to be recycled */
- u_int16_t rcystop; /* last ptr in rcyblock + 1 */
+ u_int16_t rcm_ptrnext; /* next ptr in rcm_block to be reclaimed */
+ u_int16_t rcm_ptrstop; /* last ptr in rcm_block + 1 */
u_int16_t count;
u_int16_t alloc_leaf; /* current alloc point in alloc_cur */
+ u_int16_t rcm_indirect; /* indirect block being reclaimed */
+ u_int32_t rcm_ino; /* number of inode being reclaimed */
cachefs_blockix_t block;
cachefs_blockix_t auxblock;
cachefs_blockix_t upblock;
- cachefs_blockix_t rcyblock; /* block currently being recycled */
+ cachefs_blockix_t rcm_block; /* block currently being reclaimed */
cachefs_blockix_t alloc_cur; /* current block allocation node */
cachefs_blockix_t recycle_cur; /* current block recycling node */
Index: cachefs-int.h
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/cachefs-int.h,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -r1.24 -r1.25
--- cachefs-int.h 29 Mar 2003 11:13:47 -0000 1.24
+++ cachefs-int.h 2 Apr 2003 09:12:31 -0000 1.25
@@ -48,6 +48,11 @@
extern int cachefs_get_block(struct inode *inode, struct page *page, int create);
+struct cachefs_reclaimable {
+ unsigned ino;
+ time_t atime;
+};
+
/*****************************************************************************/
/*
* cachefs superblock private information
@@ -62,6 +67,9 @@
unsigned long flags;
#define CACHEFS_SUPER_INIT_BLKDEV 0 /* true if initialising blockdev */
#define CACHEFS_SUPER_BATCH_TIMER 1 /* true if batch timer expired */
+#define CACHEFS_SUPER_DO_RECLAIM 2 /* true if should do reclamation */
+#define CACHEFS_SUPER_RCM_IMM_SCAN 3 /* true if should scan for immediately
+ * reclaimable inodes */
/* block allocation and recycling management */
struct rb_root blk_tree; /* block mapping tree */
@@ -83,11 +91,28 @@
cachefs_blockix_t recycle_cur; /* current node in recycle stack */
unsigned recycle_cur_n; /* current occupancy of reserve stack */
- struct list_head recycleq; /* inodes to be deleted */
+ /* inode reclamation */
+ spinlock_t rcm_lock;
+
+ unsigned *rcm_imm_buf; /* circular immediate-reclaim buffer */
+ unsigned short rcm_imm_head;
+ unsigned short rcm_imm_tail;
+
+#define CACHEFS_RCM_IMM_BUFSIZE (PAGE_SIZE/sizeof(unsigned))
+
+ struct cachefs_reclaimable *rcm_atm_list; /* atime-based reclaimable inode list */
+ unsigned short rcm_atm_end; /* end of buffer contents */
+
+#define CACHEFS_RCM_ATM_LISTSIZE (PAGE_SIZE/sizeof(struct cachefs_reclaimable))
+
+ unsigned rcm_ino; /* inode being reclaimed */
+ unsigned rcm_indirect; /* current indirect block index */
+ cachefs_blockix_t rcm_block; /* current block being recycled */
+ unsigned short rcm_ptrnext; /* next entry in rcyblock to process */
+ unsigned short rcm_ptrstop; /* entry in rcyblock to stop at */
- cachefs_blockix_t rcyblock; /* current block being recycled */
- unsigned short rcynext; /* next entry in rcyblock to process */
- unsigned short rcystop; /* entry in rcyblock to stop at */
+ struct cachefs_inode *rcm_inode; /* inode being reclaimed */
+ struct page *rcm_curpage; /* page holding rcm_block */
/* update journal tracking */
unsigned short ujnl_step; /* journal block size */
@@ -147,15 +172,9 @@
extern void cachefs_add_cache(struct cachefs_super *super);
extern void cachefs_del_cache(struct cachefs_super *super);
-extern int cachefs_recycle_begin_new_node(struct cachefs_super *super,
- cachefs_blockix_t bix,
- cachefs_blockix_t upblock,
- unsigned short upentry,
- void (*manage)(struct cachefs_super *super));
-
-extern void cachefs_recycle_nodes(struct cachefs_super *super);
extern void cachefs_recycle_unready_blocks(struct cachefs_super *super);
extern void cachefs_recycle_transfer_stack(struct cachefs_super *super);
+extern void cachefs_recycle_reclaim(struct cachefs_super *super);
/*****************************************************************************/
/*
@@ -184,6 +203,8 @@
const struct cachefs_index *definition,
const void *data);
+extern int cachefs_index_zap(struct cachefs_super *super);
+
/*****************************************************************************/
/*
* on-disc per-cache inode record
@@ -310,6 +331,11 @@
return ((struct cachefs_page *) page->private)->mapped_block;
}
+static inline void cachefs_page_modify(struct cachefs_super *super, struct page **page)
+{
+ cachefs_block_modify(super,__cachefs_get_page_block(*page),page);
+}
+
/*****************************************************************************/
/*
* transaction record and tracking structure
@@ -407,7 +433,6 @@
extern void cachefs_trans_sync(struct cachefs_super *super, int wait);
extern int cachefs_ujnl_replay(struct cachefs_super *super);
-
/*****************************************************************************/
/*
Index: aops.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/aops.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- aops.c 21 Mar 2003 14:01:01 -0000 1.23
+++ aops.c 2 Apr 2003 09:12:31 -0000 1.24
@@ -1029,13 +1029,12 @@
up(&super->alloc_sem);
/* change the appropriate pointer on disc to point to this block */
- cachefs_block_modify(super,__cachefs_get_page_block(step[1].page),&step[1].page);
+ cachefs_page_modify(super,&step[1].page);
step->bix = jentry->block;
data = kmap(step[1].page);
*(cachefs_blockix_t *)(data + step->offset) = step->bix;
kunmap(data);
- flush_dcache_page(step[1].page);
unlock_page(step[1].page);
@@ -1044,7 +1043,6 @@
storage->size = inode->vfs_inode.i_size;
storage->mtime = CURRENT_TIME.tv_sec;
kunmap(inode->storage);
- flush_dcache_page(inode->storage);
/* okay... done that */
cachefs_trans_commit(step->transaction);
Index: Makefile
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/Makefile,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- Makefile 21 Mar 2003 14:01:01 -0000 1.13
+++ Makefile 2 Apr 2003 09:12:31 -0000 1.14
@@ -2,7 +2,7 @@
# Makefile for general caching filesystem
#
-CFLAGS += -finstrument-functions
+#CFLAGS += -finstrument-functions
cachefs-objs := \
block.o \
More information about the linux-afs-cvs
mailing list