This is a note to let you know that I've just added the patch titled

    nfsd4: fix struct file leak

to the 2.6.37-stable tree which can be found at:
    
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     nfsd4-fix-struct-file-leak.patch
and it can be found in the queue-2.6.37 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <[email protected]> know about it.


From 0997b173609b9229ece28941c118a2a9b278796e Mon Sep 17 00:00:00 2001
From: J. Bruce Fields <[email protected]>
Date: Wed, 2 Mar 2011 18:01:35 -0500
Subject: nfsd4: fix struct file leak
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

From: J. Bruce Fields <[email protected]>

commit 0997b173609b9229ece28941c118a2a9b278796e upstream.

Make sure we properly reference count the struct files that a lock
depends on, and release them when the lock stateid is released.

This fixes a major leak of struct files when using locking over nfsv4.

Reported-by: Rick Koshi <[email protected]>
Tested-by: Ivo PÅ™ikryl <[email protected]>
Signed-off-by: J. Bruce Fields <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
 fs/nfsd/nfs4state.c |   32 +++++++++++++++++++++-----------
 1 file changed, 21 insertions(+), 11 deletions(-)

--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -408,6 +408,9 @@ static void unhash_generic_stateid(struc
 
 static void free_generic_stateid(struct nfs4_stateid *stp)
 {
+       int oflag = nfs4_access_bmap_to_omode(stp);
+
+       nfs4_file_put_access(stp->st_file, oflag);
        put_nfs4_file(stp->st_file);
        kmem_cache_free(stateid_slab, stp);
 }
@@ -459,11 +462,8 @@ release_stateid_lockowners(struct nfs4_s
 
 static void release_open_stateid(struct nfs4_stateid *stp)
 {
-       int oflag = nfs4_access_bmap_to_omode(stp);
-
        unhash_generic_stateid(stp);
        release_stateid_lockowners(stp);
-       nfs4_file_put_access(stp->st_file, oflag);
        free_generic_stateid(stp);
 }
 
@@ -3661,6 +3661,7 @@ alloc_init_lock_stateid(struct nfs4_stat
        stp->st_stateid.si_stateownerid = sop->so_id;
        stp->st_stateid.si_fileid = fp->fi_id;
        stp->st_stateid.si_generation = 0;
+       stp->st_access_bmap = 0;
        stp->st_deny_bmap = open_stp->st_deny_bmap;
        stp->st_openstp = open_stp;
 
@@ -3675,6 +3676,17 @@ check_lock_length(u64 offset, u64 length
             LOFF_OVERFLOW(offset, length)));
 }
 
+static void get_lock_access(struct nfs4_stateid *lock_stp, u32 access)
+{
+       struct nfs4_file *fp = lock_stp->st_file;
+       int oflag = nfs4_access_to_omode(access);
+
+       if (test_bit(access, &lock_stp->st_access_bmap))
+               return;
+       nfs4_file_get_access(fp, oflag);
+       __set_bit(access, &lock_stp->st_access_bmap);
+}
+
 /*
  *  LOCK operation 
  */
@@ -3772,18 +3784,16 @@ nfsd4_lock(struct svc_rqst *rqstp, struc
        switch (lock->lk_type) {
                case NFS4_READ_LT:
                case NFS4_READW_LT:
-                       if (find_readable_file(lock_stp->st_file)) {
-                               nfs4_get_vfs_file(rqstp, fp, 
&cstate->current_fh, NFS4_SHARE_ACCESS_READ);
-                               filp = find_readable_file(lock_stp->st_file);
-                       }
+                       filp = find_readable_file(lock_stp->st_file);
+                       if (filp)
+                               get_lock_access(lock_stp, 
NFS4_SHARE_ACCESS_READ);
                        file_lock.fl_type = F_RDLCK;
                        break;
                case NFS4_WRITE_LT:
                case NFS4_WRITEW_LT:
-                       if (find_writeable_file(lock_stp->st_file)) {
-                               nfs4_get_vfs_file(rqstp, fp, 
&cstate->current_fh, NFS4_SHARE_ACCESS_WRITE);
-                               filp = find_writeable_file(lock_stp->st_file);
-                       }
+                       filp = find_writeable_file(lock_stp->st_file);
+                       if (filp)
+                               get_lock_access(lock_stp, 
NFS4_SHARE_ACCESS_WRITE);
                        file_lock.fl_type = F_WRLCK;
                        break;
                default:


Patches currently in stable-queue which might be from [email protected] are

queue-2.6.37/nfsd4-minor-nfs4state.c-reshuffling.patch
queue-2.6.37/nfsd4-fix-struct-file-leak.patch
queue-2.6.37/nfsd41-modify-the-members-value-of-nfsd4_op_flags.patch
queue-2.6.37/nfsd-wrong-index-used-in-inner-loop.patch

_______________________________________________
stable mailing list
[email protected]
http://linux.kernel.org/mailman/listinfo/stable

Reply via email to