From: Andrew Morton It oopses a lot. Cc: "David S. Miller" Signed-off-by: Andrew Morton --- net/socket.c | 115 ++++++++++++++++++------------------------------- 1 files changed, 43 insertions(+), 72 deletions(-) diff -puN net/socket.c~revert-NET-Do-not-lose-accepted-socket-when-ENFILE-EMFILE net/socket.c --- devel/net/socket.c~revert-NET-Do-not-lose-accepted-socket-when-ENFILE-EMFILE 2006-01-28 17:21:58.000000000 -0800 +++ devel-akpm/net/socket.c 2006-01-28 17:21:58.000000000 -0800 @@ -351,8 +351,8 @@ static struct dentry_operations sockfs_d /* * Obtains the first available file descriptor and sets it up for use. * - * These functions create file structures and maps them to fd space - * of the current process. On success it returns file descriptor + * This function creates file structure and maps it to fd space + * of 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,67 +365,52 @@ static struct dentry_operations sockfs_d * but we take care of internal coherence yet. */ -static int sock_alloc_fd(struct file **filep) +int sock_map_fd(struct socket *sock) { int fd; + struct qstr this; + char name[32]; + + /* + * Find a file descriptor suitable for return to the user. + */ fd = get_unused_fd(); - if (likely(fd >= 0)) { + if (fd >= 0) { struct file *file = get_empty_filp(); - if (unlikely(!file)) { + if (!file) { put_unused_fd(fd); - return -ENFILE; + fd = -ENFILE; + goto out; } - *filep = file; - } else - *filep = NULL; - return fd; -} -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); - - if (likely(fd >= 0)) { - int err = sock_attach_fd(sock, newfile); - - if (unlikely(err < 0)) { - fput(newfile); + 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 (!file->f_dentry) { + put_filp(file); put_unused_fd(fd); - return err; + fd = -ENOMEM; + goto out; } - fd_install(fd, newfile); + 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; + fd_install(fd, file); } + +out: return fd; } @@ -1367,8 +1352,7 @@ asmlinkage long sys_listen(int fd, int b asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen) { struct socket *sock, *newsock; - struct file *newfile; - int err, len, newfd; + int err, len; char address[MAX_SOCK_ADDR]; sock = sockfd_lookup(fd, &err); @@ -1388,38 +1372,28 @@ asmlinkage long sys_accept(int fd, struc */ __module_get(newsock->ops->owner); - newfd = sock_alloc_fd(&newfile); - if (newfd < 0) { - err = newfd; - goto out_release; - } - - err = sock_attach_fd(sock, newfile); - if (err < 0) - goto out_fd; - err = security_socket_accept(sock, newsock); if (err) - goto out_fd; + goto out_release; err = sock->ops->accept(sock, newsock, sock->file->f_flags); if (err < 0) - goto out_fd; + goto out_release; if (upeer_sockaddr) { if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) { err = -ECONNABORTED; - goto out_fd; + goto out_release; } err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen); if (err < 0) - goto out_fd; + goto out_release; } /* File flags are not inherited via accept() unlike another OSes. */ - fd_install(newfd, newfile); - err = newfd; + if ((err = sock_map_fd(newsock)) < 0) + goto out_release; security_socket_post_accept(sock, newsock); @@ -1427,9 +1401,6 @@ out_put: sockfd_put(sock); out: return err; -out_fd: - fput(newfile); - put_unused_fd(newfd); out_release: sock_release(newsock); goto out_put; _