qemu-img convert -f qcow2 -O raw -n --target-is-zero image.qcow2 /dev/system/lvm_thin_volumeПри работе с существующими томами тонкого пула LVM или устройствами iSCSI такая команда вероятнее всего будет предворяться вызовом blkdiscard, выполняющим операцию trim (она же unmap, она же discard) для данного устройства. В общем случае, формально, не гарантируется, что после выполнения этой команды чтение целевого устройства будет возвращать нули, однако, в частных случаях (особенно при использовании LVM), такое поведение очевидно детерминировано и может быть заранее проверенно.
Развертывание образа qcow2
Fixing console UART on Quartz64 Model B
Recently, I've obtained Quartz64 Model B single board computer (the board revision is 1.4 2022.06.06). It is equipped with so-called RasbperryPi-compatible 40-pin extension header, which provides access to UART console. The board is powered by Rockchip RK3566 Quad-Core ARM Processor and default UART baudrate is 1500000 as it was for RK3328 for instance.
Surprisingly, I had nothing on the console when I powered the board up. Even though HDMI output works fine, and the board was booting successfully. It took some time to realize that something is wrong with the board itself. Then it appeared that other people also suffer from the similar issue: https://forum.pine64.org/showthread.php?tid=17131&pid=115539#pid115539
At some point I attached an oscilloscope to the UART TX pin:
These saw teeth are supposed to be rectangular for not-disturbed signal. So, the hardware origin of the issue became more evident. Unfortunately, Pine64 support didn't help me with this issue, they only adviced to try different OS, different power supply, etc. All of that didn't helped.
The board schematic is not very complicated for UART TX (the same is valid for RX):
The resistors can be probed relatively easily, it appeared that all of them have correct nominals. So, the final decision appeared to replace Q1 (for RX line) and Q2 (for TX line) SOT-323 MOSFETs. There are only two components of SOT-323 size on the board and they can be easily located with the help of components placement:
The MOSFETs have KN on their case and three pins and each located at its own side of the board. The pars are relatively big to be manually resoldered. I used Pine64 Pencil with ILS soldering tip. It seems that high-temperature lead-free soldering was used on the factory, so the temperature close to 400C was required to unsolder the parts. After the parts were replaced with the spares supplied by local electronic distributor, UART console has been working as initially expected.
Использование chrony для синхронизации времени с GPS
Возможность использования систем спутниковой навигации в качестве источника точного времени востребована в настоящее время, во многом благодаря обилию доступных по цене приёмников. Сервер точного времени chrony, развиваемый как легковесная замена ntpd, выбран во многих дистрибутивах в качестве сервера времени по умолчанию, и, конечно, поддерживает такую возможность.
Де-факто стандартом приёмников является, пришедший с водного транспорта, протокол NMEA 0183, зачастую используемый поверх RS232. Для целей синхронизации времени как правило используется отдельная линия с TTL сигналом с частотой 1 Гц. При использовании линий RS232 для передачи TTL сигнала используется DCD (первый пин разъема DB9). На популярных в последнее время одноплатных компьютерах для приема сигнала 1 Гц используется интерфейс GPIO.
На стороне ядра Linux сигнал обрабатывается подсистемой PPS: модулем pps-ldisc в случае DCD, или модулем pps-gpio для GPIO. Пользовательские приложения получают доступ к таблице событий через символьные устройства /dev/ppsX.
Данные, передаваемые по протоколу NMEA, доступны для чтения через соответсвующее устройство: /dev/ttyY. В отличии от ntpd, chrony не содержит код для разбора протокола NMEA, поэтому полагается на gpsd, который, в свою очередь, передает chrony данные о точном времени через unix сокет.
gpsd обладает скудными возможностями конфигурации, а собственные способности автоконфигурации его зачасную подводят. При запуске gpsd необходимо использовать следующие аргументы командной строки:
- -n начать приём данных сразу после запуска; по умолчанию, gpsd ждет клиентских подключений для начала работы;
- -s 9600 указывается скорость обмена для приёмника;
- /dev/ttyY устройсто с NMEA.
При использовании устройств с именами вида /dev/ttyY gpsd пытается активировать на них линейную дисциплину PPS для получения сигнала с линии DCD. Сигнала, да и самой линии, может не быть, особенно в случаях с одноплатными компьютерами, а сообщить gpsd об этом явно возможности не предусмотрено. Однако, если устройство имеет имя /dev/gpsd0, то gpsd пытается открыть уже готовое устройство /dev/pps0, которое очень удачно может обслуживаться модулем pps-gpio. В последнем случае, придётся пойти на поклон к udev и попросить его делать символическую ссылку для нужного нам tty устройства. Примерное содержимое /etc/udev/rules.d/98-gpsd.rules:
ACTION=="remove", GOTO="gpsd_end" KERNEL=="ttyS2", SYMLINK+="gpsd0", MODE="0600", OWNER="root", GROUP="root" LABEL="gpsd_end"
Для chrony следует указать источник точного времени в виде сокета следующим образом. Примерное содержимое /etc/chrony.d/gps.conf:
refclock SOCK /run/chrony.gpsd0.sock refid GPS
Имя сокета для подключения не может быть задано произвольно. Дело в том, что gpsd нельзя указать, куда он должен передавать информацию о времени, вместо этого он самостоятельно начинает запись в сокет с именем /run/chrony.gpsd0.sock если его обнаружит. Следует убедиться, что gpsd запускается после chronyd. Текст gpsd0 после первой точки в имени файла соответсвует имени устройства используемого gpsd для чтения NMEA.
С помощью утилиты chronyc можно проверить, что всё работает корректно.
chronyc> sources MS Name/IP address Stratum Poll Reach LastRx Last sample =============================================================================== #* GPS 0 4 377 21 -721ns[-2140ns] +/- 1333ns ^- 2a00:ab00:203:9::1000:1 2 6 337 2 +9783us[+9783us] +/- 65ms ^- ftpshare1.corbina.net 2 6 377 2 -4050us[-4050us] +/- 39ms ^- tms04.deltatelesystems.ru 2 6 377 63 +11ms[ +11ms] +/- 104ms ^- 2a00:ab00:203:9::1000:6 2 6 177 1 +12ms[ +12ms] +/- 63ms
Возможные значения колнки "S":
- * — используется в качестве основного источника,
- + — используется,
- - — не используется,
- ? — не используется, идёт сбор информации о стабильности источника.
Изменение размера шард для InfluxDB 1.7
Хранилище сервера баз данных временных рядов InfluxDB 1.x использует шарды фиксированного по времени размера независимо от количества хранящихся в них записей. Шарды не могут быть слиты или разделены. При устаревании данные удаляются отдельными шардами. Использование слишком маленького размера шарда приводит к проблемам с производительностью и избыточному потреблению памяти: на каждый шард требуется хранить в памяти отдельный дескриптор, даже если используется TSI1 индексирование.
Размер шарда является свойством политики хранения (retention policy), и, хотя настройка может быть изменена в онлайне, её изменение не приводит к перебалансировке уже существующих шард. Это приводит к проблемам для баз данных где требуется бесконечный или достаточно длительный срок хранения, т.е. шарды удаляются медленно, так как, несмотря на собственные рекомендации, настройки политики хранения по умолчанию состоят в том чтобы хранить данные бесконечно и разделять на шарды по 1 неделе.
Одним из возможных способов перебалансировки шардов в онлайн является создание новой политики хранения с нужными параметрами, и последующего копирования туда данных запросом (что скорее всего приведет к избыточному потреблению оперативной памяти и потребует копирования по частям). Проблема этого подхода состоит в том, что невозможно переименовать политику хранения, поэтому потребуется перенастройка всех непрерывных запросов (continuous queries) и, возможно, перенастройка клиентских приложений.
В качестве альтернативного решения предлагается следующая оффлайн (при остановленном сервере) процедура: экспорт данных из существующей политики хранения в бинарном виде, удаление политики хранения, создание новой политики хранения (с прежним именем и новыми настройками) и импорт сохраненных данных. Для процедуры используется модифицированная (добавлена команда droprp) утилита influx_tools:
git clone -b influx_tools/droprp https://github.com/matwey/influxdb.git cd influxdb/cmd/influx_tool go build .
Экспорт данных производится следующим образом:
./influx_tools export -config /etc/influxdb/config.toml -no-conflict-path -database ${DB_NAME} -rp ${RP_NAME} -duration 8736h -format binary | xz -3 -c - > /tmp/ifx_dump
здесь 8736h — новый размер шарда, в данном случае 52 недели. Сжатие можно опустить, но оно весьма эффективно работает в данном месте.
Удалим политику хранения ${RP_NAME}:
./influx_tools droprp -config /etc/influxdb/config.toml -database ${DB_NAME} -rp ${RP_NAME}
В этот момент будут удалены файлы старых шард, удалены файлы журналов упреждающей записи, и модифицирован файл meta/meta.db, который представляет из себя сериализованный документ в формате ProtoBuf, хранящий список политик хранения и шард.
Загрузим данные на прежнее место с новыми настройками политики хранения:
xzcat /tmp/ifx_dump | ./influx_tools import -config /etc/influxdb/config.toml -database ${DB_NAME} -rp ${RP_NAME} -replace -shard-duration 8736h
Пересобирем индекс для новых шард:
influx_inspect buildtsi -datadir /var/lib/influxdb/data/ -waldir /var/lib/influxdb/wal -v
Восстановим права доступа:
chown -R influxdb:influxdb /var/lib/influxdb/*
Миграция InfluxDB 0.9 до InfluxDB 1.1
# wget https://dl.influxdata.com/influxdb/releases/influxdb-0.11.1-1_linux_amd64.tar.gz
Сначала рекомендуется сбросить WAL (write-ahead log), для этого рекомендуется изолировать сервер InfluxDB от записи и выполнить его restart.
Далее, останавливаем InfluxDB 0.9 и с помощью утилиты influx_tsm из пакета InfluxDB версии 1.1 конвертируем директорию data.
Предполагается, что резервную копию данных мы уже сделали внешним образом.
# influx_tsm -parallel -nobackup /var/lib/influxdb/data
Утилита выводит список всех найденных файлов устаревшего формата b1 или bz1 и спрашивает Proceed? y/N:
После подтверждения данные преобразуются в новый формат tsm.
Далее осталось преобразовать в новый формат /var/lib/influxdb/meta. Для этого на некоторое время придется запустить InfluxDB версии 0.11
# ./influxdb-0.11.1-1/usr/bin/influxd -config /etc/influxdb/config.toml
И попросить его сделать резервную копию:
# influxd backup /tmp/backup/ 2016/11/27 17:41:37 backing up metastore to /tmp/backup/meta.00 2016/11/27 17:41:37 backup complete
После этого сервер 0.11 можно выключить и загрузить резервную копию назад, но уже используя InfluxDB версии 1.1:
# influxd restore -metadir=/var/lib/influxdb/meta/ /tmp/backup/ Using metastore snapshot: /tmp/backup/meta.00
После этого восстановим права доступа
# chown -R influxdb:influxdb /var/lib/influxdb/
И можно запускать сервер InfluxDB 1.1
# systemctl start influxd
Открываем консоль influx и проверяем что все наши данные доступны.
Настройка звука в конфигурации с несколькими одинаковыми звуковыми картами
00:03.0 Audio device [0403]: Intel Corporation Xeon E3-1200 v3/4th Gen Core Processor HD Audio Controller [8086:0c0c] (rev 06) 00:1b.0 Audio device [0403]: Intel Corporation 9 Series Chipset Family HD Audio Controller [8086:8ca0]Пользователи жалуются, что звук не работает. Проблема состоит в том, что YaST создаёт следующую конфигурацию в 50-sound.conf:
options snd slots=snd-hda-intel,snd-hda-intel alias snd-card-0 snd-hda-intel alias snd-card-1 snd-hda-intelЗдесь snd-card-0 — звуковое устройство "по умолчанию". Очевидно, что в таком подходе ситуация, когда один и тот же модуль отвечает за два устройства, обрабатывается не корректно. Кто из устройств первый попал в функцию azx_probe модуля, тот и станет snd-card-0. В нашем случае, это не то устройство, которое нам хотелось бы. Это можно проверить, сделав
ls -l /sys/class/sound/card0/device lrwxrwxrwx 1 root root 0 окт 9 21:36 /sys/class/sound/card0/device -> ../../../0000:00:03.0
Для восстановления правильного порядка предлагается делать следующее.
Во-первых, внимательно изучив исходники модуля, добавляем в 50-sound.conf:
options snd-hda-intel index=1,0Во-вторых, надеемся, что при следующих загрузках порядок инициализации не будет меняться случайным образом, потому-что кто первый попадет в функцию azx_probe, тот теперь и будет card1. И это всё происходит в 2015 году, когда повсюду systemd и прочий udev, а звуковую карту за её DeviceId привязать нельзя.
Настройка вложенной виртуализации в ESXi 6.0
Во-первых, в vmx-файл настроенной гостевой системы дописывается директива vhv.enable = "TRUE". Включить эту настройку из клиентского приложения, видимо, нельзя. Для редактирования файла можно сначала загрузить его на локальную машину, а затем отредактированную версию загрузить назад, используя браузер датастора гипервизора.
Во-вторых, нужно попросить гипервизор перечитать vmx-файл, как описано в тикете 1026043 базы знаний VMWare. А именно, используя ssh для доступа к командной строке гипервизора выполнить команды:
# vim-cmd vmsvc/getallvms # vim-cmd vmsvc/reload VmidПервая команда просто отображает список всех виртуальных машин гипервизора, она нужна чтобы определить Vmid интересующей нас машины, это число используется во второй команде.
После этого стартуем виртуальную машину и проверяем, что аппаратная виртуализация стала доступна нам в гостевой системе:
# cat /proc/cpuinfo | grep vmx flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts nopl xtopology tsc_reliable nonstop_tsc aperfmperf pni pclmulqdq vmx ssse3 cx16 sse4_1 sse4_2 popcnt aes hypervisor lahf_lm ida arat epb dtherm tpr_shadow vnmi ept vpid flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts nopl xtopology tsc_reliable nonstop_tsc aperfmperf pni pclmulqdq vmx ssse3 cx16 sse4_1 sse4_2 popcnt aes hypervisor lahf_lm ida arat epb dtherm tpr_shadow vnmi ept vpid # lsmod | grep kvm kvm_intel 151704 3 kvm 493230 1 kvm_intel
Удаленная сетевая консоль ядра Linux
Полное описание сетевой консоли находится в документации ядра. Для настройки достаточно добавить в modprobe.d/99-local.conf:
options netconsole netconsole=@/,514@192.168.10.7/00:0C:29:F3:92:97Здесь, 514 - номер UDP порта, 192.168.10.7 - IP удаленного хоста куда будет отсылаться информация, 00:0C:29:F3:92:97 - его MAC адрес, если его не указать явно то будет использоваться широковещательный адрес FF:FF:FF:FF:FF:FF, что может затруднить передачу информации в зависимости от настроек сетевого оборудования.
И загрузить модуль netconsole или, по желанию, поставить его на автозагрузку при старте системы.
После загрузки модуля netconsole, сетевая консоль начинает немедленно функционировать, а в системном журнале можно увидеть примерно следующее:
May 1 18:57:51 192.168.10.4 kernel: [162255.522603] netconsole: local port 6665 May 1 18:57:51 192.168.10.4 kernel: [162255.522673] netconsole: local IP 0.0.0.0 May 1 18:57:51 192.168.10.4 kernel: [162255.522710] netconsole: interface eth0 May 1 18:57:51 192.168.10.4 kernel: [162255.522746] netconsole: remote port 514 May 1 18:57:51 192.168.10.4 kernel: [162255.522784] netconsole: remote IP 192.168.10.7 May 1 18:57:51 192.168.10.4 kernel: [162255.522826] netconsole: remote ethernet address 00:0c:29:f3:92:97 May 1 18:57:51 192.168.10.4 kernel: [162255.522881] netconsole: local IP 192.168.10.4 May 1 18:57:51 192.168.10.4 kernel: [162255.523032] console [netcon0] enabled May 1 18:57:51 192.168.10.4 kernel: [162255.523349] netconsole: network logging started
Данные приходят в самом простом текстовом виде и их можно читать самым простым способом:
netcat -u -l 514Если у нас в наличии есть syslog-ng — можно использовать его следующим образом:
source s_remote_udp {
network(transport("udp") ip(0.0.0.0) port(514));
};
filter f_remote_remhost {
netmask(192.168.10.4);
};
destination d_remote_remhost {
file("/var/log/remote/remhost.log");
};
log {
source(s_remote_udp);
filter(f_remote_remhost);
destination(d_remote_remhost);
};Проверить, что всё работает можно следующим образом:
echo '<7>Hello world!' > /dev/kmsg dmesg -n 8Сообщение должно появиться в журнале и быть передано по сети на удаленный хост.
Удаленная отладка ядра Linux
Опции конфигурации ядра должны быть такими:
CONFIG_KGDB=y CONFIG_KGDB_SERIAL_CONSOLE=yКроме того, драйвер последовательного порта должен быть включен в состояние Y.
Далее нам понадобятся отладочные символы и исходные коды ядра, которые находятся в пакетах -debuginfo и -debugsource. Скорее всего, архитектуры удаленной и локальной системы не будут совпадать, так как особенно часто ядро Linux не работает на архитектуре armv7l, поэтому просто распакуем данные следующим образом:
> rpm2cpio kernel-default-base-debuginfo-4.2.rc4-1.1.gaf243bc.armv7hl.rpm | cpio -id > rpm2cpio kernel-default-debuginfo-4.2.rc4-1.1.gaf243bc.armv7hl.rpm | cpio -id > rpm2cpio kernel-default-debugsource-4.2.rc4-1.1.gaf243bc.armv7hl.rpm | cpio -idВ текущей директории будет создана поддиректория /usr содержащая отладочные символы и исходные коды в стандартной иерархии. Кроме того, нам понадобятся сами бинарные файлы ядра:
> rpm2cpio kernel-default-base-4.2.rc4-1.1.gaf243bc.armv7hl.rpm | cpio -id > rpm2cpio kernel-default-4.2.rc4-1.1.gaf243bc.armv7hl.rpm | cpio -id
Далее, следует подключить последовательный порт, и открыть удаленную консоль следующим, например, образом:
> screen /dev/ttyUSB0 115200и начать загрузку целевого устройства. Для активации механизма kgdb потребуется добавить параметры командной строки ядра в загрузчике:
U-Boot# setenv append "kgdboc=ttyO0,115200 kgdbwait" U-Boot# boot
Если все пойдет правильно, то загрузка ядра остановится после примерно следующих строк:
[ 3.753423] 44e09000.serial: ttyO0 at MMIO 0x44e09000 (irq = 154, base_baud = 3000000) is a OMAP UART0 [ 4.497783] console [ttyO0] enabled [ 4.502387] STMicroelectronics ASC driver initialized [ 4.507960] KGDB: Registered I/O driver kgdboc [ 4.512673] KGDB: Waiting for connection from remote gdb... Entering kdb (current=0xdb0b3480, pid 1) on processor 0 due to Keyboard Entry [0]kdb>kdb ождает ввода команд, среди прочего доступна команда help, выводящая список базовых команд. На этом консоль можно закрыть: Ctrl-A :quit и открыть отладчик gdb.
Для начала установим пути к отладочным символам и исходным кодам и загрузим объектный файл ядра целевой системы (внимание, сначала этот файл нужно будет распаковать командой gz).
(gdb) set debug-file-directory /tmp/dbg/usr/lib/debug (gdb) directory /tmp/dbg/usr/src/debug/kernel-default-4.2.rc4/linux-4.2-rc4/linux-obj (gdb) file /tmp/dbg/boot/vmlinux-4.2.0-rc4-1.gaf243bc-default Reading symbols from /tmp/dbg/boot/vmlinux-4.2.0-rc4-1.gaf243bc-default...Reading symbols from /tmp/dbg/usr/lib/debug/boot/vmlinux-4.2.0-rc4-1.gaf243bc-default.debug...done. done.После этого нужно подключиться к целевой системе:
(gdb) target remote /dev/ttyUSB0 Remote debugging using /dev/ttyUSB0 0xc031dc08 in arch_kgdb_breakpoint () at ../arch/arm/include/asm/outercache.h:142
Далее можно использовать отладчик как обычно. Через команду monitor доступны все команды из консоли kdb, среди них есть достаточно полезные, например dmesg или lsmod:
(gdb) monitor lsmod Module Size modstruct Used by musb_am335x 1431 0xbf000278 1 (Loading) 0xbf000000 [ ]Обратите внимание, что команда lsmod любезно нам показывает адрес 0xbf000000, куда в памяти загружен модуль musb_am335x. Этот адрес нужен чтобы отлаживать код из модуля:
(gdb) add-symbol-file /tmp/dbg/lib/modules/4.2.0-rc4-1.gaf243bc-default/kernel/drivers/usb/musb/musb_am335x.ko 0xbf000000
Устойчивые имена сетевых интерфейсов
Считается, что подобный подход дает больше информации, чем прибитие гвоздями имен интерфейсов eth? к MAC-адресам в 70-persistent-net.rules. Однако, не обходится без недостатков. Например, при запуске системы под гипервизором VMWare ESXi, единственный сетевой интерфейс у меня называется eno16777728. Устройства, определяемые в DTB для одноплатных компьютеров на базе ARM, не поддерживаются схемой именования и имеют обычные имена eth?. А при подключении USB устройств, типа мобильных телефонов или модемов, схема именования генерирует скорее неустойчивые имена, потому-что в имя входит расположение устройства на шине USB, которое изменится при следующем подключении, таким образом придется настраивать интерфейс заново, потому-что предыдущие сохраненные настройки будут относиться к интерфейсу с другим именем.
К счастью, udev заполняет переменную ID_NET_NAME_MAC, представляющую имя интерфейса, основанное исключительно на его MAC-адресе. По-умолчанию, эта переменная не используется, но можно поменять стандартное поведение для USB-устройств. Один способ - через настройку udev, второй - используя systemd.link, файл, используемый systemd, для конфигурации сетевых интерфейсов.
Создадим файл /etc/systemd/network/90-usb.link следуя инструкции:
[Match] Path=*-usb-* [Link] NamePolicy=macЮнит-файл состоит из двух секций: [Match] для описания устройств к которым он относится и [Link] для описания того, что с ними делать. В примере выше мы просим systemd использовать политику именования основанную на MAC-адресах для всех устройств подключенных через USB. После выполнения systemctl daemon-reload можно подключить устройство и увидеть его интерфейс с именем enx112233445566. Достаточно длинное, но уникальное (в известных пределах) и не изменится при следующем подключении устройства.
Кроме изменения имени через systemd.link можно настроить WOL, MTU, ограничить скорость на интерфейсе, назначить устройству другой MAC-адрес.
Изменение размера раздела
Сначала отмонтируем все разделы и проверим файловую систему.
# swapoff /dev/sda2 # umount /dev/sda1 # e2fsck /dev/sda1 e2fsck 1.42.6 (21-Sep-2012) /dev/sda1: clean, 49/14056 files, 47157/56196 blocks
Используем parted для того, чтобы сначала уменьшить и передвинуть второй раздел, а затем расширить первый на освободившееся место. Так как второй раздел - swap, то его мы просто передвинем, не заботясь о содержимом. Иначе говоря, сначала мы совсем сломаем, а потом заново её разметим.
# parted /dev/sda GNU Parted 2.4 Using /dev/sda Welcome to GNU Parted! Type 'help' to view a list of commands. (parted) unit s (parted) print Model: ATA QEMU HARDDISK (scsi) Disk /dev/sda: 120103200s Sector size (logical/physical): 512B/512B Partition Table: msdos Number Start End Size Type File system Flags 1 63s 112454s 112392s primary ext2 boot, type=83 2 112455s 1686824s 1574370s primary linux-swap(v1) type=82 3 1686825s 120101939s 118415115s primary reiserfs type=83
Для изменения раздела используется команда resize номер_раздела начало конец
(parted) resize 2 224973 1686824 WARNING: you are attempting to use parted to operate on (resize) a file system. parted's file system manipulation code is not as robust as what you'll find in dedicated, file-system-specific packages like e2fsprogs. We recommend you use parted only to manipulate partition tables, whenever possible. Support for performing most operations on most types of file systems will be removed in an upcoming release. (parted) print Model: ATA QEMU HARDDISK (scsi) Disk /dev/sda: 120103200s Sector size (logical/physical): 512B/512B Partition Table: msdos Number Start End Size Type File system Flags 1 63s 112454s 112392s primary ext2 boot, type=83 2 224973s 1686824s 1461852s primary linux-swap(v1) type=82 3 1686825s 120101939s 118415115s primary reiserfs type=83
К сожалению в этот момент оно само подмонтировало всё назад, поэтому нужно снова отмонтировать первый раздел. Раздел swap в данный момент уже должен быть работоспособен, потому-что mkswap на нем выполнился сам автоматически. К сожалению, я не нашел способа отключить всю эту самодеятельность.
# umount /dev/sda1 # e2fsck -p /dev/sda1
Снова идем в parted:
# parted GNU Parted 2.4 Using /dev/sda Welcome to GNU Parted! Type 'help' to view a list of commands. (parted) unit s (parted) print Model: ATA QEMU HARDDISK (scsi) Disk /dev/sda: 120103200s Sector size (logical/physical): 512B/512B Partition Table: msdos Number Start End Size Type File system Flags 1 63s 112454s 112392s primary ext2 boot, type=83 2 224973s 1686824s 1461852s primary linux-swap(v1) type=82 3 1686825s 120101939s 118415115s primary reiserfs type=83 (parted) resize 1 63 224972 WARNING: you are attempting to use parted to operate on (resize) a file system. parted's file system manipulation code is not as robust as what you'll find in dedicated, file-system-specific packages like e2fsprogs. We recommend you use parted only to manipulate partition tables, whenever possible. Support for performing most operations on most types of file systems will be removed in an upcoming release. (parted) quit Warning: You should reinstall your boot loader before rebooting. Read section 4 of the Parted User documentation for more information. Information: You may need to update /etc/fstab.
Готово, parted не только изменил размер раздела, но еще и молча расширил для нас файловую систему, а теперь предупреждает о необходимости обновить загрузчик.
snapper: настройка снимков подтомов
Создадим новую конфигурацию (профиль) для этого подтома: snapper -c pgsql create-config /var/lib/pgsql, здесь pgsql произвольное имя:
# snapper list-configs Config | Subvolume -------+--------------- root | / pgsql | /var/lib/pgsql
Далее, все команды нужно выполнять с ключом -c pgsql, чтобы оперировать нужным профилем.
# snapper -c pgsql get-config ... NUMBER_CLEANUP | yes NUMBER_LIMIT | 50 NUMBER_LIMIT_IMPORTANT | 10 NUMBER_MIN_AGE | 1800
Здесь NUMBER_CLEANUP разрешает удалять старые снимки если их число превышает NUMBER_LIMIT и одновременно возраст (в секундах) больше NUMBER_MIN_AGE.
TIMELINE_CLEANUP | yes TIMELINE_CREATE | yes TIMELINE_LIMIT_DAILY | 10 TIMELINE_LIMIT_HOURLY | 10 TIMELINE_LIMIT_MONTHLY | 10 TIMELINE_LIMIT_YEARLY | 10 TIMELINE_MIN_AGE | 1800
Здесь соответствующая настройка разрешает автоматическое создание снимков раз в час. Команда TIMELINE_CLEANUP удаляет старые снимки, используя следующие правила: удаляется снимок только если он старше TIMELINE_MIN_AGE секунд и одновременно после удаления останутся TIMELINE_LIMIT_* снимков с соответствующими интервалами.
Таким образом, в вышеописанном стандартном случае всегда будут доступны снимки: 10 с интервалом в час с текущего момента, 10 с интервалом в один день с текущего момента, 10 с интервалом в один месяц и так далее.
Конвертация CVS в Mercurial
Поскольку CVS немного устарел, нужно куда-то переехать. К сожалению, правильную работу с моделями с амперсандом не поддерживает ни одна из найденных утилит миграции. Об инкрементальной миграции (когда существуют два параллельных репозитория (разных систем контроля), которые каким-то чудом остаются друг с другом синхронизированы) тоже придется забыть.
Краткая схема действий. Сначала все модули из CVS конвертируются в формат fastimport, далее полученные дампы преобразуются и конвертируются в mercurial. Mercurial имеет в данной ситуации преимущество над git в том, что сабрепозитории управляются просто служебными файлами в дереве репозитория.
Все CVS модули можно разделить на две категории: те, которые содержат в себе модули с амперсандом, и те, которые нет (сами являются ими). Второй набор конвертируется просто. Для преобразования первого набора нужно пойти в cvsroot и вставить символические ссылки в те места, где должны были быть директории, соответствующие модулям с амперсандом. После преобразования каждый модуль из первого набора потеряет связь со своими вложенными модулями, и файлы с путями, соответствующими им, окажутся преобразованы несколько раз — один раз в репозитории относящимся к вложенному модулю и по разу в каждом репозитории модуля первого типа. Перед импортом в mercurial данная связь будет восстановлена.
Использование cvs2git из пакета cvs2svn не требует особой внимательности, кроме параметра COMMIT_THRESHOLD который склеивает коммиты. Дело в том, что в CVS каждый файл имеет свою историю, а в формате fast-import (как в git и mercurial) историю имеет весь репозиторий, поэтому отдельные изменения файлов надо слепить в прообразы будущих коммитов. По-умолчанию COMMIT_THRESHOLD равен 5 минутам, это значит, что изменения всех файлов попадающих в пятиминутное окно будут слеплены в один коммит.
Кроме того, можно задать отображение тегов, отображение авторов и другие параметры.
Для преобразования из формата fastimport в репозиторий mercurial используется расширение hg-fastimport. Отметим, что изначальный автор забросил этот проект и считает его неудачным, а более правильным подходом к преобразованию называет другой свой проект. Видимо поэтому расширение очень странным образом обрабатывает TAG.FIXUP ветви (в CVS можно было накладывать теги на те ревизии файлов, которые во времени друг с другом вообще никогда не встречались, поэтому для отображения таких тегов создается отдельная специальная ветка), что обычно требует подправления кода.
Формат fastimport представляет из себя файл (или несколько), задающий дерево репозитория в топологическом порядке. Каждый узел дерева, который затем станет коммитом, помечается уникальным текстовым идентификатором, например ":1000000003". После преобразования модулей второго типа в соответствующих новых репозиториях будет лежать файл .hg/shamap, с отображением коммитов mercurial в идентификаторы fastimport. Кроме того, каждый узел дерева в текстовом виде содержит список измененных файлов, например
M 100644 :30 sub/Makefileздесь :30 — маркер блоба, т.е. фактически содержания файла. Используя путь файла можно идентифицировать все файлы занесенные к нам из вложенных модулей. Нам бы хотелось преобразовать fastimport дамп таким образом чтобы в этих местах возникли ссылки на внешние репозитории, например так
M 160000 2d1eb0523f244f7bb1d58f016583a25ba3d40426 sub
Для этого предлагается следующих алгоритм. У нас есть два дерева в виде дампов fastimport: дерево вложенного репозитория и дерево основного. Кроме того, есть отображение маркеров узлов вложенного репозитория на хэш коммита. Обойдя каждое из деревьев для каждого узла, мы можем полностью восстановить состояние, т.е. набор всех существовавших файлов и их содержимое. Кроме того, для основного репозитория возможно определить состояние вложенной директории (будущего сабрепозитория). На рисунке схематично изображены узлы основного дерева (пронумерованы арабскими цифрами) и узлы дерева сабрепозитория (пронумерованы латинскими буквами). Черными стрелками показана очередность коммитов, стрелка идет от более нового коммита к его предку.
Далее, сравнивая состояния вложенного репозитория и соответствующие под-состояния основного репозитория, можно построить отображение узлов основного дерева на вложенное (красные стрелки на рисунке).
Возможны ситуации когда связь многозначная. Вообразим, что в предложенном примере G откатывает F, поэтому имеет такое же содержимое что и E, кроме того, в другой ветке есть C с таким же содержимым. Сообщения коммитов могут отсутствовать, время коммитов может отличаеться. В данной ситуации предлагаются следующие критерии разрешения конфликта.
Так как основное дерево обходится в топологическом порядке, то к моменту когда мы оказывается в узле 5 узел 4 уже обработан и мы знаем что ему соответствует узел D. Для всех возможных кандидатов C, E, G рассчитаем расстояние между ними и узлом D. Узел D не достижим из C, поэтому C отбрасывается. Оставшийся выбор производится на основании сообщения коммита и близости времени. Либо можно представить простой алгоритм, который за не полиномиальное время назначит соответствие, однако без информации о времени и сообщениях коммитов все-равно не обойтись.
Таким образом, у нас есть отображение меток дерева основного репозитория на метки (или хэши) вложенного репозитория. Этой информации достаточно, чтобы заменить все нужные вхождения об изменениях файлов в дампе. После этого, дамп можно скормить в hg-fastimport.
Наиболее удобным способом расположения иерархии репозиториев на сервере оказался следующий. Каждый вложенный репозиторий кладется в корень иерархии, кроме того, в каждый проект. Причем этим вторичным клонам мы запретим запись. А на первичный репозиторий навесим хуки, которые будут дергать pull во всех клонах.
[extensions] hgext.acl= [hooks] pretxnchangegroup.acl = python:hgext.acl.hook [acl] sources = serve push bundle [acl.deny] ** = * [paths] default = /repos/subrepo
OBS: локальная сборка под ARM
osc build --clean --alternative-project openSUSE:Factory:ARM qemu armv7l name.spec
Здесь указывается, что используется альтернативный проект для сборки — openSUSE:Factory:ARM (версию подставить по желанию), используется репозиторий qemu, который есть в этом проекте. Поэтому и указывается этот альтернативный проект.
Несмотря на то, что в данном примере указана архитектура armv7l, технически, это x86_64. В среду сборки будет установлен бинарный транслятор qemu, работающий через подсистему ядра binfmt. При инициализации ядро настраивается таким образом, что при виде сигнатуры ELF для архитектуры ARM вызывает бинарик как qemu-arm /usr/bin/..., подобно тому, как при виде символов "#!" в начале исполняемого файла вызывается указанный интерпретатор. Работает поэтому достаточно медленно.
К сожалению, с пакетами kiwi такое не проходит.
Сетевой стек на ATSAMD20
Нам понадобится:
- Atmel Software Framework — распространяемая под странным образом модифицированной BSD лицензией библиотека, реализующая удобный уровень индирекции при работе с переферией микроконтроллеров Atmel. Мы ей воспользуемся для работы через SPI. Внутри библиотеки весьма красивый код, понятный API и гора документации, исполненной в doxygen. Поэтому, основываясь на чувстве прекрасного, будем её использовать.
- ec28j60driver — драйвер для ENC28J60, реализует высокоуровневые функции работы с Ethernet путем обмена через SPI. Возьмем этот, потому-что написан он не левой пяткой и был достаточно легко портирован для работы с Atmel Software Framework. (см. ветку asf)
- lwIP — легковесный стек TCP/IP. Он отсылает или принимает Ethernet-пакеты через драйвер устройства и дальше разбирается что-же там внутри пришло. На сайте присутствует куча примеров.
Настройки для lwIP следующие:
lwoptions.h:
#define MEM_LIBC_MALLOC 1 #define MEMP_MEM_MALLOC 1 #define MEM_ALIGNMENT 4
cc.h:
#define BYTE_ORDER LITTLE_ENDIAN
Стиль программирования приложений, определяемый использованием RAW API библиотеки lwIP, через 5 минут создает полное ощущение, что ты пишешь gen_server на erlang, но последний почему-то кривой, неудобный и недоделанный.
Далее в таблице приводится размер кода прошивки, получаемый при различных вариантах конфигурации:
| config | -O3 | -Os |
|---|---|---|
| TCP/IP + DHCP + DEBUG(printf) | 96k | 82k |
| TCP/IP + DHCP | 54k | 40k |
| TCP/IP | 45k | 36k |
| UDP/IP + SNMP | 54k | 43k |
| UDP/IP | 28k | 24k |
Как-то так оно и работает.
openSUSE 13.1 на BeagleBone Black
На нем вполне успешно может загрузиться и даже работать openSUSE 13.1. Готовые образы для нанесения на microSD карточку находятся здесь. Эти же самые образы должны в теории работать и на BeagleBone. Конечно, пока все на этапе интеграции и поиска ошибок, поэтому имеется подробная инструкция по запуску:
- Скачать, распаковать и сделать dd на карточку образ системы *.raw.xz
- Подключить отладочный TTL-RS232 порт (можно использовать, например, такой, но важно помнить, что разработчики BeagleBone Black не поставили на свою плату преобразователь уровней и сигнал с отладочного RS232 идет в виде 3.3V. Подключение через обычный COM-порт на большом компьютере обречено на провал.), руководствуясь распиновкой. Используя screen /dev/ttyUSB0 115200, во-первых, можно будет легко видеть все этапы начиная от работы u-boot. Во-вторых, запустится Yast2 firstboot и попросит вас задать root пароль, завести пользователя, установить временную зону и системное время (аналогично тому, как это происходит на соответствующем этапе установки с DVD), а для этого потребуется интерактивное взаимодействие.
- Помните, что для загрузки с внешней карты памяти при подаче питания на устройство нужно удерживать кнопку S2 (она же boot select switch). Подсказка — загрузившись с SD карты можно подмонтировать раздел встроенной MMC памяти и переименовать или удалить файл загрузчика MLO, после этого загрузка будет всегда начинаться с SD, но загрузиться с MMC больше не получится.
Технические подробности (тем, кто хочет продолжить ковыряния) изложены в списке рассылки: http://lists.opensuse.org/opensuse-arm/2014-01/msg00001.html.
Atmel ATSAMD20-XPRO: собираем компилятор
Возьмем последний binutils-2.24:
./configure --target=arm-none-eabi -enable-interwork --enable-multilib --disable-nls --disable-libssp --prefix=/opt/arm-none-eabi make make install-strip export PATH=$PATH:/opt/arm-none-eabi/bin
Возьмем newlib-2.0.0 и распакуем его, пусть проветривается.
Возьмем gcc-4.8.2 который слышал о cortex-m0plus. Возьмем дебиановские патчи отсюда. Наложим их и скомпилируем:
mkdir build ../configure --target=arm-none-eabi --prefix=/opt/arm-none-eabi --enable-languages="c,c++" --enable-interwork --enable-multilib --with- newlib --with-headers=/path/to/src/newlib-2.0.0/newlib/libc/include/ --disable-nls --disable-libssp --with-system-zlib --with-multilib-lis t=armv6-m # в этом месте ./configure может ругаться, надо проследить чтобы он заголовки смог переписать на место make make all-gcc make install-gcc
newlib собирается со следующими ключами (без --disable-newlib-supplied-syscalls не собираются некоторые куски для armv6-m, и atmel-овский asf ругается на дублирующиеся определения функций из syscalls):
./configure --target=arm-none-eabi -enable-interwork --enable-multilib --disable-libssp --disable-nls --prefix=/opt/arm-none-eabi --disable-newlib-supplied-syscalls --enable-newlib-register-fini --enable-newlib-io-long-long make make install
После доделываем gcc:
cd build make all make install
Atmel ATSAMD20-XPRO
ATSAMD20-XPRO оценочный набор для новой серии микроконтроллеров Atmel ATSAMD20 на ядре Cortex-M0+. Выглядит следующим образом:
Купить в России можно например тут: Дельта Электроника.
Этот пост о том как подключать эту плату в GNU/Linux. Плата снабжена интерфейсом micro-USB для отладки, реализуемым через отдельную микросхему. Atmel называет это «Embedded Debugger», анонсируется наличие виртуального последовательного интерфейса (прикрученного к основному чипу) и собственно средств отладки и программирования.
При подключении появляется устройство:
Bus 001 Device 010: ID 03eb:2111 Atmel Corp.
[13761.329235] usb 1-1.5: New USB device found, idVendor=03eb, idProduct=2111 [13761.329240] usb 1-1.5: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [13761.329242] usb 1-1.5: Product: EDBG CMSIS-DAP [13761.329245] usb 1-1.5: Manufacturer: Atmel Corp. [13761.329247] usb 1-1.5: SerialNumber: ATML1873040200000110 [13761.330868] hid-generic 0003:03EB:2111.000A: hiddev0,hidraw3: USB HID v1.11 Device [Atmel Corp. EDBG CMSIS-DAP] on usb-0000:00:1a.0-1.5/input0 [13761.330964] cdc_acm 1-1.5:1.1: ttyACM0: USB ACM device
Устройство, как видно, отдает нам виртуальный последовательный интерфейс на /dev/ttyACM? и интерфейс CMSIS-DAP на /dev/hid*.
В openocd недавно добавили поддержку этого интерфейса. Пока пакеты openocd с поддержкой CMSIS-DAP доступны здесь:
В пакетах есть небольшой баг, связанный с тем, что udev стремится поставить на /dev/hidraw* группу владельца plugdev, которая по-умолчанию в системе не существует и в пакете не создается. openocd будет искать свой devel-project и потом попадет в Factory.
Запускаем и убеждается, что таки оно работает:
> openocd -f /usr/share/openocd/scripts/board/atmel_samd20_xplained_pro.cfg
Open On-Chip Debugger 0.8.0-dev-snapshot (2013-12-13-18:45)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.sourceforge.net/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'cmsis-dap'
Info : CMSIS-DAP: SWD Supported
Info : CMSIS-DAP: Interface Initialised (SWD)
adapter speed: 500 kHz
adapter_nsrst_delay: 100
cortex_m reset_config sysresetreq
Info : CMSIS-DAP: FW Version = 01.0F.00DB
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 1 TDO = 1 nTRST = 0 nRESET = 1
Info : DAP_SWJ Sequence (reset: 50+ '1' followed by 0)
Info : CMSIS-DAP: Interface ready
Info : clock speed 500 kHz
Info : IDCODE 0x0bc11477
Info : at91samd20j18.cpu: hardware has 4 breakpoints, 2 watchpoints
Быстродействие UNIX сокетов
На графике черная кривая — производительность unix-сокетов, красная и зеленая — для сравнения копирование памяти memcpy в рамках одного процесса и, соответственно, копирование из разделяемой (shared) памяти. Если рост производительности при увеличении "размера пакета" для сокетов не является чем-то не очевидным, то падение производительности операции memcpy при росте значения третьего аргумента функции не тривиально.
Характеристики тестового стенда. Процессор: Intel(R) Core(TM) i5-3470 CPU @ 3.20GHz, память: DDR3 Kingston HyperX KHX1600C9D3P1K2/8G. Ядро: 3.7.10.
Xen: проброс USB устройств
Вся конструкция управляется несколькими командами. Посмотреть, какие устройства доступны:
# xm usb-list-assignable-devices 4-2 : ID 067b:2303 Prolific Technology Inc. USB-Serial ControllerСоздать в домене паравиртуальный USB хост контроллер: xm usb-hc-create Domain UsbVer PortNum, где параметры — название домена, версия USB (поддерживаются 1 и 2) и количество USB-портов. После этого, в гостевом домене с помощью lsusb видно появившийся контроллер. Для удаления есть обратная команда xm usb-hc-destroy
Для присваивания устройства есть команда xm usb-attach Domain HostNum PortNum Device, где параметры — название домена, номер хост контроллера (их можно хоть пачку создать), номер порта на виртуальном контроллере, первая колонка выдачи usb-list-assignable-devices. Обратная команда — xm usb-destroy. При этом, в dom0 устройство пропадет на глазах у изумленного драйвера:
[12129.803899] pl2303 ttyUSB0: pl2303 converter now disconnected from ttyUSB0 [12129.803938] pl2303 4-2:1.0: device disconnectedно появится в гостевом домене:
# lsusb Bus 001 Device 002: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Важное замечание. Если в гостевом домене ничего не появилось, кроме записей в dmesg:
[12332.892117] usb 1-1: new full-speed USB device number 70 using vusb [12332.892126] usb 1-1: parent hub has no TTто скорее всего, устройство не поддерживает USB 2.0, к которому его прицепили, нужно сделать другой контроллер с правильным параметром UsbVer.
Кроме того, устройство можно прибить гвоздями в конфигурационном файле домена:
vusb=['usbver=1, numports=4, port_1=4-2']Список литературы:







