Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NFSv4.1: Convert pNFS deviceid to use kfree_rcu()

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>

+7 -8
+1 -1
fs/nfs/blocklayout/dev.c
··· 33 33 container_of(d, struct pnfs_block_dev, node); 34 34 35 35 bl_free_device(dev); 36 - kfree(dev); 36 + kfree_rcu(dev, node.rcu); 37 37 } 38 38 39 39 static int
+1 -1
fs/nfs/filelayout/filelayoutdev.c
··· 55 55 nfs4_pnfs_ds_put(ds); 56 56 } 57 57 kfree(dsaddr->stripe_indices); 58 - kfree(dsaddr); 58 + kfree_rcu(dsaddr, id_node.rcu); 59 59 } 60 60 61 61 /* Decode opaque device data and return the result */
+1 -1
fs/nfs/flexfilelayout/flexfilelayoutdev.c
··· 30 30 { 31 31 nfs4_print_deviceid(&mirror_ds->id_node.deviceid); 32 32 nfs4_pnfs_ds_put(mirror_ds->ds); 33 - kfree(mirror_ds); 33 + kfree_rcu(mirror_ds, id_node.rcu); 34 34 } 35 35 36 36 /* Decode opaque device data and construct new_ds using it */
+1 -1
fs/nfs/objlayout/objio_osd.c
··· 57 57 58 58 dprintk("%s: free od=%p\n", __func__, de->od.od); 59 59 osduld_put_device(de->od.od); 60 - kfree(de); 60 + kfree_rcu(d, rcu); 61 61 } 62 62 63 63 struct objio_segment {
+1
fs/nfs/pnfs.h
··· 302 302 unsigned long flags; 303 303 unsigned long timestamp_unavailable; 304 304 struct nfs4_deviceid deviceid; 305 + struct rcu_head rcu; 305 306 atomic_t ref; 306 307 }; 307 308
+2 -4
fs/nfs/pnfs_dev.c
··· 175 175 rcu_read_lock(); 176 176 d = _lookup_deviceid(server->pnfs_curr_ld, server->nfs_client, id, 177 177 hash); 178 - if (d != NULL) 179 - atomic_inc(&d->ref); 178 + if (d != NULL && !atomic_inc_not_zero(&d->ref)) 179 + d = NULL; 180 180 rcu_read_unlock(); 181 181 return d; 182 182 } ··· 236 236 } 237 237 hlist_del_init_rcu(&d->node); 238 238 spin_unlock(&nfs4_deviceid_lock); 239 - synchronize_rcu(); 240 239 241 240 /* balance the initial ref set in pnfs_insert_deviceid */ 242 241 if (atomic_dec_and_test(&d->ref)) ··· 320 321 if (hlist_empty(&tmp)) 321 322 return; 322 323 323 - synchronize_rcu(); 324 324 while (!hlist_empty(&tmp)) { 325 325 d = hlist_entry(tmp.first, struct nfs4_deviceid_node, tmpnode); 326 326 hlist_del(&d->tmpnode);