Skip to content

Commit 559da4b

Browse files
author
Atsushi Abe
authored
Handle one-shot false good against TUR at failover process (#410)
1 parent bab0649 commit 559da4b

File tree

2 files changed

+73
-12
lines changed

2 files changed

+73
-12
lines changed

messages/tape_linux_sg/root.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ root:table {
134134
30292I:string { "Changer %s was reserved from this node but failed to reserve from the current path." }
135135
30293I:string { "Changer %s was reserved from another node (%s)." }
136136
30294I:string { "Setting up timeout values from %s." }
137+
30295I:string { "Have unstable TUR response, start over (Cur = %d, Prev = %d)." }
138+
30296I:string { "Capturing a stable TUR at line %d." }
137139

138140
30392D:string { "Backend %s %s." }
139141
30393D:string { "Backend %s: %d %s." }

src/tape_drivers/linux/sg/sg_tape.c

Lines changed: 71 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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, 30295I, 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 */
620653
int sg_get_device_list(struct tc_drive_info *buf, int count);
621654
int 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, 30296I, __LINE__);
812+
ret = _get_stable_tur_response(priv);
774813
if (ret == -EDEV_RESERVATION_CONFLICT) {
775814
/* Select another path, recover reservation */
776815
ltfsmsg(LTFS_INFO, 30269I, 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, 30270I, 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, 30296I, __LINE__);
833+
ret = _get_stable_tur_response(priv);
834+
if (ret == -EDEV_RESERVATION_CONFLICT) {
835+
/* Select another path, recover reservation */
836+
ltfsmsg(LTFS_INFO, 30269I, 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, 30272I, 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, 30271I, 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, 30270I, priv->drive_serial);
851+
_register_key(priv, priv->key);
852+
ret = sg_reserve(device);
853+
if (!ret) {
854+
ltfsmsg(LTFS_INFO, 30272I, 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, 30271I, priv->drive_serial);
861+
_clear_por(priv);
862+
ret = -EDEV_NEED_FAILOVER;
863+
}
805864
}
806865
}
807866

0 commit comments

Comments
 (0)