aboutsummaryrefslogtreecommitdiffstats
path: root/fs/locks.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/locks.c')
-rw-r--r--fs/locks.c92
1 files changed, 48 insertions, 44 deletions
diff --git a/fs/locks.c b/fs/locks.c
index 4fa269b0bdef..a237ba632e8d 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -432,9 +432,27 @@ static void lease_break_callback(struct file_lock *fl)
432 kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG); 432 kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG);
433} 433}
434 434
435static void
436lease_setup(struct file_lock *fl, void **priv)
437{
438 struct file *filp = fl->fl_file;
439 struct fasync_struct *fa = *priv;
440
441 /*
442 * fasync_insert_entry() returns the old entry if any. If there was no
443 * old entry, then it used "priv" and inserted it into the fasync list.
444 * Clear the pointer to indicate that it shouldn't be freed.
445 */
446 if (!fasync_insert_entry(fa->fa_fd, filp, &fl->fl_fasync, fa))
447 *priv = NULL;
448
449 __f_setown(filp, task_pid(current), PIDTYPE_PID, 0);
450}
451
435static const struct lock_manager_operations lease_manager_ops = { 452static const struct lock_manager_operations lease_manager_ops = {
436 .lm_break = lease_break_callback, 453 .lm_break = lease_break_callback,
437 .lm_change = lease_modify, 454 .lm_change = lease_modify,
455 .lm_setup = lease_setup,
438}; 456};
439 457
440/* 458/*
@@ -1607,10 +1625,11 @@ generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **pr
1607 } 1625 }
1608 1626
1609 if (my_before != NULL) { 1627 if (my_before != NULL) {
1628 lease = *my_before;
1610 error = lease->fl_lmops->lm_change(my_before, arg); 1629 error = lease->fl_lmops->lm_change(my_before, arg);
1611 if (!error) 1630 if (error)
1612 *flp = *my_before; 1631 goto out;
1613 goto out; 1632 goto out_setup;
1614 } 1633 }
1615 1634
1616 error = -EINVAL; 1635 error = -EINVAL;
@@ -1631,9 +1650,15 @@ generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **pr
1631 error = check_conflicting_open(dentry, arg); 1650 error = check_conflicting_open(dentry, arg);
1632 if (error) 1651 if (error)
1633 goto out_unlink; 1652 goto out_unlink;
1653
1654out_setup:
1655 if (lease->fl_lmops->lm_setup)
1656 lease->fl_lmops->lm_setup(lease, priv);
1634out: 1657out:
1635 if (is_deleg) 1658 if (is_deleg)
1636 mutex_unlock(&inode->i_mutex); 1659 mutex_unlock(&inode->i_mutex);
1660 if (!error && !my_before)
1661 *flp = NULL;
1637 return error; 1662 return error;
1638out_unlink: 1663out_unlink:
1639 locks_unlink_lock(before); 1664 locks_unlink_lock(before);
@@ -1661,10 +1686,11 @@ static int generic_delete_lease(struct file *filp)
1661 1686
1662/** 1687/**
1663 * generic_setlease - sets a lease on an open file 1688 * generic_setlease - sets a lease on an open file
1664 * @filp: file pointer 1689 * @filp: file pointer
1665 * @arg: type of lease to obtain 1690 * @arg: type of lease to obtain
1666 * @flp: input - file_lock to use, output - file_lock inserted 1691 * @flp: input - file_lock to use, output - file_lock inserted
1667 * @priv: private data for lm_setup 1692 * @priv: private data for lm_setup (may be NULL if lm_setup
1693 * doesn't require it)
1668 * 1694 *
1669 * The (input) flp->fl_lmops->lm_break function is required 1695 * The (input) flp->fl_lmops->lm_break function is required
1670 * by break_lease(). 1696 * by break_lease().
@@ -1704,29 +1730,23 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp,
1704} 1730}
1705EXPORT_SYMBOL(generic_setlease); 1731EXPORT_SYMBOL(generic_setlease);
1706 1732
1707static int
1708__vfs_setlease(struct file *filp, long arg, struct file_lock **lease, void **priv)
1709{
1710 if (filp->f_op->setlease)
1711 return filp->f_op->setlease(filp, arg, lease, priv);
1712 else
1713 return generic_setlease(filp, arg, lease, priv);
1714}
1715
1716/** 1733/**
1717 * vfs_setlease - sets a lease on an open file 1734 * vfs_setlease - sets a lease on an open file
1718 * @filp: file pointer 1735 * @filp: file pointer
1719 * @arg: type of lease to obtain 1736 * @arg: type of lease to obtain
1720 * @lease: file_lock to use when adding a lease 1737 * @lease: file_lock to use when adding a lease
1721 * @priv: private info for lm_setup when adding a lease 1738 * @priv: private info for lm_setup when adding a lease (may be
1739 * NULL if lm_setup doesn't require it)
1722 * 1740 *
1723 * Call this to establish a lease on the file. The "lease" argument is not 1741 * Call this to establish a lease on the file. The "lease" argument is not
1724 * used for F_UNLCK requests and may be NULL. For commands that set or alter 1742 * used for F_UNLCK requests and may be NULL. For commands that set or alter
1725 * an existing lease, the (*lease)->fl_lmops->lm_break operation must be set; 1743 * an existing lease, the (*lease)->fl_lmops->lm_break operation must be set;
1726 * if not, this function will return -ENOLCK (and generate a scary-looking 1744 * if not, this function will return -ENOLCK (and generate a scary-looking
1727 * stack trace). 1745 * stack trace).
1746 *
1747 * The "priv" pointer is passed directly to the lm_setup function as-is. It
1748 * may be NULL if the lm_setup operation doesn't require it.
1728 */ 1749 */
1729
1730int 1750int
1731vfs_setlease(struct file *filp, long arg, struct file_lock **lease, void **priv) 1751vfs_setlease(struct file *filp, long arg, struct file_lock **lease, void **priv)
1732{ 1752{
@@ -1734,17 +1754,18 @@ vfs_setlease(struct file *filp, long arg, struct file_lock **lease, void **priv)
1734 int error; 1754 int error;
1735 1755
1736 spin_lock(&inode->i_lock); 1756 spin_lock(&inode->i_lock);
1737 error = __vfs_setlease(filp, arg, lease, priv); 1757 if (filp->f_op->setlease)
1758 error = filp->f_op->setlease(filp, arg, lease, priv);
1759 else
1760 error = generic_setlease(filp, arg, lease, priv);
1738 spin_unlock(&inode->i_lock); 1761 spin_unlock(&inode->i_lock);
1739
1740 return error; 1762 return error;
1741} 1763}
1742EXPORT_SYMBOL_GPL(vfs_setlease); 1764EXPORT_SYMBOL_GPL(vfs_setlease);
1743 1765
1744static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) 1766static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg)
1745{ 1767{
1746 struct file_lock *fl, *ret; 1768 struct file_lock *fl;
1747 struct inode *inode = file_inode(filp);
1748 struct fasync_struct *new; 1769 struct fasync_struct *new;
1749 int error; 1770 int error;
1750 1771
@@ -1757,26 +1778,9 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg)
1757 locks_free_lock(fl); 1778 locks_free_lock(fl);
1758 return -ENOMEM; 1779 return -ENOMEM;
1759 } 1780 }
1760 ret = fl; 1781 new->fa_fd = fd;
1761 spin_lock(&inode->i_lock);
1762 error = __vfs_setlease(filp, arg, &ret, NULL);
1763 if (error)
1764 goto out_unlock;
1765 if (ret == fl)
1766 fl = NULL;
1767 1782
1768 /* 1783 error = vfs_setlease(filp, arg, &fl, (void **)&new);
1769 * fasync_insert_entry() returns the old entry if any.
1770 * If there was no old entry, then it used 'new' and
1771 * inserted it into the fasync list. Clear new so that
1772 * we don't release it here.
1773 */
1774 if (!fasync_insert_entry(fd, filp, &ret->fl_fasync, new))
1775 new = NULL;
1776
1777 __f_setown(filp, task_pid(current), PIDTYPE_PID, 0);
1778out_unlock:
1779 spin_unlock(&inode->i_lock);
1780 if (fl) 1784 if (fl)
1781 locks_free_lock(fl); 1785 locks_free_lock(fl);
1782 if (new) 1786 if (new)