if (b == NULL)
break;
- if (list_empty(&b->cleaning)) {
- list_add_tail(&b->cleaning, &tc->cleaning);
+ if (!test_and_set_bit(B_Cleaning, &b->b.flags)) {
getdref(b, MKREF(cleaning));
igrab(ino);
}
+ if (list_empty(&b->cleaning))
+ list_add_tail(&b->cleaning, &tc->cleaning);
+
/* FIXME do I need a memory barrier. to ensure truncate
* sees the not-list_empty, and we see i_size? */
((loff_t)bnum << ino->i_blkbits)
>= i_size_read(ino))) {
list_del_init(&b->cleaning);
- putdref(b, MKREF(cleaning));
- iput(ino);
+ if (test_and_clear_bit(B_Cleaning, &b->b.flags)) {
+ putdref(b, MKREF(cleaning));
+ iput(ino);
+ }
}
putdref(b, MKREF(cleaning));
}
*/
done_cleaning:
list_del_init(&b->cleaning);
- ino = b->b.inode;
- putdref(b, MKREF(cleaning));
+ if (test_and_clear_bit(B_Cleaning, &b->b.flags)) {
+ ino = b->b.inode;
+ putdref(b, MKREF(cleaning));
+ iput(ino);
+ }
putref(cb, MKREF(clean2));
- iput(ino);
if (rv)
goto out;
}
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)) {
+ if (!list_empty(&db->cleaning))
list_del_init(&db->cleaning);
+ if (test_and_clear_bit(B_Cleaning, &db->b.flags)) {
putdref(db, MKREF(cleaning));
iput(db->b.inode);
if (test_and_clear_bit(B_Async, &db->b.flags)) {
#define dblk(__bl) container_of(__bl, struct datablock, b)
enum {
- /* NOTE: 31 flags in used. Need to overlap 'data' with 'index' if
+ /* NOTE: 32 flags in used. Need to overlap 'data' with 'index' if
* we need much more
*/
/* First flags that are meaningful for both Data and Index blocks
B_PhysValid, /* ->physaddr is correct */
/* Flags that are only relevant for Data Block
- * currently 6 */
+ * currently 7 */
B_PinPending, /* set on data blocks while checkpoint_locked if we might
* want to mark them dirty
B_HaveWriteback,/* We own the page writeback flag and when all blocks
* are unlocked we should clear it. */
B_Claimed, /* Used for exclusive allocation of inodes */
+ B_Cleaning, /* Used by cleaner to track which blocks it has a
+ * reference on already. */
+
/* Flags that are only relevant for Index Blocks
- * currently 2 */
+ * currently 3 */
B_OnFree, /* index block on the free list */
B_PrimaryRef, /* This indexblock has not been incorporated into the
* parent, and so can only be found by being a sibling