aboutsummaryrefslogtreecommitdiffstats
path: root/fs/locks.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-07 15:34:24 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-07 15:34:24 -0400
commit2d56d3c43cc97ae48586745556f5a5b564d61582 (patch)
tree28f2edc1e69b79e94d99023041dd0358861b6956 /fs/locks.c
parent0f9008ef38d5a6305d94bbdd8f20d68fc75c63b6 (diff)
parent586759f03e2e9031ac5589912a51a909ed53c30a (diff)
Merge branch 'server-cluster-locking-api' of git://linux-nfs.org/~bfields/linux
* 'server-cluster-locking-api' of git://linux-nfs.org/~bfields/linux: gfs2: nfs lock support for gfs2 lockd: add code to handle deferred lock requests lockd: always preallocate block in nlmsvc_lock() lockd: handle test_lock deferrals lockd: pass cookie in nlmsvc_testlock lockd: handle fl_grant callbacks lockd: save lock state on deferral locks: add fl_grant callback for asynchronous lock return nfsd4: Convert NFSv4 to new lock interface locks: add lock cancel command locks: allow {vfs,posix}_lock_file to return conflicting lock locks: factor out generic/filesystem switch from setlock code locks: factor out generic/filesystem switch from test_lock locks: give posix_test_lock same interface as ->lock locks: make ->lock release private data before returning in GETLK case locks: create posix-to-flock helper functions locks: trivial removal of unnecessary parentheses
Diffstat (limited to 'fs/locks.c')
-rw-r--r--fs/locks.c264
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
667int 667int
668posix_test_lock(struct file *filp, struct file_lock *fl, 668posix_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
803static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request, struct file_lock *conflock) 803static 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 */
1018int posix_lock_file(struct file *filp, struct file_lock *fl) 1019int 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}
1022EXPORT_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 */
1032int 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}
1037EXPORT_SYMBOL(posix_lock_file_conf); 1024EXPORT_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 */
1609int 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}
1616EXPORT_SYMBOL_GPL(vfs_test_lock);
1617
1618static 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
1639static 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 */
1616int fcntl_getlk(struct file *filp, struct flock __user *l) 1653int 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 */
1720int 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}
1727EXPORT_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 */
1770int fcntl_getlk64(struct file *filp, struct flock64 __user *l) 1822int 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
2015EXPORT_SYMBOL(posix_unblock_lock); 2047EXPORT_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 */
2056int 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
2063EXPORT_SYMBOL_GPL(vfs_cancel_lock);
2064
2017static void lock_get_status(char* out, struct file_lock *fl, int id, char *pfx) 2065static 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;