Polling on sockets in kernel space and struct file
Subsystems (2)
Hi all,
As part of implementing a new experimental protocol family, we are trying to create a socket in kernel. This seems to be easy, just use sock_create_kern(). However, the socket returned by this function does not have associated file structure; thus it cannot be polled on using poll_initwait() and friends.
We have tried to create the appropriate struct file using sock_map_fd(), but this has two problems:
1) We do not want our internal socket to be visible in the process context, i.e. it should not have a file descriptor.
2) During process exit, we get a kernel BUG from iput() in fs/inode.c:1260.
We then tried another approach using anon_inode_getfile() to get a struct file, but this still produces the problem 2) above.
Any help/advice on how to proceed would be appreciated; for reference our work in progress can be seen at
http://github.com/sustrik/linux-2.6/blob/sp-v2.6.36/net/sp/af_sp.c
Thanks,
Martin
Quoted 11 lines · Martin Sustrik
Hi all,
As part of implementing a new experimental protocol family, we are trying to create a socket in kernel. This seems to be easy, just use
sock_create_kern(). However, the socket returned by this function does not have associated file structure; thus it cannot be polled on usingpoll_initwait()and friends.We have tried to create the appropriate struct file using
sock_map_fd(), but this has two problems:
Quoted 8 lines
1) We do not want our internal socket to be visible in the process context, i.e. it should not have a file descriptor.
2) During process exit, we get a kernel BUG from
iput()infs/inode.c:1260.
you could call sock_map_fd() then :
int fd = sock_map_fd(sock, flags);
struct file *file = NULL;
if (fd != -1) {
file = fget(fd);
sys_close(fd); /* still racy */
}
if (file) ...Take a look at net/9p/trans_fd.c
Quoted 7 lines
We then tried another approach using
anon_inode_getfile()to get a struct file, but this still produces the problem 2) above.Any help/advice on how to proceed would be appreciated; for reference our work in progress can be seen at
http://github.com/sustrik/linux-2.6/blob/sp-v2.6.36/net/sp/af_sp.c
Hi Eric,
oddly enough our BUG at fs/inode.c seems to have gone away; may be a race of some sort...
Quoted 13 lines
you could call
sock_map_fd()then :int fd = sock_map_fd(sock, flags); struct file *file = NULL; if (fd != -1) { file = fget(fd); sys_close(fd); /* still racy */ } if (file) ...
Quoted 1 line
Take a look at
net/9p/trans_fd.c
Interesting approach.
We're currently doing the following -- we add this function to net/socket.c:
int sock_map_anon(struct socket *sock, const char *name, int flags)
{
struct file *newfile;
newfile = anon_inode_getfile(name, &socket_file_ops, sock, flags);
sock->file = newfile;
return 0;
}and then call it instead of sock_map_fd() from our sock_create():
/* Create peer socket and associated file structure */ rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sp->peer); if (rc < 0) goto out; rc = sock_map_anon(sp->peer, "[sp]", 0); if (rc < 0) goto out_release;
Is this a valid approach to achieve the same thing?
It's not clear what, if anything special we need to do to correctly release the anonymous inode when we are releasing our socket... is sock_release(sp->peer) sufficient?
Also, I see in 9p/trans_fd.c that it's using get_file() to increment the file refcount; do we need to do this for all sockets/files we create in kernel space or is this only for the sys_close() hack?
Thanks,
-mato