aboutsummaryrefslogtreecommitdiffstats
path: root/net/socket.c
diff options
context:
space:
mode:
authorBenjamin LaHaise <bcrl@linux.intel.com>2006-03-21 01:27:12 -0500
committerDavid S. Miller <davem@davemloft.net>2006-03-21 01:27:12 -0500
commit6cb153cab92a6dc8771d496b10a50cd066fa7f71 (patch)
tree001935e638dbdae754ebe40900c4540bff5bc5b8 /net/socket.c
parent8aca8a27d96cd75a30c380130496c98b658c9b98 (diff)
[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>
Diffstat (limited to 'net/socket.c')
-rw-r--r--net/socket.c192
1 files changed, 106 insertions, 86 deletions
diff --git a/net/socket.c b/net/socket.c
index 74283610db15..510ae18d220a 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -426,6 +426,28 @@ int sock_map_fd(struct socket *sock)
426 return fd; 426 return fd;
427} 427}
428 428
429static struct socket *sock_from_file(struct file *file, int *err)
430{
431 struct inode *inode;
432 struct socket *sock;
433
434 if (file->f_op == &socket_file_ops)
435 return file->private_data; /* set in sock_map_fd */
436
437 inode = file->f_dentry->d_inode;
438 if (!S_ISSOCK(inode->i_mode)) {
439 *err = -ENOTSOCK;
440 return NULL;
441 }
442
443 sock = SOCKET_I(inode);
444 if (sock->file != file) {
445 printk(KERN_ERR "socki_lookup: socket file changed!\n");
446 sock->file = file;
447 }
448 return sock;
449}
450
429/** 451/**
430 * sockfd_lookup - Go from a file number to its socket slot 452 * sockfd_lookup - Go from a file number to its socket slot
431 * @fd: file handle 453 * @fd: file handle
@@ -442,31 +464,31 @@ int sock_map_fd(struct socket *sock)
442struct socket *sockfd_lookup(int fd, int *err) 464struct socket *sockfd_lookup(int fd, int *err)
443{ 465{
444 struct file *file; 466 struct file *file;
445 struct inode *inode;
446 struct socket *sock; 467 struct socket *sock;
447 468
448 if (!(file = fget(fd))) 469 if (!(file = fget(fd))) {
449 {
450 *err = -EBADF; 470 *err = -EBADF;
451 return NULL; 471 return NULL;
452 } 472 }
453 473 sock = sock_from_file(file, err);
454 if (file->f_op == &socket_file_ops) 474 if (!sock)
455 return file->private_data; /* set in sock_map_fd */
456
457 inode = file->f_dentry->d_inode;
458 if (!S_ISSOCK(inode->i_mode)) {
459 *err = -ENOTSOCK;
460 fput(file); 475 fput(file);
461 return NULL; 476 return sock;
462 } 477}
463 478
464 sock = SOCKET_I(inode); 479static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
465 if (sock->file != file) { 480{
466 printk(KERN_ERR "socki_lookup: socket file changed!\n"); 481 struct file *file;
467 sock->file = file; 482 struct socket *sock;
483
484 file = fget_light(fd, fput_needed);
485 if (file) {
486 sock = sock_from_file(file, err);
487 if (sock)
488 return sock;
489 fput_light(file, *fput_needed);
468 } 490 }
469 return sock; 491 return NULL;
470} 492}
471 493
472/** 494/**
@@ -1301,19 +1323,17 @@ asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
1301{ 1323{
1302 struct socket *sock; 1324 struct socket *sock;
1303 char address[MAX_SOCK_ADDR]; 1325 char address[MAX_SOCK_ADDR];
1304 int err; 1326 int err, fput_needed;
1305 1327
1306 if((sock = sockfd_lookup(fd,&err))!=NULL) 1328 if((sock = sockfd_lookup_light(fd, &err, &fput_needed))!=NULL)
1307 { 1329 {
1308 if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) { 1330 if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) {
1309 err = security_socket_bind(sock, (struct sockaddr *)address, addrlen); 1331 err = security_socket_bind(sock, (struct sockaddr *)address, addrlen);
1310 if (err) { 1332 if (!err)
1311 sockfd_put(sock); 1333 err = sock->ops->bind(sock,
1312 return err; 1334 (struct sockaddr *)address, addrlen);
1313 }
1314 err = sock->ops->bind(sock, (struct sockaddr *)address, addrlen);
1315 } 1335 }
1316 sockfd_put(sock); 1336 fput_light(sock->file, fput_needed);
1317 } 1337 }
1318 return err; 1338 return err;
1319} 1339}
@@ -1330,20 +1350,17 @@ int sysctl_somaxconn = SOMAXCONN;
1330asmlinkage long sys_listen(int fd, int backlog) 1350asmlinkage long sys_listen(int fd, int backlog)
1331{ 1351{
1332 struct socket *sock; 1352 struct socket *sock;
1333 int err; 1353 int err, fput_needed;
1334 1354
1335 if ((sock = sockfd_lookup(fd, &err)) != NULL) { 1355 if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) {
1336 if ((unsigned) backlog > sysctl_somaxconn) 1356 if ((unsigned) backlog > sysctl_somaxconn)
1337 backlog = sysctl_somaxconn; 1357 backlog = sysctl_somaxconn;
1338 1358
1339 err = security_socket_listen(sock, backlog); 1359 err = security_socket_listen(sock, backlog);
1340 if (err) { 1360 if (!err)
1341 sockfd_put(sock); 1361 err = sock->ops->listen(sock, backlog);
1342 return err;
1343 }
1344 1362
1345 err=sock->ops->listen(sock, backlog); 1363 fput_light(sock->file, fput_needed);
1346 sockfd_put(sock);
1347 } 1364 }
1348 return err; 1365 return err;
1349} 1366}
@@ -1365,10 +1382,10 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int _
1365{ 1382{
1366 struct socket *sock, *newsock; 1383 struct socket *sock, *newsock;
1367 struct file *newfile; 1384 struct file *newfile;
1368 int err, len, newfd; 1385 int err, len, newfd, fput_needed;
1369 char address[MAX_SOCK_ADDR]; 1386 char address[MAX_SOCK_ADDR];
1370 1387
1371 sock = sockfd_lookup(fd, &err); 1388 sock = sockfd_lookup_light(fd, &err, &fput_needed);
1372 if (!sock) 1389 if (!sock)
1373 goto out; 1390 goto out;
1374 1391
@@ -1421,7 +1438,7 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int _
1421 security_socket_post_accept(sock, newsock); 1438 security_socket_post_accept(sock, newsock);
1422 1439
1423out_put: 1440out_put:
1424 sockfd_put(sock); 1441 fput_light(sock->file, fput_needed);
1425out: 1442out:
1426 return err; 1443 return err;
1427out_fd: 1444out_fd:
@@ -1449,9 +1466,9 @@ asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrl
1449{ 1466{
1450 struct socket *sock; 1467 struct socket *sock;
1451 char address[MAX_SOCK_ADDR]; 1468 char address[MAX_SOCK_ADDR];
1452 int err; 1469 int err, fput_needed;
1453 1470
1454 sock = sockfd_lookup(fd, &err); 1471 sock = sockfd_lookup_light(fd, &err, &fput_needed);
1455 if (!sock) 1472 if (!sock)
1456 goto out; 1473 goto out;
1457 err = move_addr_to_kernel(uservaddr, addrlen, address); 1474 err = move_addr_to_kernel(uservaddr, addrlen, address);
@@ -1465,7 +1482,7 @@ asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrl
1465 err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen, 1482 err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen,
1466 sock->file->f_flags); 1483 sock->file->f_flags);
1467out_put: 1484out_put:
1468 sockfd_put(sock); 1485 fput_light(sock->file, fput_needed);
1469out: 1486out:
1470 return err; 1487 return err;
1471} 1488}
@@ -1479,9 +1496,9 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int _
1479{ 1496{
1480 struct socket *sock; 1497 struct socket *sock;
1481 char address[MAX_SOCK_ADDR]; 1498 char address[MAX_SOCK_ADDR];
1482 int len, err; 1499 int len, err, fput_needed;
1483 1500
1484 sock = sockfd_lookup(fd, &err); 1501 sock = sockfd_lookup_light(fd, &err, &fput_needed);
1485 if (!sock) 1502 if (!sock)
1486 goto out; 1503 goto out;
1487 1504
@@ -1495,7 +1512,7 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int _
1495 err = move_addr_to_user(address, len, usockaddr, usockaddr_len); 1512 err = move_addr_to_user(address, len, usockaddr, usockaddr_len);
1496 1513
1497out_put: 1514out_put:
1498 sockfd_put(sock); 1515 fput_light(sock->file, fput_needed);
1499out: 1516out:
1500 return err; 1517 return err;
1501} 1518}
@@ -1509,20 +1526,19 @@ asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int _
1509{ 1526{
1510 struct socket *sock; 1527 struct socket *sock;
1511 char address[MAX_SOCK_ADDR]; 1528 char address[MAX_SOCK_ADDR];
1512 int len, err; 1529 int len, err, fput_needed;
1513 1530
1514 if ((sock = sockfd_lookup(fd, &err))!=NULL) 1531 if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) {
1515 {
1516 err = security_socket_getpeername(sock); 1532 err = security_socket_getpeername(sock);
1517 if (err) { 1533 if (err) {
1518 sockfd_put(sock); 1534 fput_light(sock->file, fput_needed);
1519 return err; 1535 return err;
1520 } 1536 }
1521 1537
1522 err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 1); 1538 err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 1);
1523 if (!err) 1539 if (!err)
1524 err=move_addr_to_user(address,len, usockaddr, usockaddr_len); 1540 err=move_addr_to_user(address,len, usockaddr, usockaddr_len);
1525 sockfd_put(sock); 1541 fput_light(sock->file, fput_needed);
1526 } 1542 }
1527 return err; 1543 return err;
1528} 1544}
@@ -1541,10 +1557,16 @@ asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flag
1541 int err; 1557 int err;
1542 struct msghdr msg; 1558 struct msghdr msg;
1543 struct iovec iov; 1559 struct iovec iov;
1544 1560 int fput_needed;
1545 sock = sockfd_lookup(fd, &err); 1561 struct file *sock_file;
1562
1563 sock_file = fget_light(fd, &fput_needed);
1564 if (!sock_file)
1565 return -EBADF;
1566
1567 sock = sock_from_file(sock_file, &err);
1546 if (!sock) 1568 if (!sock)
1547 goto out; 1569 goto out_put;
1548 iov.iov_base=buff; 1570 iov.iov_base=buff;
1549 iov.iov_len=len; 1571 iov.iov_len=len;
1550 msg.msg_name=NULL; 1572 msg.msg_name=NULL;
@@ -1553,8 +1575,7 @@ asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flag
1553 msg.msg_control=NULL; 1575 msg.msg_control=NULL;
1554 msg.msg_controllen=0; 1576 msg.msg_controllen=0;
1555 msg.msg_namelen=0; 1577 msg.msg_namelen=0;
1556 if(addr) 1578 if (addr) {
1557 {
1558 err = move_addr_to_kernel(addr, addr_len, address); 1579 err = move_addr_to_kernel(addr, addr_len, address);
1559 if (err < 0) 1580 if (err < 0)
1560 goto out_put; 1581 goto out_put;
@@ -1567,8 +1588,7 @@ asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flag
1567 err = sock_sendmsg(sock, &msg, len); 1588 err = sock_sendmsg(sock, &msg, len);
1568 1589
1569out_put: 1590out_put:
1570 sockfd_put(sock); 1591 fput_light(sock_file, fput_needed);
1571out:
1572 return err; 1592 return err;
1573} 1593}
1574 1594
@@ -1595,8 +1615,14 @@ asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned f
1595 struct msghdr msg; 1615 struct msghdr msg;
1596 char address[MAX_SOCK_ADDR]; 1616 char address[MAX_SOCK_ADDR];
1597 int err,err2; 1617 int err,err2;
1618 struct file *sock_file;
1619 int fput_needed;
1620
1621 sock_file = fget_light(fd, &fput_needed);
1622 if (!sock_file)
1623 return -EBADF;
1598 1624
1599 sock = sockfd_lookup(fd, &err); 1625 sock = sock_from_file(sock_file, &err);
1600 if (!sock) 1626 if (!sock)
1601 goto out; 1627 goto out;
1602 1628
@@ -1618,8 +1644,8 @@ asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned f
1618 if(err2<0) 1644 if(err2<0)
1619 err=err2; 1645 err=err2;
1620 } 1646 }
1621 sockfd_put(sock);
1622out: 1647out:
1648 fput_light(sock_file, fput_needed);
1623 return err; 1649 return err;
1624} 1650}
1625 1651
@@ -1639,25 +1665,24 @@ asmlinkage long sys_recv(int fd, void __user * ubuf, size_t size, unsigned flags
1639 1665
1640asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen) 1666asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen)
1641{ 1667{
1642 int err; 1668 int err, fput_needed;
1643 struct socket *sock; 1669 struct socket *sock;
1644 1670
1645 if (optlen < 0) 1671 if (optlen < 0)
1646 return -EINVAL; 1672 return -EINVAL;
1647 1673
1648 if ((sock = sockfd_lookup(fd, &err))!=NULL) 1674 if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL)
1649 { 1675 {
1650 err = security_socket_setsockopt(sock,level,optname); 1676 err = security_socket_setsockopt(sock,level,optname);
1651 if (err) { 1677 if (err)
1652 sockfd_put(sock); 1678 goto out_put;
1653 return err;
1654 }
1655 1679
1656 if (level == SOL_SOCKET) 1680 if (level == SOL_SOCKET)
1657 err=sock_setsockopt(sock,level,optname,optval,optlen); 1681 err=sock_setsockopt(sock,level,optname,optval,optlen);
1658 else 1682 else
1659 err=sock->ops->setsockopt(sock, level, optname, optval, optlen); 1683 err=sock->ops->setsockopt(sock, level, optname, optval, optlen);
1660 sockfd_put(sock); 1684out_put:
1685 fput_light(sock->file, fput_needed);
1661 } 1686 }
1662 return err; 1687 return err;
1663} 1688}
@@ -1669,23 +1694,20 @@ asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optv
1669 1694
1670asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen) 1695asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen)
1671{ 1696{
1672 int err; 1697 int err, fput_needed;
1673 struct socket *sock; 1698 struct socket *sock;
1674 1699
1675 if ((sock = sockfd_lookup(fd, &err))!=NULL) 1700 if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) {
1676 { 1701 err = security_socket_getsockopt(sock, level, optname);
1677 err = security_socket_getsockopt(sock, level, 1702 if (err)
1678 optname); 1703 goto out_put;
1679 if (err) {
1680 sockfd_put(sock);
1681 return err;
1682 }
1683 1704
1684 if (level == SOL_SOCKET) 1705 if (level == SOL_SOCKET)
1685 err=sock_getsockopt(sock,level,optname,optval,optlen); 1706 err=sock_getsockopt(sock,level,optname,optval,optlen);
1686 else 1707 else
1687 err=sock->ops->getsockopt(sock, level, optname, optval, optlen); 1708 err=sock->ops->getsockopt(sock, level, optname, optval, optlen);
1688 sockfd_put(sock); 1709out_put:
1710 fput_light(sock->file, fput_needed);
1689 } 1711 }
1690 return err; 1712 return err;
1691} 1713}
@@ -1697,19 +1719,15 @@ asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optv
1697 1719
1698asmlinkage long sys_shutdown(int fd, int how) 1720asmlinkage long sys_shutdown(int fd, int how)
1699{ 1721{
1700 int err; 1722 int err, fput_needed;
1701 struct socket *sock; 1723 struct socket *sock;
1702 1724
1703 if ((sock = sockfd_lookup(fd, &err))!=NULL) 1725 if ((sock = sockfd_lookup_light(fd, &err, &fput_needed))!=NULL)
1704 { 1726 {
1705 err = security_socket_shutdown(sock, how); 1727 err = security_socket_shutdown(sock, how);
1706 if (err) { 1728 if (!err)
1707 sockfd_put(sock); 1729 err = sock->ops->shutdown(sock, how);
1708 return err; 1730 fput_light(sock->file, fput_needed);
1709 }
1710
1711 err=sock->ops->shutdown(sock, how);
1712 sockfd_put(sock);
1713 } 1731 }
1714 return err; 1732 return err;
1715} 1733}
@@ -1738,6 +1756,7 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
1738 unsigned char *ctl_buf = ctl; 1756 unsigned char *ctl_buf = ctl;
1739 struct msghdr msg_sys; 1757 struct msghdr msg_sys;
1740 int err, ctl_len, iov_size, total_len; 1758 int err, ctl_len, iov_size, total_len;
1759 int fput_needed;
1741 1760
1742 err = -EFAULT; 1761 err = -EFAULT;
1743 if (MSG_CMSG_COMPAT & flags) { 1762 if (MSG_CMSG_COMPAT & flags) {
@@ -1746,7 +1765,7 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
1746 } else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr))) 1765 } else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
1747 return -EFAULT; 1766 return -EFAULT;
1748 1767
1749 sock = sockfd_lookup(fd, &err); 1768 sock = sockfd_lookup_light(fd, &err, &fput_needed);
1750 if (!sock) 1769 if (!sock)
1751 goto out; 1770 goto out;
1752 1771
@@ -1814,7 +1833,7 @@ out_freeiov:
1814 if (iov != iovstack) 1833 if (iov != iovstack)
1815 sock_kfree_s(sock->sk, iov, iov_size); 1834 sock_kfree_s(sock->sk, iov, iov_size);
1816out_put: 1835out_put:
1817 sockfd_put(sock); 1836 fput_light(sock->file, fput_needed);
1818out: 1837out:
1819 return err; 1838 return err;
1820} 1839}
@@ -1832,6 +1851,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flag
1832 struct msghdr msg_sys; 1851 struct msghdr msg_sys;
1833 unsigned long cmsg_ptr; 1852 unsigned long cmsg_ptr;
1834 int err, iov_size, total_len, len; 1853 int err, iov_size, total_len, len;
1854 int fput_needed;
1835 1855
1836 /* kernel mode address */ 1856 /* kernel mode address */
1837 char addr[MAX_SOCK_ADDR]; 1857 char addr[MAX_SOCK_ADDR];
@@ -1847,7 +1867,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flag
1847 if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr))) 1867 if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr)))
1848 return -EFAULT; 1868 return -EFAULT;
1849 1869
1850 sock = sockfd_lookup(fd, &err); 1870 sock = sockfd_lookup_light(fd, &err, &fput_needed);
1851 if (!sock) 1871 if (!sock)
1852 goto out; 1872 goto out;
1853 1873
@@ -1914,7 +1934,7 @@ out_freeiov:
1914 if (iov != iovstack) 1934 if (iov != iovstack)
1915 sock_kfree_s(sock->sk, iov, iov_size); 1935 sock_kfree_s(sock->sk, iov, iov_size);
1916out_put: 1936out_put:
1917 sockfd_put(sock); 1937 fput_light(sock->file, fput_needed);
1918out: 1938out:
1919 return err; 1939 return err;
1920} 1940}