NFSv4.1/flexfiles: Add refcounting to struct nfs4_ff_layout_mirror
authorTrond Myklebust <trond.myklebust@primarydata.com>
Mon, 24 Aug 2015 22:08:30 +0000 (18:08 -0400)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Tue, 25 Aug 2015 18:40:07 +0000 (14:40 -0400)
We do want to share mirrors between layout segments, so add a refcount
to enable that.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
fs/nfs/flexfilelayout/flexfilelayout.c
fs/nfs/flexfilelayout/flexfilelayout.h

index cc2c5f7f2bc19fcf19e0f9215f4c9eccd42876fb..62de0b8038c8d2901140a4ea6799354d1c0e89fe 100644 (file)
@@ -135,6 +135,31 @@ decode_name(struct xdr_stream *xdr, u32 *id)
        return 0;
 }
 
+static struct nfs4_ff_layout_mirror *ff_layout_alloc_mirror(gfp_t gfp_flags)
+{
+       struct nfs4_ff_layout_mirror *mirror;
+
+       mirror = kzalloc(sizeof(*mirror), gfp_flags);
+       if (mirror != NULL) {
+               spin_lock_init(&mirror->lock);
+               atomic_set(&mirror->ref, 1);
+       }
+       return mirror;
+}
+
+static void ff_layout_free_mirror(struct nfs4_ff_layout_mirror *mirror)
+{
+       kfree(mirror->fh_versions);
+       nfs4_ff_layout_put_deviceid(mirror->mirror_ds);
+       kfree(mirror);
+}
+
+static void ff_layout_put_mirror(struct nfs4_ff_layout_mirror *mirror)
+{
+       if (mirror != NULL && atomic_dec_and_test(&mirror->ref))
+               ff_layout_free_mirror(mirror);
+}
+
 static void ff_layout_free_mirror_array(struct nfs4_ff_layout_segment *fls)
 {
        int i;
@@ -144,11 +169,7 @@ static void ff_layout_free_mirror_array(struct nfs4_ff_layout_segment *fls)
                        /* normally mirror_ds is freed in
                         * .free_deviceid_node but we still do it here
                         * for .alloc_lseg error path */
-                       if (fls->mirror_array[i]) {
-                               kfree(fls->mirror_array[i]->fh_versions);
-                               nfs4_ff_layout_put_deviceid(fls->mirror_array[i]->mirror_ds);
-                               kfree(fls->mirror_array[i]);
-                       }
+                       ff_layout_put_mirror(fls->mirror_array[i]);
                }
                kfree(fls->mirror_array);
                fls->mirror_array = NULL;
@@ -262,15 +283,12 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh,
                if (ds_count != 1)
                        goto out_err_free;
 
-               fls->mirror_array[i] =
-                       kzalloc(sizeof(struct nfs4_ff_layout_mirror),
-                               gfp_flags);
+               fls->mirror_array[i] = ff_layout_alloc_mirror(gfp_flags);
                if (fls->mirror_array[i] == NULL) {
                        rc = -ENOMEM;
                        goto out_err_free;
                }
 
-               spin_lock_init(&fls->mirror_array[i]->lock);
                fls->mirror_array[i]->ds_count = ds_count;
                fls->mirror_array[i]->lseg = &fls->generic_hdr;
 
index f92f9a0a856b3e698c8859923438549d1bffed37..26b8258e256f89e6cb0c9bbafce352a229c73573 100644 (file)
@@ -77,6 +77,7 @@ struct nfs4_ff_layout_mirror {
        u32                             uid;
        u32                             gid;
        struct rpc_cred                 *cred;
+       atomic_t                        ref;
        spinlock_t                      lock;
        struct nfs4_ff_layoutstat       read_stat;
        struct nfs4_ff_layoutstat       write_stat;