test_bit(I_Destroyed, &LAFSI(in)->iflags))) {
dblk(b)->my_inode = NULL;
LAFSI(in)->dblock = NULL;
+ LAFSI(in)->iblock = NULL;
spin_unlock(&lafs_hash_lock);
if (test_bit(I_Destroyed, &LAFSI(in)->iflags))
lafs_destroy_inode(in);
{
/* find, and load if needed, this inum */
struct inode *ino = NULL;
+ struct inode *oldino;
struct datablock *b = NULL;
struct inode *inodefile;
struct sb_key *k;
if (err)
goto err;
- if (b->my_inode) {
+ oldino = b->my_inode;
+ if (oldino) {
/* The inode is new, but the block thinks it has an
* old inode, so we must be in the process of destroying
* the old one.
* So fail the lookup without even looking at the content
* of the block (Which might not be clear yet).
*/
- err = -ENOENT;
- goto err;
+ spin_lock(&oldino->i_data.private_lock);
+ if (!test_bit(I_Deleting, &LAFSI(oldino)->iflags)) {
+ b->my_inode = NULL;
+ LAFSI(oldino)->dblock = NULL;
+ LAFSI(oldino)->iblock = NULL;
+ }
+ spin_unlock(&oldino->i_data.private_lock);
+ if (b->my_inode) {
+ err = -ENOENT;
+ goto err;
+ }
}
err = lafs_import_inode(ino, b);
li->type = 0;
+ /* Now is a good time to break the linkage between
+ * inode and dblock - but node if the file is
+ * being deleted
+ */
+ if (!test_bit(I_Deleting, &LAFSI(ino)->iflags)) {
+ struct datablock *db;
+ spin_lock(&ino->i_data.private_lock);
+ db = LAFSI(ino)->dblock;
+ if (db) {
+ struct indexblock *ib = LAFSI(ino)->iblock;
+ LAFS_BUG(ib && atomic_read(&ib->b.refcnt), &db->b);
+ db->my_inode = NULL;
+ LAFSI(ino)->dblock = NULL;
+ LAFSI(ino)->iblock = NULL;
+ }
+ spin_unlock(&ino->i_data.private_lock);
+ }
+
/* FIXME release quota inodes if filesystem */
}