Продолжая тему улучшения кода ядра Linux хочу дать несколько рекомендаций, основанных как на жизненном опыте, так и на существующей документации.
Первые попытки могут и не увенчаться успехом, ниже некоторые рекомендации, чтобы снизить вероятность такого исхода. Коротко отмечу основные области возникновения проблем во время подготовки и отправки изменений:
- Устаревшие, консервативные и специальные подсистемы ядра
- Стиль кода и оформление изменений
- Новизна изменения
- Нюансы процесса
Дополнительно коротко расскажу про существующие механизмы проверки.
Подсистемы ядра
Среди всего множества подсистем ядра выделим следующие:
- arch/<архитектура>
- drivers/scsi
- fs/ (основная часть)
- drivers/isdn, drivers/ide и им подобные
- drivers/staging
Первая — архитектурный код. Часто содержит устаревшие архитектуры или код, который требует тщательного изучения и понимания. Изменять там что-то имеет смысл только если у вас действительно есть железка, на которой можно протестировать, и реальная проблема, с которой вы боретесь.
Вторая, SCSI, — пожалуй, самая консервативная подсистема в ядре, хотя туда и можно протащить изменения, но это самый жёсткий путь.
Третья — основная часть поддержки файловых систем. Одна из очень специфичных и чувствительных подсистем в ядре. Мейнтейнер Al Viro за словом в карман не полезет, и если вы попытаетесь сделать что-то не подумавши, то тут уж не обижайтесь — ответ получите не из приятных.
Четвёртая категория — изжившие подсистемы, поэтому туда принимаются только глобальные правки при смене внутреннего API.
Пятая подсистема для Вас! Не зря же я упоминал про staging ранее. В этой подсистеме драйверы проходят инкубационный период, то есть с одной стороны необходимость наличия драйвера вызвана рынком (есть устройства, нужна поддержка), но с другой — качество кода недостаточно для включения в одну из существующих подсистем. Отличное место для пробы пера. Greg KH очень лояльный мейнтейнер, только обязательно проверяйте изменения перед отправкой, иначе расстроите его.
Стиль и оформление
Существуют очень хорошие материалы в документации по стилю кода и оформлению изменений, а именно CodingStyle и SubmittingPatches. Настоятельно рекомендую ознакомится с ними перед началом каких-либо действий.
Новизна изменения
Перед тем как делать изменения поищите, может быть кто-то уже сделал это же самое? Не имеет смысла дублировать работу. Так, например, пользователь blueboar2 оформил изменение, а оказалось, что существует более раннее, чуть ли не годичной давности. А если присмотреться, то можно найти и гораздо старее.
Нюансы процесса
Не унывайте, если на ваше изменение нет реакции.
Во-первых надо учитывать, что мейнтенер может быть занят или отсутствовать.
Во-вторых, обычное время выдержки изменений на публике неделя или больше. Таким образом мейнтейнер даёт возможность высказаться другим участникам сообщества по поводу предлагаемого изменения.
В-третьих, существует примерно раз в квартал пару недель тишины. Это так называемое merge window, иными словами окно, когда мейнтейнеры подсистем шлют накопившиеся за предыдущий цикл изменения главному, то есть Linus'у. Окно начинается ровно с момента выхода очередной стабильной версии, в скором будущем v4.0. Также необходимо учитывать, что многие мейнтейнеры перестают принимать новый код уже после -rc5 (v4.0-rc5 ожидается в понедельник 23 марта), так как им самим надо разобраться со своими деревьями.
Механизмы проверки
Ниже я опишу несколько способов и инструментов для проверки изменения.
Для начала убедитесь, что ваше изменение как минимум компилируется. К примеру, если ваша правка была для drivers/staging/unisys/virtpci/virtpci.c, то через drivers/staging/unisys/virtpci/Makefile можно легко понять, какая конфигурационная опция отвечает за включение драйвера:
obj-$(CONFIG_UNISYS_VIRTPCI) += virtpci.o
То есть нам надо найти как включить эту опцию. Поскольку мы знаем, что правка находится в staging, в подкаталоге unisys, в Kconfig которого определёно меню UNISYSPAR, поэтому включить надо
CONFIG_STAGING=y
CONFIG_UNISYSPAR=y
CONFIG_UNISYS_VIRTPCI=m
Можно также пойти и по пути make menuconfig
, догадавшись по описаниям что вы хотите включить.
В некоторых случаях, если сборка происходит на другой архитектуре, можно либо сделать это в виртуальной машине (KVM/Qemu), либо (в редких случаях) попытаться добавить в Kconfig зависимость на COMPILE_TEST, как например вот для такого драйвера:
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -269,7 +269,7 @@ config ATA_PIIX
config SATA_DWC
tristate "DesignWare Cores SATA support"
- depends on 460EX
+ depends on 460EX || COMPILE_TEST
help
This option enables support for the on-chip SATA controller of the
AppliedMicro processor 460EX.
И добавить в кофигурацию ядра:
CONFIG_COMPILE_TEST=y
Совершенно не стоит отправлять такие патчи, не убедившись, что они собираются на всех архитектурах и не вносят огромное число предупреждений, не то разгневанный Linus придёт к вам в почтовый ящик.
Как же потестировать сборку? Вот тут мы переходим к следующим прекрасным переменным окружения при сборке, а именно W=1 C=1
. Первая из них поднимает уровень предупреждений компилятора, вторая же, при установленном пакете sparse
запускает статический анализатор кода. Следовательно, объединяя с -j8
, получим:
$ make C=1 W=1 -j8
Перед сборкой полезным будет запуск
$ make includecheck
Он осуществит поиск дублирующихся включений одних и тех же *.h файлов.
Теперь на руках у вас собранный модуль. Вы оформили изменения в виде *.patch файла с помощью git format-patch
. Неплохо бы проверить стилистическу кода. Запустим checkpatch.pl
:
$ scripts/checkpatch.pl 00*
total: 0 errors, 0 warnings, 43 lines checked
0001-dmaengine-hsu-remove-redundant-pieces-of-code.patch has no obvious style problems and is ready for submission.
Лишний раз перед отправкой убедитесь, что вы оформили всё так, как требуется. Теперь смело запускайте git send-email
.
И напоследок, для простейших изменений есть специальный адрес: trivial@kernel.org. Почитайте ещё такую статью по типу howto: Submitting (Trivial) Linux Kernel Patches.
Автор: andy_shev