aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Layton <jlayton@primarydata.com>2015-01-16 15:05:55 -0500
committerJeff Layton <jeff.layton@primarydata.com>2015-01-16 16:08:17 -0500
commit8634b51f6ca298fb8b07aa4847340764903533ab (patch)
treee3c32514f05317bacc40aba8782a9912f887cebd
parentbd61e0a9c852de2d705b6f1bb2cc54c5774db570 (diff)
locks: convert lease handling to file_lock_context
Signed-off-by: Jeff Layton <jlayton@primarydata.com> Acked-by: Christoph Hellwig <hch@lst.de>
-rw-r--r--fs/locks.c252
-rw-r--r--include/linux/fs.h5
2 files changed, 102 insertions, 155 deletions
diff --git a/fs/locks.c b/fs/locks.c
index e50bb4d9e757..d46e70567b99 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -216,6 +216,7 @@ locks_get_lock_context(struct inode *inode)
216 216
217 INIT_LIST_HEAD(&new->flc_flock); 217 INIT_LIST_HEAD(&new->flc_flock);
218 INIT_LIST_HEAD(&new->flc_posix); 218 INIT_LIST_HEAD(&new->flc_posix);
219 INIT_LIST_HEAD(&new->flc_lease);
219 220
220 /* 221 /*
221 * Assign the pointer if it's not already assigned. If it is, then 222 * Assign the pointer if it's not already assigned. If it is, then
@@ -240,6 +241,7 @@ locks_free_lock_context(struct file_lock_context *ctx)
240 if (ctx) { 241 if (ctx) {
241 WARN_ON_ONCE(!list_empty(&ctx->flc_flock)); 242 WARN_ON_ONCE(!list_empty(&ctx->flc_flock));
242 WARN_ON_ONCE(!list_empty(&ctx->flc_posix)); 243 WARN_ON_ONCE(!list_empty(&ctx->flc_posix));
244 WARN_ON_ONCE(!list_empty(&ctx->flc_lease));
243 kmem_cache_free(flctx_cache, ctx); 245 kmem_cache_free(flctx_cache, ctx);
244 } 246 }
245} 247}
@@ -677,22 +679,6 @@ static void locks_wake_up_blocks(struct file_lock *blocker)
677 spin_unlock(&blocked_lock_lock); 679 spin_unlock(&blocked_lock_lock);
678} 680}
679 681
680/* Insert file lock fl into an inode's lock list at the position indicated
681 * by pos. At the same time add the lock to the global file lock list.
682 *
683 * Must be called with the i_lock held!
684 */
685static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl)
686{
687 fl->fl_nspid = get_pid(task_tgid(current));
688
689 /* insert into file's list */
690 fl->fl_next = *pos;
691 *pos = fl;
692
693 locks_insert_global_locks(fl);
694}
695
696static void 682static void
697locks_insert_lock_ctx(struct file_lock *fl, struct list_head *before) 683locks_insert_lock_ctx(struct file_lock *fl, struct list_head *before)
698{ 684{
@@ -701,63 +687,28 @@ locks_insert_lock_ctx(struct file_lock *fl, struct list_head *before)
701 locks_insert_global_locks(fl); 687 locks_insert_global_locks(fl);
702} 688}
703 689
704/** 690static void
705 * locks_delete_lock - Delete a lock and then free it. 691locks_unlink_lock_ctx(struct file_lock *fl)
706 * @thisfl_p: pointer that points to the fl_next field of the previous
707 * inode->i_flock list entry
708 *
709 * Unlink a lock from all lists and free the namespace reference, but don't
710 * free it yet. Wake up processes that are blocked waiting for this lock and
711 * notify the FS that the lock has been cleared.
712 *
713 * Must be called with the i_lock held!
714 */
715static void locks_unlink_lock(struct file_lock **thisfl_p)
716{ 692{
717 struct file_lock *fl = *thisfl_p;
718
719 locks_delete_global_locks(fl); 693 locks_delete_global_locks(fl);
720 694 list_del_init(&fl->fl_list);
721 *thisfl_p = fl->fl_next;
722 fl->fl_next = NULL;
723
724 if (fl->fl_nspid) { 695 if (fl->fl_nspid) {
725 put_pid(fl->fl_nspid); 696 put_pid(fl->fl_nspid);
726 fl->fl_nspid = NULL; 697 fl->fl_nspid = NULL;
727 } 698 }
728
729 locks_wake_up_blocks(fl); 699 locks_wake_up_blocks(fl);
730} 700}
731 701
732/* 702static void
733 * Unlink a lock from all lists and free it. 703locks_delete_lock_ctx(struct file_lock *fl, struct list_head *dispose)
734 *
735 * Must be called with i_lock held!
736 */
737static void locks_delete_lock(struct file_lock **thisfl_p,
738 struct list_head *dispose)
739{ 704{
740 struct file_lock *fl = *thisfl_p; 705 locks_unlink_lock_ctx(fl);
741
742 locks_unlink_lock(thisfl_p);
743 if (dispose) 706 if (dispose)
744 list_add(&fl->fl_list, dispose); 707 list_add(&fl->fl_list, dispose);
745 else 708 else
746 locks_free_lock(fl); 709 locks_free_lock(fl);
747} 710}
748 711
749static void
750locks_delete_lock_ctx(struct file_lock *fl, struct list_head *dispose)
751{
752 locks_delete_global_locks(fl);
753 if (fl->fl_nspid) {
754 put_pid(fl->fl_nspid);
755 fl->fl_nspid = NULL;
756 }
757 locks_wake_up_blocks(fl);
758 list_move(&fl->fl_list, dispose);
759}
760
761/* Determine if lock sys_fl blocks lock caller_fl. Common functionality 712/* Determine if lock sys_fl blocks lock caller_fl. Common functionality
762 * checks for shared/exclusive status of overlapping locks. 713 * checks for shared/exclusive status of overlapping locks.
763 */ 714 */
@@ -1376,7 +1327,7 @@ int lease_modify(struct file_lock **before, int arg, struct list_head *dispose)
1376 printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync); 1327 printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync);
1377 fl->fl_fasync = NULL; 1328 fl->fl_fasync = NULL;
1378 } 1329 }
1379 locks_delete_lock(before, dispose); 1330 locks_delete_lock_ctx(fl, dispose);
1380 } 1331 }
1381 return 0; 1332 return 0;
1382} 1333}
@@ -1392,20 +1343,17 @@ static bool past_time(unsigned long then)
1392 1343
1393static void time_out_leases(struct inode *inode, struct list_head *dispose) 1344static void time_out_leases(struct inode *inode, struct list_head *dispose)
1394{ 1345{
1395 struct file_lock **before; 1346 struct file_lock_context *ctx = inode->i_flctx;
1396 struct file_lock *fl; 1347 struct file_lock *fl, *tmp;
1397 1348
1398 lockdep_assert_held(&inode->i_lock); 1349 lockdep_assert_held(&inode->i_lock);
1399 1350
1400 before = &inode->i_flock; 1351 list_for_each_entry_safe(fl, tmp, &ctx->flc_lease, fl_list) {
1401 while ((fl = *before) && IS_LEASE(fl) && lease_breaking(fl)) {
1402 trace_time_out_leases(inode, fl); 1352 trace_time_out_leases(inode, fl);
1403 if (past_time(fl->fl_downgrade_time)) 1353 if (past_time(fl->fl_downgrade_time))
1404 lease_modify(before, F_RDLCK, dispose); 1354 lease_modify(&fl, F_RDLCK, dispose);
1405 if (past_time(fl->fl_break_time)) 1355 if (past_time(fl->fl_break_time))
1406 lease_modify(before, F_UNLCK, dispose); 1356 lease_modify(&fl, F_UNLCK, dispose);
1407 if (fl == *before) /* lease_modify may have freed fl */
1408 before = &fl->fl_next;
1409 } 1357 }
1410} 1358}
1411 1359
@@ -1419,11 +1367,12 @@ static bool leases_conflict(struct file_lock *lease, struct file_lock *breaker)
1419static bool 1367static bool
1420any_leases_conflict(struct inode *inode, struct file_lock *breaker) 1368any_leases_conflict(struct inode *inode, struct file_lock *breaker)
1421{ 1369{
1370 struct file_lock_context *ctx = inode->i_flctx;
1422 struct file_lock *fl; 1371 struct file_lock *fl;
1423 1372
1424 lockdep_assert_held(&inode->i_lock); 1373 lockdep_assert_held(&inode->i_lock);
1425 1374
1426 for (fl = inode->i_flock ; fl && IS_LEASE(fl); fl = fl->fl_next) { 1375 list_for_each_entry(fl, &ctx->flc_lease, fl_list) {
1427 if (leases_conflict(fl, breaker)) 1376 if (leases_conflict(fl, breaker))
1428 return true; 1377 return true;
1429 } 1378 }
@@ -1447,7 +1396,8 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
1447{ 1396{
1448 int error = 0; 1397 int error = 0;
1449 struct file_lock *new_fl; 1398 struct file_lock *new_fl;
1450 struct file_lock *fl, **before; 1399 struct file_lock_context *ctx = inode->i_flctx;
1400 struct file_lock *fl;
1451 unsigned long break_time; 1401 unsigned long break_time;
1452 int want_write = (mode & O_ACCMODE) != O_RDONLY; 1402 int want_write = (mode & O_ACCMODE) != O_RDONLY;
1453 LIST_HEAD(dispose); 1403 LIST_HEAD(dispose);
@@ -1457,6 +1407,12 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
1457 return PTR_ERR(new_fl); 1407 return PTR_ERR(new_fl);
1458 new_fl->fl_flags = type; 1408 new_fl->fl_flags = type;
1459 1409
1410 /* typically we will check that ctx is non-NULL before calling */
1411 if (!ctx) {
1412 WARN_ON_ONCE(1);
1413 return error;
1414 }
1415
1460 spin_lock(&inode->i_lock); 1416 spin_lock(&inode->i_lock);
1461 1417
1462 time_out_leases(inode, &dispose); 1418 time_out_leases(inode, &dispose);
@@ -1471,9 +1427,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
1471 break_time++; /* so that 0 means no break time */ 1427 break_time++; /* so that 0 means no break time */
1472 } 1428 }
1473 1429
1474 for (before = &inode->i_flock; 1430 list_for_each_entry(fl, &ctx->flc_lease, fl_list) {
1475 ((fl = *before) != NULL) && IS_LEASE(fl);
1476 before = &fl->fl_next) {
1477 if (!leases_conflict(fl, new_fl)) 1431 if (!leases_conflict(fl, new_fl))
1478 continue; 1432 continue;
1479 if (want_write) { 1433 if (want_write) {
@@ -1482,17 +1436,16 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
1482 fl->fl_flags |= FL_UNLOCK_PENDING; 1436 fl->fl_flags |= FL_UNLOCK_PENDING;
1483 fl->fl_break_time = break_time; 1437 fl->fl_break_time = break_time;
1484 } else { 1438 } else {
1485 if (lease_breaking(inode->i_flock)) 1439 if (lease_breaking(fl))
1486 continue; 1440 continue;
1487 fl->fl_flags |= FL_DOWNGRADE_PENDING; 1441 fl->fl_flags |= FL_DOWNGRADE_PENDING;
1488 fl->fl_downgrade_time = break_time; 1442 fl->fl_downgrade_time = break_time;
1489 } 1443 }
1490 if (fl->fl_lmops->lm_break(fl)) 1444 if (fl->fl_lmops->lm_break(fl))
1491 locks_delete_lock(before, &dispose); 1445 locks_delete_lock_ctx(fl, &dispose);
1492 } 1446 }
1493 1447
1494 fl = inode->i_flock; 1448 if (list_empty(&ctx->flc_lease))
1495 if (!fl || !IS_LEASE(fl))
1496 goto out; 1449 goto out;
1497 1450
1498 if (mode & O_NONBLOCK) { 1451 if (mode & O_NONBLOCK) {
@@ -1502,12 +1455,13 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
1502 } 1455 }
1503 1456
1504restart: 1457restart:
1505 break_time = inode->i_flock->fl_break_time; 1458 fl = list_first_entry(&ctx->flc_lease, struct file_lock, fl_list);
1459 break_time = fl->fl_break_time;
1506 if (break_time != 0) 1460 if (break_time != 0)
1507 break_time -= jiffies; 1461 break_time -= jiffies;
1508 if (break_time == 0) 1462 if (break_time == 0)
1509 break_time++; 1463 break_time++;
1510 locks_insert_block(inode->i_flock, new_fl); 1464 locks_insert_block(fl, new_fl);
1511 trace_break_lease_block(inode, new_fl); 1465 trace_break_lease_block(inode, new_fl);
1512 spin_unlock(&inode->i_lock); 1466 spin_unlock(&inode->i_lock);
1513 locks_dispose_list(&dispose); 1467 locks_dispose_list(&dispose);
@@ -1525,10 +1479,8 @@ restart:
1525 time_out_leases(inode, &dispose); 1479 time_out_leases(inode, &dispose);
1526 if (any_leases_conflict(inode, new_fl)) 1480 if (any_leases_conflict(inode, new_fl))
1527 goto restart; 1481 goto restart;
1528
1529 error = 0; 1482 error = 0;
1530 } 1483 }
1531
1532out: 1484out:
1533 spin_unlock(&inode->i_lock); 1485 spin_unlock(&inode->i_lock);
1534 locks_dispose_list(&dispose); 1486 locks_dispose_list(&dispose);
@@ -1550,13 +1502,17 @@ EXPORT_SYMBOL(__break_lease);
1550void lease_get_mtime(struct inode *inode, struct timespec *time) 1502void lease_get_mtime(struct inode *inode, struct timespec *time)
1551{ 1503{
1552 bool has_lease = false; 1504 bool has_lease = false;
1553 struct file_lock *flock; 1505 struct file_lock_context *ctx = inode->i_flctx;
1506 struct file_lock *fl;
1554 1507
1555 if (inode->i_flock) { 1508 if (ctx && !list_empty_careful(&ctx->flc_lease)) {
1556 spin_lock(&inode->i_lock); 1509 spin_lock(&inode->i_lock);
1557 flock = inode->i_flock; 1510 if (!list_empty(&ctx->flc_lease)) {
1558 if (flock && IS_LEASE(flock) && (flock->fl_type == F_WRLCK)) 1511 fl = list_first_entry(&ctx->flc_lease,
1559 has_lease = true; 1512 struct file_lock, fl_list);
1513 if (fl->fl_type == F_WRLCK)
1514 has_lease = true;
1515 }
1560 spin_unlock(&inode->i_lock); 1516 spin_unlock(&inode->i_lock);
1561 } 1517 }
1562 1518
@@ -1595,20 +1551,22 @@ int fcntl_getlease(struct file *filp)
1595{ 1551{
1596 struct file_lock *fl; 1552 struct file_lock *fl;
1597 struct inode *inode = file_inode(filp); 1553 struct inode *inode = file_inode(filp);
1554 struct file_lock_context *ctx = inode->i_flctx;
1598 int type = F_UNLCK; 1555 int type = F_UNLCK;
1599 LIST_HEAD(dispose); 1556 LIST_HEAD(dispose);
1600 1557
1601 spin_lock(&inode->i_lock); 1558 if (ctx && !list_empty_careful(&ctx->flc_lease)) {
1602 time_out_leases(file_inode(filp), &dispose); 1559 spin_lock(&inode->i_lock);
1603 for (fl = file_inode(filp)->i_flock; fl && IS_LEASE(fl); 1560 time_out_leases(file_inode(filp), &dispose);
1604 fl = fl->fl_next) { 1561 list_for_each_entry(fl, &ctx->flc_lease, fl_list) {
1605 if (fl->fl_file == filp) { 1562 if (fl->fl_file != filp)
1563 continue;
1606 type = target_leasetype(fl); 1564 type = target_leasetype(fl);
1607 break; 1565 break;
1608 } 1566 }
1567 spin_unlock(&inode->i_lock);
1568 locks_dispose_list(&dispose);
1609 } 1569 }
1610 spin_unlock(&inode->i_lock);
1611 locks_dispose_list(&dispose);
1612 return type; 1570 return type;
1613} 1571}
1614 1572
@@ -1641,9 +1599,10 @@ check_conflicting_open(const struct dentry *dentry, const long arg)
1641static int 1599static int
1642generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **priv) 1600generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **priv)
1643{ 1601{
1644 struct file_lock *fl, **before, **my_before = NULL, *lease; 1602 struct file_lock *fl, *my_fl = NULL, *lease;
1645 struct dentry *dentry = filp->f_path.dentry; 1603 struct dentry *dentry = filp->f_path.dentry;
1646 struct inode *inode = dentry->d_inode; 1604 struct inode *inode = dentry->d_inode;
1605 struct file_lock_context *ctx;
1647 bool is_deleg = (*flp)->fl_flags & FL_DELEG; 1606 bool is_deleg = (*flp)->fl_flags & FL_DELEG;
1648 int error; 1607 int error;
1649 LIST_HEAD(dispose); 1608 LIST_HEAD(dispose);
@@ -1651,6 +1610,10 @@ generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **pr
1651 lease = *flp; 1610 lease = *flp;
1652 trace_generic_add_lease(inode, lease); 1611 trace_generic_add_lease(inode, lease);
1653 1612
1613 ctx = locks_get_lock_context(inode);
1614 if (!ctx)
1615 return -ENOMEM;
1616
1654 /* 1617 /*
1655 * In the delegation case we need mutual exclusion with 1618 * In the delegation case we need mutual exclusion with
1656 * a number of operations that take the i_mutex. We trylock 1619 * a number of operations that take the i_mutex. We trylock
@@ -1684,13 +1647,12 @@ generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **pr
1684 * except for this filp. 1647 * except for this filp.
1685 */ 1648 */
1686 error = -EAGAIN; 1649 error = -EAGAIN;
1687 for (before = &inode->i_flock; 1650 list_for_each_entry(fl, &ctx->flc_lease, fl_list) {
1688 ((fl = *before) != NULL) && IS_LEASE(fl);
1689 before = &fl->fl_next) {
1690 if (fl->fl_file == filp) { 1651 if (fl->fl_file == filp) {
1691 my_before = before; 1652 my_fl = fl;
1692 continue; 1653 continue;
1693 } 1654 }
1655
1694 /* 1656 /*
1695 * No exclusive leases if someone else has a lease on 1657 * No exclusive leases if someone else has a lease on
1696 * this file: 1658 * this file:
@@ -1705,9 +1667,8 @@ generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **pr
1705 goto out; 1667 goto out;
1706 } 1668 }
1707 1669
1708 if (my_before != NULL) { 1670 if (my_fl != NULL) {
1709 lease = *my_before; 1671 error = lease->fl_lmops->lm_change(&my_fl, arg, &dispose);
1710 error = lease->fl_lmops->lm_change(my_before, arg, &dispose);
1711 if (error) 1672 if (error)
1712 goto out; 1673 goto out;
1713 goto out_setup; 1674 goto out_setup;
@@ -1717,7 +1678,7 @@ generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **pr
1717 if (!leases_enable) 1678 if (!leases_enable)
1718 goto out; 1679 goto out;
1719 1680
1720 locks_insert_lock(before, lease); 1681 locks_insert_lock_ctx(lease, &ctx->flc_lease);
1721 /* 1682 /*
1722 * The check in break_lease() is lockless. It's possible for another 1683 * The check in break_lease() is lockless. It's possible for another
1723 * open to race in after we did the earlier check for a conflicting 1684 * open to race in after we did the earlier check for a conflicting
@@ -1729,8 +1690,10 @@ generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **pr
1729 */ 1690 */
1730 smp_mb(); 1691 smp_mb();
1731 error = check_conflicting_open(dentry, arg); 1692 error = check_conflicting_open(dentry, arg);
1732 if (error) 1693 if (error) {
1733 goto out_unlink; 1694 locks_unlink_lock_ctx(lease);
1695 goto out;
1696 }
1734 1697
1735out_setup: 1698out_setup:
1736 if (lease->fl_lmops->lm_setup) 1699 if (lease->fl_lmops->lm_setup)
@@ -1740,33 +1703,35 @@ out:
1740 locks_dispose_list(&dispose); 1703 locks_dispose_list(&dispose);
1741 if (is_deleg) 1704 if (is_deleg)
1742 mutex_unlock(&inode->i_mutex); 1705 mutex_unlock(&inode->i_mutex);
1743 if (!error && !my_before) 1706 if (!error && !my_fl)
1744 *flp = NULL; 1707 *flp = NULL;
1745 return error; 1708 return error;
1746out_unlink:
1747 locks_unlink_lock(before);
1748 goto out;
1749} 1709}
1750 1710
1751static int generic_delete_lease(struct file *filp) 1711static int generic_delete_lease(struct file *filp)
1752{ 1712{
1753 int error = -EAGAIN; 1713 int error = -EAGAIN;
1754 struct file_lock *fl, **before; 1714 struct file_lock *fl, *victim = NULL;
1755 struct dentry *dentry = filp->f_path.dentry; 1715 struct dentry *dentry = filp->f_path.dentry;
1756 struct inode *inode = dentry->d_inode; 1716 struct inode *inode = dentry->d_inode;
1717 struct file_lock_context *ctx = inode->i_flctx;
1757 LIST_HEAD(dispose); 1718 LIST_HEAD(dispose);
1758 1719
1720 if (!ctx) {
1721 trace_generic_delete_lease(inode, NULL);
1722 return error;
1723 }
1724
1759 spin_lock(&inode->i_lock); 1725 spin_lock(&inode->i_lock);
1760 time_out_leases(inode, &dispose); 1726 list_for_each_entry(fl, &ctx->flc_lease, fl_list) {
1761 for (before = &inode->i_flock; 1727 if (fl->fl_file == filp) {
1762 ((fl = *before) != NULL) && IS_LEASE(fl); 1728 victim = fl;
1763 before = &fl->fl_next) {
1764 if (fl->fl_file == filp)
1765 break; 1729 break;
1730 }
1766 } 1731 }
1767 trace_generic_delete_lease(inode, fl); 1732 trace_generic_delete_lease(inode, fl);
1768 if (fl && IS_LEASE(fl)) 1733 if (victim)
1769 error = fl->fl_lmops->lm_change(before, F_UNLCK, &dispose); 1734 error = fl->fl_lmops->lm_change(&victim, F_UNLCK, &dispose);
1770 spin_unlock(&inode->i_lock); 1735 spin_unlock(&inode->i_lock);
1771 locks_dispose_list(&dispose); 1736 locks_dispose_list(&dispose);
1772 return error; 1737 return error;
@@ -2447,56 +2412,37 @@ locks_remove_flock(struct file *filp)
2447 fl.fl_ops->fl_release_private(&fl); 2412 fl.fl_ops->fl_release_private(&fl);
2448} 2413}
2449 2414
2415static void
2416locks_remove_lease(struct file *filp)
2417{
2418 struct inode *inode = file_inode(filp);
2419 struct file_lock_context *ctx = inode->i_flctx;
2420 struct file_lock *fl, *tmp;
2421 LIST_HEAD(dispose);
2422
2423 if (!ctx || list_empty(&ctx->flc_lease))
2424 return;
2425
2426 spin_lock(&inode->i_lock);
2427 list_for_each_entry_safe(fl, tmp, &ctx->flc_lease, fl_list)
2428 lease_modify(&fl, F_UNLCK, &dispose);
2429 spin_unlock(&inode->i_lock);
2430 locks_dispose_list(&dispose);
2431}
2432
2450/* 2433/*
2451 * This function is called on the last close of an open file. 2434 * This function is called on the last close of an open file.
2452 */ 2435 */
2453void locks_remove_file(struct file *filp) 2436void locks_remove_file(struct file *filp)
2454{ 2437{
2455 struct inode * inode = file_inode(filp);
2456 struct file_lock *fl;
2457 struct file_lock **before;
2458 LIST_HEAD(dispose);
2459
2460 /* remove any OFD locks */ 2438 /* remove any OFD locks */
2461 locks_remove_posix(filp, filp); 2439 locks_remove_posix(filp, filp);
2462 2440
2463 /* remove flock locks */ 2441 /* remove flock locks */
2464 locks_remove_flock(filp); 2442 locks_remove_flock(filp);
2465 2443
2466 if (!inode->i_flock) 2444 /* remove any leases */
2467 return; 2445 locks_remove_lease(filp);
2468
2469 spin_lock(&inode->i_lock);
2470 before = &inode->i_flock;
2471
2472 while ((fl = *before) != NULL) {
2473 if (fl->fl_file == filp) {
2474 if (IS_LEASE(fl)) {
2475 lease_modify(before, F_UNLCK, &dispose);
2476 continue;
2477 }
2478
2479 /*
2480 * There's a leftover lock on the list of a type that
2481 * we didn't expect to see. Most likely a classic
2482 * POSIX lock that ended up not getting released
2483 * properly, or that raced onto the list somehow. Log
2484 * some info about it and then just remove it from
2485 * the list.
2486 */
2487 WARN(1, "leftover lock: dev=%u:%u ino=%lu type=%hhd flags=0x%x start=%lld end=%lld\n",
2488 MAJOR(inode->i_sb->s_dev),
2489 MINOR(inode->i_sb->s_dev), inode->i_ino,
2490 fl->fl_type, fl->fl_flags,
2491 fl->fl_start, fl->fl_end);
2492
2493 locks_delete_lock(before, &dispose);
2494 continue;
2495 }
2496 before = &fl->fl_next;
2497 }
2498 spin_unlock(&inode->i_lock);
2499 locks_dispose_list(&dispose);
2500} 2446}
2501 2447
2502/** 2448/**
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 571f113588e9..2ddec3cf81b9 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -969,6 +969,7 @@ struct file_lock {
969struct file_lock_context { 969struct file_lock_context {
970 struct list_head flc_flock; 970 struct list_head flc_flock;
971 struct list_head flc_posix; 971 struct list_head flc_posix;
972 struct list_head flc_lease;
972}; 973};
973 974
974/* The following constant reflects the upper bound of the file/locking space */ 975/* The following constant reflects the upper bound of the file/locking space */
@@ -1990,7 +1991,7 @@ static inline int break_lease(struct inode *inode, unsigned int mode)
1990 * end up racing with tasks trying to set a new lease on this file. 1991 * end up racing with tasks trying to set a new lease on this file.
1991 */ 1992 */
1992 smp_mb(); 1993 smp_mb();
1993 if (inode->i_flock) 1994 if (inode->i_flctx && !list_empty_careful(&inode->i_flctx->flc_lease))
1994 return __break_lease(inode, mode, FL_LEASE); 1995 return __break_lease(inode, mode, FL_LEASE);
1995 return 0; 1996 return 0;
1996} 1997}
@@ -2003,7 +2004,7 @@ static inline int break_deleg(struct inode *inode, unsigned int mode)
2003 * end up racing with tasks trying to set a new lease on this file. 2004 * end up racing with tasks trying to set a new lease on this file.
2004 */ 2005 */
2005 smp_mb(); 2006 smp_mb();
2006 if (inode->i_flock) 2007 if (inode->i_flctx && !list_empty_careful(&inode->i_flctx->flc_lease))
2007 return __break_lease(inode, mode, FL_DELEG); 2008 return __break_lease(inode, mode, FL_DELEG);
2008 return 0; 2009 return 0;
2009} 2010}