intelfb: fixup p calculation
[safe/jmp/linux-2.6] / net / socket.c
index a00851f..b807f36 100644 (file)
@@ -68,6 +68,7 @@
 #include <linux/netdevice.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/mutex.h>
 #include <linux/wanrouter.h>
 #include <linux/if_bridge.h>
 #include <linux/if_frad.h>
 #include <linux/compat.h>
 #include <linux/kmod.h>
 #include <linux/audit.h>
-
-#ifdef CONFIG_NET_RADIO
-#include <linux/wireless.h>            /* Note : will define WIRELESS_EXT */
-#endif /* CONFIG_NET_RADIO */
+#include <linux/wireless.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -109,6 +107,10 @@ static unsigned int sock_poll(struct file *file,
                              struct poll_table_struct *wait);
 static long sock_ioctl(struct file *file,
                      unsigned int cmd, unsigned long arg);
+#ifdef CONFIG_COMPAT
+static long compat_sock_ioctl(struct file *file,
+                     unsigned int cmd, unsigned long arg);
+#endif
 static int sock_fasync(int fd, struct file *filp, int on);
 static ssize_t sock_readv(struct file *file, const struct iovec *vector,
                          unsigned long count, loff_t *ppos);
@@ -117,6 +119,9 @@ static ssize_t sock_writev(struct file *file, const struct iovec *vector,
 static ssize_t sock_sendpage(struct file *file, struct page *page,
                             int offset, size_t size, loff_t *ppos, int more);
 
+extern ssize_t generic_splice_sendpage(struct inode *inode, struct file *out,
+                               size_t len, unsigned int flags);
+
 
 /*
  *     Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
@@ -130,13 +135,17 @@ static struct file_operations socket_file_ops = {
        .aio_write =    sock_aio_write,
        .poll =         sock_poll,
        .unlocked_ioctl = sock_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = compat_sock_ioctl,
+#endif
        .mmap =         sock_mmap,
        .open =         sock_no_open,   /* special open code to disallow open via /proc */
        .release =      sock_close,
        .fasync =       sock_fasync,
        .readv =        sock_readv,
        .writev =       sock_writev,
-       .sendpage =     sock_sendpage
+       .sendpage =     sock_sendpage,
+       .splice_write = generic_splice_sendpage,
 };
 
 /*
@@ -314,7 +323,8 @@ static int init_inodecache(void)
 {
        sock_inode_cachep = kmem_cache_create("sock_inode_cache",
                                sizeof(struct socket_alloc),
-                               0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+                               0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
+                                       SLAB_MEM_SPREAD),
                                init_once, NULL);
        if (sock_inode_cachep == NULL)
                return -ENOMEM;
@@ -351,8 +361,8 @@ static struct dentry_operations sockfs_dentry_operations = {
 /*
  *     Obtains the first available file descriptor and sets it up for use.
  *
- *     This function creates file structure and maps it to fd space
- *     of current process. On success it returns file descriptor
+ *     These functions create file structures and maps them to fd space
+ *     of the current process. On success it returns file descriptor
  *     and file struct implicitly stored in sock->file.
  *     Note that another thread may close file descriptor before we return
  *     from this function. We use the fact that now we do not refer
@@ -365,53 +375,90 @@ static struct dentry_operations sockfs_dentry_operations = {
  *     but we take care of internal coherence yet.
  */
 
