@@ -458,8 +458,14 @@ int gfs2_instantiate(struct gfs2_holder *gh)
458458
459459static void do_promote (struct gfs2_glock * gl )
460460{
461+ struct gfs2_sbd * sdp = gl -> gl_name .ln_sbd ;
461462 struct gfs2_holder * gh , * current_gh ;
462463
464+ if (gfs2_withdrawn (sdp )) {
465+ do_error (gl , LM_OUT_ERROR );
466+ return ;
467+ }
468+
463469 current_gh = find_first_holder (gl );
464470 list_for_each_entry (gh , & gl -> gl_holders , gh_list ) {
465471 if (test_bit (HIF_HOLDER , & gh -> gh_iflags ))
@@ -565,7 +571,6 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret)
565571 state_change (gl , state );
566572 }
567573
568-
569574 /* Demote to UN request arrived during demote to SH or DF */
570575 if (test_bit (GLF_DEMOTE_IN_PROGRESS , & gl -> gl_flags ) &&
571576 gl -> gl_state != LM_ST_UNLOCKED &&
@@ -654,54 +659,47 @@ __acquires(&gl->gl_lockref.lock)
654659 struct lm_lockstruct * ls = & sdp -> sd_lockstruct ;
655660 int ret ;
656661
657- if (target != LM_ST_UNLOCKED && gfs2_withdrawn (sdp ))
658- goto skip_inval ;
662+ /*
663+ * When a filesystem is withdrawing, the remaining cluster nodes will
664+ * take care of recovering the withdrawing node's journal. We only
665+ * need to make sure that once we trigger remote recovery, we won't
666+ * write to the shared block device anymore. This means that here,
667+ *
668+ * - no new writes to the filesystem must be triggered (->go_sync()).
669+ *
670+ * - any cached data should be discarded by calling ->go_inval(), dirty
671+ * or not and journaled or unjournaled.
672+ *
673+ * - no more dlm locking operations should be issued (->lm_lock()).
674+ */
659675
660676 GLOCK_BUG_ON (gl , gl -> gl_state == target );
661677 GLOCK_BUG_ON (gl , gl -> gl_state == gl -> gl_target );
678+
662679 if (!glops -> go_inval || !glops -> go_sync )
663680 goto skip_inval ;
664681
665682 spin_unlock (& gl -> gl_lockref .lock );
666- ret = glops -> go_sync (gl );
667- /* If we had a problem syncing (due to io errors or whatever,
668- * we should not invalidate the metadata or tell dlm to
669- * release the glock to other nodes.
670- */
671- if (ret ) {
672- if (cmpxchg (& sdp -> sd_log_error , 0 , ret )) {
673- fs_err (sdp , "Error %d syncing glock\n" , ret );
674- gfs2_dump_glock (NULL , gl , true);
675- gfs2_withdraw (sdp );
683+ if (!gfs2_withdrawn (sdp )) {
684+ ret = glops -> go_sync (gl );
685+ if (ret ) {
686+ if (cmpxchg (& sdp -> sd_log_error , 0 , ret )) {
687+ fs_err (sdp , "Error %d syncing glock\n" , ret );
688+ gfs2_dump_glock (NULL , gl , true);
689+ gfs2_withdraw (sdp );
690+ }
676691 }
677- spin_lock (& gl -> gl_lockref .lock );
678- goto skip_inval ;
679692 }
680693
681694 if (target == LM_ST_UNLOCKED || target == LM_ST_DEFERRED )
682695 glops -> go_inval (gl , target == LM_ST_DEFERRED ? 0 : DIO_METADATA );
683696 spin_lock (& gl -> gl_lockref .lock );
684697
685698skip_inval :
686- if (gfs2_withdrawn (sdp ) && target != LM_ST_UNLOCKED ) {
687- request_demote (gl , LM_ST_UNLOCKED , 0 , false);
688- /*
689- * Ordinarily, we would call dlm and its callback would call
690- * finish_xmote, which would call state_change() to the new state.
691- * Since we withdrew, we won't call dlm, so call state_change
692- * manually, but to the UNLOCKED state we desire.
693- */
694- state_change (gl , LM_ST_UNLOCKED );
695- /*
696- * We skip telling dlm to do the locking, so we won't get a
697- * reply that would otherwise clear GLF_LOCK. So we clear it here.
698- */
699- if (!test_bit (GLF_CANCELING , & gl -> gl_flags ))
700- clear_bit (GLF_LOCK , & gl -> gl_flags );
701- clear_bit (GLF_DEMOTE_IN_PROGRESS , & gl -> gl_flags );
702- gl -> gl_lockref .count ++ ;
703- gfs2_glock_queue_work (gl , GL_GLOCK_DFT_HOLD );
704- return ;
699+ if (gfs2_withdrawn (sdp )) {
700+ if (target != LM_ST_UNLOCKED )
701+ target = LM_OUT_ERROR ;
702+ goto out ;
705703 }
706704
707705 if (ls -> ls_ops -> lm_lock ) {
@@ -717,19 +715,23 @@ __acquires(&gl->gl_lockref.lock)
717715 }
718716 clear_bit (GLF_PENDING_REPLY , & gl -> gl_flags );
719717
720- if (ret == - ENODEV && gl -> gl_target == LM_ST_UNLOCKED &&
721- target == LM_ST_UNLOCKED ) {
718+ if (ret == - ENODEV ) {
722719 /*
723720 * The lockspace has been released and the lock has
724721 * been unlocked implicitly.
725722 */
723+ if (target != LM_ST_UNLOCKED ) {
724+ target = LM_OUT_ERROR ;
725+ goto out ;
726+ }
726727 } else {
727728 fs_err (sdp , "lm_lock ret %d\n" , ret );
728729 GLOCK_BUG_ON (gl , !gfs2_withdrawn (sdp ));
729730 return ;
730731 }
731732 }
732733
734+ out :
733735 /* Complete the operation now. */
734736 finish_xmote (gl , target );
735737 gl -> gl_lockref .count ++ ;
@@ -2081,8 +2083,17 @@ static void dump_glock_func(struct gfs2_glock *gl)
20812083static void withdraw_glock (struct gfs2_glock * gl )
20822084{
20832085 spin_lock (& gl -> gl_lockref .lock );
2084- if (!__lockref_is_dead (& gl -> gl_lockref ))
2086+ if (!__lockref_is_dead (& gl -> gl_lockref )) {
2087+ /*
2088+ * We don't want to write back any more dirty data. Unlock the
2089+ * remaining inode and resource group glocks; this will cause
2090+ * their ->go_inval() hooks to toss out all the remaining
2091+ * cached data, dirty or not.
2092+ */
2093+ if (gl -> gl_ops -> go_inval && gl -> gl_state != LM_ST_UNLOCKED )
2094+ request_demote (gl , LM_ST_UNLOCKED , 0 , false);
20852095 do_error (gl , LM_OUT_ERROR ); /* remove pending waiters */
2096+ }
20862097 spin_unlock (& gl -> gl_lockref .lock );
20872098}
20882099
0 commit comments