diff options
-rw-r--r-- | fs/locks.c | 38 | ||||
-rw-r--r-- | include/linux/fs.h | 1 |
2 files changed, 26 insertions, 13 deletions
diff --git a/fs/locks.c b/fs/locks.c index 749a0dc7cd4b..a31648e3ec1b 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -1611,6 +1611,24 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd) | |||
1611 | return error; | 1611 | return error; |
1612 | } | 1612 | } |
1613 | 1613 | ||
1614 | /** | ||
1615 | * vfs_test_lock - test file byte range lock | ||
1616 | * @filp: The file to test lock for | ||
1617 | * @fl: The lock to test | ||
1618 | * @conf: Place to return a copy of the conflicting lock, if found | ||
1619 | * | ||
1620 | * Returns -ERRNO on failure. Indicates presence of conflicting lock by | ||
1621 | * setting conf->fl_type to something other than F_UNLCK. | ||
1622 | */ | ||
1623 | int vfs_test_lock(struct file *filp, struct file_lock *fl) | ||
1624 | { | ||
1625 | if (filp->f_op && filp->f_op->lock) | ||
1626 | return filp->f_op->lock(filp, F_GETLK, fl); | ||
1627 | posix_test_lock(filp, fl); | ||
1628 | return 0; | ||
1629 | } | ||
1630 | EXPORT_SYMBOL_GPL(vfs_test_lock); | ||
1631 | |||
1614 | static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl) | 1632 | static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl) |
1615 | { | 1633 | { |
1616 | flock->l_pid = fl->fl_pid; | 1634 | flock->l_pid = fl->fl_pid; |
@@ -1663,12 +1681,9 @@ int fcntl_getlk(struct file *filp, struct flock __user *l) | |||
1663 | if (error) | 1681 | if (error) |
1664 | goto out; | 1682 | goto out; |
1665 | 1683 | ||
1666 | if (filp->f_op && filp->f_op->lock) { | 1684 | error = vfs_test_lock(filp, &file_lock); |
1667 | error = filp->f_op->lock(filp, F_GETLK, &file_lock); | 1685 | if (error) |
1668 | if (error < 0) | 1686 | goto out; |
1669 | goto out; | ||
1670 | } else | ||
1671 | posix_test_lock(filp, &file_lock); | ||
1672 | 1687 | ||
1673 | flock.l_type = file_lock.fl_type; | 1688 | flock.l_type = file_lock.fl_type; |
1674 | if (file_lock.fl_type != F_UNLCK) { | 1689 | if (file_lock.fl_type != F_UNLCK) { |
@@ -1797,13 +1812,10 @@ int fcntl_getlk64(struct file *filp, struct flock64 __user *l) | |||
1797 | if (error) | 1812 | if (error) |
1798 | goto out; | 1813 | goto out; |
1799 | 1814 | ||
1800 | if (filp->f_op && filp->f_op->lock) { | 1815 | error = vfs_test_lock(filp, &file_lock); |
1801 | error = filp->f_op->lock(filp, F_GETLK, &file_lock); | 1816 | if (error) |
1802 | if (error < 0) | 1817 | goto out; |
1803 | goto out; | 1818 | |
1804 | } else | ||
1805 | posix_test_lock(filp, &file_lock); | ||
1806 | |||
1807 | flock.l_type = file_lock.fl_type; | 1819 | flock.l_type = file_lock.fl_type; |
1808 | if (file_lock.fl_type != F_UNLCK) | 1820 | if (file_lock.fl_type != F_UNLCK) |
1809 | posix_lock_to_flock64(&flock, &file_lock); | 1821 | posix_lock_to_flock64(&flock, &file_lock); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 9e1ddffe3884..2a2a43988f50 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -856,6 +856,7 @@ extern int posix_lock_file_conf(struct file *, struct file_lock *, struct file_l | |||
856 | extern int posix_lock_file(struct file *, struct file_lock *); | 856 | extern int posix_lock_file(struct file *, struct file_lock *); |
857 | extern int posix_lock_file_wait(struct file *, struct file_lock *); | 857 | extern int posix_lock_file_wait(struct file *, struct file_lock *); |
858 | extern int posix_unblock_lock(struct file *, struct file_lock *); | 858 | extern int posix_unblock_lock(struct file *, struct file_lock *); |
859 | extern int vfs_test_lock(struct file *, struct file_lock *); | ||
859 | extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl); | 860 | extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl); |
860 | extern int __break_lease(struct inode *inode, unsigned int flags); | 861 | extern int __break_lease(struct inode *inode, unsigned int flags); |
861 | extern void lease_get_mtime(struct inode *, struct timespec *time); | 862 | extern void lease_get_mtime(struct inode *, struct timespec *time); |