-int sock_map_fd(struct socket *sock)
+static int sock_alloc_fd(struct file **filep)
 {
        int fd;
-       struct qstr this;
-       char name[32];
-
-       /*
-        *      Find a file descriptor suitable for return to the user. 
-        */
 
        fd = get_unused_fd();
-       if (fd >= 0) {
+       if (likely(fd >= 0)) {
                struct file *file = get_empty_filp();
 
-               if (!file) {
+               *filep = file;
+               if (unlikely(!file)) {
                        put_unused_fd(fd);
-                       fd = -ENFILE;
-                       goto out;
+                       return -ENFILE;
                }
+       } else
+               *filep = NULL;
+       return fd;
+}
 
-               this.len = sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino);
-               this.name = name;
-               this.hash = SOCK_INODE(sock)->i_ino;
+static int sock_attach_fd(struct socket *sock, struct file *file)
+{
+       struct qstr this;
+       char name[32];
+
+       this.len = sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino);
+       this.name = name;
+       this.hash = SOCK_INODE(sock)->i_ino;
+
+       file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this);
+       if (unlikely(!file->f_dentry))
+               return -ENOMEM;
+
+       file->f_dentry->d_op = &sockfs_dentry_operations;
+       d_add(file->f_dentry, SOCK_INODE(sock));
+       file->f_vfsmnt = mntget(sock_mnt);
+       file->f_mapping = file->f_dentry->d_inode->i_mapping;
+
+       sock->file = file;
+       file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops;
+       file->f_mode = FMODE_READ | FMODE_WRITE;
+       file->f_flags = O_RDWR;
+       file->f_pos = 0;
+       file->private_data = sock;
+
+       return 0;
+}
+
+int sock_map_fd(struct socket *sock)
+{
+       struct file *newfile;
+       int fd = sock_alloc_fd(&newfile);
 
-               file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this);
-               if (!file->f_dentry) {
-                       put_filp(file);
+       if (likely(fd >= 0)) {
+               int err = sock_attach_fd(sock, newfile);
+
+               if (unlikely(err < 0)) {
+                       put_filp(newfile);
                        put_unused_fd(fd);
-                       fd = -ENOMEM;
-                       goto out;
+                       return err;
                }
-               file->f_dentry->d_op = &sockfs_dentry_operations;
-               d_add(file->f_dentry, SOCK_INODE(sock));
-               file->f_vfsmnt = mntget(sock_mnt);
-               file->f_mapping = file->f_dentry->d_inode->i_mapping;
+               fd_install(fd, newfile);
+       }
+       return fd;
+}
 
-               sock->file = file;
-               file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops;
-               file->f_mode = FMODE_READ | FMODE_WRITE;
-               file->f_flags = O_RDWR;
-               file->f_pos = 0;
-               file->private_data = sock;
-               fd_install(fd, file);
+static struct socket *sock_from_file(struct file *file, int *err)
+{
+       struct inode *inode;
+       struct socket *sock;
+
+       if (file->f_op == &socket_file_ops)
+               return file->private_data;      /* set in sock_map_fd */
+
+       inode = file->f_dentry->d_inode;
+       if (!S_ISSOCK(inode->i_mode)) {
+               *err = -ENOTSOCK;
+               return NULL;
        }
 
-out:
-       return fd;
+       sock = SOCKET_I(inode);
+       if (sock->file != file) {
+               printk(KERN_ERR "socki_lookup: socket file changed!\n");
+               sock->file = file;
+       }
+       return sock;
 }
 
 /**
@@ -430,31 +477,31 @@ out:
 struct socket *sockfd_lookup(int fd, int *err)
 {
        struct file *file;
-       struct inode *inode;
        struct socket *sock;
 
-       if (!(file = fget(fd)))
-       {
+       if (!(file = fget(fd))) {
                *err = -EBADF;
                return NULL;
        }
-
-       if (file->f_op == &socket_file_ops)
-               return file->private_data;      /* set in sock_map_fd */
-
-       inode = file->f_dentry->d_inode;
-       if (!S_ISSOCK(inode->i_mode)) {
-               *err = -ENOTSOCK;
+       sock = sock_from_file(file, err);
+       if (!sock)
                fput(file);
-               return NULL;
-       }
+       return sock;
+}
 
