mutex_lock_nested(&fs->orphans->i_mutex, I_MUTEX_QUOTA);
bnum = (om->nextfree + om->reserved) >>
(fs->blocksize_bits-4);
-
b = lafs_get_block(fs->orphans, bnum, NULL, GFP_KERNEL,
MKREF(orphan_reserve));
+ om->reserved++;
+ mutex_unlock(&fs->orphans->i_mutex);
if (b) {
if (async)
err = lafs_read_block_async(b);
err = lafs_read_block(b);
if (err)
putdref(b, MKREF(orphan_reserve));
- else
- om->reserved++;
} else
err = -ENOMEM;
- mutex_unlock(&fs->orphans->i_mutex);
+ if (err) {
+ mutex_lock_nested(&fs->orphans->i_mutex, I_MUTEX_QUOTA);
+ om->reserved--;
+ mutex_unlock(&fs->orphans->i_mutex);
+ }
lafs_iolock_written(&b->b);
set_bit(B_PinPending, &b->b.flags);
lafs_iounlock_block(&b->b);
*/
if ((om->nextfree + om->reserved) <=
(bnum << (fs->blocksize_bits-4))
- )
+ ) {
+ LAFS_BUG(!test_bit(B_PinPending, &b->b.flags), &b->b);
lafs_erase_dblock(b);
+ }
putdref(b, MKREF(orphan_reserve));
}
* so we can try again later.
* All IO requests here must be async as we run from the cleaner
* thread.
+ * We can block in orphan->i_mutex or even in erase_dblock in
+ * orphan_abort, but i_mutex is only held for very short periods
+ * like a spinlock, and erase_dblock should not block as the block
+ * should be PinPending;
*/
void lafs_orphan_release(struct fs *fs, struct datablock *b, struct inode *ino)
{