aboutsummaryrefslogtreecommitdiffstats
path: root/fs/locks.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/locks.c')
-rw-r--r--fs/locks.c93
1 files changed, 56 insertions, 37 deletions
diff --git a/fs/locks.c b/fs/locks.c
index a0bc03495bd4..c2c09b4798d6 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1276,7 +1276,7 @@ int fcntl_getlease(struct file *filp)
1276 */ 1276 */
1277static int __setlease(struct file *filp, long arg, struct file_lock **flp) 1277static int __setlease(struct file *filp, long arg, struct file_lock **flp)
1278{ 1278{
1279 struct file_lock *fl, **before, **my_before = NULL, *lease = *flp; 1279 struct file_lock *fl, **before, **my_before = NULL, *lease;
1280 struct dentry *dentry = filp->f_dentry; 1280 struct dentry *dentry = filp->f_dentry;
1281 struct inode *inode = dentry->d_inode; 1281 struct inode *inode = dentry->d_inode;
1282 int error, rdlease_count = 0, wrlease_count = 0; 1282 int error, rdlease_count = 0, wrlease_count = 0;
@@ -1287,6 +1287,8 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp)
1287 if (!flp || !(*flp) || !(*flp)->fl_lmops || !(*flp)->fl_lmops->fl_break) 1287 if (!flp || !(*flp) || !(*flp)->fl_lmops || !(*flp)->fl_lmops->fl_break)
1288 goto out; 1288 goto out;
1289 1289
1290 lease = *flp;
1291
1290 error = -EAGAIN; 1292 error = -EAGAIN;
1291 if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0)) 1293 if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
1292 goto out; 1294 goto out;
@@ -1589,7 +1591,8 @@ out:
1589/* Apply the lock described by l to an open file descriptor. 1591/* Apply the lock described by l to an open file descriptor.
1590 * This implements both the F_SETLK and F_SETLKW commands of fcntl(). 1592 * This implements both the F_SETLK and F_SETLKW commands of fcntl().
1591 */ 1593 */
1592int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock __user *l) 1594int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
1595 struct flock __user *l)
1593{ 1596{
1594 struct file_lock *file_lock = locks_alloc_lock(); 1597 struct file_lock *file_lock = locks_alloc_lock();
1595 struct flock flock; 1598 struct flock flock;
@@ -1618,6 +1621,7 @@ int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock __user *l)
1618 goto out; 1621 goto out;
1619 } 1622 }
1620 1623
1624again:
1621 error = flock_to_posix_lock(filp, file_lock, &flock); 1625 error = flock_to_posix_lock(filp, file_lock, &flock);
1622 if (error) 1626 if (error)
1623 goto out; 1627 goto out;
@@ -1646,25 +1650,33 @@ int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock __user *l)
1646 if (error) 1650 if (error)
1647 goto out; 1651 goto out;
1648 1652
1649 if (filp->f_op && filp->f_op->lock != NULL) { 1653 if (filp->f_op && filp->f_op->lock != NULL)
1650 error = filp->f_op->lock(filp, cmd, file_lock); 1654 error = filp->f_op->lock(filp, cmd, file_lock);
1651 goto out; 1655 else {
1652 } 1656 for (;;) {
1657 error = __posix_lock_file(inode, file_lock);
1658 if ((error != -EAGAIN) || (cmd == F_SETLK))
1659 break;
1660 error = wait_event_interruptible(file_lock->fl_wait,
1661 !file_lock->fl_next);
1662 if (!error)
1663 continue;
1653 1664
1654 for (;;) { 1665 locks_delete_block(file_lock);
1655 error = __posix_lock_file(inode, file_lock);
1656 if ((error != -EAGAIN) || (cmd == F_SETLK))
1657 break; 1666 break;
1658 error = wait_event_interruptible(file_lock->fl_wait, 1667 }
1659 !file_lock->fl_next); 1668 }
1660 if (!error)
1661 continue;
1662 1669
1663 locks_delete_block(file_lock); 1670 /*
1664 break; 1671 * Attempt to detect a close/fcntl race and recover by
1672 * releasing the lock that was just acquired.
1673 */
1674 if (!error && fcheck(fd) != filp && flock.l_type != F_UNLCK) {
1675 flock.l_type = F_UNLCK;
1676 goto again;
1665 } 1677 }
1666 1678
1667 out: 1679out:
1668 locks_free_lock(file_lock); 1680 locks_free_lock(file_lock);
1669 return error; 1681 return error;
1670} 1682}
@@ -1722,7 +1734,8 @@ out:
1722/* Apply the lock described by l to an open file descriptor. 1734/* Apply the lock described by l to an open file descriptor.
1723 * This implements both the F_SETLK and F_SETLKW commands of fcntl(). 1735 * This implements both the F_SETLK and F_SETLKW commands of fcntl().
1724 */ 1736 */
1725int fcntl_setlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l) 1737int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
1738 struct flock64 __user *l)
1726{ 1739{
1727 struct file_lock *file_lock = locks_alloc_lock(); 1740 struct file_lock *file_lock = locks_alloc_lock();
1728 struct flock64 flock; 1741 struct flock64 flock;
@@ -1751,6 +1764,7 @@ int fcntl_setlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l)
1751 goto out; 1764 goto out;
1752 } 1765 }
1753 1766
1767again:
1754 error = flock64_to_posix_lock(filp, file_lock, &flock); 1768 error = flock64_to_posix_lock(filp, file_lock, &flock);
1755 if (error) 1769 if (error)
1756 goto out; 1770 goto out;
@@ -1779,22 +1793,30 @@ int fcntl_setlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l)
1779 if (error) 1793 if (error)
1780 goto out; 1794 goto out;
1781 1795
1782 if (filp->f_op && filp->f_op->lock != NULL) { 1796 if (filp->f_op && filp->f_op->lock != NULL)
1783 error = filp->f_op->lock(filp, cmd, file_lock); 1797 error = filp->f_op->lock(filp, cmd, file_lock);
1784 goto out; 1798 else {
1785 } 1799 for (;;) {
1800 error = __posix_lock_file(inode, file_lock);
1801 if ((error != -EAGAIN) || (cmd == F_SETLK64))
1802 break;
1803 error = wait_event_interruptible(file_lock->fl_wait,
1804 !file_lock->fl_next);
1805 if (!error)
1806 continue;
1786 1807
1787 for (;;) { 1808 locks_delete_block(file_lock);
1788 error = __posix_lock_file(inode, file_lock);
1789 if ((error != -EAGAIN) || (cmd == F_SETLK64))
1790 break; 1809 break;
1791 error = wait_event_interruptible(file_lock->fl_wait, 1810 }
1792 !file_lock->fl_next); 1811 }
1793 if (!error)
1794 continue;
1795 1812
1796 locks_delete_block(file_lock); 1813 /*
1797 break; 1814 * Attempt to detect a close/fcntl race and recover by
1815 * releasing the lock that was just acquired.
1816 */
1817 if (!error && fcheck(fd) != filp && flock.l_type != F_UNLCK) {
1818 flock.l_type = F_UNLCK;
1819 goto again;
1798 } 1820 }
1799 1821
1800out: 1822out:
@@ -1886,12 +1908,7 @@ void locks_remove_flock(struct file *filp)
1886 1908
1887 while ((fl = *before) != NULL) { 1909 while ((fl = *before) != NULL) {
1888 if (fl->fl_file == filp) { 1910 if (fl->fl_file == filp) {
1889 /* 1911 if (IS_FLOCK(fl)) {
1890 * We might have a POSIX lock that was created at the same time
1891 * the filp was closed for the last time. Just remove that too,
1892 * regardless of ownership, since nobody can own it.
1893 */
1894 if (IS_FLOCK(fl) || IS_POSIX(fl)) {
1895 locks_delete_lock(before); 1912 locks_delete_lock(before);
1896 continue; 1913 continue;
1897 } 1914 }
@@ -2181,21 +2198,23 @@ void steal_locks(fl_owner_t from)
2181{ 2198{
2182 struct files_struct *files = current->files; 2199 struct files_struct *files = current->files;
2183 int i, j; 2200 int i, j;
2201 struct fdtable *fdt;
2184 2202
2185 if (from == files) 2203 if (from == files)
2186 return; 2204 return;
2187 2205
2188 lock_kernel(); 2206 lock_kernel();
2189 j = 0; 2207 j = 0;
2208 fdt = files_fdtable(files);
2190 for (;;) { 2209 for (;;) {
2191 unsigned long set; 2210 unsigned long set;
2192 i = j * __NFDBITS; 2211 i = j * __NFDBITS;
2193 if (i >= files->max_fdset || i >= files->max_fds) 2212 if (i >= fdt->max_fdset || i >= fdt->max_fds)
2194 break; 2213 break;
2195 set = files->open_fds->fds_bits[j++]; 2214 set = fdt->open_fds->fds_bits[j++];
2196 while (set) { 2215 while (set) {
2197 if (set & 1) { 2216 if (set & 1) {
2198 struct file *file = files->fd[i]; 2217 struct file *file = fdt->fd[i];
2199 if (file) 2218 if (file)
2200 __steal_locks(file, from); 2219 __steal_locks(file, from);
2201 } 2220 }