-       sock = SOCKET_I(inode);
-       if (sock->file != file) {
-               printk(KERN_ERR "socki_lookup: socket file changed!\n");
-               sock->file = file;
+static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
+{
+       struct file *file;
+       struct socket *sock;
+
+       file = fget_light(fd, fput_needed);
+       if (file) {
+               sock = sock_from_file(file, err);
+               if (sock)
+                       return sock;
+               fput_light(file, *fput_needed);
        }
-       return sock;
+       return NULL;
 }
 
 /**
@@ -496,7 +543,7 @@ static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
        return -ENXIO;
 }
 
-struct file_operations bad_sock_fops = {
+const struct file_operations bad_sock_fops = {
        .owner = THIS_MODULE,
        .open = sock_no_open,
 };
@@ -792,36 +839,36 @@ static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf,
  * with module unload.
  */
 
-static DECLARE_MUTEX(br_ioctl_mutex);
+static DEFINE_MUTEX(br_ioctl_mutex);
 static int (*br_ioctl_hook)(unsigned int cmd, void __user *arg) = NULL;
 
 void brioctl_set(int (*hook)(unsigned int, void __user *))
 {
-       down(&br_ioctl_mutex);
+       mutex_lock(&br_ioctl_mutex);
        br_ioctl_hook = hook;
-       up(&br_ioctl_mutex);
+       mutex_unlock(&br_ioctl_mutex);
 }
 EXPORT_SYMBOL(brioctl_set);
 
-static DECLARE_MUTEX(vlan_ioctl_mutex);
+static DEFINE_MUTEX(vlan_ioctl_mutex);
 static int (*vlan_ioctl_hook)(void __user *arg);
 
 void vlan_ioctl_set(int (*hook)(void __user *))
 {
-       down(&vlan_ioctl_mutex);
+       mutex_lock(&vlan_ioctl_mutex);
        vlan_ioctl_hook = hook;
-       up(&vlan_ioctl_mutex);
+       mutex_unlock(&vlan_ioctl_mutex);
 }
 EXPORT_SYMBOL(vlan_ioctl_set);
 
-static DECLARE_MUTEX(dlci_ioctl_mutex);
+static DEFINE_MUTEX(dlci_ioctl_mutex);
 static int (*dlci_ioctl_hook)(unsigned int, void __user *);
 
 void dlci_ioctl_set(int (*hook)(unsigned int, void __user *))
 {
-       down(&dlci_ioctl_mutex);
+       mutex_lock(&dlci_ioctl_mutex);
        dlci_ioctl_hook = hook;
-       up(&dlci_ioctl_mutex);
+       mutex_unlock(&dlci_ioctl_mutex);
 }
 EXPORT_SYMBOL(dlci_ioctl_set);
 
@@ -840,11 +887,11 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
        if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
                err = dev_ioctl(cmd, argp);
        } else
-#ifdef WIRELESS_EXT
+#ifdef CONFIG_WIRELESS_EXT
        if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
                err = dev_ioctl(cmd, argp);
        } else
-#endif /* WIRELESS_EXT */
+#endif /* CONFIG_WIRELESS_EXT */
        switch (cmd) {
                case FIOSETOWN:
                case SIOCSPGRP:
@@ -865,10 +912,10 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
                        if (!br_ioctl_hook)
                                request_module("bridge");
 
-                       down(&br_ioctl_mutex);
+                       mutex_lock(&br_ioctl_mutex);
                        if (br_ioctl_hook) 
                                err = br_ioctl_hook(cmd, argp);
-                       up(&br_ioctl_mutex);
+                       mutex_unlock(&br_ioctl_mutex);
                        break;
                case SIOCGIFVLAN:
                case SIOCSIFVLAN:
@@ -876,10 +923,10 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
                        if (!vlan_ioctl_hook)
                                request_module("8021q");
 
-                       down(&vlan_ioctl_mutex);
+                       mutex_lock(&vlan_ioctl_mutex);
                        if (vlan_ioctl_hook)
                                err = vlan_ioctl_hook(argp);
-                       up(&vlan_ioctl_mutex);
+                       mutex_unlock(&vlan_ioctl_mutex);
                        break;
                case SIOCGIFDIVERT:
                case SIOCSIFDIVERT:
@@ -893,9 +940,9 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
                                request_module("dlci");
 
                        if (dlci_ioctl_hook) {
-                               down(&dlci_ioctl_mutex);
+                               mutex_lock(&dlci_ioctl_mutex);
                                err = dlci_ioctl_hook(cmd, argp);
-                               up(&dlci_ioctl_mutex);
+                               mutex_unlock(&dlci_ioctl_mutex);
                        }
                        break;
                default:
@@ -1289,19 +1336,17 @@ asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
 {
        struct socket *sock;
        char address[MAX_SOCK_ADDR];
-       int err;
+       int err, fput_needed;
 
-       if((sock = sockfd_lookup(fd,&err))!=NULL)
+       if((sock = sockfd_lookup_light(fd, &err, &fput_needed))!=NULL)
        {
                if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) {
                        err = security_socket_bind(sock, (struct sockaddr *)address, addrlen);
-                       if (err) {
-                               sockfd_put(sock);
-                               return err;
-                       }
-                       err = sock->ops->bind(sock, (struct sockaddr *)address, addrlen);
+                       if (!err)
+                               err = sock->ops->bind(sock,
+                                       (struct sockaddr *)address, addrlen);
                }
-               sockfd_put(sock);
+               fput_light(sock->file, fput_needed);
        }                       
        return err;
 }
