NFSv4.1: Convert pNFS deviceid to use kfree_rcu()
authorTrond Myklebust <trond.myklebust@primarydata.com>
Mon, 9 Mar 2015 19:23:35 +0000 (15:23 -0400)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Fri, 27 Mar 2015 16:32:24 +0000 (12:32 -0400)
Use of synchronize_rcu() when unmounting and potentially freeing a lot
of deviceids is problematic. There really is no reason why we can't just
use kfree_rcu() here.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
fs/nfs/blocklayout/dev.c
fs/nfs/filelayout/filelayoutdev.c
fs/nfs/flexfilelayout/flexfilelayoutdev.c
fs/nfs/objlayout/objio_osd.c
fs/nfs/pnfs.h
fs/nfs/pnfs_dev.c

index 5aed4f98df411be1d7612f566f5929d1db28c97a..e535599a07191619c28eba93342388a59267114e 100644 (file)
@@ -33,7 +33,7 @@ bl_free_deviceid_node(struct nfs4_deviceid_node *d)
                container_of(d, struct pnfs_block_dev, node);
 
        bl_free_device(dev);
-       kfree(dev);
+       kfree_rcu(dev, node.rcu);
 }
 
 static int
index 4f372e2246034415583485aa680bd43a0a83a04f..4946ef40ba875e6255857ca3c27b6df352c7a46a 100644 (file)
@@ -55,7 +55,7 @@ nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)
                        nfs4_pnfs_ds_put(ds);
        }
        kfree(dsaddr->stripe_indices);
-       kfree(dsaddr);
+       kfree_rcu(dsaddr, id_node.rcu);
 }
 
 /* Decode opaque device data and return the result */
index e2c01f204a956b584725d1d187d1ea1fc22d6ab0..77a2d026aa12b62bdc29dac2345cff0b3237e9c4 100644 (file)
@@ -30,7 +30,7 @@ void nfs4_ff_layout_free_deviceid(struct nfs4_ff_layout_ds *mirror_ds)
 {
        nfs4_print_deviceid(&mirror_ds->id_node.deviceid);
        nfs4_pnfs_ds_put(mirror_ds->ds);
-       kfree(mirror_ds);
+       kfree_rcu(mirror_ds, id_node.rcu);
 }
 
 /* Decode opaque device data and construct new_ds using it */
index 24e1d7403c0be241fa90dd6645f86dddadf0add9..8b5e0e687d5e91607f8fa20d5e0bdfaed9d00a84 100644 (file)
@@ -57,7 +57,7 @@ objio_free_deviceid_node(struct nfs4_deviceid_node *d)
 
        dprintk("%s: free od=%p\n", __func__, de->od.od);
        osduld_put_device(de->od.od);
-       kfree(de);
+       kfree_rcu(d, rcu);
 }
 
 struct objio_segment {
index 635f0865671cf38b27eea4a49261c9405a4a4731..a1fc16c971a7f98c8e2ca963fe13899013226f1e 100644 (file)
@@ -302,6 +302,7 @@ struct nfs4_deviceid_node {
        unsigned long                   flags;
        unsigned long                   timestamp_unavailable;
        struct nfs4_deviceid            deviceid;
+       struct rcu_head                 rcu;
        atomic_t                        ref;
 };
 
index aa2ec00151839f1519a2c7e0ab65509d9f2cfba3..bf23ac97d57d28a5d28880197a8d25b7e33a27af 100644 (file)
@@ -175,8 +175,8 @@ __nfs4_find_get_deviceid(struct nfs_server *server,
        rcu_read_lock();
        d = _lookup_deviceid(server->pnfs_curr_ld, server->nfs_client, id,
                        hash);
-       if (d != NULL)
-               atomic_inc(&d->ref);
+       if (d != NULL && !atomic_inc_not_zero(&d->ref))
+               d = NULL;
        rcu_read_unlock();
        return d;
 }
@@ -236,7 +236,6 @@ nfs4_delete_deviceid(const struct pnfs_layoutdriver_type *ld,
        }
        hlist_del_init_rcu(&d->node);
        spin_unlock(&nfs4_deviceid_lock);
-       synchronize_rcu();
 
        /* balance the initial ref set in pnfs_insert_deviceid */
        if (atomic_dec_and_test(&d->ref))
@@ -321,7 +320,6 @@ _deviceid_purge_client(const struct nfs_client *clp, long hash)
        if (hlist_empty(&tmp))
                return;
 
-       synchronize_rcu();
        while (!hlist_empty(&tmp)) {
                d = hlist_entry(tmp.first, struct nfs4_deviceid_node, tmpnode);
                hlist_del(&d->tmpnode);