afs/fs/cachefs super.c,1.25,1.26 recycling.c,1.16,1.17
journal.c,1.29,1.30 io.c,1.11,1.12 interface.c,1.1,1.2
inode.c,1.16,1.17 index.c,1.14,1.15 cachetest-main.c,1.7,1.8
cachefs-int.h,1.26,1.27 block.c,1.2,1.3 aops.c,1.25,1.26
dwh at infradead.org
dwh at infradead.org
Thu Apr 24 14:02:37 BST 2003
Update of /home/cvs/afs/fs/cachefs
In directory phoenix.infradead.org:/tmp/cvs-serv29171/fs/cachefs
Modified Files:
super.c recycling.c journal.c io.c interface.c inode.c index.c
cachetest-main.c cachefs-int.h block.c aops.c
Log Message:
advanced the netfs API some more
implemented the journalling sync function
now clear ptr2ptr targets for returning things in func prologue
added a missing pointer clearance
Index: super.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/super.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- super.c 17 Apr 2003 11:59:03 -0000 1.25
+++ super.c 24 Apr 2003 12:02:33 -0000 1.26
@@ -297,6 +297,7 @@
INIT_LIST_HEAD(&super->batch_errorq);
init_waitqueue_head(&super->batch_done_wq);
init_waitqueue_head(&super->batch_timer_wq);
+ init_waitqueue_head(&super->batch_sync_wq);
init_timer(&super->batch_timer);
super->batch_timer.function = cachefs_trans_batch_timer;
super->batch_timer.data = (unsigned long) super;
@@ -308,7 +309,7 @@
init_completion(&super->dmn_dead);
init_waitqueue_head(&super->dmn_sleepq);
- rwlock_init(&super->ino_tree_lock);
+ spin_lock_init(&super->ino_tree_lock);
/* create the linear-mapping inode */
ret = cachefs_iget(super,CACHEFS_INO_MISC,&inode2);
@@ -692,15 +693,20 @@
{
struct cachefs_super *super = sb->s_fs_info;
+ printk("\n\n");
kenter("{%p}",super);
if (!super) BUG();
- cachefs_del_cache(super);
+ cachefs_withdraw_cache(super);
+
+ cachefs_trans_sync(super,1);
super->dmn_die = 1;
wake_up(&super->dmn_sleepq);
wait_for_completion(&super->dmn_dead);
+
+ del_timer_sync(&super->batch_timer);
if (super->alloc_node) {
dbgpgfree(super->alloc_node);
Index: recycling.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/recycling.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- recycling.c 2 Apr 2003 09:12:31 -0000 1.16
+++ recycling.c 24 Apr 2003 12:02:33 -0000 1.17
@@ -228,6 +228,7 @@
/* if the front recycling node is saturated, then transfer the entire stack */
if (super->recycle_room==0) {
+ kdebug("transfer entire stack");
allocTOS = super->recycle_cur;
cur_n = super->recycle_cur_n;
block = super->recycle_block;
@@ -250,12 +251,14 @@
return;
}
+ super->recycle_block = NULL;
super->recycle_node = NULL;
super->recycle_cur = 0;
super->recycle_cur_n = 0;
}
/* otherwise transfer from the second-in-line if there is one */
else {
+ kdebug("transfer 2OS+ of stack");
node = (struct cachefs_ondisc_free_node *) kmap(super->recycle_node);
allocTOS = node->next;
kunmap(super->recycle_node);
Index: journal.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/journal.c,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -r1.29 -r1.30
--- journal.c 2 Apr 2003 09:12:31 -0000 1.29
+++ journal.c 24 Apr 2003 12:02:33 -0000 1.30
@@ -145,7 +145,7 @@
for (loop=0; loop<CACHEFS_EFFECTS_PER_TRANS; loop++) {
if (trans->effects[loop].block)
- cachefs_block_put(trans->super,trans->effects[loop].block);
+ cachefs_block_put(trans->super,xchg(&trans->effects[loop].block,NULL));
if (trans->effects[loop].held_page)
put_page(trans->effects[loop].held_page);
}
@@ -161,7 +161,7 @@
}
if (trans->jblock)
- cachefs_block_put(trans->super,trans->jblock);
+ cachefs_block_put(trans->super,xchg(&trans->jblock,NULL));
atomic_inc(&trans->super->cnt_ujnl_free);
dbgfree(trans);
@@ -561,6 +561,8 @@
up(&super->batch_sem);
+ wake_up_all(&super->batch_sync_wq);
+
} /* end cachefs_trans_batch_write() */
/*****************************************************************************/
@@ -660,6 +662,7 @@
offset<<super->sb->s_blocksize_bits);
cachefs_block_put(super,block);
+ block = NULL;
if (!tmp)
break;
@@ -1186,20 +1189,54 @@
*/
void cachefs_trans_sync(struct cachefs_super *super, int wait)
{
- _enter("{batch=%hd}",super->ujnl_batch);
+ int16_t next_batch;
+
+ DECLARE_WAITQUEUE(myself,current);
- set_bit(CACHEFS_SUPER_BATCH_TIMER,&super->flags);
- wake_up_all(&super->batch_timer_wq);
+ kenter("{batch=%hd}",super->ujnl_batch);
-#if 0
- if (wait) {
- yield();
- down(&super->batch_sem);
- up(&super->batch_sem);
+ /* if we're not supposed to wait, just induce consideration of a batch write */
+ if (!wait) {
+ set_bit(CACHEFS_SUPER_BATCH_TIMER,&super->flags);
+ wake_up_all(&super->batch_timer_wq);
+ kleave("");
+ return;
}
-#endif
- _leave("");
+ /* prevent new transactions starting until we've worked out where the sync ends */
+ down_write(&super->batch_ctrl_sem);
+
+ if (super->ujnl_serial==0) {
+ /* no pending transactions */
+ up_write(&super->batch_ctrl_sem);
+ }
+ else {
+ /* transactions present - must wait till pending batch is written */
+ next_batch = super->ujnl_batch + 1;
+
+ set_bit(CACHEFS_SUPER_BATCH_TIMER,&super->flags);
+ wake_up_all(&super->batch_timer_wq);
+
+ up_write(&super->batch_ctrl_sem);
+
+ /* now wait for next batch number to come up */
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ add_wait_queue(&super->batch_sync_wq,&myself);
+
+ while (next_batch - super->ujnl_batch > 0) {
+ schedule();
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ }
+
+ remove_wait_queue(&super->batch_sync_wq,&myself);
+ set_current_state(TASK_RUNNING);
+ }
+
+ /* now we have to wait for any currently active batch write */
+ down(&super->batch_sem);
+ up(&super->batch_sem);
+
+ kleave("");
} /* end cachefs_trans_sync() */
/*****************************************************************************/
Index: io.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/io.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- io.c 21 Mar 2003 14:01:01 -0000 1.11
+++ io.c 24 Apr 2003 12:02:34 -0000 1.12
@@ -32,6 +32,7 @@
unsigned to);
static int cachefs_vio_invalidatepage(struct page *page, unsigned long offset);
static int cachefs_vio_releasepage(struct page *page, int gfp_flags);
+static int cachefs_vio_set_page_dirty(struct page *page);
struct address_space_operations cachefs_vio_addrspace_operations = {
.readpage = cachefs_vio_readpage,
@@ -41,7 +42,7 @@
.sync_page = block_sync_page,
.prepare_write = cachefs_vio_prepare_write,
.commit_write = cachefs_vio_commit_write,
- .set_page_dirty = __set_page_dirty_nobuffers,
+ .set_page_dirty = cachefs_vio_set_page_dirty,
.releasepage = cachefs_vio_releasepage,
.invalidatepage = cachefs_vio_invalidatepage,
};
@@ -106,6 +107,8 @@
{
struct bio *bio;
+ *_bio = NULL;
+
_enter("{bits=%u},%llu,%d,%x,",sb->s_blocksize_bits,first_sector,nr_vecs,gfp_flags);
bio = bio_alloc(gfp_flags,nr_vecs);
@@ -125,7 +128,28 @@
static int cachefs_vio_writepages(struct address_space *mapping, struct writeback_control *wbc)
{
+ struct page *page;
+
+ write_lock(&mapping->page_lock);
+
+ list_splice_init(&mapping->dirty_pages,&mapping->io_pages);
+
+ if (list_empty(&mapping->dirty_pages) && list_empty(&mapping->io_pages)) {
+ write_unlock(&mapping->page_lock);
+ return 0;
+ }
+
+ /* shouldn't ever get this far */
printk("CacheFS: meta-data writepages not supported\n");
+
+ printk("- inode %lx\n",mapping->host->i_ino);
+
+ list_for_each_entry(page,&mapping->io_pages,list) {
+ printk(" - pg %lu\n",page->index);
+ }
+
+ write_unlock(&mapping->page_lock);
+
BUG();
return -EIO;
}
@@ -299,7 +323,17 @@
ClearPageMappedToDisk(page);
pageio->flags = 0;
- if (block) cachefs_block_put(page->mapping->host->i_sb->s_fs_info,block);
+ if (block) {
+ int usage = atomic_read(&block->usage);
+
+ if ((usage&0xffffff00)==0x6b6b6b00) {
+ printk("\nBLOCK PUT ERROR pg=%p{ix=%lu} blk=%p{u=%x}\n",
+ page,page->index,block,usage);
+ BUG();
+ }
+
+ cachefs_block_put(page->mapping->host->i_sb->s_fs_info,block);
+ }
/*
* We release buffers only if the entire page is being invalidated.
@@ -319,6 +353,7 @@
*/
static int cachefs_vio_releasepage(struct page *page, int gfp_flags)
{
+ struct cachefs_block *block;
struct cachefs_page *pageio;
_enter("{%lu},%x",page->index,gfp_flags);
@@ -330,9 +365,9 @@
ClearPageMappedToDisk(page);
if (pageio) {
- if (pageio->mapped_block)
- cachefs_block_put(page->mapping->host->i_sb->s_fs_info,
- pageio->mapped_block);
+ block = xchg(&pageio->mapped_block,NULL);
+ if (block)
+ cachefs_block_put(page->mapping->host->i_sb->s_fs_info,block);
dbgfree(pageio);
kfree(pageio);
}
@@ -341,6 +376,20 @@
_leave(" = 0");
return 0;
} /* end cachefs_vio_releasepage() */
+
+/*****************************************************************************/
+/*
+ *
+ */
+static int cachefs_vio_set_page_dirty(struct page *page)
+{
+ kenter("{%lu}",page->index);
+
+ BUG();
+
+ return __set_page_dirty_nobuffers(page);
+
+} /* end cachefs_vio_set_page_dirty() */
/*****************************************************************************/
/*
Index: interface.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/interface.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- interface.c 17 Apr 2003 11:59:04 -0000 1.1
+++ interface.c 24 Apr 2003 12:02:34 -0000 1.2
@@ -16,10 +16,9 @@
LIST_HEAD(cachefs_cache_list);
DECLARE_RWSEM(cachefs_addremove_sem);
-static cachefs_match_val_t cachefs_fsdef_index_match(struct cachefs_object *index,
- const void *_entry);
+static cachefs_match_val_t cachefs_fsdef_index_match(void *target, const void *entry);
-static void cachefs_fsdef_index_update(struct cachefs_object *source, void *entry);
+static void cachefs_fsdef_index_update(void *source, void *entry);
static struct cachefs_index_def cachefs_fsdef_index_def = {
.name = ".fsdef",
@@ -28,20 +27,37 @@
.update = cachefs_fsdef_index_update
};
-static struct cachefs_object cachefs_fsdef_index = {
+static struct cachefs_cookie cachefs_fsdef_index = {
+ .usage = ATOMIC_INIT(1),
.idef = &cachefs_fsdef_index_def,
.sem = __RWSEM_INITIALIZER(cachefs_fsdef_index.sem),
.active_inodes = LIST_HEAD_INIT(cachefs_fsdef_index.active_inodes),
};
-/* number expected in cachefs_file::numactive */
-static int cachefs_num_active_inodes;
+static void __cachefs_cookie_put(struct cachefs_cookie *cookie);
+static inline void cachefs_cookie_put(struct cachefs_cookie *cookie)
+{
+ if (atomic_dec_and_test(&cookie->usage))
+ __cachefs_cookie_put(cookie);
+ else if (atomic_read(&cookie->usage)<0)
+ BUG();
+}
+
+static void __cachefs_put_active_inode(struct cachefs_active_inode *active);
+static inline void cachefs_put_active_inode(struct cachefs_active_inode *active)
+{
+ if (atomic_dec_and_lock(&active->usage,&active->super->ino_tree_lock))
+ __cachefs_put_active_inode(active);
+ else if (atomic_read(&active->usage)<0)
+ BUG();
+}
/*****************************************************************************/
/*
* register a network filesystem for caching
*/
-int cachefs_register_netfs(struct cachefs_netfs *netfs)
+int cachefs_register_netfs(struct cachefs_netfs *netfs,
+ struct cachefs_index_def *primary_idef)
{
struct cachefs_netfs *ptr;
int ret;
@@ -50,10 +66,26 @@
INIT_LIST_HEAD(&netfs->link);
- INIT_LIST_HEAD(&netfs->primary_index.active_inodes);
- init_rwsem(&netfs->primary_index.sem);
+ netfs->primary_index = kmalloc(sizeof(*netfs->primary_index),GFP_KERNEL);
+ if (!netfs->primary_index) {
+ kleave(" = -ENOMEM");
+ return -ENOMEM;
+ }
+
+ memset(netfs->primary_index,0,sizeof(*netfs->primary_index));
+
+ atomic_set(&netfs->primary_index->usage,1);
+ atomic_set(&netfs->primary_index->children,0);
- netfs->primary_index.iparent = &cachefs_fsdef_index;
+ netfs->primary_index->idef = primary_idef;
+ netfs->primary_index->iparent = &cachefs_fsdef_index;
+ netfs->primary_index->netfs_data = netfs;
+
+ atomic_inc(&netfs->primary_index->iparent->usage);
+ atomic_inc(&netfs->primary_index->iparent->children);
+
+ INIT_LIST_HEAD(&netfs->primary_index->active_inodes);
+ init_rwsem(&netfs->primary_index->sem);
/* check it's not already present */
down_write(&cachefs_addremove_sem);
@@ -79,6 +111,7 @@
/*****************************************************************************/
/*
* unregister a network filesystem from the cache
+ * - all cookies must have been released first
*/
void cachefs_unregister_netfs(struct cachefs_netfs *netfs)
{
@@ -88,7 +121,7 @@
list_del(&netfs->link);
- cachefs_unregister_object(&netfs->primary_index,0);
+ cachefs_relinquish_cookie(netfs->primary_index,0);
up_write(&cachefs_addremove_sem);
@@ -104,21 +137,22 @@
*/
void cachefs_add_cache(struct cachefs_super *super, struct cachefs_active_inode *active)
{
- unsigned long flags;
-
printk("\n\n\n");
kenter("");
/* prepare an active-inode record for the FSDEF index of this cache */
+ memset(active,0,sizeof(*active));
+
atomic_set(&active->usage,2);
active->super = super;
active->ino = CACHEFS_INO_FSDEF_CATALOGUE;
active->flags = (1 << CACHEFS_ACTIVE_INODE_ISINDEX | 1 << CACHEFS_ACTIVE_INODE_LIVE);
active->storage = NULL;
- active->object = &cachefs_fsdef_index;
+ active->cookie = &cachefs_fsdef_index;
init_waitqueue_head(&active->initwq);
+ init_rwsem(&active->sem);
/* actually do the stuff */
down_write(&cachefs_addremove_sem);
@@ -127,38 +161,54 @@
up_write(&cachefs_addremove_sem);
- write_lock_irqsave(&super->ino_tree_lock,flags);
+ spin_lock(&super->ino_tree_lock);
rb_link_node(&active->node,NULL,&super->ino_tree.rb_node);
rb_insert_color(&active->node,&super->ino_tree);
- write_unlock_irqrestore(&super->ino_tree_lock,flags);
+ spin_unlock(&super->ino_tree_lock);
down_write(&cachefs_fsdef_index.sem);
list_add_tail(&active->link,&cachefs_fsdef_index.active_inodes);
+ atomic_inc(&cachefs_fsdef_index.usage);
up_write(&cachefs_fsdef_index.sem);
- cachefs_num_active_inodes++;
-
kleave("");
} /* end cachefs_add_cache() */
/*****************************************************************************/
/*
- * remove an unmounted cache from the list
+ * withdraw an unmounted cache from the active service
*/
-void cachefs_del_cache(struct cachefs_super *super)
+void cachefs_withdraw_cache(struct cachefs_super *super)
{
- kenter("");
+ struct cachefs_active_inode *active;
+ struct rb_node *n;
- down_write(&cachefs_addremove_sem);
+ kenter("");
- BUG();
+ /* make the cache unavailable for cookie acquisition */
+ set_bit(CACHEFS_SUPER_WITHDRAWN,&super->flags);
+ down_write(&cachefs_addremove_sem);
list_del_init(&super->mnt_link);
-
up_write(&cachefs_addremove_sem);
+ /* we now have to destroy all the active inodes pertaining to this superblock */
+ spin_lock(&super->ino_tree_lock);
+ while ((n = rb_first(&super->ino_tree))) {
+ active = rb_entry(n,struct cachefs_active_inode,node);
+ rb_erase(n,&super->ino_tree);
+ spin_unlock(&super->ino_tree_lock);
+
+ /* we've extracted an active inode from the tree */
+ cachefs_withdraw_active_inode(active);
+ cachefs_put_active_inode(active);
+
+ spin_lock(&super->ino_tree_lock);
+ }
+ spin_unlock(&super->ino_tree_lock);
+
kleave("");
-} /* end cachefs_del_cache() */
+} /* end cachefs_withdraw_cache() */
/*****************************************************************************/
/*
@@ -168,24 +218,24 @@
* - all parent index objects are created if necessary
* - returns -ENODATA if the object doesn't exist and "create" is false
*/
-static int cachefs_lookup_object(struct cachefs_object *object,
+static int cachefs_lookup_object(struct cachefs_cookie *cookie,
struct cachefs_super *super,
int create)
{
struct cachefs_active_inode *ipactive, *active, *xactive;
- struct cachefs_object *iparent;
+ struct cachefs_cookie *iparent;
struct rb_node *parent, **p;
unsigned long flags;
int ret;
- iparent = object->iparent;
+ iparent = cookie->iparent;
if (!iparent) return 0; /* FSDEF entries don't have a parent */
- kenter("{%s/%s},",iparent->idef->name,object->idef ? (char*)object->idef->name : "<file>");
+ kenter("{%s/%s},",iparent->idef->name,cookie->idef ? (char*)cookie->idef->name : "<file>");
/* see if there's an entry for this object already */
- list_for_each_entry(active,&object->active_inodes,link) {
- kdebug("check entry %p x %p [ino %u]",object,super,active->ino);
+ list_for_each_entry(active,&cookie->active_inodes,link) {
+ kdebug("check entry %p x %p [ino %u]",cookie,super,active->ino);
if (active->super==super) {
kdebug("found entry");
@@ -203,7 +253,7 @@
}
/* allocate an entry for this object */
- kdebug("alloc entry %p x %p",object,super);
+ kdebug("alloc entry %p x %p",cookie,super);
active = kmalloc(sizeof(*active),GFP_KERNEL);
if (!active) {
@@ -211,21 +261,26 @@
return -ENOMEM;
}
+ memset(active,0,sizeof(*active));
+
active->super = super;
active->ino = 0;
active->flags = 1 << CACHEFS_ACTIVE_INODE_LIVE;
active->storage = NULL;
- active->object = object;
+ active->cookie = cookie;
- if (object->idef)
+ if (cookie->idef)
active->flags |= 1 << CACHEFS_ACTIVE_INODE_ISINDEX;
atomic_set(&active->usage,1);
INIT_LIST_HEAD(&active->link);
init_waitqueue_head(&active->initwq);
+ init_rwsem(&active->sem);
found_entry:
- /* we need to insert an entry for this object in the object's parent index, so the first
+ down_write(&active->sem);
+
+ /* we need to insert an entry for this cache in the object's parent index, so the first
* thing to do is to see if the parent index is represented on disc, and if not, create it
* if necessary
*/
@@ -235,7 +290,10 @@
if (ret<0) {
if (ret==-ENODATA) {
/* set a negative entry */
- list_add_tail(&active->link,&object->active_inodes);
+ if (list_empty(&active->link)) {
+ list_add_tail(&active->link,&cookie->active_inodes);
+ atomic_inc(&cookie->usage);
+ }
}
up_write(&iparent->sem);
@@ -259,14 +317,25 @@
/* search the parent index for a reference compatible with this object */
ret = cachefs_index_search(ipactive,active);
switch (ret) {
- default: goto error;
- case 0: goto add_to_active_tree;
+ default:
+ goto error;
+
+ case 0:
+ if (list_empty(&active->link)) {
+ list_add_tail(&active->link,&cookie->active_inodes);
+ atomic_inc(&cookie->usage);
+ }
+ goto add_to_active_tree;
case -ENOENT:
/* we can at least set a valid negative entry */
- list_add_tail(&active->link,&object->active_inodes);
+ if (list_empty(&active->link)) {
+ list_add_tail(&active->link,&cookie->active_inodes);
+ atomic_inc(&cookie->usage);
+ }
if (!create) {
+ up_write(&active->sem);
up_read(&iparent->sem);
goto nodata;
}
@@ -286,7 +355,7 @@
atomic_inc(&active->usage);
- write_lock_irqsave(&super->ino_tree_lock,flags);
+ spin_lock_irqsave(&super->ino_tree_lock,flags);
p = &super->ino_tree.rb_node;
while (*p) {
@@ -304,8 +373,9 @@
rb_link_node(&active->node,parent,p);
rb_insert_color(&active->node,&super->ino_tree);
- write_unlock_irqrestore(&super->ino_tree_lock,flags);
+ spin_unlock_irqrestore(&super->ino_tree_lock,flags);
+ up_write(&active->sem);
up_read(&iparent->sem);
kleave(" = 0");
return 0;
@@ -313,7 +383,9 @@
error:
up_read(&iparent->sem);
error2:
- if (list_empty(&active->link)) kfree(active);
+ up_write(&active->sem);
+ if (list_empty(&active->link))
+ kfree(active);
kleave(" = %d",ret);
return ret;
@@ -344,41 +416,89 @@
/*****************************************************************************/
/*
- * register an object
+ * request a cookie to represent a data file or an index
+ * - iparent specifies the parent index to pin in memory
+ * - the top level index cookie for each netfs is stored in the cachefs_netfs struct upon
+ * registration
+ * - idef is NULL for a data file
+ * - idef points to the definition for an index
+ * - the netfs_data will be passed to the functions pointed to in *idef
* - all attached caches will be searched to see if they contain this object
* - index objects aren't stored on disc until there's a dependent file that needs storing
* - file objects are stored in a selected cache immediately, and all the indexes forming the path
* to it are instantiated if necessary
+ * - we never let on to the netfs about errors
+ * - we may set a NULL cookie pointer, but that's okay
*/
-int cachefs_register_object(struct cachefs_object *object)
+void cachefs_acquire_cookie(struct cachefs_cookie *iparent,
+ struct cachefs_index_def *idef,
+ void *netfs_data,
+ struct cachefs_cookie **_cookie)
{
struct cachefs_active_inode *active;
+ struct cachefs_cookie *cookie;
struct cachefs_super *super;
struct list_head *_p, *_n;
int ret = 0;
- kenter("{%s}",object->idef?(char*)object->idef->name:"<file>");
+ *_cookie = NULL;
+
+ kenter("{%s},{%s},%p,",
+ iparent ? (char*)iparent->idef->name : "<no-parent>",
+ idef ? (char*)idef->name : "<file>",
+ netfs_data);
+
+ /* if no parent cookie, then don't create one here either */
+ if (!iparent) {
+ *_cookie = NULL;
+ kleave(" [no parent]");
+ return;
+ }
+
+ /* allocate a cookie first and pass it back */
+ cookie = kmalloc(sizeof(*cookie),GFP_KERNEL);
+ if (!cookie) {
+ *_cookie = NULL;
+ kleave(" [ENOMEM]");
+ return;
+ }
+
+ memset(cookie,0,sizeof(*cookie));
+
+ atomic_set(&cookie->usage,1);
+ atomic_set(&cookie->children,0);
- INIT_LIST_HEAD(&object->active_inodes);
- init_rwsem(&object->sem);
+ atomic_inc(&iparent->usage);
+ atomic_inc(&iparent->children);
+ cookie->idef = idef;
+ cookie->iparent = iparent;
+ cookie->netfs_data = netfs_data;
+
+ INIT_LIST_HEAD(&cookie->active_inodes);
+ init_rwsem(&cookie->sem);
+
+ *_cookie = cookie;
+
+ /* now we need to see whether the backing objects for this cookie yet exist */
down_read(&cachefs_addremove_sem);
if (list_empty(&cachefs_cache_list)) {
up_read(&cachefs_addremove_sem);
- kleave(" = 0 [no caches]");
- return 0;
+ kleave(" [no caches]");
+ return;
}
- down_write(&object->sem);
+ down_write(&cookie->sem);
/* search every cache to see if the object is already present */
list_for_each_entry(super,&cachefs_cache_list,mnt_link) {
- ret = cachefs_lookup_object(object,super,0);
+ ret = cachefs_lookup_object(cookie,super,0);
switch (ret) {
case 0:
- if (!object->idef)
+ if (!cookie->idef)
break; /* only want the first file entry */
case -ENODATA:
+ ret = 0;
continue;
default:
goto error;
@@ -386,13 +506,13 @@
}
/* if this object is a file, select a cache on which to store it */
- if (!object->idef) {
+ if (!cookie->idef) {
super = cachefs_select_cache_for_file();
/* we don't want to keep any negative records for a file other than the one for the
* chosen superblock (which we'll turn into a positive entry)
*/
- list_for_each_safe(_p,_n,&object->active_inodes) {
+ list_for_each_safe(_p,_n,&cookie->active_inodes) {
active = list_entry(_p,struct cachefs_active_inode,link);
if (active->super==super || active->ino==0) {
list_del(&active->link);
@@ -405,51 +525,153 @@
goto error; /* couldn't decide on a cache */
/* instantiate the file */
- ret = cachefs_lookup_object(object,super,1);
- switch (ret) {
- case 0: break;
- case -ENODATA: BUG();
- default: goto error;
- }
+ ret = cachefs_lookup_object(cookie,super,1);
+ if (ret==0)
+ goto done;
+ if (ret==-ENODATA)
+ BUG();
}
- /* the caller shouldn't see the fact that we don't have any attached inodes yet */
- if (ret==-ENODATA) ret = 0;
-
error:
- up_write(&object->sem);
+ printk("CacheFS: error from cache fs: %d\n",ret);
+ done:
+ up_write(&cookie->sem);
up_read(&cachefs_addremove_sem);
+ kleave("");
+} /* end cachefs_acquire_cookie() */
- kleave(" = %d",ret);
- return ret;
-} /* end cachefs_register_object() */
-
-EXPORT_SYMBOL(cachefs_register_object);
+EXPORT_SYMBOL(cachefs_acquire_cookie);
/*****************************************************************************/
/*
- * unregister an object from the cache
+ * release a cookie back to the cache
* - the object will be marked as recyclable on disc if retire is true
+ * - all dependents of this cookie must have already been unregistered (indexes/files/pages)
*/
-void cachefs_unregister_object(struct cachefs_object *object, int retire)
+void cachefs_relinquish_cookie(struct cachefs_cookie *cookie, int retire)
{
- kenter("{%s},%d",object->idef?(char*)object->idef->name:"<file>",retire);
+ struct cachefs_active_inode *active;
- BUG();
+ kenter("{%s},%d",
+ cookie && cookie->idef ? (char*)cookie->idef->name : "<file>",
+ retire);
+
+ if (!cookie) {
+ kleave(" [no cookie]");
+ return;
+ }
+
+ if (atomic_read(&cookie->children)!=0) {
+ printk("CacheFS: cookie still has children\n");
+ BUG();
+ }
+
+ /* detach pointers back to netfs */
+ down_write(&cookie->sem);
+
+ cookie->netfs_data = NULL;
+ cookie->idef = NULL;
+
+ /* note that all the inodes supporting this object need recycling */
+ if (retire) {
+ list_for_each_entry(active,&cookie->active_inodes,link) {
+ set_bit(CACHEFS_ACTIVE_INODE_RECYCLING,&active->flags);
+ }
+ }
+
+ /* break links with all the active inodes */
+ while (!list_empty(&cookie->active_inodes)) {
+ active = list_entry(&cookie->active_inodes, struct cachefs_active_inode,link);
+
+ /* detach the cache inode from the cached object cookie */
+ set_bit(CACHEFS_ACTIVE_INODE_RELEASING,&active->flags);
+
+ list_del_init(&active->link);
+
+ down_write(&active->sem);
+ active->cookie = NULL;
+ up_write(&active->sem);
+
+ if (atomic_dec_and_test(&cookie->usage))
+ BUG(); /* shouldn't've reduced the cookie usership to 0 yet */
+
+ cachefs_put_active_inode(active);
+ }
+
+ up_write(&cookie->sem);
+
+ cachefs_cookie_put(cookie);
+
+ kleave("");
+} /* end cachefs_relinquish_cookie() */
+
+EXPORT_SYMBOL(cachefs_relinquish_cookie);
+
+/*****************************************************************************/
+/*
+ * withdraw an inode from active service
+ * - need break the links to a cached object cookie
+ * - called under two situations:
+ * (1) recycler decides to reclaim an in-use inode
+ * (2) a cache is unmounted
+ * - have to take care as the cookie can be being relinquished by the netfs simultaneously
+ * - the active inode is pinned by the caller holding a refcount on it
+ */
+void cachefs_withdraw_active_inode(struct cachefs_active_inode *active)
+{
+ struct cachefs_cookie *cookie, *xcookie = NULL;
+
+ kenter("%p",active);
+
+ set_bit(CACHEFS_ACTIVE_INODE_WITHDRAWN,&active->flags);
+
+ /* first of all we have to break the links between the active inode and the cookie
+ * - we have to hold both writelocks BUT we have to get the cookie lock FIRST
+ */
+ kdebug("%d",__LINE__);
+ down_write(&active->sem);
+
+ cookie = active->cookie;
+ kdebug("cookie: %p",cookie);
+
+ if (cookie) {
+ atomic_inc(&cookie->usage); /* pin the cookie */
+
+ up_write(&active->sem); /* re-order the locks to avoid deadlock */
+ kdebug("%d",__LINE__);
+ down_write(&cookie->sem);
+ kdebug("%d",__LINE__);
+ down_write(&active->sem);
+ kdebug("%d",__LINE__);
+
+ list_del_init(&active->link);
+
+ xcookie = active->cookie;
+ active->cookie = NULL;
+
+ up_write(&cookie->sem);
+ }
-} /* end cachefs_unregister_object() */
+ up_write(&active->sem);
-EXPORT_SYMBOL(cachefs_unregister_object);
+ cachefs_cookie_put(cookie);
+
+ if (xcookie) {
+ cachefs_cookie_put(xcookie);
+ cachefs_put_active_inode(active);
+ }
+
+ kleave("");
+} /* end cachefs_withdraw_active_inode() */
/*****************************************************************************/
/*
* see if the netfs definition matches
*/
-static cachefs_match_val_t cachefs_fsdef_index_match(struct cachefs_object *index,
- const void *_entry)
+static cachefs_match_val_t cachefs_fsdef_index_match(void *target, const void *entry)
{
- const struct cachefs_ondisc_fsdef *fsdef = _entry;
- struct cachefs_netfs *netfs = container_of(index,struct cachefs_netfs,primary_index);
+ const struct cachefs_ondisc_fsdef *fsdef = entry;
+ struct cachefs_netfs *netfs = target;
kenter("{%s.%u},{%s.%u}",
netfs->name,netfs->version,
@@ -473,10 +695,10 @@
/*
* update the netfs definition to be stored on disc
*/
-static void cachefs_fsdef_index_update(struct cachefs_object *source, void *entry)
+static void cachefs_fsdef_index_update(void *source, void *entry)
{
struct cachefs_ondisc_fsdef *fsdef = entry;
- struct cachefs_netfs *netfs = container_of(source,struct cachefs_netfs,primary_index);
+ struct cachefs_netfs *netfs = source;
kenter("{%s.%u},",netfs->name,netfs->version);
@@ -485,3 +707,45 @@
fsdef->version = netfs->version;
} /* end cachefs_fsdef_index_update() */
+
+/*****************************************************************************/
+/*
+ * destroy a cookie
+ */
+static void __cachefs_cookie_put(struct cachefs_cookie *cookie)
+{
+ kenter("");
+
+ kfree(cookie);
+
+ kleave("");
+} /* end __cachefs_cookie_put() */
+
+/*****************************************************************************/
+/*
+ * destroy an active inode
+ * - called with super->ino_tree_lock held
+ */
+static void __cachefs_put_active_inode(struct cachefs_active_inode *active)
+{
+ struct cachefs_super *super;
+
+ kenter("");
+
+ /* remove from the cache's inode tree */
+ super = active->super;
+
+ if (!test_bit(CACHEFS_ACTIVE_INODE_WITHDRAWN,&active->flags))
+ rb_erase(&active->node,&super->ino_tree);
+
+ spin_unlock(&super->ino_tree_lock);
+
+ if (active->storage) {
+ BUG();
+ cachefs_block_put(active->super,active->storage);
+ }
+
+ kfree(active);
+
+ kleave("");
+} /* end __cachefs_put_active_inode() */
Index: inode.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/inode.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- inode.c 17 Apr 2003 11:59:04 -0000 1.16
+++ inode.c 24 Apr 2003 12:02:34 -0000 1.17
@@ -252,6 +252,8 @@
kenter(",%lu,",ino);
+ *_inode = NULL;
+
/* it does reside in this cache - create an inode for it */
vfs_inode = iget_locked(super->sb,ino);
if (!vfs_inode) {
Index: index.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/index.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- index.c 17 Apr 2003 11:59:04 -0000 1.14
+++ index.c 24 Apr 2003 12:02:34 -0000 1.15
@@ -29,8 +29,8 @@
#include "cachefs-int.h"
struct cachefs_index_search_record {
- struct cachefs_object *index;
- struct cachefs_object *target;
+ struct cachefs_cookie *index;
+ struct cachefs_cookie *target;
struct cachefs_inode *iinode;
unsigned entsize;
int entry;
@@ -115,15 +115,15 @@
loff_t pos;
int ret;
- kenter("{%s,%u}",index->object->idef->name,index->ino);
+ kenter("{%s,%u}",index->cookie->idef->name,index->ino);
/* get the inode */
ret = cachefs_iget(index->super,index->ino,&rec.iinode);
if (ret<0)
goto error;
- rec.index = index->object;
- rec.target = target->object;
+ rec.index = index->cookie;
+ rec.target = target->cookie;
rec.entry = UINT_MAX;
rec.entsize = rec.iinode->index_esize;
@@ -220,6 +220,10 @@
kenter("{%lu},",iinode->vfs_inode.i_ino);
+ *_page = NULL;
+ *_newentry = 0;
+ *_next = 0;
+
storage = kmap(iinode->storage) + iinode->storage_offset;
newentry = storage->freelink;
kunmap(iinode->storage);
@@ -292,7 +296,7 @@
/*****************************************************************************/
/*
* allocate an entry in the specified index file and associate an inode with it
- * - target->object->def determines whether the new inode will be a file or an index
+ * - target->cookie->def determines whether the new inode will be a file or an index
* - if an inode is successfully allocated, target->ino will be set with the inode number
*/
int cachefs_index_allocate(struct cachefs_inode *iinode,
@@ -307,7 +311,7 @@
unsigned ino, ixentry, offset, inonext, ixnext, ino_offset;
int ret, loop;
- kenter("{%lu},{%s},",iinode->vfs_inode.i_ino,index->object->idef->name);
+ kenter("{%lu},{%s},",iinode->vfs_inode.i_ino,index->cookie->idef->name);
super = index->super;
inopage = NULL;
@@ -334,7 +338,7 @@
offset = (ixentry % iinode->index_epp) * iinode->index_esize;
trans->jentry->mark = CACHEFS_ONDISC_UJNL_INDEX_ALLOCING;
- if (!target->object->idef)
+ if (!target->cookie->idef)
trans->jentry->mark = CACHEFS_ONDISC_UJNL_INODE_ALLOCING;
trans->jentry->index = iinode->vfs_inode.i_ino;
@@ -369,10 +373,10 @@
xent->ino = ino;
xent->type = CACHEFS_ONDISC_INDEX_DATAFILE;
- if (target->object->idef)
+ if (target->cookie->idef)
xent->type = CACHEFS_ONDISC_INDEX_INDEXFILE;
- index->object->idef->update(target->object,xent->data);
+ index->cookie->idef->update(target->cookie->netfs_data,xent->data);
kunmap(ixpage);
@@ -395,8 +399,8 @@
storage->pindex = iinode->vfs_inode.i_ino;
storage->pindex_entry = ixentry;
- if (target->object->idef) {
- struct cachefs_index_def *definition = target->object->idef;
+ if (target->cookie->idef) {
+ struct cachefs_index_def *definition = target->cookie->idef;
storage->index_dsize = definition->data_size;
storage->index_esize = storage->index_dsize;
@@ -444,7 +448,7 @@
struct cachefs_inode *iinode;
int ret;
- kenter("{%u,%s},",index->ino,index->object->idef->name);
+ kenter("{%u,%s},",index->ino,index->cookie->idef->name);
/* get the index inode */
ret = cachefs_iget(index->super,index->ino,&iinode);
Index: cachetest-main.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/cachetest-main.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- cachetest-main.c 17 Apr 2003 11:59:04 -0000 1.7
+++ cachetest-main.c 24 Apr 2003 12:02:34 -0000 1.8
@@ -33,7 +33,7 @@
struct afs_cell {
char name[64]; /* [KEY] cell name */
struct in_addr vlservers[15]; /* VLDB server IP addresses */
- struct cachefs_object cache; /* caching cookie */
+ struct cachefs_cookie *cache; /* caching cookie */
};
struct afs_volume {
@@ -41,22 +41,22 @@
u_int32_t vids[3]; /* volume IDs */
struct in_addr fsservers[8]; /* file server IP addresses */
u_int8_t fstypemsks[8]; /* file server volume type masks */
- struct cachefs_object cache; /* caching cookie */
+ struct cachefs_cookie *cache; /* caching cookie */
};
struct afs_inode {
u_int32_t fid; /* [KEY] file ID */
- struct cachefs_object cache; /* caching cookie */
+ struct cachefs_cookie *cache; /* caching cookie */
};
/* AFS network filesystem
* - the primary index contains cell references
*/
-static cachefs_match_val_t cell_match(struct cachefs_object *target, const void *entry);
-static void cell_update(struct cachefs_object *source, void *entry);
+static cachefs_match_val_t cell_match(void *target, const void *entry);
+static void cell_update(void *source, void *entry);
-static struct cachefs_index_def cachetest_netfs = {
- .name = "AFS",
+static struct cachefs_index_def cachetest_cell_index_def = {
+ .name = "cell_ix",
.data_size = 124,
.keys[0] = { CACHEFS_INDEX_KEYS_ASCIIZ, 64 },
.match = cell_match,
@@ -69,7 +69,6 @@
static struct cachefs_netfs cachetest = {
.name = "cachetest",
.version = 0,
- .primary_index = { .idef = &cachetest_netfs},
.ops = &cachetest_ops,
};
@@ -77,11 +76,11 @@
* - this is an index containing volume location database references
* - objects of this type will be typically embedded in the AFS fs's cell record structures
*/
-static cachefs_match_val_t vldb_match(struct cachefs_object *target, const void *entry);
-static void vldb_update(struct cachefs_object *source, void *entry);
+static cachefs_match_val_t vldb_match(void *target, const void *entry);
+static void vldb_update(void *source, void *entry);
-static struct cachefs_index_def cachetest_cell = {
- .name = "cell",
+static struct cachefs_index_def cachetest_volume_index_def = {
+ .name = "vol_ix",
.data_size = 124,
.keys[0] = { CACHEFS_INDEX_KEYS_ASCIIZ, 64 },
.match = vldb_match,
@@ -90,21 +89,17 @@
static struct afs_cell afs_mycell = {
.name = "cambridge.redhat.com",
- .cache = {
- .idef = &cachetest_cell,
- .iparent = &cachetest.primary_index,
- },
};
/* AFS root volume
* - this is an index containing file references
* - objects of this type will be typically embedded in the AFS fs's volume record structures
*/
-static cachefs_match_val_t file_match(struct cachefs_object *target, const void *entry);
-static void file_update(struct cachefs_object *source, void *entry);
+static cachefs_match_val_t file_match(void *target, const void *entry);
+static void file_update(void *source, void *entry);
-static struct cachefs_index_def cachetest_volume = {
- .name = "volume",
+static struct cachefs_index_def cachetest_file_index_def = {
+ .name = "file_ix",
.data_size = 4,
.keys[0] = { CACHEFS_INDEX_KEYS_BIN, 4 },
.match = file_match,
@@ -113,10 +108,6 @@
static struct afs_volume afs_root_volume = {
.name = "#afs.root",
- .cache = {
- .idef = &cachetest_volume,
- .iparent = &afs_mycell.cache,
- },
};
/* AFS root dir
@@ -125,10 +116,6 @@
*/
static struct afs_inode afs_root_dir = {
.fid = 0x1234abcd,
- .cache = {
- .idef = NULL,
- .iparent = &afs_root_volume.cache,
- },
};
/*****************************************************************************/
@@ -141,26 +128,29 @@
printk(KERN_INFO "cachefstest: general fs caching v0.1 tester registering\n");
- ret = cachefs_register_netfs(&cachetest);
+ ret = cachefs_register_netfs(&cachetest,&cachetest_cell_index_def);
if (ret<0)
goto error;
printk("\n### Register cell object\n");
- ret = cachefs_register_object(&afs_mycell.cache);
- if (ret<0)
- goto error;
+ cachefs_acquire_cookie(cachetest.primary_index,
+ &cachetest_volume_index_def,
+ &afs_mycell,
+ &afs_mycell.cache);
printk("\n### Register volume object\n");
- ret = cachefs_register_object(&afs_root_volume.cache);
- if (ret<0)
- goto error;
+ cachefs_acquire_cookie(afs_mycell.cache,
+ &cachetest_file_index_def,
+ &afs_root_volume,
+ &afs_root_volume.cache);
printk("\n### Register file object\n");
- ret = cachefs_register_object(&afs_root_dir.cache);
- if (ret<0)
- goto error;
+ cachefs_acquire_cookie(afs_root_volume.cache,
+ NULL,
+ &afs_root_dir,
+ &afs_root_dir.cache);
- return ret;
+ return 0;
error:
printk(KERN_ERR "cachefstest: failed to register: %d\n",ret);
@@ -175,9 +165,9 @@
{
printk(KERN_INFO "cachefstest: general fs caching v0.1 tester unregistering.\n");
- cachefs_unregister_object(&afs_root_dir.cache,0);
- cachefs_unregister_object(&afs_root_volume.cache,0);
- cachefs_unregister_object(&afs_mycell.cache,0);
+ cachefs_relinquish_cookie(afs_root_dir.cache,0);
+ cachefs_relinquish_cookie(afs_root_volume.cache,0);
+ cachefs_relinquish_cookie(afs_mycell.cache,0);
cachefs_unregister_netfs(&cachetest);
} /* end cachefstest_exit() */
@@ -186,7 +176,7 @@
/*
*
*/
-static cachefs_match_val_t cell_match(struct cachefs_object *target, const void *entry)
+static cachefs_match_val_t cell_match(void *target, const void *entry)
{
struct afs_cell *cell = container_of(target,struct afs_cell,cache);
@@ -202,7 +192,7 @@
/*
* update a cell entry from the specified object
*/
-static void cell_update(struct cachefs_object *source, void *entry)
+static void cell_update(void *source, void *entry)
{
struct afs_cell *cell = container_of(source,struct afs_cell,cache);
@@ -216,7 +206,7 @@
/*
*
*/
-static cachefs_match_val_t vldb_match(struct cachefs_object *target, const void *entry)
+static cachefs_match_val_t vldb_match(void *target, const void *entry)
{
struct afs_volume *volume = container_of(target,struct afs_volume,cache);
@@ -232,7 +222,7 @@
/*
*
*/
-static void vldb_update(struct cachefs_object *source, void *entry)
+static void vldb_update(void *source, void *entry)
{
struct afs_volume *volume = container_of(source,struct afs_volume,cache);
@@ -246,7 +236,7 @@
/*
*
*/
-static cachefs_match_val_t file_match(struct cachefs_object *target, const void *entry)
+static cachefs_match_val_t file_match(void *target, const void *entry)
{
struct afs_inode *inode = container_of(target,struct afs_inode,cache);
u_int32_t fid = htonl(inode->fid);
@@ -263,7 +253,7 @@
/*
*
*/
-static void file_update(struct cachefs_object *source, void *entry)
+static void file_update(void *source, void *entry)
{
struct afs_inode *inode = container_of(source,struct afs_inode,cache);
u_int32_t fid = htonl(inode->fid);
Index: cachefs-int.h
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/cachefs-int.h,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- cachefs-int.h 17 Apr 2003 11:59:04 -0000 1.26
+++ cachefs-int.h 24 Apr 2003 12:02:34 -0000 1.27
@@ -73,6 +73,7 @@
#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 */
+#define CACHEFS_SUPER_WITHDRAWN 4 /* true if cache has been withdrawn */
/* block allocation and recycling management */
struct rb_root blk_tree; /* block mapping tree */
@@ -145,6 +146,7 @@
wait_queue_head_t batch_done_wq; /* blocks write complete wait queue */
struct timer_list batch_timer; /* time to next batch write */
wait_queue_head_t batch_timer_wq; /* batch timer wait queue */
+ wait_queue_head_t batch_sync_wq; /* batch sync wait queue */
struct list_head jnld_link; /* journalling daemon list */
@@ -156,7 +158,7 @@
int dmn_die; /* request to die */
/* event counting */
- atomic_t cnt_blk_tree; /* number of outstanding blk_tree */
+ atomic_t cnt_blk_tree; /* number of outstanding blk_tree nodes */
atomic_t cnt_ujnl_mkrq; /* number of marks requested */
atomic_t cnt_ujnl_mkgr; /* number of marks granted */
atomic_t cnt_ujnl_mkwr; /* number of marks written */
@@ -167,14 +169,14 @@
/* index management */
struct rb_root ino_tree; /* tree of active inodes */
- rwlock_t ino_tree_lock;
+ spinlock_t ino_tree_lock;
/* superblock copy */
struct cachefs_ondisc_superblock *layout;
};
extern void cachefs_add_cache(struct cachefs_super *super, struct cachefs_active_inode *active);
-extern void cachefs_del_cache(struct cachefs_super *super);
+extern void cachefs_withdraw_cache(struct cachefs_super *super);
extern void cachefs_recycle_unready_blocks(struct cachefs_super *super);
extern void cachefs_recycle_transfer_stack(struct cachefs_super *super);
@@ -182,6 +184,25 @@
/*****************************************************************************/
/*
+ * data file or index object cookie
+ * - a file will only appear in one cache
+ * - a request to cache a file may or may not be honoured, subject to constraints such as disc
+ * space
+ * - indexes files are created on disc just-in-time
+ */
+struct cachefs_cookie
+{
+ atomic_t usage; /* number of users of this cookie */
+ atomic_t children; /* number of children of this cookie */
+ struct cachefs_index_def *idef; /* index definition */
+ struct cachefs_cookie *iparent; /* index holding this entry */
+ struct list_head active_inodes; /* inode(s) backing this file/index */
+ struct rw_semaphore sem;
+ void *netfs_data; /* back pointer to netfs */
+};
+
+/*****************************************************************************/
+/*
* cache file and directory management
* - negative entry if .ino==0 (and node will be unused)
*/
@@ -195,15 +216,20 @@
#define CACHEFS_ACTIVE_INODE_ISINDEX 0 /* T if inode is index file (F if file) */
#define CACHEFS_ACTIVE_INODE_LIVE 1 /* T if struct is live */
#define CACHEFS_ACTIVE_INODE_INITING 2 /* T if struct is being initialised */
-#define CACHEFS_ACTIVE_INODE_RETIRING 3 /* T if inode is being retired */
+#define CACHEFS_ACTIVE_INODE_RELEASING 3 /* T if inode is being released */
+#define CACHEFS_ACTIVE_INODE_RECYCLING 4 /* T if inode is being retired */
+#define CACHEFS_ACTIVE_INODE_WITHDRAWN 5 /* T if inode has been withdrawn */
struct cachefs_block *storage; /* block containing data storage info */
wait_queue_head_t initwq; /* initialisation wait queue */
- struct cachefs_object *object; /* netfs's file/index object */
struct list_head link; /* link in object->active_inodes */
+ struct cachefs_cookie *cookie; /* netfs's file/index object */
+ struct rw_semaphore sem; /* guard on object pointer */
};
+extern void cachefs_withdraw_active_inode(struct cachefs_active_inode *active);
+
extern int cachefs_index_search(struct cachefs_active_inode *index,
struct cachefs_active_inode *target);
@@ -326,8 +352,15 @@
static inline void cachefs_block_put(struct cachefs_super *super, struct cachefs_block *block)
{
+ int usage = atomic_read(&block->usage);
/*kenter(",{bix=%u u=%d",block->bix,atomic_read(&block->usage));*/
- BUG_ON(atomic_read(&block->usage)<0);
+
+ if ((usage&0xffffff00)==0x6b6b6b00) {
+ printk("\ncachefs_block_put(%p,%p{u=%d})\n",super,block,usage);
+ BUG();
+ }
+
+ BUG_ON(usage<=0);
if (atomic_dec_and_test(&block->usage))
__cachefs_block_put(super,block);
}
Index: block.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/block.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- block.c 17 Apr 2003 11:59:04 -0000 1.2
+++ block.c 24 Apr 2003 12:02:34 -0000 1.3
@@ -125,6 +125,8 @@
_enter(",%u,,",bix);
+ if (_block) *_block = NULL;
+
/* get the block definition */
ret = cachefs_block_insert(super,bix,&block);
if (ret<0)
@@ -167,6 +169,9 @@
_enter(",%lx,%u,%d,,",inode?inode->vfs_inode.i_ino:CACHEFS_INO_MISC,bix,wipe);
+ if (_block) *_block = NULL;
+ if (_page) *_page = NULL;
+
/* get the block definition */
ret = cachefs_block_insert(super,bix,&block);
if (ret<0) {
@@ -242,10 +247,13 @@
clear_bit(CACHEFS_BLOCK_ALLOC,&block->flags);
wake_up_all(&block->writewq);
- if (_block)
+ if (_block) {
*_block = block;
- else
+ }
+ else {
cachefs_block_put(super,block);
+ block = NULL;
+ }
if (_page) {
*_page = page;
@@ -395,6 +403,8 @@
_enter(",%u,",bix);
+ *_block = NULL;
+
/* allocate a block record just in case */
newblock = kmalloc(sizeof(*newblock),GFP_KERNEL);
if (!newblock)
@@ -460,6 +470,8 @@
unsigned long flags;
_enter(",%d,",bix);
+
+ *_block = NULL;
read_lock_irqsave(&super->blk_tree_lock,flags);
node = super->blk_tree.rb_node;
Index: aops.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/aops.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- aops.c 17 Apr 2003 11:59:04 -0000 1.25
+++ aops.c 24 Apr 2003 12:02:34 -0000 1.26
@@ -73,6 +73,8 @@
{
struct cachefs_page *cookie = (struct cachefs_page*) page->private;
+ *_cookie = NULL;
+
if (!cookie) {
cookie = kmalloc(sizeof(*cookie),gfp_flags);
if (!cookie)
@@ -208,6 +210,8 @@
_enter("{bits=%u},%llu,%d,%x,",sb->s_blocksize_bits,first_sector,nr_vecs,gfp_flags);
+ *_bio = NULL;
+
bio = bio_alloc(gfp_flags,nr_vecs);
if (!bio && (current->flags & PF_MEMALLOC)) {
@@ -838,6 +842,7 @@
*/
static int cachefs_releasepage(struct page *page, int gfp_flags)
{
+ struct cachefs_block *block;
struct cachefs_page *cookie;
_enter("{%lu},%x",page->index,gfp_flags);
@@ -849,9 +854,9 @@
ClearPageMappedToDisk(page);
if (cookie) {
- if (cookie->mapped_block)
- cachefs_block_put(page->mapping->host->i_sb->s_fs_info,
- cookie->mapped_block);
+ block = xchg(&cookie->mapped_block,NULL);
+ if (block)
+ cachefs_block_put(page->mapping->host->i_sb->s_fs_info,block);
dbgfree(cookie);
kfree(cookie);
}
@@ -1054,8 +1059,6 @@
cachefs_trans_commit(step->transaction);
step->transaction = NULL;
- cachefs_block_put(super,block);
-
/* synchronise after committing (so our allocation will be sync'd before block reuse) */
if ((step->flags & CACHEFS_BLOCK_NEED_SYNC) &&
test_bit(CACHEFS_BLOCK_CRITICAL,&block->flags)
@@ -1063,11 +1066,15 @@
cachefs_trans_sync(super,0);
}
+ cachefs_block_put(super,block);
+ block = NULL;
+
_leave(" = 0 [block %u]",step->bix);
return 0;
error_block:
cachefs_block_put(super,block);
+ block = NULL;
error_sem:
up(&super->alloc_sem);
cachefs_trans_put(step->transaction);
@@ -1288,9 +1295,9 @@
}
if (ret<0) {
- if (cookie->mapped_block)
- cachefs_block_put(inode->vfs_inode.i_sb->s_fs_info,cookie->mapped_block);
- cookie->mapped_block = NULL;
+ struct cachefs_block *block = xchg(&cookie->mapped_block,NULL);
+ if (block)
+ cachefs_block_put(inode->vfs_inode.i_sb->s_fs_info,block);
_leave(" = %d",ret);
return ret;
}
@@ -1322,6 +1329,8 @@
struct page *page;
_enter("{%lu},%u",inode->vfs_inode.i_ino,index);
+
+ *_page = NULL;
page = read_cache_page(mapping,index,(filler_t*)mapping->a_ops->readpage,NULL);
dbgpgalloc(page);
More information about the linux-afs-cvs
mailing list