@@ -1318,20 +1363,17 @@ int sysctl_somaxconn = SOMAXCONN;
 asmlinkage long sys_listen(int fd, int backlog)
 {
        struct socket *sock;
-       int err;
+       int err, fput_needed;
        
-       if ((sock = sockfd_lookup(fd, &err)) != NULL) {
+       if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) {
                if ((unsigned) backlog > sysctl_somaxconn)
                        backlog = sysctl_somaxconn;
 
                err = security_socket_listen(sock, backlog);
-               if (err) {
-                       sockfd_put(sock);
-                       return err;
-               }
+               if (!err)
+                       err = sock->ops->listen(sock, backlog);
 
-               err=sock->ops->listen(sock, backlog);
-               sockfd_put(sock);
+               fput_light(sock->file, fput_needed);
        }
        return err;
 }
@@ -1352,10 +1394,11 @@ asmlinkage long sys_listen(int fd, int backlog)
 asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen)
 {
        struct socket *sock, *newsock;
-       int err, len;
+       struct file *newfile;
+       int err, len, newfd, fput_needed;
        char address[MAX_SOCK_ADDR];
 
-       sock = sockfd_lookup(fd, &err);
+       sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
                goto out;
 
@@ -1372,37 +1415,49 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int _
         */
        __module_get(newsock->ops->owner);
 
+       newfd = sock_alloc_fd(&newfile);
+       if (unlikely(newfd < 0)) {
+               err = newfd;
+               sock_release(newsock);
+               goto out_put;
+       }
+
+       err = sock_attach_fd(newsock, newfile);
+       if (err < 0)
+               goto out_fd;
+
        err = security_socket_accept(sock, newsock);
        if (err)
-               goto out_release;
+               goto out_fd;
 
        err = sock->ops->accept(sock, newsock, sock->file->f_flags);
        if (err < 0)
-               goto out_release;
+               goto out_fd;
 
        if (upeer_sockaddr) {
                if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) {
                        err = -ECONNABORTED;
-                       goto out_release;
+                       goto out_fd;
                }
                err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen);
                if (err < 0)
-                       goto out_release;
+                       goto out_fd;
        }
 
        /* File flags are not inherited via accept() unlike another OSes. */
 
-       if ((err = sock_map_fd(newsock)) < 0)
-               goto out_release;
+       fd_install(newfd, newfile);
+       err = newfd;
 
        security_socket_post_accept(sock, newsock);
 
 out_put:
-       sockfd_put(sock);
+       fput_light(sock->file, fput_needed);
 out:
        return err;
-out_release:
-       sock_release(newsock);
+out_fd:
+       fput(newfile);
+       put_unused_fd(newfd);
        goto out_put;
 }
 
@@ -1423,9 +1478,9 @@ asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrl
 {
        struct socket *sock;
        char address[MAX_SOCK_ADDR];
-       int err;
+       int err, fput_needed;
 
-       sock = sockfd_lookup(fd, &err);
+       sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
                goto out;
        err = move_addr_to_kernel(uservaddr, addrlen, address);
@@ -1439,7 +1494,7 @@ asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrl
        err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen,
                                 sock->file->f_flags);
 out_put:
