Commit 3df057ac authored by J. Bruce Fields's avatar J. Bruce Fields

locks: fix leak on merging leases

We must also free the passed-in lease in the case it wasn't used because
an existing lease was upgrade/downgraded or already existed.

Note the nfsd caller doesn't care because it's fl_change callback
returns an error in those cases.
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 21b75b01
...@@ -1504,7 +1504,7 @@ static int do_fcntl_delete_lease(struct file *filp) ...@@ -1504,7 +1504,7 @@ static int do_fcntl_delete_lease(struct file *filp)
static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg)
{ {
struct file_lock *fl; struct file_lock *fl, *ret;
struct fasync_struct *new; struct fasync_struct *new;
struct inode *inode = filp->f_path.dentry->d_inode; struct inode *inode = filp->f_path.dentry->d_inode;
int error; int error;
...@@ -1518,6 +1518,7 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) ...@@ -1518,6 +1518,7 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg)
locks_free_lock(fl); locks_free_lock(fl);
return -ENOMEM; return -ENOMEM;
} }
ret = fl;
lock_flocks(); lock_flocks();
error = __vfs_setlease(filp, arg, &fl); error = __vfs_setlease(filp, arg, &fl);
if (error) { if (error) {
...@@ -1525,6 +1526,8 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) ...@@ -1525,6 +1526,8 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg)
locks_free_lock(fl); locks_free_lock(fl);
goto out_free_fasync; goto out_free_fasync;
} }
if (ret != fl)
locks_free_lock(fl);
/* /*
* fasync_insert_entry() returns the old entry if any. * fasync_insert_entry() returns the old entry if any.
...@@ -1532,7 +1535,7 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) ...@@ -1532,7 +1535,7 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg)
* inserted it into the fasync list. Clear new so that * inserted it into the fasync list. Clear new so that
* we don't release it here. * we don't release it here.
*/ */
if (!fasync_insert_entry(fd, filp, &fl->fl_fasync, new)) if (!fasync_insert_entry(fd, filp, &ret->fl_fasync, new))
new = NULL; new = NULL;
if (error < 0) { if (error < 0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment