[!!test_bit(B_Phase1, &b->b.flags)]);
clear_bit(B_Pinned, &b->b.flags);
spin_unlock(&fs->lock);
+ lafs_inode_checkpin(b->b.inode);
if (!test_bit(B_Root, &b->b.flags))
lafs_refile(&b->b.parent->b, 0);
if (onlist)
ino->i_nlink = 1;
LAFSI(ino)->md.file.parent = dir->i_ino;
lafs_dirty_inode(ino);
+ lafs_inode_checkpin(ino);
dir_log_commit(&uh, fs, dir, &de->d_name, ino->i_ino, DIROP_LINK, NULL);
dir_create_commit(&doh, fs, dir, de->d_name.name, de->d_name.len,
ino->i_ino, DT_REG);
inode_inc_link_count(inode);
lafs_dirty_inode(inode);
+ lafs_inode_checkpin(inode);
clear_bit(B_PinPending, &inodb->b.flags);
putdref(inodb, MKREF(inode_update));
lafs_orphan_commit(&oi);
lafs_checkpoint_unlock(fs);
lafs_dirty_inode(inode);
+ lafs_inode_checkpin(inode);
lafs_dir_handle_orphans(dir);
putdref(inodb, MKREF(inode_update));
clear_bit(B_PinPending, &inodb->b.flags);
clear_bit(B_PinPending, &inodb->b.flags);
putdref(inodb, MKREF(inode_update));
lafs_dirty_inode(dir);
+ lafs_inode_checkpin(inode);
+ lafs_inode_checkpin(dir);
lafs_checkpoint_unlock(fs);
lafs_dir_handle_orphans(dir);
return 0;
putdref(b, MKREF(symlink));
ino->i_size = l;
lafs_dirty_inode(ino);
+ lafs_inode_checkpin(ino);
dir_log_commit(&uh, fs, dir, &de->d_name, ino->i_ino, DIROP_LINK, NULL);
dir_create_commit(&doh, fs, dir, de->d_name.name, de->d_name.len,
ino->i_nlink = 2; /* From parent, and from '.' */
lafs_dirty_inode(dir);
lafs_dirty_inode(ino);
+ lafs_inode_checkpin(dir);
+ lafs_inode_checkpin(ino);
lafs_orphan_release(fs, inodb);
dir_create_commit(&doh, fs, dir, de->d_name.name, de->d_name.len,
ino->i_ino, DT_DIR);
LAFSI(ino)->md.file.parent = dir->i_ino;
ino->i_nlink = 1;
lafs_dirty_inode(ino);
+ lafs_inode_checkpin(ino);
dir_log_commit(&uh, fs, dir, &de->d_name, ino->i_ino, DIROP_LINK, NULL);
dir_create_commit(&doh, fs, dir, de->d_name.name, de->d_name.len,
inode_dec_link_count(new_inode);
inode_dec_link_count(new_inode);
lafs_dirty_inode(new_inode);
+ lafs_inode_checkpin(new_inode);
}
lafs_dirty_inode(old_inode);
+ lafs_inode_checkpin(new_dir);
+ lafs_inode_checkpin(old_dir);
clear_bit(B_PinPending, &olddb->b.flags);
putdref(olddb, MKREF(inode_update));
if (new_inode) {
/* FIXME unpin the db if it is in the same phase?? */
spin_unlock(&ino->i_mapping->private_lock);
+ lafs_inode_checkpin(p->inode);
ino = db->b.inode;
spin_lock(&ino->i_mapping->private_lock);
}
atomic_dec(&b->parent->pincnt[oldphase]);
lafs_refile(&b->parent->b, 0);
}
+ lafs_inode_checkpin(b->inode);
}
lafs_iounlock_block(b, 0);
return;
int ph;
int free_me = 0;
int onlru = 0;
+ struct inode *checkpin = NULL;
spin_lock(&lafs_hash_lock);
if (!list_empty(&b->lru) &&
dec = onlru;
spin_unlock(&fs->lock);
}
+ if (test_bit(B_InoIdx, &b->flags) &&
+ b->inode->i_nlink)
+ checkpin = b->inode;
if (!test_bit(B_Root, &b->flags)) {
atomic_dec(&b->parent->pincnt[ph]);
if (next_parent != &b->parent->b) {
physref = 0;
}
+ if (checkpin)
+ lafs_inode_checkpin(checkpin);
+
if (free_me)
kfree(b);
b = NULL;
return err;
}
+void lafs_inode_checkpin(struct inode *ino)
+{
+ /* Make sure I_Pinned is set correctly.
+ * It should be set precisely if i_nlink is non-zero,
+ * and ->iblock is B_Pinned.
+ * When it is set, we own a reference to the inode.
+ *
+ * This needs to be called whenever we change
+ * i_nlink, and whenever we pin or unpin an InoIdx
+ * block.
+ */
+ if (ino->i_nlink == 0) {
+ /* I_Pinned should not be set */
+ if (test_and_clear_bit(I_Pinned, &LAFSI(ino)->iflags))
+ iput(ino);
+ } else {
+ /* Need to check if iblock is Pinned. */
+ struct indexblock *ib = NULL;
+ if (LAFSI(ino)->iblock) {
+ spin_lock(&ino->i_data.private_lock);
+ ib = LAFSI(ino)->iblock;
+ if (ib && !test_bit(B_Pinned, &ib->b.flags))
+ ib = NULL;
+ spin_unlock(&ino->i_data.private_lock);
+ }
+ if (ib) {
+ if (!test_and_set_bit(I_Pinned, &LAFSI(ino)->iflags))
+ igrab(ino);
+ } else {
+ if (test_and_clear_bit(I_Pinned, &LAFSI(ino)->iflags))
+ iput(ino);
+ }
+ }
+}
+
struct datablock *lafs_inode_dblock(struct inode *ino, int async, REFARG)
{
struct datablock *db = NULL;
struct inode *lafs_iget(struct super_block *fs, ino_t inum, int async);
struct inode *lafs_iget_fs(struct fs *fs, int fsnum, int inum, int async);
int __must_check lafs_import_inode(struct inode *ino, struct datablock *b);
+void lafs_inode_checkpin(struct inode *ino);
void lafs_clear_inode(struct inode *ino);
void lafs_delete_inode(struct inode *ino);
void lafs_dirty_inode(struct inode *ino);
#define I_Deleting 3 /* preserve the inode while truncate-on-delete happens */
#define I_Destroyed 4 /* inode destroy has been delayed */
#define I_Trunc 5 /* a truncation is in process */
+#define I_Pinned 6 /* InoIdx is pinned, i_nlink is non-zero, and consequently
+ * we own an extra ref to the inode.
+ */
/* next three indicate if we hold a reference on the relevant qent */
#define I_QUid 8
#define I_QGid 9