Skip to content

Commit 8f947e0

Browse files
jankaraakpm00
authored andcommitted
ocfs2: implement handshaking with ocfs2 recovery thread
We will need ocfs2 recovery thread to acknowledge transitions of recovery_state when disabling particular types of recovery. This is similar to what currently happens when disabling recovery completely, just more general. Implement the handshake and use it for exit from recovery. Link: https://lkml.kernel.org/r/[email protected] Fixes: 5f530de ("ocfs2: Use s_umount for quota recovery protection") Signed-off-by: Jan Kara <[email protected]> Reviewed-by: Heming Zhao <[email protected]> Tested-by: Heming Zhao <[email protected]> Acked-by: Joseph Qi <[email protected]> Cc: Changwei Ge <[email protected]> Cc: Joel Becker <[email protected]> Cc: Jun Piao <[email protected]> Cc: Junxiao Bi <[email protected]> Cc: Mark Fasheh <[email protected]> Cc: Murad Masimov <[email protected]> Cc: Shichangkuo <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent c0fb830 commit 8f947e0

File tree

2 files changed

+39
-17
lines changed

2 files changed

+39
-17
lines changed

fs/ocfs2/journal.c

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -190,31 +190,48 @@ int ocfs2_recovery_init(struct ocfs2_super *osb)
190190
return 0;
191191
}
192192

193-
/* we can't grab the goofy sem lock from inside wait_event, so we use
194-
* memory barriers to make sure that we'll see the null task before
195-
* being woken up */
196193
static int ocfs2_recovery_thread_running(struct ocfs2_super *osb)
197194
{
198-
mb();
199195
return osb->recovery_thread_task != NULL;
200196
}
201197

202-
void ocfs2_recovery_exit(struct ocfs2_super *osb)
198+
static void ocfs2_recovery_disable(struct ocfs2_super *osb,
199+
enum ocfs2_recovery_state state)
203200
{
204-
struct ocfs2_recovery_map *rm;
205-
206-
/* disable any new recovery threads and wait for any currently
207-
* running ones to exit. Do this before setting the vol_state. */
208201
mutex_lock(&osb->recovery_lock);
209-
osb->recovery_state = OCFS2_REC_DISABLED;
202+
/*
203+
* If recovery thread is not running, we can directly transition to
204+
* final state.
205+
*/
206+
if (!ocfs2_recovery_thread_running(osb)) {
207+
osb->recovery_state = state + 1;
208+
goto out_lock;
209+
}
210+
osb->recovery_state = state;
211+
/* Wait for recovery thread to acknowledge state transition */
212+
wait_event_cmd(osb->recovery_event,
213+
!ocfs2_recovery_thread_running(osb) ||
214+
osb->recovery_state >= state + 1,
215+
mutex_unlock(&osb->recovery_lock),
216+
mutex_lock(&osb->recovery_lock));
217+
out_lock:
210218
mutex_unlock(&osb->recovery_lock);
211-
wait_event(osb->recovery_event, !ocfs2_recovery_thread_running(osb));
212219

213-
/* At this point, we know that no more recovery threads can be
214-
* launched, so wait for any recovery completion work to
215-
* complete. */
220+
/*
221+
* At this point we know that no more recovery work can be queued so
222+
* wait for any recovery completion work to complete.
223+
*/
216224
if (osb->ocfs2_wq)
217225
flush_workqueue(osb->ocfs2_wq);
226+
}
227+
228+
void ocfs2_recovery_exit(struct ocfs2_super *osb)
229+
{
230+
struct ocfs2_recovery_map *rm;
231+
232+
/* disable any new recovery threads and wait for any currently
233+
* running ones to exit. Do this before setting the vol_state. */
234+
ocfs2_recovery_disable(osb, OCFS2_REC_WANT_DISABLE);
218235

219236
/*
220237
* Now that recovery is shut down, and the osb is about to be
@@ -1569,7 +1586,8 @@ static int __ocfs2_recovery_thread(void *arg)
15691586

15701587
ocfs2_free_replay_slots(osb);
15711588
osb->recovery_thread_task = NULL;
1572-
mb(); /* sync with ocfs2_recovery_thread_running */
1589+
if (osb->recovery_state == OCFS2_REC_WANT_DISABLE)
1590+
osb->recovery_state = OCFS2_REC_DISABLED;
15731591
wake_up(&osb->recovery_event);
15741592

15751593
mutex_unlock(&osb->recovery_lock);
@@ -1585,13 +1603,13 @@ void ocfs2_recovery_thread(struct ocfs2_super *osb, int node_num)
15851603
int was_set = -1;
15861604

15871605
mutex_lock(&osb->recovery_lock);
1588-
if (osb->recovery_state < OCFS2_REC_DISABLED)
1606+
if (osb->recovery_state < OCFS2_REC_WANT_DISABLE)
15891607
was_set = ocfs2_recovery_map_set(osb, node_num);
15901608

15911609
trace_ocfs2_recovery_thread(node_num, osb->node_num,
15921610
osb->recovery_state, osb->recovery_thread_task, was_set);
15931611

1594-
if (osb->recovery_state == OCFS2_REC_DISABLED)
1612+
if (osb->recovery_state >= OCFS2_REC_WANT_DISABLE)
15951613
goto out;
15961614

15971615
if (osb->recovery_thread_task)

fs/ocfs2/ocfs2.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,10 @@ void ocfs2_initialize_journal_triggers(struct super_block *sb,
310310

311311
enum ocfs2_recovery_state {
312312
OCFS2_REC_ENABLED = 0,
313+
OCFS2_REC_WANT_DISABLE,
314+
/*
315+
* Must be OCFS2_REC_WANT_DISABLE + 1 for ocfs2_recovery_exit() to work
316+
*/
313317
OCFS2_REC_DISABLED,
314318
};
315319

0 commit comments

Comments
 (0)