&b->b);
clear_bit(B_Valid, &b->b.flags);
+ lafs_unclean(b);
if (test_and_clear_bit(B_Dirty, &b->b.flags))
lafs_space_return(fs, 1);
if (test_and_clear_bit(B_Realloc, &b->b.flags))
u32 inum, fsnum;
struct inode *ino = NULL;
struct datablock *b, *tmp;
+ int rv = 0;
+ mutex_lock(&fs->cleaner.lock);
dprintk("try_clean: state = %d\n", tc->ac.state);
if (tc->ch == NULL && tc->ss) {
/* Need to read in the cluster header */
fs->prime_sb->s_blocksize),
&tc->ac);
+ rv = 0;
if (err == -EAGAIN)
- return 0;
+ goto out;
if (err == -EIO) {
//printk("CLEANER got IO error !!\n");
// FIXME adjust youth to so as not to touch this again
bad_header:
tc->ac.state = 0;
tc->ss = 0;
- return 0;
+ rv = 0;
+ goto out;
}
BUG_ON(err);
// FIXME check checksum of the cluster_header
iput(b->b.inode);
putdref(b, MKREF(cleaning));
putref(cb, MKREF(clean2));
+ rv = -1;
if (err)
- return -1;
+ goto out;
}
- return tc->ch == NULL && tc->ss == 0 &&
+ rv = tc->ch == NULL && tc->ss == 0 &&
list_empty(&tc->cleaning);
+out:
+ mutex_unlock(&fs->cleaner.lock);
+ return rv;
+}
+
+void lafs_unclean(struct datablock *db)
+{
+ if (!list_empty_careful(&db->cleaning)) {
+ struct fs *fs = fs_from_inode(db->b.inode);
+ mutex_lock(&fs->cleaner.lock);
+ if (!list_empty(&db->cleaning)) {
+ list_del_init(&db->cleaning);
+ putdref(db, MKREF(cleaning));
+ iput(db->b.inode);
+ if (test_and_clear_bit(B_Async, &db->b.flags))
+ putdref(db, MKREF(async));
+ }
+ mutex_unlock(&fs->cleaner.lock);
+ }
}
static unsigned long do_clean(struct fs *fs)
int lafs_start_cleaner(struct fs *fs);
void lafs_stop_cleaner(struct fs *fs);
void lafs_wake_cleaner(struct fs *fs);
+void lafs_unclean(struct datablock *db);
/* cluster.c */
unsigned long long lafs_cluster_allocate(struct block *b, int cnum);
init_waitqueue_head(&fs->sb_writes_wait);
init_waitqueue_head(&fs->async_complete);
init_waitqueue_head(&fs->trunc_wait);
+ mutex_init(&fs->cleaner.lock);
spin_lock_init(&fs->stable_lock);
spin_lock_init(&fs->alloc_lock);
spin_lock_init(&fs->lock);