diff options
Diffstat (limited to 'fs/ocfs2/journal.c')
| -rw-r--r-- | fs/ocfs2/journal.c | 111 |
1 files changed, 90 insertions, 21 deletions
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 4f502382180f..ff531928269e 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c | |||
| @@ -50,6 +50,8 @@ | |||
| 50 | #include "sysfile.h" | 50 | #include "sysfile.h" |
| 51 | #include "uptodate.h" | 51 | #include "uptodate.h" |
| 52 | #include "quota.h" | 52 | #include "quota.h" |
| 53 | #include "file.h" | ||
| 54 | #include "namei.h" | ||
| 53 | 55 | ||
| 54 | #include "buffer_head_io.h" | 56 | #include "buffer_head_io.h" |
| 55 | #include "ocfs2_trace.h" | 57 | #include "ocfs2_trace.h" |
| @@ -69,13 +71,15 @@ static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb, | |||
| 69 | static int ocfs2_trylock_journal(struct ocfs2_super *osb, | 71 | static int ocfs2_trylock_journal(struct ocfs2_super *osb, |
| 70 | int slot_num); | 72 | int slot_num); |
| 71 | static int ocfs2_recover_orphans(struct ocfs2_super *osb, | 73 | static int ocfs2_recover_orphans(struct ocfs2_super *osb, |
| 72 | int slot); | 74 | int slot, |
| 75 | enum ocfs2_orphan_reco_type orphan_reco_type); | ||
| 73 | static int ocfs2_commit_thread(void *arg); | 76 | static int ocfs2_commit_thread(void *arg); |
| 74 | static void ocfs2_queue_recovery_completion(struct ocfs2_journal *journal, | 77 | static void ocfs2_queue_recovery_completion(struct ocfs2_journal *journal, |
| 75 | int slot_num, | 78 | int slot_num, |
| 76 | struct ocfs2_dinode *la_dinode, | 79 | struct ocfs2_dinode *la_dinode, |
| 77 | struct ocfs2_dinode *tl_dinode, | 80 | struct ocfs2_dinode *tl_dinode, |
| 78 | struct ocfs2_quota_recovery *qrec); | 81 | struct ocfs2_quota_recovery *qrec, |
| 82 | enum ocfs2_orphan_reco_type orphan_reco_type); | ||
| 79 | 83 | ||
| 80 | static inline int ocfs2_wait_on_mount(struct ocfs2_super *osb) | 84 | static inline int ocfs2_wait_on_mount(struct ocfs2_super *osb) |
| 81 | { | 85 | { |
| @@ -149,7 +153,8 @@ int ocfs2_compute_replay_slots(struct ocfs2_super *osb) | |||
| 149 | return 0; | 153 | return 0; |
| 150 | } | 154 | } |
| 151 | 155 | ||
| 152 | void ocfs2_queue_replay_slots(struct ocfs2_super *osb) | 156 | void ocfs2_queue_replay_slots(struct ocfs2_super *osb, |
| 157 | enum ocfs2_orphan_reco_type orphan_reco_type) | ||
| 153 | { | 158 | { |
| 154 | struct ocfs2_replay_map *replay_map = osb->replay_map; | 159 | struct ocfs2_replay_map *replay_map = osb->replay_map; |
| 155 | int i; | 160 | int i; |
| @@ -163,7 +168,8 @@ void ocfs2_queue_replay_slots(struct ocfs2_super *osb) | |||
| 163 | for (i = 0; i < replay_map->rm_slots; i++) | 168 | for (i = 0; i < replay_map->rm_slots; i++) |
| 164 | if (replay_map->rm_replay_slots[i]) | 169 | if (replay_map->rm_replay_slots[i]) |
| 165 | ocfs2_queue_recovery_completion(osb->journal, i, NULL, | 170 | ocfs2_queue_recovery_completion(osb->journal, i, NULL, |
| 166 | NULL, NULL); | 171 | NULL, NULL, |
| 172 | orphan_reco_type); | ||
| 167 | replay_map->rm_state = REPLAY_DONE; | 173 | replay_map->rm_state = REPLAY_DONE; |
| 168 | } | 174 | } |
| 169 | 175 | ||
| @@ -1174,6 +1180,7 @@ struct ocfs2_la_recovery_item { | |||
| 1174 | struct ocfs2_dinode *lri_la_dinode; | 1180 | struct ocfs2_dinode *lri_la_dinode; |
| 1175 | struct ocfs2_dinode *lri_tl_dinode; | 1181 | struct ocfs2_dinode *lri_tl_dinode; |
| 1176 | struct ocfs2_quota_recovery *lri_qrec; | 1182 | struct ocfs2_quota_recovery *lri_qrec; |
| 1183 | enum ocfs2_orphan_reco_type lri_orphan_reco_type; | ||
| 1177 | }; | 1184 | }; |
| 1178 | 1185 | ||
| 1179 | /* Does the second half of the recovery process. By this point, the | 1186 | /* Does the second half of the recovery process. By this point, the |
| @@ -1195,6 +1202,7 @@ void ocfs2_complete_recovery(struct work_struct *work) | |||
| 1195 | struct ocfs2_dinode *la_dinode, *tl_dinode; | 1202 | struct ocfs2_dinode *la_dinode, *tl_dinode; |
| 1196 | struct ocfs2_la_recovery_item *item, *n; | 1203 | struct ocfs2_la_recovery_item *item, *n; |
| 1197 | struct ocfs2_quota_recovery *qrec; | 1204 | struct ocfs2_quota_recovery *qrec; |
| 1205 | enum ocfs2_orphan_reco_type orphan_reco_type; | ||
| 1198 | LIST_HEAD(tmp_la_list); | 1206 | LIST_HEAD(tmp_la_list); |
| 1199 | 1207 | ||
| 1200 | trace_ocfs2_complete_recovery( | 1208 | trace_ocfs2_complete_recovery( |
| @@ -1212,6 +1220,7 @@ void ocfs2_complete_recovery(struct work_struct *work) | |||
| 1212 | la_dinode = item->lri_la_dinode; | 1220 | la_dinode = item->lri_la_dinode; |
| 1213 | tl_dinode = item->lri_tl_dinode; | 1221 | tl_dinode = item->lri_tl_dinode; |
| 1214 | qrec = item->lri_qrec; | 1222 | qrec = item->lri_qrec; |
| 1223 | orphan_reco_type = item->lri_orphan_reco_type; | ||
| 1215 | 1224 | ||
| 1216 | trace_ocfs2_complete_recovery_slot(item->lri_slot, | 1225 | trace_ocfs2_complete_recovery_slot(item->lri_slot, |
| 1217 | la_dinode ? le64_to_cpu(la_dinode->i_blkno) : 0, | 1226 | la_dinode ? le64_to_cpu(la_dinode->i_blkno) : 0, |
| @@ -1236,7 +1245,8 @@ void ocfs2_complete_recovery(struct work_struct *work) | |||
| 1236 | kfree(tl_dinode); | 1245 | kfree(tl_dinode); |
| 1237 | } | 1246 | } |
| 1238 | 1247 | ||
| 1239 | ret = ocfs2_recover_orphans(osb, item->lri_slot); | 1248 | ret = ocfs2_recover_orphans(osb, item->lri_slot, |
| 1249 | orphan_reco_type); | ||
| 1240 | if (ret < 0) | 1250 | if (ret < 0) |
| 1241 | mlog_errno(ret); | 1251 | mlog_errno(ret); |
| 1242 | 1252 | ||
| @@ -1261,7 +1271,8 @@ static void ocfs2_queue_recovery_completion(struct ocfs2_journal *journal, | |||
| 1261 | int slot_num, | 1271 | int slot_num, |
| 1262 | struct ocfs2_dinode *la_dinode, | 1272 | struct ocfs2_dinode *la_dinode, |
| 1263 | struct ocfs2_dinode *tl_dinode, | 1273 | struct ocfs2_dinode *tl_dinode, |
| 1264 | struct ocfs2_quota_recovery *qrec) | 1274 | struct ocfs2_quota_recovery *qrec, |
| 1275 | enum ocfs2_orphan_reco_type orphan_reco_type) | ||
| 1265 | { | 1276 | { |
| 1266 | struct ocfs2_la_recovery_item *item; | 1277 | struct ocfs2_la_recovery_item *item; |
| 1267 | 1278 | ||
| @@ -1285,6 +1296,7 @@ static void ocfs2_queue_recovery_completion(struct ocfs2_journal *journal, | |||
| 1285 | item->lri_slot = slot_num; | 1296 | item->lri_slot = slot_num; |
| 1286 | item->lri_tl_dinode = tl_dinode; | 1297 | item->lri_tl_dinode = tl_dinode; |
| 1287 | item->lri_qrec = qrec; | 1298 | item->lri_qrec = qrec; |
| 1299 | item->lri_orphan_reco_type = orphan_reco_type; | ||
| 1288 | 1300 | ||
| 1289 | spin_lock(&journal->j_lock); | 1301 | spin_lock(&journal->j_lock); |
| 1290 | list_add_tail(&item->lri_list, &journal->j_la_cleanups); | 1302 | list_add_tail(&item->lri_list, &journal->j_la_cleanups); |
| @@ -1304,7 +1316,8 @@ void ocfs2_complete_mount_recovery(struct ocfs2_super *osb) | |||
| 1304 | /* No need to queue up our truncate_log as regular cleanup will catch | 1316 | /* No need to queue up our truncate_log as regular cleanup will catch |
| 1305 | * that */ | 1317 | * that */ |
| 1306 | ocfs2_queue_recovery_completion(journal, osb->slot_num, | 1318 | ocfs2_queue_recovery_completion(journal, osb->slot_num, |
| 1307 | osb->local_alloc_copy, NULL, NULL); | 1319 | osb->local_alloc_copy, NULL, NULL, |
| 1320 | ORPHAN_NEED_TRUNCATE); | ||
| 1308 | ocfs2_schedule_truncate_log_flush(osb, 0); | 1321 | ocfs2_schedule_truncate_log_flush(osb, 0); |
| 1309 | 1322 | ||
| 1310 | osb->local_alloc_copy = NULL; | 1323 | osb->local_alloc_copy = NULL; |
| @@ -1312,7 +1325,7 @@ void ocfs2_complete_mount_recovery(struct ocfs2_super *osb) | |||
| 1312 | 1325 | ||
| 1313 | /* queue to recover orphan slots for all offline slots */ | 1326 | /* queue to recover orphan slots for all offline slots */ |
| 1314 | ocfs2_replay_map_set_state(osb, REPLAY_NEEDED); | 1327 | ocfs2_replay_map_set_state(osb, REPLAY_NEEDED); |
| 1315 | ocfs2_queue_replay_slots(osb); | 1328 | ocfs2_queue_replay_slots(osb, ORPHAN_NEED_TRUNCATE); |
| 1316 | ocfs2_free_replay_slots(osb); | 1329 | ocfs2_free_replay_slots(osb); |
| 1317 | } | 1330 | } |
| 1318 | 1331 | ||
| @@ -1323,7 +1336,8 @@ void ocfs2_complete_quota_recovery(struct ocfs2_super *osb) | |||
| 1323 | osb->slot_num, | 1336 | osb->slot_num, |
| 1324 | NULL, | 1337 | NULL, |
| 1325 | NULL, | 1338 | NULL, |
| 1326 | osb->quota_rec); | 1339 | osb->quota_rec, |
| 1340 | ORPHAN_NEED_TRUNCATE); | ||
| 1327 | osb->quota_rec = NULL; | 1341 | osb->quota_rec = NULL; |
| 1328 | } | 1342 | } |
| 1329 | } | 1343 | } |
| @@ -1360,7 +1374,7 @@ restart: | |||
| 1360 | 1374 | ||
| 1361 | /* queue recovery for our own slot */ | 1375 | /* queue recovery for our own slot */ |
| 1362 | ocfs2_queue_recovery_completion(osb->journal, osb->slot_num, NULL, | 1376 | ocfs2_queue_recovery_completion(osb->journal, osb->slot_num, NULL, |
| 1363 | NULL, NULL); | 1377 | NULL, NULL, ORPHAN_NO_NEED_TRUNCATE); |
| 1364 | 1378 | ||
| 1365 | spin_lock(&osb->osb_lock); | 1379 | spin_lock(&osb->osb_lock); |
| 1366 | while (rm->rm_used) { | 1380 | while (rm->rm_used) { |
| @@ -1419,13 +1433,14 @@ skip_recovery: | |||
| 1419 | continue; | 1433 | continue; |
| 1420 | } | 1434 | } |
| 1421 | ocfs2_queue_recovery_completion(osb->journal, rm_quota[i], | 1435 | ocfs2_queue_recovery_completion(osb->journal, rm_quota[i], |
| 1422 | NULL, NULL, qrec); | 1436 | NULL, NULL, qrec, |
| 1437 | ORPHAN_NEED_TRUNCATE); | ||
| 1423 | } | 1438 | } |
| 1424 | 1439 | ||
| 1425 | ocfs2_super_unlock(osb, 1); | 1440 | ocfs2_super_unlock(osb, 1); |
| 1426 | 1441 | ||
| 1427 | /* queue recovery for offline slots */ | 1442 | /* queue recovery for offline slots */ |
| 1428 | ocfs2_queue_replay_slots(osb); | 1443 | ocfs2_queue_replay_slots(osb, ORPHAN_NEED_TRUNCATE); |
| 1429 | 1444 | ||
| 1430 | bail: | 1445 | bail: |
| 1431 | mutex_lock(&osb->recovery_lock); | 1446 | mutex_lock(&osb->recovery_lock); |
| @@ -1447,7 +1462,6 @@ bail: | |||
| 1447 | * requires that we call do_exit(). And it isn't exported, but | 1462 | * requires that we call do_exit(). And it isn't exported, but |
| 1448 | * complete_and_exit() seems to be a minimal wrapper around it. */ | 1463 | * complete_and_exit() seems to be a minimal wrapper around it. */ |
| 1449 | complete_and_exit(NULL, status); | 1464 | complete_and_exit(NULL, status); |
| 1450 | return status; | ||
| 1451 | } | 1465 | } |
| 1452 | 1466 | ||
| 1453 | void ocfs2_recovery_thread(struct ocfs2_super *osb, int node_num) | 1467 | void ocfs2_recovery_thread(struct ocfs2_super *osb, int node_num) |
| @@ -1712,7 +1726,7 @@ static int ocfs2_recover_node(struct ocfs2_super *osb, | |||
| 1712 | 1726 | ||
| 1713 | /* This will kfree the memory pointed to by la_copy and tl_copy */ | 1727 | /* This will kfree the memory pointed to by la_copy and tl_copy */ |
| 1714 | ocfs2_queue_recovery_completion(osb->journal, slot_num, la_copy, | 1728 | ocfs2_queue_recovery_completion(osb->journal, slot_num, la_copy, |
| 1715 | tl_copy, NULL); | 1729 | tl_copy, NULL, ORPHAN_NEED_TRUNCATE); |
| 1716 | 1730 | ||
| 1717 | status = 0; | 1731 | status = 0; |
| 1718 | done: | 1732 | done: |
| @@ -1902,7 +1916,7 @@ void ocfs2_queue_orphan_scan(struct ocfs2_super *osb) | |||
| 1902 | 1916 | ||
| 1903 | for (i = 0; i < osb->max_slots; i++) | 1917 | for (i = 0; i < osb->max_slots; i++) |
| 1904 | ocfs2_queue_recovery_completion(osb->journal, i, NULL, NULL, | 1918 | ocfs2_queue_recovery_completion(osb->journal, i, NULL, NULL, |
| 1905 | NULL); | 1919 | NULL, ORPHAN_NO_NEED_TRUNCATE); |
| 1906 | /* | 1920 | /* |
| 1907 | * We queued a recovery on orphan slots, increment the sequence | 1921 | * We queued a recovery on orphan slots, increment the sequence |
| 1908 | * number and update LVB so other node will skip the scan for a while | 1922 | * number and update LVB so other node will skip the scan for a while |
| @@ -2001,6 +2015,13 @@ static int ocfs2_orphan_filldir(struct dir_context *ctx, const char *name, | |||
| 2001 | if (IS_ERR(iter)) | 2015 | if (IS_ERR(iter)) |
| 2002 | return 0; | 2016 | return 0; |
| 2003 | 2017 | ||
| 2018 | /* Skip inodes which are already added to recover list, since dio may | ||
| 2019 | * happen concurrently with unlink/rename */ | ||
| 2020 | if (OCFS2_I(iter)->ip_next_orphan) { | ||
| 2021 | iput(iter); | ||
| 2022 | return 0; | ||
| 2023 | } | ||
| 2024 | |||
| 2004 | trace_ocfs2_orphan_filldir((unsigned long long)OCFS2_I(iter)->ip_blkno); | 2025 | trace_ocfs2_orphan_filldir((unsigned long long)OCFS2_I(iter)->ip_blkno); |
| 2005 | /* No locking is required for the next_orphan queue as there | 2026 | /* No locking is required for the next_orphan queue as there |
| 2006 | * is only ever a single process doing orphan recovery. */ | 2027 | * is only ever a single process doing orphan recovery. */ |
| @@ -2109,7 +2130,8 @@ static void ocfs2_clear_recovering_orphan_dir(struct ocfs2_super *osb, | |||
| 2109 | * advertising our state to ocfs2_delete_inode(). | 2130 | * advertising our state to ocfs2_delete_inode(). |
| 2110 | */ | 2131 | */ |
| 2111 | static int ocfs2_recover_orphans(struct ocfs2_super *osb, | 2132 | static int ocfs2_recover_orphans(struct ocfs2_super *osb, |
| 2112 | int slot) | 2133 | int slot, |
| 2134 | enum ocfs2_orphan_reco_type orphan_reco_type) | ||
| 2113 | { | 2135 | { |
| 2114 | int ret = 0; | 2136 | int ret = 0; |
| 2115 | struct inode *inode = NULL; | 2137 | struct inode *inode = NULL; |
| @@ -2133,13 +2155,60 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb, | |||
| 2133 | (unsigned long long)oi->ip_blkno); | 2155 | (unsigned long long)oi->ip_blkno); |
| 2134 | 2156 | ||
| 2135 | iter = oi->ip_next_orphan; | 2157 | iter = oi->ip_next_orphan; |
| 2158 | oi->ip_next_orphan = NULL; | ||
| 2159 | |||
| 2160 | /* | ||
| 2161 | * We need to take and drop the inode lock to | ||
| 2162 | * force read inode from disk. | ||
| 2163 | */ | ||
| 2164 | ret = ocfs2_inode_lock(inode, NULL, 0); | ||
| 2165 | if (ret) { | ||
| 2166 | mlog_errno(ret); | ||
| 2167 | goto next; | ||
| 2168 | } | ||
| 2169 | ocfs2_inode_unlock(inode, 0); | ||
| 2170 | |||
| 2171 | if (inode->i_nlink == 0) { | ||
| 2172 | spin_lock(&oi->ip_lock); | ||
| 2173 | /* Set the proper information to get us going into | ||
| 2174 | * ocfs2_delete_inode. */ | ||
| 2175 | oi->ip_flags |= OCFS2_INODE_MAYBE_ORPHANED; | ||
| 2176 | spin_unlock(&oi->ip_lock); | ||
| 2177 | } else if (orphan_reco_type == ORPHAN_NEED_TRUNCATE) { | ||
| 2178 | struct buffer_head *di_bh = NULL; | ||
| 2179 | |||
| 2180 | ret = ocfs2_rw_lock(inode, 1); | ||
| 2181 | if (ret) { | ||
| 2182 | mlog_errno(ret); | ||
| 2183 | goto next; | ||
| 2184 | } | ||
| 2185 | |||
| 2186 | ret = ocfs2_inode_lock(inode, &di_bh, 1); | ||
| 2187 | if (ret < 0) { | ||
| 2188 | ocfs2_rw_unlock(inode, 1); | ||
| 2189 | mlog_errno(ret); | ||
| 2190 | goto next; | ||
| 2191 | } | ||
| 2192 | |||
| 2193 | ret = ocfs2_truncate_file(inode, di_bh, | ||
| 2194 | i_size_read(inode)); | ||
| 2195 | ocfs2_inode_unlock(inode, 1); | ||
| 2196 | ocfs2_rw_unlock(inode, 1); | ||
| 2197 | brelse(di_bh); | ||
| 2198 | if (ret < 0) { | ||
| 2199 | if (ret != -ENOSPC) | ||
| 2200 | mlog_errno(ret); | ||
| 2201 | goto next; | ||
| 2202 | } | ||
| 2203 | |||
| 2204 | ret = ocfs2_del_inode_from_orphan(osb, inode, 0, 0); | ||
| 2205 | if (ret) | ||
| 2206 | mlog_errno(ret); | ||
| 2136 | 2207 | ||
| 2137 | spin_lock(&oi->ip_lock); | 2208 | wake_up(&OCFS2_I(inode)->append_dio_wq); |
| 2138 | /* Set the proper information to get us going into | 2209 | } /* else if ORPHAN_NO_NEED_TRUNCATE, do nothing */ |
| 2139 | * ocfs2_delete_inode. */ | ||
| 2140 | oi->ip_flags |= OCFS2_INODE_MAYBE_ORPHANED; | ||
| 2141 | spin_unlock(&oi->ip_lock); | ||
| 2142 | 2210 | ||
| 2211 | next: | ||
| 2143 | iput(inode); | 2212 | iput(inode); |
| 2144 | 2213 | ||
| 2145 | inode = iter; | 2214 | inode = iter; |