-       sockfd_put(sock);
+       fput_light(sock->file, fput_needed);
 out:
        return err;
 }
@@ -1453,9 +1508,9 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int _
 {
        struct socket *sock;
        char address[MAX_SOCK_ADDR];
-       int len, err;
+       int len, err, fput_needed;
        
-       sock = sockfd_lookup(fd, &err);
+       sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
                goto out;
 
@@ -1469,7 +1524,7 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int _
        err = move_addr_to_user(address, len, usockaddr, usockaddr_len);
 
 out_put:
-       sockfd_put(sock);
+       fput_light(sock->file, fput_needed);
 out:
        return err;
 }
@@ -1483,20 +1538,19 @@ asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int _
 {
        struct socket *sock;
        char address[MAX_SOCK_ADDR];
-       int len, err;
+       int len, err, fput_needed;
 
-       if ((sock = sockfd_lookup(fd, &err))!=NULL)
-       {
+       if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) {
                err = security_socket_getpeername(sock);
                if (err) {
-                       sockfd_put(sock);
+                       fput_light(sock->file, fput_needed);
                        return err;
                }
 
                err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 1);
                if (!err)
                        err=move_addr_to_user(address,len, usockaddr, usockaddr_len);
-               sockfd_put(sock);
+               fput_light(sock->file, fput_needed);
        }
        return err;
 }
@@ -1515,10 +1569,16 @@ asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flag
        int err;
        struct msghdr msg;
        struct iovec iov;
-       
-       sock = sockfd_lookup(fd, &err);
+       int fput_needed;
+       struct file *sock_file;
+
+       sock_file = fget_light(fd, &fput_needed);
+       if (!sock_file)
+               return -EBADF;
+
+       sock = sock_from_file(sock_file, &err);
        if (!sock)
-               goto out;
+               goto out_put;
        iov.iov_base=buff;
        iov.iov_len=len;
        msg.msg_name=NULL;
@@ -1527,8 +1587,7 @@ asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flag
        msg.msg_control=NULL;
        msg.msg_controllen=0;
        msg.msg_namelen=0;
-       if(addr)
-       {
+       if (addr) {
                err = move_addr_to_kernel(addr, addr_len, address);
                if (err < 0)
                        goto out_put;
@@ -1541,8 +1600,7 @@ asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flag
        err = sock_sendmsg(sock, &msg, len);
 
 out_put:               
-       sockfd_put(sock);
-out:
+       fput_light(sock_file, fput_needed);
        return err;
 }
 
@@ -1569,8 +1627,14 @@ asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned f
        struct msghdr msg;
        char address[MAX_SOCK_ADDR];
        int err,err2;
+       struct file *sock_file;
+       int fput_needed;
+
+       sock_file = fget_light(fd, &fput_needed);
+       if (!sock_file)
+               return -EBADF;
 
-       sock = sockfd_lookup(fd, &err);
+       sock = sock_from_file(sock_file, &err);
        if (!sock)
                goto out;
 
@@ -1592,8 +1656,8 @@ asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned f
                if(err2<0)
                        err=err2;
        }
-       sockfd_put(sock);                       
 out:
+       fput_light(sock_file, fput_needed);
        return err;
 }
 
@@ -1613,25 +1677,24 @@ asmlinkage long sys_recv(int fd, void __user * ubuf, size_t size, unsigned flags
 
 asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen)
 {
-       int err;
+       int err, fput_needed;
        struct socket *sock;
 
        if (optlen < 0)
                return -EINVAL;
                        
-       if ((sock = sockfd_lookup(fd, &err))!=NULL)
+       if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL)
        {
                err = security_socket_setsockopt(sock,level,optname);
-               if (err) {
-                       sockfd_put(sock);
-                       return err;
-               }
+               if (err)
+                       goto out_put;
 
                if (level == SOL_SOCKET)
                        err=sock_setsockopt(sock,level,optname,optval,optlen);
                else
                        err=sock->ops->setsockopt(sock, level, optname, optval, optlen);
-               sockfd_put(sock);
+out_put:
+               fput_light(sock->file, fput_needed);
        }
        return err;
 }
