[NET]: use fget_light() in net/socket.c
Here's an updated copy of the patch to use fget_light in net/socket.c. Rerunning the tests show a drop of ~80Mbit/s on average, which looks bad until you see the drop in cpu usage from ~89% to ~82%. That will get fixed in another patch... Before: max 8113.70, min 8026.32, avg 8072.34 87380 16384 16384 10.01 8045.55 87.11 87.11 1.774 1.774 87380 16384 16384 10.01 8065.14 90.86 90.86 1.846 1.846 87380 16384 16384 10.00 8077.76 89.85 89.85 1.822 1.822 87380 16384 16384 10.00 8026.32 89.80 89.80 1.833 1.833 87380 16384 16384 10.01 8108.59 89.81 89.81 1.815 1.815 87380 16384 16384 10.01 8034.53 89.01 89.01 1.815 1.815 87380 16384 16384 10.00 8113.70 90.45 90.45 1.827 1.827 87380 16384 16384 10.00 8111.37 89.90 89.90 1.816 1.816 87380 16384 16384 10.01 8077.75 87.96 87.96 1.784 1.784 87380 16384 16384 10.00 8062.70 90.25 90.25 1.834 1.834 After: max 8035.81, min 7963.69, avg 7998.14 87380 16384 16384 10.01 8000.93 82.11 82.11 1.682 1.682 87380 16384 16384 10.01 8016.17 83.67 83.67 1.710 1.710 87380 16384 16384 10.01 7963.69 83.47 83.47 1.717 1.717 87380 16384 16384 10.01 8014.35 81.71 81.71 1.671 1.671 87380 16384 16384 10.00 7967.68 83.41 83.41 1.715 1.715 87380 16384 16384 10.00 7995.22 81.00 81.00 1.660 1.660 87380 16384 16384 10.00 8002.61 83.90 83.90 1.718 1.718 87380 16384 16384 10.00 8035.81 81.71 81.71 1.666 1.666 87380 16384 16384 10.01 8005.36 82.56 82.56 1.690 1.690 87380 16384 16384 10.00 7979.61 82.50 82.50 1.694 1.694 Signed-off-by: Benjamin LaHaise <bcrl@linux.intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
8aca8a27d9
commit
6cb153cab9
194
net/socket.c
194
net/socket.c
|
@ -426,6 +426,28 @@ int sock_map_fd(struct socket *sock)
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
sock = SOCKET_I(inode);
|
||||||
|
if (sock->file != file) {
|
||||||
|
printk(KERN_ERR "socki_lookup: socket file changed!\n");
|
||||||
|
sock->file = file;
|
||||||
|
}
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sockfd_lookup - Go from a file number to its socket slot
|
* sockfd_lookup - Go from a file number to its socket slot
|
||||||
* @fd: file handle
|
* @fd: file handle
|
||||||
|
@ -442,33 +464,33 @@ int sock_map_fd(struct socket *sock)
|
||||||
struct socket *sockfd_lookup(int fd, int *err)
|
struct socket *sockfd_lookup(int fd, int *err)
|
||||||
{
|
{
|
||||||
struct file *file;
|
struct file *file;
|
||||||
struct inode *inode;
|
|
||||||
struct socket *sock;
|
struct socket *sock;
|
||||||
|
|
||||||
if (!(file = fget(fd)))
|
if (!(file = fget(fd))) {
|
||||||
{
|
|
||||||
*err = -EBADF;
|
*err = -EBADF;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
sock = sock_from_file(file, err);
|
||||||
if (file->f_op == &socket_file_ops)
|
if (!sock)
|
||||||
return file->private_data; /* set in sock_map_fd */
|
|
||||||
|
|
||||||
inode = file->f_dentry->d_inode;
|
|
||||||
if (!S_ISSOCK(inode->i_mode)) {
|
|
||||||
*err = -ENOTSOCK;
|
|
||||||
fput(file);
|
fput(file);
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
sock = SOCKET_I(inode);
|
|
||||||
if (sock->file != file) {
|
|
||||||
printk(KERN_ERR "socki_lookup: socket file changed!\n");
|
|
||||||
sock->file = file;
|
|
||||||
}
|
|
||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sock_alloc - allocate a socket
|
* sock_alloc - allocate a socket
|
||||||
*
|
*
|
||||||
|
@ -1301,19 +1323,17 @@ asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
|
||||||
{
|
{
|
||||||
struct socket *sock;
|
struct socket *sock;
|
||||||
char address[MAX_SOCK_ADDR];
|
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) {
|
if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) {
|
||||||
err = security_socket_bind(sock, (struct sockaddr *)address, addrlen);
|
err = security_socket_bind(sock, (struct sockaddr *)address, addrlen);
|
||||||
if (err) {
|
if (!err)
|
||||||
sockfd_put(sock);
|
err = sock->ops->bind(sock,
|
||||||
return err;
|
(struct sockaddr *)address, addrlen);
|
||||||
}
|
|
||||||
err = sock->ops->bind(sock, (struct sockaddr *)address, addrlen);
|
|
||||||
}
|
}
|
||||||
sockfd_put(sock);
|
fput_light(sock->file, fput_needed);
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1330,20 +1350,17 @@ int sysctl_somaxconn = SOMAXCONN;
|
||||||
asmlinkage long sys_listen(int fd, int backlog)
|
asmlinkage long sys_listen(int fd, int backlog)
|
||||||
{
|
{
|
||||||
struct socket *sock;
|
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)
|
if ((unsigned) backlog > sysctl_somaxconn)
|
||||||
backlog = sysctl_somaxconn;
|
backlog = sysctl_somaxconn;
|
||||||
|
|
||||||
err = security_socket_listen(sock, backlog);
|
err = security_socket_listen(sock, backlog);
|
||||||
if (err) {
|
if (!err)
|
||||||
sockfd_put(sock);
|
err = sock->ops->listen(sock, backlog);
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err=sock->ops->listen(sock, backlog);
|
fput_light(sock->file, fput_needed);
|
||||||
sockfd_put(sock);
|
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1365,10 +1382,10 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int _
|
||||||
{
|
{
|
||||||
struct socket *sock, *newsock;
|
struct socket *sock, *newsock;
|
||||||
struct file *newfile;
|
struct file *newfile;
|
||||||
int err, len, newfd;
|
int err, len, newfd, fput_needed;
|
||||||
char address[MAX_SOCK_ADDR];
|
char address[MAX_SOCK_ADDR];
|
||||||
|
|
||||||
sock = sockfd_lookup(fd, &err);
|
sock = sockfd_lookup_light(fd, &err, &fput_needed);
|
||||||
if (!sock)
|
if (!sock)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -1421,7 +1438,7 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int _
|
||||||
security_socket_post_accept(sock, newsock);
|
security_socket_post_accept(sock, newsock);
|
||||||
|
|
||||||
out_put:
|
out_put:
|
||||||
sockfd_put(sock);
|
fput_light(sock->file, fput_needed);
|
||||||
out:
|
out:
|
||||||
return err;
|
return err;
|
||||||
out_fd:
|
out_fd:
|
||||||
|
@ -1449,9 +1466,9 @@ asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrl
|
||||||
{
|
{
|
||||||
struct socket *sock;
|
struct socket *sock;
|
||||||
char address[MAX_SOCK_ADDR];
|
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)
|
if (!sock)
|
||||||
goto out;
|
goto out;
|
||||||
err = move_addr_to_kernel(uservaddr, addrlen, address);
|
err = move_addr_to_kernel(uservaddr, addrlen, address);
|
||||||
|
@ -1465,7 +1482,7 @@ asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrl
|
||||||
err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen,
|
err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen,
|
||||||
sock->file->f_flags);
|
sock->file->f_flags);
|
||||||
out_put:
|
out_put:
|
||||||
sockfd_put(sock);
|
fput_light(sock->file, fput_needed);
|
||||||
out:
|
out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1479,9 +1496,9 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int _
|
||||||
{
|
{
|
||||||
struct socket *sock;
|
struct socket *sock;
|
||||||
char address[MAX_SOCK_ADDR];
|
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)
|
if (!sock)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -1495,7 +1512,7 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int _
|
||||||
err = move_addr_to_user(address, len, usockaddr, usockaddr_len);
|
err = move_addr_to_user(address, len, usockaddr, usockaddr_len);
|
||||||
|
|
||||||
out_put:
|
out_put:
|
||||||
sockfd_put(sock);
|
fput_light(sock->file, fput_needed);
|
||||||
out:
|
out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1509,20 +1526,19 @@ asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int _
|
||||||
{
|
{
|
||||||
struct socket *sock;
|
struct socket *sock;
|
||||||
char address[MAX_SOCK_ADDR];
|
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);
|
err = security_socket_getpeername(sock);
|
||||||
if (err) {
|
if (err) {
|
||||||
sockfd_put(sock);
|
fput_light(sock->file, fput_needed);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 1);
|
err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 1);
|
||||||
if (!err)
|
if (!err)
|
||||||
err=move_addr_to_user(address,len, usockaddr, usockaddr_len);
|
err=move_addr_to_user(address,len, usockaddr, usockaddr_len);
|
||||||
sockfd_put(sock);
|
fput_light(sock->file, fput_needed);
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1541,10 +1557,16 @@ asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flag
|
||||||
int err;
|
int err;
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
struct iovec iov;
|
struct iovec iov;
|
||||||
|
int fput_needed;
|
||||||
sock = sockfd_lookup(fd, &err);
|
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)
|
if (!sock)
|
||||||
goto out;
|
goto out_put;
|
||||||
iov.iov_base=buff;
|
iov.iov_base=buff;
|
||||||
iov.iov_len=len;
|
iov.iov_len=len;
|
||||||
msg.msg_name=NULL;
|
msg.msg_name=NULL;
|
||||||
|
@ -1553,8 +1575,7 @@ asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flag
|
||||||
msg.msg_control=NULL;
|
msg.msg_control=NULL;
|
||||||
msg.msg_controllen=0;
|
msg.msg_controllen=0;
|
||||||
msg.msg_namelen=0;
|
msg.msg_namelen=0;
|
||||||
if(addr)
|
if (addr) {
|
||||||
{
|
|
||||||
err = move_addr_to_kernel(addr, addr_len, address);
|
err = move_addr_to_kernel(addr, addr_len, address);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out_put;
|
goto out_put;
|
||||||
|
@ -1567,8 +1588,7 @@ asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flag
|
||||||
err = sock_sendmsg(sock, &msg, len);
|
err = sock_sendmsg(sock, &msg, len);
|
||||||
|
|
||||||
out_put:
|
out_put:
|
||||||
sockfd_put(sock);
|
fput_light(sock_file, fput_needed);
|
||||||
out:
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1595,8 +1615,14 @@ asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned f
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
char address[MAX_SOCK_ADDR];
|
char address[MAX_SOCK_ADDR];
|
||||||
int err,err2;
|
int err,err2;
|
||||||
|
struct file *sock_file;
|
||||||
|
int fput_needed;
|
||||||
|
|
||||||
sock = sockfd_lookup(fd, &err);
|
sock_file = fget_light(fd, &fput_needed);
|
||||||
|
if (!sock_file)
|
||||||
|
return -EBADF;
|
||||||
|
|
||||||
|
sock = sock_from_file(sock_file, &err);
|
||||||
if (!sock)
|
if (!sock)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -1618,8 +1644,8 @@ asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned f
|
||||||
if(err2<0)
|
if(err2<0)
|
||||||
err=err2;
|
err=err2;
|
||||||
}
|
}
|
||||||
sockfd_put(sock);
|
|
||||||
out:
|
out:
|
||||||
|
fput_light(sock_file, fput_needed);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1639,25 +1665,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)
|
asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen)
|
||||||
{
|
{
|
||||||
int err;
|
int err, fput_needed;
|
||||||
struct socket *sock;
|
struct socket *sock;
|
||||||
|
|
||||||
if (optlen < 0)
|
if (optlen < 0)
|
||||||
return -EINVAL;
|
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);
|
err = security_socket_setsockopt(sock,level,optname);
|
||||||
if (err) {
|
if (err)
|
||||||
sockfd_put(sock);
|
goto out_put;
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (level == SOL_SOCKET)
|
if (level == SOL_SOCKET)
|
||||||
err=sock_setsockopt(sock,level,optname,optval,optlen);
|
err=sock_setsockopt(sock,level,optname,optval,optlen);
|
||||||
else
|
else
|
||||||
err=sock->ops->setsockopt(sock, level, optname, optval, optlen);
|
err=sock->ops->setsockopt(sock, level, optname, optval, optlen);
|
||||||
sockfd_put(sock);
|
out_put:
|
||||||
|
fput_light(sock->file, fput_needed);
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1669,23 +1694,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)
|
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;
|
struct socket *sock;
|
||||||
|
|
||||||
if ((sock = sockfd_lookup(fd, &err))!=NULL)
|
if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) {
|
||||||
{
|
err = security_socket_getsockopt(sock, level, optname);
|
||||||
err = security_socket_getsockopt(sock, level,
|
if (err)
|
||||||
optname);
|
goto out_put;
|
||||||
if (err) {
|
|
||||||
sockfd_put(sock);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (level == SOL_SOCKET)
|
if (level == SOL_SOCKET)
|
||||||
err=sock_getsockopt(sock,level,optname,optval,optlen);
|
err=sock_getsockopt(sock,level,optname,optval,optlen);
|
||||||
else
|
else
|
||||||
err=sock->ops->getsockopt(sock, level, optname, optval, optlen);
|
err=sock->ops->getsockopt(sock, level, optname, optval, optlen);
|
||||||
sockfd_put(sock);
|
out_put:
|
||||||
|
fput_light(sock->file, fput_needed);
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1697,19 +1719,15 @@ asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optv
|
||||||
|
|
||||||
asmlinkage long sys_shutdown(int fd, int how)
|
asmlinkage long sys_shutdown(int fd, int how)
|
||||||
{
|
{
|
||||||
int err;
|
int err, fput_needed;
|
||||||
struct socket *sock;
|
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);
|
err = security_socket_shutdown(sock, how);
|
||||||
if (err) {
|
if (!err)
|
||||||
sockfd_put(sock);
|
err = sock->ops->shutdown(sock, how);
|
||||||
return err;
|
fput_light(sock->file, fput_needed);
|
||||||
}
|
|
||||||
|
|
||||||
err=sock->ops->shutdown(sock, how);
|
|
||||||
sockfd_put(sock);
|
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1738,6 +1756,7 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
|
||||||
unsigned char *ctl_buf = ctl;
|
unsigned char *ctl_buf = ctl;
|
||||||
struct msghdr msg_sys;
|
struct msghdr msg_sys;
|
||||||
int err, ctl_len, iov_size, total_len;
|
int err, ctl_len, iov_size, total_len;
|
||||||
|
int fput_needed;
|
||||||
|
|
||||||
err = -EFAULT;
|
err = -EFAULT;
|
||||||
if (MSG_CMSG_COMPAT & flags) {
|
if (MSG_CMSG_COMPAT & flags) {
|
||||||
|
@ -1746,7 +1765,7 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
|
||||||
} else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
|
} else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
sock = sockfd_lookup(fd, &err);
|
sock = sockfd_lookup_light(fd, &err, &fput_needed);
|
||||||
if (!sock)
|
if (!sock)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -1814,7 +1833,7 @@ out_freeiov:
|
||||||
if (iov != iovstack)
|
if (iov != iovstack)
|
||||||
sock_kfree_s(sock->sk, iov, iov_size);
|
sock_kfree_s(sock->sk, iov, iov_size);
|
||||||
out_put:
|
out_put:
|
||||||
sockfd_put(sock);
|
fput_light(sock->file, fput_needed);
|
||||||
out:
|
out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1832,6 +1851,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flag
|
||||||
struct msghdr msg_sys;
|
struct msghdr msg_sys;
|
||||||
unsigned long cmsg_ptr;
|
unsigned long cmsg_ptr;
|
||||||
int err, iov_size, total_len, len;
|
int err, iov_size, total_len, len;
|
||||||
|
int fput_needed;
|
||||||
|
|
||||||
/* kernel mode address */
|
/* kernel mode address */
|
||||||
char addr[MAX_SOCK_ADDR];
|
char addr[MAX_SOCK_ADDR];
|
||||||
|
@ -1847,7 +1867,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flag
|
||||||
if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr)))
|
if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
sock = sockfd_lookup(fd, &err);
|
sock = sockfd_lookup_light(fd, &err, &fput_needed);
|
||||||
if (!sock)
|
if (!sock)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -1914,7 +1934,7 @@ out_freeiov:
|
||||||
if (iov != iovstack)
|
if (iov != iovstack)
|
||||||
sock_kfree_s(sock->sk, iov, iov_size);
|
sock_kfree_s(sock->sk, iov, iov_size);
|
||||||
out_put:
|
out_put:
|
||||||
sockfd_put(sock);
|
fput_light(sock->file, fput_needed);
|
||||||
out:
|
out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue