Про Oracle, ASM, iSCSI и ядро 2.6.39-400

Date January 19th, 2015 Author Vitaly Agapov

Накормить дрянью так, чтобы все были в восторге – в этом кулинария схожа с политикой.

Святослав Логинов «Многорукий бог далайна»

oracle-bad Опять заметка про Oracle и опять в стиле "баги атакуют". Может, кому-нибудь пригодится. Итак, есть Oracle 11g, RAC (хоть это и не имеет значения) и группа дисков, получаемых по iSCSI и скормленных в ASM. Пока всё неплохо, но тут переходим к ключевому моменту: всё это работает на RHEL5 с UEK-ядром из ветки 2.6.39-400.

В какой-то момент становится понятно, что, если остановить iSCSI-таргет, с которого мы получаем диски, то, несмотря на normal redundancy и на наличие нескольких failgroups, инстанс ASM умирает, прихватывая с собой весь clusterware. Надёжность летит к чертям, кластер может упасть от любого чиха.

Вот что можно выяснить по горячим следам… После остановки таргета iSCSI-инициатор, который периодически шлёт туда NOP Out'ы (эдакие iSCSI-пинги), обнаруживает, что тот недоступен и стартует таймаут node.session.timeo.replacement_timeout из конфига, по истечении которых на все текущие IO-команды возвращает ошибку. ASM, получая эту ошибку, ругается. Если команда была на чтение, то просто ругается. Если на запись, то инстанс ASM останавливается и пытается перезапуститься.

По умолчанию replacement_timeout равен 120 секундам. Значение влияет только на то, насколько быстро ASM получит обратно ошибку и насколько быстро он упадёт. На время этого таймаута блочный scsi-девайс блокируется – в файле /sys/block/sdX/device/state будет состояние "blocked", то есть все IO-команды будут задерживаться и не возвращать никаких ответов. ASM и все запросы к представлениям v$asm… будут висеть.

Зато когда таймаут истечёт, IO-команды получат коды ошибок, а статус блочного девайса вернётся в "running". Диск в системе при этом видится как живой, хотя на самом деле его нет. Это показалось сначала каким-то стрёмным багом. Уверенность в этом усилилась, когда я проверил, как всё это работает в RHEL6 на 3.8-м ядре. Там как раз после таймаута девайс уходит в transport-offline, asm его тоже метит как оффлайн и все счастливы.

Но оказалось, что это не баг, а так и было задумано. Фича с оффлайном девайса оказалась в ядре только начиная с версии 3.6 (вот эти коммиты: раз и два), а значит во всех старых ядрах висящий в running'е блочный девайс с давно отвалившимся таргетом – это нормальное явление.

Но вернёмся к ASM. Через 120 секунд он получает ошибку, и в alert-логе инстанса ASM мы видим подобные строки:

WARNING: Read Failed. group:1 disk:19 AU:0 offset:0 size:4096
WARNING: Write Failed. group:1 disk:2 AU:1 offset:4096 size:4096
ERROR: unrecoverable error ORA-15188 raised in ASM I/O path; terminating process 28246 
ERROR: unrecoverable error ORA-15188 raised in ASM I/O path; terminating process 21487 
PMON (ospid: 21449): terminating the instance due to error 493
ORA-1092 : opitsk aborting process
License high water mark = 52
Instance terminated by PMON, pid = 21449
USER (ospid: 31407): terminating the instance
Instance terminated by USER, pid = 31407
ERROR: -15(asmlib ASM:/opt/oracle/extapi/64/asm/orcl/1/libasm.so op ioerror error Invalid argument)
ERROR: -15(asmlib ASM:/opt/oracle/extapi/64/asm/orcl/1/libasm.so op ioerror error Invalid argument)

А в kernel-логе вот такую примечательную строку, из которой мы можем узнать код ошибки SCSI:

kernel: (31,6):asm_end_ioc:1152 ERROR: Invalid error of -67 on request 0xffff880c514a0440!

Поиск по MOS приводит к Bug 18438934 : INCORRECTLY SETTING A ASM_LOCAL_ERROR WHEN UNPLUGGING THE DISK. Из него мы узнаём, что в ядре 2.6.39.400 появились новые коды ошибок SCSI, которые драйвер ASM обрабатывать не умеет и поэтому генерит ASM_LOCAL_ERROR. Баг вроде как пофикшен в 2.6.39-400.215.9, но опыт показывает, что не совсем – падение таргета по-прежнему приводит к падению ASM-инстанса.

Поигравшись с ядром и поизучав код драйвера ASM в UEK-ядре, сделал такой вот патч для ядра 2.6.39-400.215.15.el5uek. На ядре с этим патчем ASM больше не глючит, нормально оффлайнит недоступные диски и не боится падений iSCSI-таргетов. Главной подсказкой был код ошибки 67 из kernel-лога, который в коде заменён макросом ENOLINK.

# cat asm.nolink.patch 
diff -crBN a/drivers/block/oracleasm/driver.c b/drivers/block/oracleasm/driver.c
*** a/drivers/block/oracleasm/driver.c	2015-01-16 08:52:13.000000000 +0300
--- b/drivers/block/oracleasm/driver.c	2015-01-16 08:54:52.000000000 +0300
***************
*** 1165,1170 ****
--- 1165,1171 ----
  		case -EIO:
  		case -ENODATA:
  		case -EREMOTEIO:
+ 		case -ENOLINK:
  			r->r_error = ASM_ERR_IO;
  			break;
  
***************
*** 1172,1178 ****
  			r->r_error = asm_integrity_error(r);
  			break;
  
- 		case -ENOLINK:
  		case -EBADE:
  		case -ENODEV:
  			r->r_error = ASM_ERR_NODEV;
--- 1173,1178 ----

Tags: ,
Category: Linux, Oracle | No comments »

Comments

Leave a comment

 Comment Form