Commit 0ceaf6c700f8245946a163e387add8675a0c302f

Authored by J. Bruce Fields
Committed by Linus Torvalds
1 parent 0d07025eff

locks: prevent ENOMEM on lease unlock

Removing a lock shouldn't require any allocations; a failure due to
ENOMEM leaves the caller with a choice between retrying or giving up and
leaking an unused lease.

Next we should split the other lease calls into add and delete cases.
I wanted to start with just the bugfix.

Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 1 changed file with 30 additions and 13 deletions Side-by-side Diff

... ... @@ -1441,7 +1441,8 @@
1441 1441 return 0;
1442 1442  
1443 1443 out:
1444   - locks_free_lock(lease);
  1444 + if (arg != F_UNLCK)
  1445 + locks_free_lock(lease);
1445 1446 return error;
1446 1447 }
1447 1448 EXPORT_SYMBOL(generic_setlease);
1448 1449  
... ... @@ -1493,18 +1494,17 @@
1493 1494 }
1494 1495 EXPORT_SYMBOL_GPL(vfs_setlease);
1495 1496  
1496   -/**
1497   - * fcntl_setlease - sets a lease on an open file
1498   - * @fd: open file descriptor
1499   - * @filp: file pointer
1500   - * @arg: type of lease to obtain
1501   - *
1502   - * Call this fcntl to establish a lease on the file.
1503   - * Note that you also need to call %F_SETSIG to
1504   - * receive a signal when the lease is broken.
1505   - */
1506   -int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
  1497 +static int do_fcntl_delete_lease(struct file *filp)
1507 1498 {
  1499 + struct file_lock fl, *flp = &fl;
  1500 +
  1501 + lease_init(filp, F_UNLCK, flp);
  1502 +
  1503 + return vfs_setlease(filp, F_UNLCK, &flp);
  1504 +}
  1505 +
  1506 +static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg)
  1507 +{
1508 1508 struct file_lock *fl;
1509 1509 struct fasync_struct *new;
1510 1510 struct inode *inode = filp->f_path.dentry->d_inode;
... ... @@ -1521,7 +1521,7 @@
1521 1521 }
1522 1522 lock_flocks();
1523 1523 error = __vfs_setlease(filp, arg, &fl);
1524   - if (error || arg == F_UNLCK)
  1524 + if (error)
1525 1525 goto out_unlock;
1526 1526  
1527 1527 /*
... ... @@ -1547,6 +1547,23 @@
1547 1547 if (new)
1548 1548 fasync_free(new);
1549 1549 return error;
  1550 +}
  1551 +
  1552 +/**
  1553 + * fcntl_setlease - sets a lease on an open file
  1554 + * @fd: open file descriptor
  1555 + * @filp: file pointer
  1556 + * @arg: type of lease to obtain
  1557 + *
  1558 + * Call this fcntl to establish a lease on the file.
  1559 + * Note that you also need to call %F_SETSIG to
  1560 + * receive a signal when the lease is broken.
  1561 + */
  1562 +int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
  1563 +{
  1564 + if (arg == F_UNLCK)
  1565 + return do_fcntl_delete_lease(filp);
  1566 + return do_fcntl_add_lease(fd, filp, arg);
1550 1567 }
1551 1568  
1552 1569 /**