NFSv4.1: Fix a race in set_pnfs_layoutdriver
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Fri, 15 Jun 2012 17:02:58 +0000 (13:02 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 19 Jun 2012 17:32:45 +0000 (13:32 -0400)
The call to try_module_get() dereferences ld_type outside the
spin locks, which means that it may be pointing to garbage if
a module unload was in progress.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/pnfs.c

index bdf7e52..bbc49ca 100644 (file)
@@ -70,6 +70,10 @@ find_pnfs_driver(u32 id)
 
        spin_lock(&pnfs_spinlock);
        local = find_pnfs_driver_locked(id);
+       if (local != NULL && !try_module_get(local->owner)) {
+               dprintk("%s: Could not grab reference on module\n", __func__);
+               local = NULL;
+       }
        spin_unlock(&pnfs_spinlock);
        return local;
 }
@@ -118,10 +122,6 @@ set_pnfs_layoutdriver(struct nfs_server *server, const struct nfs_fh *mntfh,
                        goto out_no_driver;
                }
        }
-       if (!try_module_get(ld_type->owner)) {
-               dprintk("%s: Could not grab reference on module\n", __func__);
-               goto out_no_driver;
-       }
        server->pnfs_curr_ld = ld_type;
        if (ld_type->set_layoutdriver
            && ld_type->set_layoutdriver(server, mntfh)) {