@@ -616,6 +616,39 @@ void _clear_por_raw(const int fd)
616616 }
617617}
618618
619+ #define _get_stable_tur_response (p ) _get_stable_tur_response_raw((p)->dev.fd)
620+
621+ int _get_stable_tur_response_raw (const int fd )
622+ {
623+ int i = 0 , ret = -1 , ret_tur = -1 ;
624+
625+ do {
626+ ret_tur = _raw_tur (fd );
627+ if (i == 0 ) {
628+ /* Keep first return code if it is not an unit attention */
629+ if (!IS_UNIT_ATTENTION (- ret_tur )) {
630+ ret = ret_tur ;
631+ i ++ ;
632+ }
633+ } else if (ret_tur == ret ) {
634+ /* Increment counter because it is same as previous response */
635+ i ++ ;
636+ } else {
637+ /* TUR response is not stable, start over */
638+ ltfsmsg (LTFS_INFO , 30295 I , ret_tur , ret );
639+ if (IS_UNIT_ATTENTION (- ret_tur )) {
640+ ret = -1 ;
641+ i = 0 ;
642+ } else {
643+ ret = ret_tur ;
644+ i = 1 ;
645+ }
646+ }
647+ } while (i < 3 );
648+
649+ return ret ;
650+ }
651+
619652/* Forward reference */
620653int sg_get_device_list (struct tc_drive_info * buf , int count );
621654int sg_reserve (void * device );
@@ -770,7 +803,13 @@ static int _reconnect_device(void *device)
770803
771804 /* Issue TUR and check reservation conflict happens or not */
772805 _clear_por (priv );
773- ret = _raw_tur (priv -> dev .fd );
806+
807+ /*
808+ * !!!!! This is a kind of work around to avoid to fetch false one-shot `good` here.
809+ * Fetch result of TUR until 3 straight same result
810+ */
811+ ltfsmsg (LTFS_INFO , 30296 I , __LINE__ );
812+ ret = _get_stable_tur_response (priv );
774813 if (ret == - EDEV_RESERVATION_CONFLICT ) {
775814 /* Select another path, recover reservation */
776815 ltfsmsg (LTFS_INFO , 30269 I , priv -> drive_serial );
@@ -785,23 +824,43 @@ static int _reconnect_device(void *device)
785824 } else {
786825 /* Read reservation information and print */
787826 _clear_por (priv );
788- memset (& r_info , 0x00 , sizeof (r_info ));
789- f_ret = _fetch_reservation_key (device , & r_info );
790- if (f_ret == - EDEV_NO_RESERVATION_HOLDER ) {
791- /* Real POR may happens */
792- ltfsmsg (LTFS_INFO , 30270 I , priv -> drive_serial );
827+
828+ /*
829+ * !!!!! This is the code just in case, check TUR response again and restore reservation
830+ * if drive reports `reservation conflict`.
831+ */
832+ ltfsmsg (LTFS_INFO , 30296 I , __LINE__ );
833+ ret = _get_stable_tur_response (priv );
834+ if (ret == - EDEV_RESERVATION_CONFLICT ) {
835+ /* Select another path, recover reservation */
836+ ltfsmsg (LTFS_INFO , 30269 I , priv -> drive_serial );
793837 _register_key (priv , priv -> key );
794- ret = sg_reserve (device );
838+ ret = _cdb_pro (device , PRO_ACT_PREEMPT_ABORT , PRO_TYPE_EXCLUSIVE ,
839+ priv -> key , priv -> key );
795840 if (!ret ) {
796841 ltfsmsg (LTFS_INFO , 30272 I , priv -> drive_serial );
797842 _clear_por (priv );
798- ret = - EDEV_REAL_POWER_ON_RESET ;
843+ ret = - EDEV_NEED_FAILOVER ;
799844 }
800845 } else {
801- /* Select same path */
802- ltfsmsg (LTFS_INFO , 30271 I , priv -> drive_serial );
803- _clear_por (priv );
804- ret = - EDEV_NEED_FAILOVER ;
846+ memset (& r_info , 0x00 , sizeof (r_info ));
847+ f_ret = _fetch_reservation_key (device , & r_info );
848+ if (f_ret == - EDEV_NO_RESERVATION_HOLDER ) {
849+ /* Real POR may happens */
850+ ltfsmsg (LTFS_INFO , 30270 I , priv -> drive_serial );
851+ _register_key (priv , priv -> key );
852+ ret = sg_reserve (device );
853+ if (!ret ) {
854+ ltfsmsg (LTFS_INFO , 30272 I , priv -> drive_serial );
855+ _clear_por (priv );
856+ ret = - EDEV_REAL_POWER_ON_RESET ;
857+ }
858+ } else {
859+ /* Select same path */
860+ ltfsmsg (LTFS_INFO , 30271 I , priv -> drive_serial );
861+ _clear_por (priv );
862+ ret = - EDEV_NEED_FAILOVER ;
863+ }
805864 }
806865 }
807866
0 commit comments