diff options
| author | Jaegeuk Kim <jaegeuk@kernel.org> | 2015-03-26 21:46:38 -0400 |
|---|---|---|
| committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2015-04-10 18:08:56 -0400 |
| commit | c9ef481097d17fb8ff8ea7930ce715b5a676f10f (patch) | |
| tree | 36dc00bc17bb7ec2ac6f7993d173c95f90c5bc31 | |
| parent | adad81ed42bbc537f37192dcdd9a83e34bb61987 (diff) | |
f2fs: fix mismatching lock and unlock pages for roll-forward recovery
Previously, inode page is not correctly locked and unlocked in pair during
the roll-forward recovery.
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
| -rw-r--r-- | fs/f2fs/recovery.c | 48 |
1 files changed, 31 insertions, 17 deletions
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index e60ffaa380f1..c69de88a6453 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c | |||
| @@ -258,6 +258,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi, | |||
| 258 | struct f2fs_summary_block *sum_node; | 258 | struct f2fs_summary_block *sum_node; |
| 259 | struct f2fs_summary sum; | 259 | struct f2fs_summary sum; |
| 260 | struct page *sum_page, *node_page; | 260 | struct page *sum_page, *node_page; |
| 261 | struct dnode_of_data tdn = *dn; | ||
| 261 | nid_t ino, nid; | 262 | nid_t ino, nid; |
| 262 | struct inode *inode; | 263 | struct inode *inode; |
| 263 | unsigned int offset; | 264 | unsigned int offset; |
| @@ -285,17 +286,15 @@ got_it: | |||
| 285 | /* Use the locked dnode page and inode */ | 286 | /* Use the locked dnode page and inode */ |
| 286 | nid = le32_to_cpu(sum.nid); | 287 | nid = le32_to_cpu(sum.nid); |
| 287 | if (dn->inode->i_ino == nid) { | 288 | if (dn->inode->i_ino == nid) { |
| 288 | struct dnode_of_data tdn = *dn; | ||
| 289 | tdn.nid = nid; | 289 | tdn.nid = nid; |
| 290 | if (!dn->inode_page_locked) | ||
| 291 | lock_page(dn->inode_page); | ||
| 290 | tdn.node_page = dn->inode_page; | 292 | tdn.node_page = dn->inode_page; |
| 291 | tdn.ofs_in_node = le16_to_cpu(sum.ofs_in_node); | 293 | tdn.ofs_in_node = le16_to_cpu(sum.ofs_in_node); |
| 292 | truncate_data_blocks_range(&tdn, 1); | 294 | goto truncate_out; |
| 293 | return 0; | ||
| 294 | } else if (dn->nid == nid) { | 295 | } else if (dn->nid == nid) { |
| 295 | struct dnode_of_data tdn = *dn; | ||
| 296 | tdn.ofs_in_node = le16_to_cpu(sum.ofs_in_node); | 296 | tdn.ofs_in_node = le16_to_cpu(sum.ofs_in_node); |
| 297 | truncate_data_blocks_range(&tdn, 1); | 297 | goto truncate_out; |
| 298 | return 0; | ||
| 299 | } | 298 | } |
| 300 | 299 | ||
| 301 | /* Get the node page */ | 300 | /* Get the node page */ |
| @@ -319,18 +318,33 @@ got_it: | |||
| 319 | bidx = start_bidx_of_node(offset, F2FS_I(inode)) + | 318 | bidx = start_bidx_of_node(offset, F2FS_I(inode)) + |
| 320 | le16_to_cpu(sum.ofs_in_node); | 319 | le16_to_cpu(sum.ofs_in_node); |
| 321 | 320 | ||
| 322 | if (ino != dn->inode->i_ino) { | 321 | /* |
| 323 | truncate_hole(inode, bidx, bidx + 1); | 322 | * if inode page is locked, unlock temporarily, but its reference |
| 323 | * count keeps alive. | ||
| 324 | */ | ||
| 325 | if (ino == dn->inode->i_ino && dn->inode_page_locked) | ||
| 326 | unlock_page(dn->inode_page); | ||
| 327 | |||
| 328 | set_new_dnode(&tdn, inode, NULL, NULL, 0); | ||
| 329 | if (get_dnode_of_data(&tdn, bidx, LOOKUP_NODE)) | ||
| 330 | goto out; | ||
| 331 | |||
| 332 | if (tdn.data_blkaddr == blkaddr) | ||
| 333 | truncate_data_blocks_range(&tdn, 1); | ||
| 334 | |||
| 335 | f2fs_put_dnode(&tdn); | ||
| 336 | out: | ||
| 337 | if (ino != dn->inode->i_ino) | ||
| 324 | iput(inode); | 338 | iput(inode); |
| 325 | } else { | 339 | else if (dn->inode_page_locked) |
| 326 | struct dnode_of_data tdn; | 340 | lock_page(dn->inode_page); |
| 327 | set_new_dnode(&tdn, inode, dn->inode_page, NULL, 0); | 341 | return 0; |
| 328 | if (get_dnode_of_data(&tdn, bidx, LOOKUP_NODE)) | 342 | |
| 329 | return 0; | 343 | truncate_out: |
| 330 | if (tdn.data_blkaddr != NULL_ADDR) | 344 | if (datablock_addr(tdn.node_page, tdn.ofs_in_node) == blkaddr) |
| 331 | truncate_data_blocks_range(&tdn, 1); | 345 | truncate_data_blocks_range(&tdn, 1); |
| 332 | f2fs_put_page(tdn.node_page, 1); | 346 | if (dn->inode->i_ino == nid && !dn->inode_page_locked) |
| 333 | } | 347 | unlock_page(dn->inode_page); |
| 334 | return 0; | 348 | return 0; |
| 335 | } | 349 | } |
| 336 | 350 | ||
