lockd: fix a leak in nlmsvc_testlock asynchronous request handling
Oleg Drokin [Thu, 29 Nov 2007 19:02:21 +0000 (14:02 -0500)]
Without the patch, there is a leakage of nlmblock structure refcount
that holds a reference nlmfile structure, that holds a reference to
struct file, when async GETFL is used (-EINPROGRESS return from
file_ops->lock()), and also in some error cases.

Fix up a style nit while we're here.

Signed-off-by: Oleg Drokin <green@linuxhacker.ru>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>

fs/lockd/svclock.c

index d120ec3..84c4d5e 100644 (file)
@@ -501,25 +501,29 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
                        block, block->b_flags, block->b_fl);
                if (block->b_flags & B_TIMED_OUT) {
                        nlmsvc_unlink_block(block);
-                       return nlm_lck_denied;
+                       ret = nlm_lck_denied;
+                       goto out;
                }
                if (block->b_flags & B_GOT_CALLBACK) {
                        if (block->b_fl != NULL
                                        && block->b_fl->fl_type != F_UNLCK) {
                                lock->fl = *block->b_fl;
                                goto conf_lock;
-                       }
-                       else {
+                       } else {
                                nlmsvc_unlink_block(block);
-                               return nlm_granted;
+                               ret = nlm_granted;
+                               goto out;
                        }
                }
-               return nlm_drop_reply;
+               ret = nlm_drop_reply;
+               goto out;
        }
 
        error = vfs_test_lock(file->f_file, &lock->fl);
-       if (error == -EINPROGRESS)
-               return nlmsvc_defer_lock_rqst(rqstp, block);
+       if (error == -EINPROGRESS) {
+               ret = nlmsvc_defer_lock_rqst(rqstp, block);
+               goto out;
+       }
        if (error) {
                ret = nlm_lck_denied_nolocks;
                goto out;