aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/locks.c92
-rw-r--r--fs/nfsd/nfs4state.c6
-rw-r--r--include/linux/fs.h1
3 files changed, 51 insertions, 48 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)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 7c803db2a027..5349528136e2 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -3793,12 +3793,10 @@ static int nfs4_setlease(struct nfs4_delegation *dp)
3793 fl->fl_file = filp; 3793 fl->fl_file = filp;
3794 ret = fl; 3794 ret = fl;
3795 status = vfs_setlease(filp, fl->fl_type, &fl, NULL); 3795 status = vfs_setlease(filp, fl->fl_type, &fl, NULL);
3796 if (status) { 3796 if (fl)
3797 locks_free_lock(fl); 3797 locks_free_lock(fl);
3798 if (status)
3798 goto out_fput; 3799 goto out_fput;
3799 }
3800 if (ret != fl)
3801 locks_free_lock(fl);
3802 spin_lock(&state_lock); 3800 spin_lock(&state_lock);
3803 spin_lock(&fp->fi_lock); 3801 spin_lock(&fp->fi_lock);
3804 /* Did the lease get broken before we took the lock? */ 3802 /* Did the lease get broken before we took the lock? */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index f1870eb67b02..9a6d56154dd5 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -874,6 +874,7 @@ struct lock_manager_operations {
874 int (*lm_grant)(struct file_lock *, int); 874 int (*lm_grant)(struct file_lock *, int);
875 void (*lm_break)(struct file_lock *); 875 void (*lm_break)(struct file_lock *);
876 int (*lm_change)(struct file_lock **, int); 876 int (*lm_change)(struct file_lock **, int);
877 void (*lm_setup)(struct file_lock *, void **);
877}; 878};
878 879
879struct lock_manager { 880struct lock_manager {