Re: [PATCH 2.6.11-rc4-mm1] connector: Add a fork connector

From: Kaigai Kohei
Date: Wed Mar 02 2005 - 22:36:24 EST


Hello, Guillaume

I tried to measure the process-creation/destruction performance on 2.6.11-rc4-mm1 plus
some extensiton(Normal/with PAGG/with Fork-Connector).
But I received a following messages endlessly on system console with Fork-Connector extensiton.

# on IA-64 environment / When an simple fork() iteration is run in parallel.
skb does not have enough length: requested msg->len=10[28], nlh->nlmsg_len=48[32], skb->len=48[must be 30].
skb does not have enough length: requested msg->len=10[28], nlh->nlmsg_len=48[32], skb->len=48[must be 30].
skb does not have enough length: requested msg->len=10[28], nlh->nlmsg_len=48[32], skb->len=48[must be 30].
:

Is's generated at drivers/connector/connector.c:__cn_rx_skb(), and this warn the length of msg's payload
does not fit in nlmsghdr's length.
This message means netlink packet is not sent to user space.
I was notified occurence of fork() by printk(). :-(

The attached simple *.c file can enable/disable fork-connector and listen the fork-notification.
Because It's first experimence for me to write a code to use netlink, point out a right how-to-use
if there's some mistakes at user side apprication.

Thanks.

P.S. I can't reproduce lockup on 367th-fork() with your latest patch.

Guillaume Thouvenin wrote:
> ChangeLog:
>
> - Add parenthesis around sizeof(struct cn_msg) + CN_FORK_INFO_SIZE
> in the CN_FORK_MSG_SIZE macro
> - fork_cn_lock is declareed with DEFINE_SPINLOCK()
> - fork_cn_lock is defined as static and local to fork_connector()
> - Create a specific module cn_fork.c in drivers/connector to
> register the callback.
> - Improve the callback that turns on/off the fork connector
>
> I also run the lmbench and results are send in response to another
> thread "A common layer for Accounting packages". When fork connector is
> turned off the overhead is negligible. This patch works with another
> small patch that fix a problem in the connector. Without it, there is a
> message that says "skb does not have enough length". It will be fix in
> the next -mm tree I think.
>
>
> Thanks everyone for the comments,
> Guillaume

--
Linux Promotion Center, NEC
KaiGai Kohei <kaigai@xxxxxxxxxxxxx>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <asm/types.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>

void usage(){
puts("usage: fclisten <on|off>");
puts(" Default -> listening fork-connector");
puts(" on -> fork-connector Enable");
puts(" off -> fork-connector Disable");
exit(0);
}

#define MODE_LISTEN (1)
#define MODE_ENABLE (2)
#define MODE_DISABLE (3)

struct cb_id
{
__u32 idx;
__u32 val;
};

struct cn_msg
{
struct cb_id id;
__u32 seq;
__u32 ack;
__u32 len; /* Length of the following data */
__u8 data[0];
};


int main(int argc, char *argv[]){
char buf[4096];
int mode, sockfd, len;
struct sockaddr_nl ad;
struct nlmsghdr *hdr = (struct nlmsghdr *)buf;
struct cn_msg *msg = (struct cn_msg *)(buf+sizeof(struct nlmsghdr));

switch(argc){
case 1:
mode = MODE_LISTEN;
break;
case 2:
if (strcasecmp("on",argv[1])==0) {
mode = MODE_ENABLE;
}else if (strcasecmp("off",argv[1])==0){
mode = MODE_DISABLE;
}else{
usage();
}
break;
default:
usage();
break;
}

if( (sockfd=socket(PF_NETLINK, SOCK_RAW, NETLINK_NFLOG)) < 0 ){
fprintf(stderr, "Fault on socket().\n");
return( 1 );
}
ad.nl_family = AF_NETLINK;
ad.nl_pad = 0;
ad.nl_pid = getpid();
ad.nl_groups = -1;
if( bind(sockfd, (struct sockaddr *)&ad, sizeof(ad)) ){
fprintf(stderr, "Fault on bind to netlink.\n");
return( 2 );
}

if (mode==MODE_LISTEN) {
while(-1){
len = recvfrom(sockfd, buf, 4096, 0, NULL, NULL);
printf("%d-byte recv Seq=%d\n", len, hdr->nlmsg_seq);
}
}else{
ad.nl_family = AF_NETLINK;
ad.nl_pad = 0;
ad.nl_pid = 0;
ad.nl_groups = 1;

hdr->nlmsg_len = sizeof(struct nlmsghdr) + sizeof(struct cn_msg) + sizeof(int);
hdr->nlmsg_type = 0;
hdr->nlmsg_flags = 0;
hdr->nlmsg_seq = 0;
hdr->nlmsg_pid = getpid();
msg->id.idx = 0xfeed;
msg->id.val = 0xbeef;
msg->seq = msg->ack = 0;
msg->len = sizeof(int);

if (mode==MODE_ENABLE){
(*(int *)(msg->data)) = 1;
} else {
(*(int *)(msg->data)) = 0;
}
sendto(sockfd, buf, sizeof(struct nlmsghdr)+sizeof(struct cn_msg)+sizeof(int),
0, (struct sockaddr *)&ad, sizeof(ad));
}
}