diff options
author | Huang Ying <ying.huang@intel.com> | 2014-09-12 07:21:11 -0400 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2014-09-16 07:10:46 -0400 |
commit | c6e489305eb5ed029002b037e36800032a994bb4 (patch) | |
tree | 11e5615fa53e993dd997556e839ba8014a350af1 | |
parent | 7704182387f7eab6217a587420f8a3b3aa2d17d5 (diff) |
f2fs: fix a race condition in next_free_nid
The nm_i->fcnt checking is executed before spin_lock, so if another
thread delete the last free_nid from the list, the wrong nid may be
gotten. So fix the race condition by moving the nm_i->fnct checking
into spin_lock.
Signed-off-by: Huang, Ying <ying.huang@intel.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r-- | fs/f2fs/node.h | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h index b24f588a0fe4..324917d757f7 100644 --- a/fs/f2fs/node.h +++ b/fs/f2fs/node.h | |||
@@ -115,9 +115,11 @@ static inline int next_free_nid(struct f2fs_sb_info *sbi, nid_t *nid) | |||
115 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 115 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
116 | struct free_nid *fnid; | 116 | struct free_nid *fnid; |
117 | 117 | ||
118 | if (nm_i->fcnt <= 0) | ||
119 | return -1; | ||
120 | spin_lock(&nm_i->free_nid_list_lock); | 118 | spin_lock(&nm_i->free_nid_list_lock); |
119 | if (nm_i->fcnt <= 0) { | ||
120 | spin_unlock(&nm_i->free_nid_list_lock); | ||
121 | return -1; | ||
122 | } | ||
121 | fnid = list_entry(nm_i->free_nid_list.next, struct free_nid, list); | 123 | fnid = list_entry(nm_i->free_nid_list.next, struct free_nid, list); |
122 | *nid = fnid->nid; | 124 | *nid = fnid->nid; |
123 | spin_unlock(&nm_i->free_nid_list_lock); | 125 | spin_unlock(&nm_i->free_nid_list_lock); |