linux/arch/sparc64/solaris/socksys.c
Arjan van de Ven 5dfe4c964a [PATCH] mark struct file_operations const 2
Many struct file_operations in the kernel can be "const".  Marking them const
moves these to the .rodata section, which avoids false sharing with potential
dirty data.  In addition it'll catch accidental writes at compile time to
these shared resources.

[akpm@osdl.org: sparc64 fix]
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-02-12 09:48:44 -08:00

205 lines
5.2 KiB
C

/* $Id: socksys.c,v 1.21 2002/02/08 03:57:14 davem Exp $
* socksys.c: /dev/inet/ stuff for Solaris emulation.
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
* Copyright (C) 1997, 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)
* Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk)
*/
/*
* Dave, _please_ give me specifications on this fscking mess so that I
* could at least get it into the state when it wouldn't screw the rest of
* the kernel over. socksys.c and timod.c _stink_ and we are not talking
* H2S here, it's isopropilmercaptan in concentrations way over LD50. -- AV
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/ioctl.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/syscalls.h>
#include <linux/in.h>
#include <net/sock.h>
#include <asm/uaccess.h>
#include <asm/termios.h>
#include "conv.h"
#include "socksys.h"
static int af_inet_protocols[] = {
IPPROTO_ICMP, IPPROTO_ICMP, IPPROTO_IGMP, IPPROTO_IPIP, IPPROTO_TCP,
IPPROTO_EGP, IPPROTO_PUP, IPPROTO_UDP, IPPROTO_IDP, IPPROTO_RAW,
0, 0, 0, 0, 0, 0,
};
#ifndef DEBUG_SOLARIS_KMALLOC
#define mykmalloc kmalloc
#define mykfree kfree
#else
extern void * mykmalloc(size_t s, gfp_t gfp);
extern void mykfree(void *);
#endif
static unsigned int (*sock_poll)(struct file *, poll_table *);
static struct file_operations socksys_file_ops = {
/* Currently empty */
};
static int socksys_open(struct inode * inode, struct file * filp)
{
int family, type, protocol, fd;
struct dentry *dentry;
int (*sys_socket)(int,int,int) =
(int (*)(int,int,int))SUNOS(97);
struct sol_socket_struct * sock;
family = ((iminor(inode) >> 4) & 0xf);
switch (family) {
case AF_UNIX:
type = SOCK_STREAM;
protocol = 0;
break;
case AF_INET:
protocol = af_inet_protocols[iminor(inode) & 0xf];
switch (protocol) {
case IPPROTO_TCP: type = SOCK_STREAM; break;
case IPPROTO_UDP: type = SOCK_DGRAM; break;
default: type = SOCK_RAW; break;
}
break;
default:
type = SOCK_RAW;
protocol = 0;
break;
}
fd = sys_socket(family, type, protocol);
if (fd < 0)
return fd;
/*
* N.B. The following operations are not legal!
*
* No shit. WTF is it supposed to do, anyway?
*
* Try instead:
* d_delete(filp->f_path.dentry), then d_instantiate with sock inode
*/
dentry = filp->f_path.dentry;
filp->f_path.dentry = dget(fcheck(fd)->f_path.dentry);
filp->f_path.dentry->d_inode->i_rdev = inode->i_rdev;
filp->f_path.dentry->d_inode->i_flock = inode->i_flock;
SOCKET_I(filp->f_path.dentry->d_inode)->file = filp;
filp->f_op = &socksys_file_ops;
sock = (struct sol_socket_struct*)
mykmalloc(sizeof(struct sol_socket_struct), GFP_KERNEL);
if (!sock) return -ENOMEM;
SOLDD(("sock=%016lx(%016lx)\n", sock, filp));
sock->magic = SOLARIS_SOCKET_MAGIC;
sock->modcount = 0;
sock->state = TS_UNBND;
sock->offset = 0;
sock->pfirst = sock->plast = NULL;
filp->private_data = sock;
SOLDD(("filp->private_data %016lx\n", filp->private_data));
sys_close(fd);
dput(dentry);
return 0;
}
static int socksys_release(struct inode * inode, struct file * filp)
{
struct sol_socket_struct * sock;
struct T_primsg *it;
/* XXX: check this */
sock = (struct sol_socket_struct *)filp->private_data;
SOLDD(("sock release %016lx(%016lx)\n", sock, filp));
it = sock->pfirst;
while (it) {
struct T_primsg *next = it->next;
SOLDD(("socksys_release %016lx->%016lx\n", it, next));
mykfree((char*)it);
it = next;
}
filp->private_data = NULL;
SOLDD(("socksys_release %016lx\n", sock));
mykfree((char*)sock);
return 0;
}
static unsigned int socksys_poll(struct file * filp, poll_table * wait)
{
struct inode *ino;
unsigned int mask = 0;
ino=filp->f_path.dentry->d_inode;
if (ino && S_ISSOCK(ino->i_mode)) {
struct sol_socket_struct *sock;
sock = (struct sol_socket_struct*)filp->private_data;
if (sock && sock->pfirst) {
mask |= POLLIN | POLLRDNORM;
if (sock->pfirst->pri == MSG_HIPRI)
mask |= POLLPRI;
}
}
if (sock_poll)
mask |= (*sock_poll)(filp, wait);
return mask;
}
static const struct file_operations socksys_fops = {
.open = socksys_open,
.release = socksys_release,
};
int __init init_socksys(void)
{
int ret;
struct file * file;
int (*sys_socket)(int,int,int) =
(int (*)(int,int,int))SUNOS(97);
int (*sys_close)(unsigned int) =
(int (*)(unsigned int))SYS(close);
ret = register_chrdev (30, "socksys", &socksys_fops);
if (ret < 0) {
printk ("Couldn't register socksys character device\n");
return ret;
}
ret = sys_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ret < 0) {
printk ("Couldn't create socket\n");
return ret;
}
file = fcheck(ret);
/* N.B. Is this valid? Suppose the f_ops are in a module ... */
socksys_file_ops = *file->f_op;
sys_close(ret);
sock_poll = socksys_file_ops.poll;
socksys_file_ops.poll = socksys_poll;
socksys_file_ops.release = socksys_release;
return 0;
}
void __exit cleanup_socksys(void)
{
if (unregister_chrdev(30, "socksys"))
printk ("Couldn't unregister socksys character device\n");
}