f2fs: fix handling orphan inodes
This patch fixes mishandling of the sbi->n_orphans variable. If users request lots of f2fs_unlink(), check_orphan_space() could be contended. In such the case, sbi->n_orphans can be read incorrectly so that f2fs_unlink() would fall into the wrong state which results in the failure of add_orphan_inode(). So, let's increment sbi->n_orphans virtually prior to the actual orphan inode stuffs. After that, let's release sbi->n_orphans by calling release_orphan_inode or remove_orphan_inode. Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
This commit is contained in:
@@ -182,7 +182,7 @@ const struct address_space_operations f2fs_meta_aops = {
|
||||
.set_page_dirty = f2fs_set_meta_page_dirty,
|
||||
};
|
||||
|
||||
int check_orphan_space(struct f2fs_sb_info *sbi)
|
||||
int acquire_orphan_inode(struct f2fs_sb_info *sbi)
|
||||
{
|
||||
unsigned int max_orphans;
|
||||
int err = 0;
|
||||
@@ -197,10 +197,19 @@ int check_orphan_space(struct f2fs_sb_info *sbi)
|
||||
mutex_lock(&sbi->orphan_inode_mutex);
|
||||
if (sbi->n_orphans >= max_orphans)
|
||||
err = -ENOSPC;
|
||||
else
|
||||
sbi->n_orphans++;
|
||||
mutex_unlock(&sbi->orphan_inode_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
void release_orphan_inode(struct f2fs_sb_info *sbi)
|
||||
{
|
||||
mutex_lock(&sbi->orphan_inode_mutex);
|
||||
sbi->n_orphans--;
|
||||
mutex_unlock(&sbi->orphan_inode_mutex);
|
||||
}
|
||||
|
||||
void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
|
||||
{
|
||||
struct list_head *head, *this;
|
||||
@@ -229,8 +238,6 @@ retry:
|
||||
list_add(&new->list, this->prev);
|
||||
else
|
||||
list_add_tail(&new->list, head);
|
||||
|
||||
sbi->n_orphans++;
|
||||
out:
|
||||
mutex_unlock(&sbi->orphan_inode_mutex);
|
||||
}
|
||||
|
Reference in New Issue
Block a user