LINUX.ORG.RU

rmmod возвращает EAGAIN (референсы на модуль)

 , ,


0

1

Приветствую,

достался в «наследство» сравнительно большое embedded проект (ARM процесор, linux 2.6.31, busybox), который нужно поддерживать. Столкнулся со следующей проблемой: ядерный модуль (часть этого проекта) всегда загружается первым, потом демон устанавливающий соединение по netlink сокету. Проблема в том, что после выгружения демона из памяти по SIGINT или SIGKILL, число референсов на этот модуль в ядре не 0 (cat /proc/net/modules | grep my_module, 3й параметр) и соответственно rmmod возвращает ошибку:

% rmmod my_module.ko
% rmmod: my_module.ko: Resource temporarily unavailable

Т.е. получаем -11 EAGAIN. Из кода демона известно, что открываются 3 netlink сокета в модуль и по таймеру один из сокетов регулярно читается, но после запуска демона число references в модуле (/proc/net/modules) поднимается с 0 до 6, после убийства демона опускается до 3, т.е. либо остаются открытые дескрипторы, либо что-то еще.

Подскажите, какие есть методы обнаружить и отловить такого рода баг?

Буду пременого благодарен! :)

★★

Ответ на: комментарий от Dennis7

Интересно, как я узнаю этой команды, используют ли другие модули мой модуль? На самом деле загружены еще два драйвера из комплекта Marvell SDK которые ничего не знают про my_module.ko, но они используются напрямую тем самым демоном.

cruz7 ★★
() автор топика
Ответ на: комментарий от tailgunner

Вы про марвеловский драйвер? Ужу делал, ничего не нашел. Аналогично в своем драйвере.

cruz7 ★★
() автор топика
Ответ на: комментарий от cruz7

Вы про марвеловский драйвер?

Про твой.

ничего не нашел. Аналогично в своем драйвере.

Т.е. ты до сих пор не знаешь, кто именно создает ссылки?

tailgunner ★★★★★
()

Пункт 0: отрезать яйца предыдущему драйверописателю

ttnl ★★★★★
()
Ответ на: комментарий от tailgunner

Т.е. ты до сих пор не знаешь, кто именно создает ссылки?

Таки если бы знал, то исходный вопрос звучал бы иначе :)

cruz7 ★★
() автор топика
Ответ на: комментарий от cruz7

Т.е. ты до сих пор не знаешь, кто именно создает ссылки?

Таки если бы знал

Ты по стеку вызовов не можешь определить вызывающий модуль или что?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Ты по стеку вызовов не можешь определить вызывающий модуль или что?

Как я уже сказал выше, в «моем» драйвере нет ни единого try_module_get(), или вы имеете в виду поставить dump_stack перед вызовом try_module_get в kernel/module.c

PS. сорри что торможу.

cruz7 ★★
() автор топика
Ответ на: комментарий от tailgunner

У тебя нет try_module_get? O_o Тогда непонятно, кем увеличивается счетчик. Может, есть MOD_INC_USE_COUNT?

Здесь http://stackoverflow.com/questions/1741415/linux-kernel-modules-when-to-use-t... не рекомендуется вызывать try_module_get() для своего модуля.

MOD_INC_USE_COUNT в драйвере тоже отсутствует.

cruz7 ★★
() автор топика
Ответ на: комментарий от cruz7

не рекомендуется вызывать try_module_get() для своего модуля.

Надо же. Век живи - век учись.

У меня такое впечатление, что у тебя где-то стоит замаскированное увеличение счетчика ссылок _вдобавок_ к автоматическому - заметь, что при открытии 3 сокетов счетчик растет до 6, а потом падает до 3, как будто автоматическое уменьшение счетчика срабатывает, а ручное - нет (или наоборот).

tailgunner ★★★★★
()
Ответ на: комментарий от cruz7

выглядит как баг в модуле. проверяй, всё ли, что инициализируется имеет деинициализацию в каком-то другом месте. я с подобным советом похож на капитана наверное, но к сожалению с netlink ничего не делал, так что подробностей его работы не знаю.

про try_module_get спасибо, я тоже не знал.

nanoolinux ★★★★
()
Ответ на: комментарий от nanoolinux

Всем привет, провел дополнительные исследования кода и вот что выяснил. Во-первых я был не прав, и создается не netlink сокет, а raw сокет нового семейства, которое регистрируется в этом ядерном модуле:

static struct proto_ops SOCKOPS_WRAPPED (hsl_ops) = {
  family:       AF_HSL,

  owner:        THIS_MODULE,
  release:      hsl_sock_release,
  bind:         _hsl_sock_bind,
  connect:      sock_no_connect,
  socketpair:   sock_no_socketpair,
  accept:       sock_no_accept,
  getname:      _hsl_sock_getname,
  poll:         datagram_poll,
  ioctl:        sock_no_ioctl,
  listen:       sock_no_listen,
  shutdown:     sock_no_shutdown,
  setsockopt:   sock_no_setsockopt,
  getsockopt:   sock_no_getsockopt,
  sendmsg:      _hsl_sock_sendmsg,
  recvmsg:      _hsl_sock_recvmsg,
  mmap:         sock_no_mmap,
  sendpage:     sock_no_sendpage,
};

static struct net_proto_family hsl_family_ops = {
  family:               AF_HSL,
  create:               _hsl_sock_create,
  owner:                THIS_MODULE
};
...

static int
_hsl_sock_create (struct net *net, struct socket *sock, int protocol)
{
  struct sock *sk = NULL;

  sock->state = SS_UNCONNECTED;
  sk = sk_alloc (current->nsproxy->net_ns, AF_HSL, GFP_KERNEL, &_prot);
  if (sk == NULL)
    goto ERR;

  sock->ops = &SOCKOPS_WRAPPED(hsl_ops);
  sock_init_data (sock,sk);

  sock_hold (sk);  /* XXX */
  ...

}

static void
_hsl_sock_destruct (struct sock *sk)
{
  struct hsl_sock *hsk, *phsk;

  if (!sk)
    return;

  ...
  sock_orphan (sk);
  skb_queue_purge (&sk->sk_receive_queue);

  sock_put (sk);
}

int
hsl_sock_release (struct socket *sock)
{
  struct sock *sk = sock->sk;

  /* Here goes logic to destroy net_devices */
  ...

  _hsl_sock_destruct (sk);

  sock->sk = NULL;

  return 0;
}

Вот как создается сокет в демоне:

fd = socket(AF_HSL, SOCK_RAW, 0);;
bind();
getsockname();
...

Во-вторых, меня смутило, что в _hsl_sock_create() вызывается sock_hold(), тем самым увеличивая reference counter сокета, хотя он уже выставляется в 1 в ф-ции sock_init_data(), а при уничтожении сокета sock_put уменьшает счетчик только на 1, и сокет полностью не удаляется из системы.

Убрал sock_hold, теперь при убийстве демона число ссылок опускается до 0 и rmmod работает, НО старте демона все равно число ссылок на модуль 6, это при том что создается только 3 raw сокета !

Посмотрел в код socket_create(): там вызывается внутрення ф-ция __socket_create() в которой собственно вызывается try_module_get, т.е. это единственное место увеличить счетчик.

PS. Ничего не понимаю(C) «Следствие ведут колобки»

cruz7 ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.