@@ -1643,23 +1706,20 @@ asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optv
 
 asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen)
 {
-       int err;
+       int err, fput_needed;
        struct socket *sock;
 
-       if ((sock = sockfd_lookup(fd, &err))!=NULL)
-       {
-               err = security_socket_getsockopt(sock, level, 
-                                                          optname);
-               if (err) {
-                       sockfd_put(sock);
-                       return err;
-               }
+       if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) {
+               err = security_socket_getsockopt(sock, level, optname);
+               if (err)
+                       goto out_put;
 
                if (level == SOL_SOCKET)
                        err=sock_getsockopt(sock,level,optname,optval,optlen);
                else
                        err=sock->ops->getsockopt(sock, level, optname, optval, optlen);
-               sockfd_put(sock);
+out_put:
+               fput_light(sock->file, fput_needed);
        }
        return err;
 }
@@ -1671,19 +1731,15 @@ asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optv
 
 asmlinkage long sys_shutdown(int fd, int how)
 {
-       int err;
+       int err, fput_needed;
        struct socket *sock;
 
-       if ((sock = sockfd_lookup(fd, &err))!=NULL)
+       if ((sock = sockfd_lookup_light(fd, &err, &fput_needed))!=NULL)
        {
                err = security_socket_shutdown(sock, how);
-               if (err) {
-                       sockfd_put(sock);
-                       return err;
-               }
-                               
-               err=sock->ops->shutdown(sock, how);
-               sockfd_put(sock);
+               if (!err)
+                       err = sock->ops->shutdown(sock, how);
+               fput_light(sock->file, fput_needed);
        }
        return err;
 }
@@ -1712,6 +1768,7 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
        unsigned char *ctl_buf = ctl;
        struct msghdr msg_sys;
        int err, ctl_len, iov_size, total_len;
+       int fput_needed;
        
        err = -EFAULT;
        if (MSG_CMSG_COMPAT & flags) {
@@ -1720,7 +1777,7 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
        } else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
                return -EFAULT;
 
-       sock = sockfd_lookup(fd, &err);
+       sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock) 
                goto out;
 
@@ -1788,7 +1845,7 @@ out_freeiov:
        if (iov != iovstack)
                sock_kfree_s(sock->sk, iov, iov_size);
 out_put:
-       sockfd_put(sock);
+       fput_light(sock->file, fput_needed);
 out:       
        return err;
 }
@@ -1806,6 +1863,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flag
        struct msghdr msg_sys;
        unsigned long cmsg_ptr;
        int err, iov_size, total_len, len;
+       int fput_needed;
 
        /* kernel mode address */
        char addr[MAX_SOCK_ADDR];
@@ -1821,7 +1879,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flag
                if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr)))
                        return -EFAULT;
 
-       sock = sockfd_lookup(fd, &err);
+       sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
                goto out;
 
@@ -1888,7 +1946,7 @@ out_freeiov:
        if (iov != iovstack)
                sock_kfree_s(sock->sk, iov, iov_size);
 out_put:
-       sockfd_put(sock);
+       fput_light(sock->file, fput_needed);
 out:
        return err;
 }
@@ -2089,6 +2147,20 @@ void socket_seq_show(struct seq_file *seq)
 }
 #endif /* CONFIG_PROC_FS */
 
+#ifdef CONFIG_COMPAT
+static long compat_sock_ioctl(struct file *file, unsigned cmd,
+                               unsigned long arg)
+{
+       struct socket *sock = file->private_data;
+       int ret = -ENOIOCTLCMD;
+
+       if (sock->ops->compat_ioctl)
+               ret = sock->ops->compat_ioctl(sock, cmd, arg);
+
+       return ret;
+}
+#endif
+
 /* ABI emulation layers need these two */
 EXPORT_SYMBOL(move_addr_to_kernel);
 EXPORT_SYMBOL(move_addr_to_user);