]> git.baikalelectronics.ru Git - kernel.git/commitdiff
NFSv4: Ensure layout headers are RCU safe
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Tue, 18 Feb 2020 22:14:40 +0000 (17:14 -0500)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Mon, 16 Mar 2020 12:34:29 +0000 (08:34 -0400)
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
fs/nfs/blocklayout/blocklayout.c
fs/nfs/filelayout/filelayout.c
fs/nfs/flexfilelayout/flexfilelayout.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h

index 690221747b4705416d9f4e4f9b7236ddaf53ac9a..d1a0e2c8b1b486bd2866b388fce595f036abe58b 100644 (file)
@@ -476,7 +476,7 @@ static void bl_free_layout_hdr(struct pnfs_layout_hdr *lo)
        err = ext_tree_remove(bl, true, 0, LLONG_MAX);
        WARN_ON(err);
 
-       kfree(bl);
+       kfree_rcu(bl, bl_layout.plh_rcu);
 }
 
 static struct pnfs_layout_hdr *__bl_alloc_layout_hdr(struct inode *inode,
index c9b605f6c9cb22168dbed2c656e03480b7b99b2b..bd234394a87ca4c578f3786d283fa4a6ed8a1398 100644 (file)
@@ -1146,7 +1146,7 @@ filelayout_alloc_layout_hdr(struct inode *inode, gfp_t gfp_flags)
 static void
 filelayout_free_layout_hdr(struct pnfs_layout_hdr *lo)
 {
-       kfree(FILELAYOUT_FROM_HDR(lo));
+       kfree_rcu(FILELAYOUT_FROM_HDR(lo), generic_hdr.plh_rcu);
 }
 
 static struct pnfs_ds_commit_info *
index 8b8171b488938a503dcb5abfbc6f51a07da8f805..e7d8ae4d0cc5667f1ea35c6e7d137e52909d4e28 100644 (file)
@@ -59,14 +59,14 @@ ff_layout_alloc_layout_hdr(struct inode *inode, gfp_t gfp_flags)
 static void
 ff_layout_free_layout_hdr(struct pnfs_layout_hdr *lo)
 {
+       struct nfs4_flexfile_layout *ffl = FF_LAYOUT_FROM_HDR(lo);
        struct nfs4_ff_layout_ds_err *err, *n;
 
-       list_for_each_entry_safe(err, n, &FF_LAYOUT_FROM_HDR(lo)->error_list,
-                                list) {
+       list_for_each_entry_safe(err, n, &ffl->error_list, list) {
                list_del(&err->list);
                kfree(err);
        }
-       kfree(FF_LAYOUT_FROM_HDR(lo));
+       kfree_rcu(ffl, generic_hdr.plh_rcu);
 }
 
 static int decode_pnfs_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
index cb99ac95468864f07d2c0e8f4b24b40f7425c367..268e7b9ff54e34d092f983671540c8d0609cf64b 100644 (file)
@@ -268,11 +268,11 @@ pnfs_free_layout_hdr(struct pnfs_layout_hdr *lo)
        struct nfs_server *server = NFS_SERVER(lo->plh_inode);
        struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld;
 
-       if (!list_empty(&lo->plh_layouts)) {
+       if (test_and_clear_bit(NFS_LAYOUT_HASHED, &lo->plh_flags)) {
                struct nfs_client *clp = server->nfs_client;
 
                spin_lock(&clp->cl_lock);
-               list_del_init(&lo->plh_layouts);
+               list_del_rcu(&lo->plh_layouts);
                spin_unlock(&clp->cl_lock);
        }
        put_cred(lo->plh_lc_cred);
@@ -784,7 +784,8 @@ pnfs_layout_bulk_destroy_byserver_locked(struct nfs_client *clp,
                        break;
                inode = igrab(lo->plh_inode);
                if (inode != NULL) {
-                       list_del_init(&lo->plh_layouts);
+                       if (test_and_clear_bit(NFS_LAYOUT_HASHED, &lo->plh_flags))
+                               list_del_rcu(&lo->plh_layouts);
                        if (pnfs_layout_add_bulk_destroy_list(inode,
                                                layout_list))
                                continue;
@@ -1870,15 +1871,14 @@ static void pnfs_clear_first_layoutget(struct pnfs_layout_hdr *lo)
 static void _add_to_server_list(struct pnfs_layout_hdr *lo,
                                struct nfs_server *server)
 {
-       if (list_empty(&lo->plh_layouts)) {
+       if (!test_and_set_bit(NFS_LAYOUT_HASHED, &lo->plh_flags)) {
                struct nfs_client *clp = server->nfs_client;
 
                /* The lo must be on the clp list if there is any
                 * chance of a CB_LAYOUTRECALL(FILE) coming in.
                 */
                spin_lock(&clp->cl_lock);
-               if (list_empty(&lo->plh_layouts))
-                       list_add_tail(&lo->plh_layouts, &server->layouts);
+               list_add_tail_rcu(&lo->plh_layouts, &server->layouts);
                spin_unlock(&clp->cl_lock);
        }
 }
index cfb89d47c79d49ef0be325e24041b8a7b508e8f5..8df9aa02d336f0b4ed5b888ea3f657f667ad605d 100644 (file)
@@ -105,6 +105,7 @@ enum {
        NFS_LAYOUT_INVALID_STID,        /* layout stateid id is invalid */
        NFS_LAYOUT_FIRST_LAYOUTGET,     /* Serialize first layoutget */
        NFS_LAYOUT_INODE_FREEING,       /* The inode is being freed */
+       NFS_LAYOUT_HASHED,              /* The layout visible */
 };
 
 enum layoutdriver_policy_flags {
@@ -203,6 +204,7 @@ struct pnfs_layout_hdr {
        loff_t                  plh_lwb; /* last write byte for layoutcommit */
        const struct cred       *plh_lc_cred; /* layoutcommit cred */
        struct inode            *plh_inode;
+       struct rcu_head         plh_rcu;
 };
 
 struct pnfs_device {