diff options
Diffstat (limited to 'fs/locks.c')
-rw-r--r-- | fs/locks.c | 264 |
1 files changed, 156 insertions, 108 deletions
diff --git a/fs/locks.c b/fs/locks.c index 325578074742..671a034dc999 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -665,11 +665,11 @@ static int locks_block_on_timeout(struct file_lock *blocker, struct file_lock *w | |||
665 | } | 665 | } |
666 | 666 | ||
667 | int | 667 | int |
668 | posix_test_lock(struct file *filp, struct file_lock *fl, | 668 | posix_test_lock(struct file *filp, struct file_lock *fl) |
669 | struct file_lock *conflock) | ||
670 | { | 669 | { |
671 | struct file_lock *cfl; | 670 | struct file_lock *cfl; |
672 | 671 | ||
672 | fl->fl_type = F_UNLCK; | ||
673 | lock_kernel(); | 673 | lock_kernel(); |
674 | for (cfl = filp->f_path.dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) { | 674 | for (cfl = filp->f_path.dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) { |
675 | if (!IS_POSIX(cfl)) | 675 | if (!IS_POSIX(cfl)) |
@@ -678,7 +678,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl, | |||
678 | break; | 678 | break; |
679 | } | 679 | } |
680 | if (cfl) { | 680 | if (cfl) { |
681 | __locks_copy_lock(conflock, cfl); | 681 | __locks_copy_lock(fl, cfl); |
682 | unlock_kernel(); | 682 | unlock_kernel(); |
683 | return 1; | 683 | return 1; |
684 | } | 684 | } |
@@ -800,7 +800,7 @@ out: | |||
800 | return error; | 800 | return error; |
801 | } | 801 | } |
802 | 802 | ||
803 | static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request, struct file_lock *conflock) | 803 | static int __posix_lock_file(struct inode *inode, struct file_lock *request, struct file_lock *conflock) |
804 | { | 804 | { |
805 | struct file_lock *fl; | 805 | struct file_lock *fl; |
806 | struct file_lock *new_fl = NULL; | 806 | struct file_lock *new_fl = NULL; |
@@ -1006,6 +1006,7 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request | |||
1006 | * posix_lock_file - Apply a POSIX-style lock to a file | 1006 | * posix_lock_file - Apply a POSIX-style lock to a file |
1007 | * @filp: The file to apply the lock to | 1007 | * @filp: The file to apply the lock to |
1008 | * @fl: The lock to be applied | 1008 | * @fl: The lock to be applied |
1009 | * @conflock: Place to return a copy of the conflicting lock, if found. | ||
1009 | * | 1010 | * |
1010 | * Add a POSIX style lock to a file. | 1011 | * Add a POSIX style lock to a file. |
1011 | * We merge adjacent & overlapping locks whenever possible. | 1012 | * We merge adjacent & overlapping locks whenever possible. |
@@ -1015,26 +1016,12 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request | |||
1015 | * whether or not a lock was successfully freed by testing the return | 1016 | * whether or not a lock was successfully freed by testing the return |
1016 | * value for -ENOENT. | 1017 | * value for -ENOENT. |
1017 | */ | 1018 | */ |
1018 | int posix_lock_file(struct file *filp, struct file_lock *fl) | 1019 | int posix_lock_file(struct file *filp, struct file_lock *fl, |
1019 | { | ||
1020 | return __posix_lock_file_conf(filp->f_path.dentry->d_inode, fl, NULL); | ||
1021 | } | ||
1022 | EXPORT_SYMBOL(posix_lock_file); | ||
1023 | |||
1024 | /** | ||
1025 | * posix_lock_file_conf - Apply a POSIX-style lock to a file | ||
1026 | * @filp: The file to apply the lock to | ||
1027 | * @fl: The lock to be applied | ||
1028 | * @conflock: Place to return a copy of the conflicting lock, if found. | ||
1029 | * | ||
1030 | * Except for the conflock parameter, acts just like posix_lock_file. | ||
1031 | */ | ||
1032 | int posix_lock_file_conf(struct file *filp, struct file_lock *fl, | ||
1033 | struct file_lock *conflock) | 1020 | struct file_lock *conflock) |
1034 | { | 1021 | { |
1035 | return __posix_lock_file_conf(filp->f_path.dentry->d_inode, fl, conflock); | 1022 | return __posix_lock_file(filp->f_path.dentry->d_inode, fl, conflock); |
1036 | } | 1023 | } |
1037 | EXPORT_SYMBOL(posix_lock_file_conf); | 1024 | EXPORT_SYMBOL(posix_lock_file); |
1038 | 1025 | ||
1039 | /** | 1026 | /** |
1040 | * posix_lock_file_wait - Apply a POSIX-style lock to a file | 1027 | * posix_lock_file_wait - Apply a POSIX-style lock to a file |
@@ -1050,7 +1037,7 @@ int posix_lock_file_wait(struct file *filp, struct file_lock *fl) | |||
1050 | int error; | 1037 | int error; |
1051 | might_sleep (); | 1038 | might_sleep (); |
1052 | for (;;) { | 1039 | for (;;) { |
1053 | error = posix_lock_file(filp, fl); | 1040 | error = posix_lock_file(filp, fl, NULL); |
1054 | if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP)) | 1041 | if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP)) |
1055 | break; | 1042 | break; |
1056 | error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); | 1043 | error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); |
@@ -1122,7 +1109,7 @@ int locks_mandatory_area(int read_write, struct inode *inode, | |||
1122 | fl.fl_end = offset + count - 1; | 1109 | fl.fl_end = offset + count - 1; |
1123 | 1110 | ||
1124 | for (;;) { | 1111 | for (;;) { |
1125 | error = __posix_lock_file_conf(inode, &fl, NULL); | 1112 | error = __posix_lock_file(inode, &fl, NULL); |
1126 | if (error != -EAGAIN) | 1113 | if (error != -EAGAIN) |
1127 | break; | 1114 | break; |
1128 | if (!(fl.fl_flags & FL_SLEEP)) | 1115 | if (!(fl.fl_flags & FL_SLEEP)) |
@@ -1610,12 +1597,62 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd) | |||
1610 | return error; | 1597 | return error; |
1611 | } | 1598 | } |
1612 | 1599 | ||
1600 | /** | ||
1601 | * vfs_test_lock - test file byte range lock | ||
1602 | * @filp: The file to test lock for | ||
1603 | * @fl: The lock to test | ||
1604 | * @conf: Place to return a copy of the conflicting lock, if found | ||
1605 | * | ||
1606 | * Returns -ERRNO on failure. Indicates presence of conflicting lock by | ||
1607 | * setting conf->fl_type to something other than F_UNLCK. | ||
1608 | */ | ||
1609 | int vfs_test_lock(struct file *filp, struct file_lock *fl) | ||
1610 | { | ||
1611 | if (filp->f_op && filp->f_op->lock) | ||
1612 | return filp->f_op->lock(filp, F_GETLK, fl); | ||
1613 | posix_test_lock(filp, fl); | ||
1614 | return 0; | ||
1615 | } | ||
1616 | EXPORT_SYMBOL_GPL(vfs_test_lock); | ||
1617 | |||
1618 | static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl) | ||
1619 | { | ||
1620 | flock->l_pid = fl->fl_pid; | ||
1621 | #if BITS_PER_LONG == 32 | ||
1622 | /* | ||
1623 | * Make sure we can represent the posix lock via | ||
1624 | * legacy 32bit flock. | ||
1625 | */ | ||
1626 | if (fl->fl_start > OFFT_OFFSET_MAX) | ||
1627 | return -EOVERFLOW; | ||
1628 | if (fl->fl_end != OFFSET_MAX && fl->fl_end > OFFT_OFFSET_MAX) | ||
1629 | return -EOVERFLOW; | ||
1630 | #endif | ||
1631 | flock->l_start = fl->fl_start; | ||
1632 | flock->l_len = fl->fl_end == OFFSET_MAX ? 0 : | ||
1633 | fl->fl_end - fl->fl_start + 1; | ||
1634 | flock->l_whence = 0; | ||
1635 | return 0; | ||
1636 | } | ||
1637 | |||
1638 | #if BITS_PER_LONG == 32 | ||
1639 | static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl) | ||
1640 | { | ||
1641 | flock->l_pid = fl->fl_pid; | ||
1642 | flock->l_start = fl->fl_start; | ||
1643 | flock->l_len = fl->fl_end == OFFSET_MAX ? 0 : | ||
1644 | fl->fl_end - fl->fl_start + 1; | ||
1645 | flock->l_whence = 0; | ||
1646 | flock->l_type = fl->fl_type; | ||
1647 | } | ||
1648 | #endif | ||
1649 | |||
1613 | /* Report the first existing lock that would conflict with l. | 1650 | /* Report the first existing lock that would conflict with l. |
1614 | * This implements the F_GETLK command of fcntl(). | 1651 | * This implements the F_GETLK command of fcntl(). |
1615 | */ | 1652 | */ |
1616 | int fcntl_getlk(struct file *filp, struct flock __user *l) | 1653 | int fcntl_getlk(struct file *filp, struct flock __user *l) |
1617 | { | 1654 | { |
1618 | struct file_lock *fl, cfl, file_lock; | 1655 | struct file_lock file_lock; |
1619 | struct flock flock; | 1656 | struct flock flock; |
1620 | int error; | 1657 | int error; |
1621 | 1658 | ||
@@ -1630,38 +1667,15 @@ int fcntl_getlk(struct file *filp, struct flock __user *l) | |||
1630 | if (error) | 1667 | if (error) |
1631 | goto out; | 1668 | goto out; |
1632 | 1669 | ||
1633 | if (filp->f_op && filp->f_op->lock) { | 1670 | error = vfs_test_lock(filp, &file_lock); |
1634 | error = filp->f_op->lock(filp, F_GETLK, &file_lock); | 1671 | if (error) |
1635 | if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private) | 1672 | goto out; |
1636 | file_lock.fl_ops->fl_release_private(&file_lock); | ||
1637 | if (error < 0) | ||
1638 | goto out; | ||
1639 | else | ||
1640 | fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock); | ||
1641 | } else { | ||
1642 | fl = (posix_test_lock(filp, &file_lock, &cfl) ? &cfl : NULL); | ||
1643 | } | ||
1644 | 1673 | ||
1645 | flock.l_type = F_UNLCK; | 1674 | flock.l_type = file_lock.fl_type; |
1646 | if (fl != NULL) { | 1675 | if (file_lock.fl_type != F_UNLCK) { |
1647 | flock.l_pid = fl->fl_pid; | 1676 | error = posix_lock_to_flock(&flock, &file_lock); |
1648 | #if BITS_PER_LONG == 32 | 1677 | if (error) |
1649 | /* | ||
1650 | * Make sure we can represent the posix lock via | ||
1651 | * legacy 32bit flock. | ||
1652 | */ | ||
1653 | error = -EOVERFLOW; | ||
1654 | if (fl->fl_start > OFFT_OFFSET_MAX) | ||
1655 | goto out; | ||
1656 | if ((fl->fl_end != OFFSET_MAX) | ||
1657 | && (fl->fl_end > OFFT_OFFSET_MAX)) | ||
1658 | goto out; | 1678 | goto out; |
1659 | #endif | ||
1660 | flock.l_start = fl->fl_start; | ||
1661 | flock.l_len = fl->fl_end == OFFSET_MAX ? 0 : | ||
1662 | fl->fl_end - fl->fl_start + 1; | ||
1663 | flock.l_whence = 0; | ||
1664 | flock.l_type = fl->fl_type; | ||
1665 | } | 1679 | } |
1666 | error = -EFAULT; | 1680 | error = -EFAULT; |
1667 | if (!copy_to_user(l, &flock, sizeof(flock))) | 1681 | if (!copy_to_user(l, &flock, sizeof(flock))) |
@@ -1670,6 +1684,48 @@ out: | |||
1670 | return error; | 1684 | return error; |
1671 | } | 1685 | } |
1672 | 1686 | ||
1687 | /** | ||
1688 | * vfs_lock_file - file byte range lock | ||
1689 | * @filp: The file to apply the lock to | ||
1690 | * @cmd: type of locking operation (F_SETLK, F_GETLK, etc.) | ||
1691 | * @fl: The lock to be applied | ||
1692 | * @conf: Place to return a copy of the conflicting lock, if found. | ||
1693 | * | ||
1694 | * A caller that doesn't care about the conflicting lock may pass NULL | ||
1695 | * as the final argument. | ||
1696 | * | ||
1697 | * If the filesystem defines a private ->lock() method, then @conf will | ||
1698 | * be left unchanged; so a caller that cares should initialize it to | ||
1699 | * some acceptable default. | ||
1700 | * | ||
1701 | * To avoid blocking kernel daemons, such as lockd, that need to acquire POSIX | ||
1702 | * locks, the ->lock() interface may return asynchronously, before the lock has | ||
1703 | * been granted or denied by the underlying filesystem, if (and only if) | ||
1704 | * fl_grant is set. Callers expecting ->lock() to return asynchronously | ||
1705 | * will only use F_SETLK, not F_SETLKW; they will set FL_SLEEP if (and only if) | ||
1706 | * the request is for a blocking lock. When ->lock() does return asynchronously, | ||
1707 | * it must return -EINPROGRESS, and call ->fl_grant() when the lock | ||
1708 | * request completes. | ||
1709 | * If the request is for non-blocking lock the file system should return | ||
1710 | * -EINPROGRESS then try to get the lock and call the callback routine with | ||
1711 | * the result. If the request timed out the callback routine will return a | ||
1712 | * nonzero return code and the file system should release the lock. The file | ||
1713 | * system is also responsible to keep a corresponding posix lock when it | ||
1714 | * grants a lock so the VFS can find out which locks are locally held and do | ||
1715 | * the correct lock cleanup when required. | ||
1716 | * The underlying filesystem must not drop the kernel lock or call | ||
1717 | * ->fl_grant() before returning to the caller with a -EINPROGRESS | ||
1718 | * return code. | ||
1719 | */ | ||
1720 | int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf) | ||
1721 | { | ||
1722 | if (filp->f_op && filp->f_op->lock) | ||
1723 | return filp->f_op->lock(filp, cmd, fl); | ||
1724 | else | ||
1725 | return posix_lock_file(filp, fl, conf); | ||
1726 | } | ||
1727 | EXPORT_SYMBOL_GPL(vfs_lock_file); | ||
1728 | |||
1673 | /* Apply the lock described by l to an open file descriptor. | 1729 | /* Apply the lock described by l to an open file descriptor. |
1674 | * This implements both the F_SETLK and F_SETLKW commands of fcntl(). | 1730 | * This implements both the F_SETLK and F_SETLKW commands of fcntl(). |
1675 | */ | 1731 | */ |
@@ -1732,21 +1788,17 @@ again: | |||
1732 | if (error) | 1788 | if (error) |
1733 | goto out; | 1789 | goto out; |
1734 | 1790 | ||
1735 | if (filp->f_op && filp->f_op->lock != NULL) | 1791 | for (;;) { |
1736 | error = filp->f_op->lock(filp, cmd, file_lock); | 1792 | error = vfs_lock_file(filp, cmd, file_lock, NULL); |
1737 | else { | 1793 | if (error != -EAGAIN || cmd == F_SETLK) |
1738 | for (;;) { | ||
1739 | error = posix_lock_file(filp, file_lock); | ||
1740 | if ((error != -EAGAIN) || (cmd == F_SETLK)) | ||
1741 | break; | ||
1742 | error = wait_event_interruptible(file_lock->fl_wait, | ||
1743 | !file_lock->fl_next); | ||
1744 | if (!error) | ||
1745 | continue; | ||
1746 | |||
1747 | locks_delete_block(file_lock); | ||
1748 | break; | 1794 | break; |
1749 | } | 1795 | error = wait_event_interruptible(file_lock->fl_wait, |
1796 | !file_lock->fl_next); | ||
1797 | if (!error) | ||
1798 | continue; | ||
1799 | |||
1800 | locks_delete_block(file_lock); | ||
1801 | break; | ||
1750 | } | 1802 | } |
1751 | 1803 | ||
1752 | /* | 1804 | /* |
@@ -1769,7 +1821,7 @@ out: | |||
1769 | */ | 1821 | */ |
1770 | int fcntl_getlk64(struct file *filp, struct flock64 __user *l) | 1822 | int fcntl_getlk64(struct file *filp, struct flock64 __user *l) |
1771 | { | 1823 | { |
1772 | struct file_lock *fl, cfl, file_lock; | 1824 | struct file_lock file_lock; |
1773 | struct flock64 flock; | 1825 | struct flock64 flock; |
1774 | int error; | 1826 | int error; |
1775 | 1827 | ||
@@ -1784,27 +1836,14 @@ int fcntl_getlk64(struct file *filp, struct flock64 __user *l) | |||
1784 | if (error) | 1836 | if (error) |
1785 | goto out; | 1837 | goto out; |
1786 | 1838 | ||
1787 | if (filp->f_op && filp->f_op->lock) { | 1839 | error = vfs_test_lock(filp, &file_lock); |
1788 | error = filp->f_op->lock(filp, F_GETLK, &file_lock); | 1840 | if (error) |
1789 | if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private) | 1841 | goto out; |
1790 | file_lock.fl_ops->fl_release_private(&file_lock); | 1842 | |
1791 | if (error < 0) | 1843 | flock.l_type = file_lock.fl_type; |
1792 | goto out; | 1844 | if (file_lock.fl_type != F_UNLCK) |
1793 | else | 1845 | posix_lock_to_flock64(&flock, &file_lock); |
1794 | fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock); | 1846 | |
1795 | } else { | ||
1796 | fl = (posix_test_lock(filp, &file_lock, &cfl) ? &cfl : NULL); | ||
1797 | } | ||
1798 | |||
1799 | flock.l_type = F_UNLCK; | ||
1800 | if (fl != NULL) { | ||
1801 | flock.l_pid = fl->fl_pid; | ||
1802 | flock.l_start = fl->fl_start; | ||
1803 | flock.l_len = fl->fl_end == OFFSET_MAX ? 0 : | ||
1804 | fl->fl_end - fl->fl_start + 1; | ||
1805 | flock.l_whence = 0; | ||
1806 | flock.l_type = fl->fl_type; | ||
1807 | } | ||
1808 | error = -EFAULT; | 1847 | error = -EFAULT; |
1809 | if (!copy_to_user(l, &flock, sizeof(flock))) | 1848 | if (!copy_to_user(l, &flock, sizeof(flock))) |
1810 | error = 0; | 1849 | error = 0; |
@@ -1875,21 +1914,17 @@ again: | |||
1875 | if (error) | 1914 | if (error) |
1876 | goto out; | 1915 | goto out; |
1877 | 1916 | ||
1878 | if (filp->f_op && filp->f_op->lock != NULL) | 1917 | for (;;) { |
1879 | error = filp->f_op->lock(filp, cmd, file_lock); | 1918 | error = vfs_lock_file(filp, cmd, file_lock, NULL); |
1880 | else { | 1919 | if (error != -EAGAIN || cmd == F_SETLK64) |
1881 | for (;;) { | ||
1882 | error = posix_lock_file(filp, file_lock); | ||
1883 | if ((error != -EAGAIN) || (cmd == F_SETLK64)) | ||
1884 | break; | ||
1885 | error = wait_event_interruptible(file_lock->fl_wait, | ||
1886 | !file_lock->fl_next); | ||
1887 | if (!error) | ||
1888 | continue; | ||
1889 | |||
1890 | locks_delete_block(file_lock); | ||
1891 | break; | 1920 | break; |
1892 | } | 1921 | error = wait_event_interruptible(file_lock->fl_wait, |
1922 | !file_lock->fl_next); | ||
1923 | if (!error) | ||
1924 | continue; | ||
1925 | |||
1926 | locks_delete_block(file_lock); | ||
1927 | break; | ||
1893 | } | 1928 | } |
1894 | 1929 | ||
1895 | /* | 1930 | /* |
@@ -1934,10 +1969,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner) | |||
1934 | lock.fl_ops = NULL; | 1969 | lock.fl_ops = NULL; |
1935 | lock.fl_lmops = NULL; | 1970 | lock.fl_lmops = NULL; |
1936 | 1971 | ||
1937 | if (filp->f_op && filp->f_op->lock != NULL) | 1972 | vfs_lock_file(filp, F_SETLK, &lock, NULL); |
1938 | filp->f_op->lock(filp, F_SETLK, &lock); | ||
1939 | else | ||
1940 | posix_lock_file(filp, &lock); | ||
1941 | 1973 | ||
1942 | if (lock.fl_ops && lock.fl_ops->fl_release_private) | 1974 | if (lock.fl_ops && lock.fl_ops->fl_release_private) |
1943 | lock.fl_ops->fl_release_private(&lock); | 1975 | lock.fl_ops->fl_release_private(&lock); |
@@ -2014,6 +2046,22 @@ posix_unblock_lock(struct file *filp, struct file_lock *waiter) | |||
2014 | 2046 | ||
2015 | EXPORT_SYMBOL(posix_unblock_lock); | 2047 | EXPORT_SYMBOL(posix_unblock_lock); |
2016 | 2048 | ||
2049 | /** | ||
2050 | * vfs_cancel_lock - file byte range unblock lock | ||
2051 | * @filp: The file to apply the unblock to | ||
2052 | * @fl: The lock to be unblocked | ||
2053 | * | ||
2054 | * Used by lock managers to cancel blocked requests | ||
2055 | */ | ||
2056 | int vfs_cancel_lock(struct file *filp, struct file_lock *fl) | ||
2057 | { | ||
2058 | if (filp->f_op && filp->f_op->lock) | ||
2059 | return filp->f_op->lock(filp, F_CANCELLK, fl); | ||
2060 | return 0; | ||
2061 | } | ||
2062 | |||
2063 | EXPORT_SYMBOL_GPL(vfs_cancel_lock); | ||
2064 | |||
2017 | static void lock_get_status(char* out, struct file_lock *fl, int id, char *pfx) | 2065 | static void lock_get_status(char* out, struct file_lock *fl, int id, char *pfx) |
2018 | { | 2066 | { |
2019 | struct inode *inode = NULL; | 2067 | struct inode *inode = NULL; |