diff options
author | Josef Bacik <josef@redhat.com> | 2011-09-21 16:55:59 -0400 |
---|---|---|
committer | Josef Bacik <josef@redhat.com> | 2011-10-19 15:12:46 -0400 |
commit | a8c9e5769718d47e87cce40c9b84cab421804797 (patch) | |
tree | 6bfc08ccb5afa532449741230f5733c4f44499fc /fs/btrfs/inode.c | |
parent | 3b16a4e3c355ee3c790473decfcf83d4faeb8ce0 (diff) |
Btrfs: fix orphan cleanup regression
In fixing how we deal with bad inodes, we had a regression in the orphan cleanup
code, since it expects to get a bad inode back. So fix it to deal with getting
-ESTALE back by deleting the orphan item manually and moving on. Thanks,
Reported-by: Simon Kirby <sim@hostway.ca>
Signed-off-by: Josef Bacik <josef@redhat.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 36 |
1 files changed, 17 insertions, 19 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 88e3956be57d..8005be176252 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -2285,37 +2285,35 @@ int btrfs_orphan_cleanup(struct btrfs_root *root) | |||
2285 | found_key.type = BTRFS_INODE_ITEM_KEY; | 2285 | found_key.type = BTRFS_INODE_ITEM_KEY; |
2286 | found_key.offset = 0; | 2286 | found_key.offset = 0; |
2287 | inode = btrfs_iget(root->fs_info->sb, &found_key, root, NULL); | 2287 | inode = btrfs_iget(root->fs_info->sb, &found_key, root, NULL); |
2288 | if (IS_ERR(inode)) { | 2288 | ret = PTR_RET(inode); |
2289 | ret = PTR_ERR(inode); | 2289 | if (ret && ret != -ESTALE) |
2290 | goto out; | 2290 | goto out; |
2291 | } | ||
2292 | |||
2293 | /* | ||
2294 | * add this inode to the orphan list so btrfs_orphan_del does | ||
2295 | * the proper thing when we hit it | ||
2296 | */ | ||
2297 | spin_lock(&root->orphan_lock); | ||
2298 | list_add(&BTRFS_I(inode)->i_orphan, &root->orphan_list); | ||
2299 | spin_unlock(&root->orphan_lock); | ||
2300 | 2291 | ||
2301 | /* | 2292 | /* |
2302 | * if this is a bad inode, means we actually succeeded in | 2293 | * Inode is already gone but the orphan item is still there, |
2303 | * removing the inode, but not the orphan record, which means | 2294 | * kill the orphan item. |
2304 | * we need to manually delete the orphan since iput will just | ||
2305 | * do a destroy_inode | ||
2306 | */ | 2295 | */ |
2307 | if (is_bad_inode(inode)) { | 2296 | if (ret == -ESTALE) { |
2308 | trans = btrfs_start_transaction(root, 0); | 2297 | trans = btrfs_start_transaction(root, 1); |
2309 | if (IS_ERR(trans)) { | 2298 | if (IS_ERR(trans)) { |
2310 | ret = PTR_ERR(trans); | 2299 | ret = PTR_ERR(trans); |
2311 | goto out; | 2300 | goto out; |
2312 | } | 2301 | } |
2313 | btrfs_orphan_del(trans, inode); | 2302 | ret = btrfs_del_orphan_item(trans, root, |
2303 | found_key.objectid); | ||
2304 | BUG_ON(ret); | ||
2314 | btrfs_end_transaction(trans, root); | 2305 | btrfs_end_transaction(trans, root); |
2315 | iput(inode); | ||
2316 | continue; | 2306 | continue; |
2317 | } | 2307 | } |
2318 | 2308 | ||
2309 | /* | ||
2310 | * add this inode to the orphan list so btrfs_orphan_del does | ||
2311 | * the proper thing when we hit it | ||
2312 | */ | ||
2313 | spin_lock(&root->orphan_lock); | ||
2314 | list_add(&BTRFS_I(inode)->i_orphan, &root->orphan_list); | ||
2315 | spin_unlock(&root->orphan_lock); | ||
2316 | |||
2319 | /* if we have links, this was a truncate, lets do that */ | 2317 | /* if we have links, this was a truncate, lets do that */ |
2320 | if (inode->i_nlink) { | 2318 | if (inode->i_nlink) { |
2321 | if (!S_ISREG(inode->i_mode)) { | 2319 | if (!S_ISREG(inode->i_mode)) { |