aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHuang Ying <ying.huang@intel.com>2014-09-12 07:21:11 -0400
committerJaegeuk Kim <jaegeuk@kernel.org>2014-09-16 07:10:46 -0400
commitc6e489305eb5ed029002b037e36800032a994bb4 (patch)
tree11e5615fa53e993dd997556e839ba8014a350af1
parent7704182387f7eab6217a587420f8a3b3aa2d17d5 (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.h6
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);