Merge tag 'docs-5.7-2' of git://git.lwn.net/linux
[linux-block.git] / fs / nfs / callback_proc.c
index cd4c6bc81caedd10114046463683032c40b2bfbb..e61dbc9b86ae25a759f1c617c2ed414bb5ad9975 100644 (file)
@@ -121,31 +121,31 @@ out:
  */
 static struct inode *nfs_layout_find_inode_by_stateid(struct nfs_client *clp,
                const nfs4_stateid *stateid)
+       __must_hold(RCU)
 {
        struct nfs_server *server;
        struct inode *inode;
        struct pnfs_layout_hdr *lo;
 
+       rcu_read_lock();
        list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
-               list_for_each_entry(lo, &server->layouts, plh_layouts) {
+               list_for_each_entry_rcu(lo, &server->layouts, plh_layouts) {
+                       if (!pnfs_layout_is_valid(lo))
+                               continue;
                        if (stateid != NULL &&
                            !nfs4_stateid_match_other(stateid, &lo->plh_stateid))
                                continue;
+                       if (!nfs_sb_active(server->super))
+                               continue;
                        inode = igrab(lo->plh_inode);
-                       if (!inode)
-                               return ERR_PTR(-EAGAIN);
-                       if (!nfs_sb_active(inode->i_sb)) {
-                               rcu_read_unlock();
-                               spin_unlock(&clp->cl_lock);
-                               iput(inode);
-                               spin_lock(&clp->cl_lock);
-                               rcu_read_lock();
-                               return ERR_PTR(-EAGAIN);
-                       }
-                       return inode;
+                       rcu_read_unlock();
+                       if (inode)
+                               return inode;
+                       nfs_sb_deactive(server->super);
+                       return ERR_PTR(-EAGAIN);
                }
        }
-
+       rcu_read_unlock();
        return ERR_PTR(-ENOENT);
 }
 
@@ -163,28 +163,25 @@ static struct inode *nfs_layout_find_inode_by_fh(struct nfs_client *clp,
        struct inode *inode;
        struct pnfs_layout_hdr *lo;
 
+       rcu_read_lock();
        list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
-               list_for_each_entry(lo, &server->layouts, plh_layouts) {
+               list_for_each_entry_rcu(lo, &server->layouts, plh_layouts) {
                        nfsi = NFS_I(lo->plh_inode);
                        if (nfs_compare_fh(fh, &nfsi->fh))
                                continue;
                        if (nfsi->layout != lo)
                                continue;
+                       if (!nfs_sb_active(server->super))
+                               continue;
                        inode = igrab(lo->plh_inode);
-                       if (!inode)
-                               return ERR_PTR(-EAGAIN);
-                       if (!nfs_sb_active(inode->i_sb)) {
-                               rcu_read_unlock();
-                               spin_unlock(&clp->cl_lock);
-                               iput(inode);
-                               spin_lock(&clp->cl_lock);
-                               rcu_read_lock();
-                               return ERR_PTR(-EAGAIN);
-                       }
-                       return inode;
+                       rcu_read_unlock();
+                       if (inode)
+                               return inode;
+                       nfs_sb_deactive(server->super);
+                       return ERR_PTR(-EAGAIN);
                }
        }
-
+       rcu_read_unlock();
        return ERR_PTR(-ENOENT);
 }
 
@@ -194,14 +191,9 @@ static struct inode *nfs_layout_find_inode(struct nfs_client *clp,
 {
        struct inode *inode;
 
-       spin_lock(&clp->cl_lock);
-       rcu_read_lock();
        inode = nfs_layout_find_inode_by_stateid(clp, stateid);
        if (inode == ERR_PTR(-ENOENT))
                inode = nfs_layout_find_inode_by_fh(clp, fh);
-       rcu_read_unlock();
-       spin_unlock(&clp->cl_lock);
-
        return inode;
 }
 
@@ -280,7 +272,7 @@ static u32 initiate_file_draining(struct nfs_client *clp,
                goto unlock;
        }
 
-       pnfs_set_layout_stateid(lo, &args->cbl_stateid, true);
+       pnfs_set_layout_stateid(lo, &args->cbl_stateid, NULL, true);
        switch (pnfs_mark_matching_lsegs_return(lo, &free_me_list,
                                &args->cbl_range,
                                be32_to_cpu(args->cbl_stateid.seqid))) {
@@ -605,6 +597,7 @@ __be32 nfs4_callback_recallany(void *argp, void *resp,
        struct cb_recallanyargs *args = argp;
        __be32 status;
        fmode_t flags = 0;
+       bool schedule_manager = false;
 
        status = cpu_to_be32(NFS4ERR_OP_NOT_IN_SESSION);
        if (!cps->clp) /* set in cb_sequence */
@@ -627,6 +620,18 @@ __be32 nfs4_callback_recallany(void *argp, void *resp,
 
        if (args->craa_type_mask & BIT(RCA4_TYPE_MASK_FILE_LAYOUT))
                pnfs_recall_all_layouts(cps->clp);
+
+       if (args->craa_type_mask & BIT(PNFS_FF_RCA4_TYPE_MASK_READ)) {
+               set_bit(NFS4CLNT_RECALL_ANY_LAYOUT_READ, &cps->clp->cl_state);
+               schedule_manager = true;
+       }
+       if (args->craa_type_mask & BIT(PNFS_FF_RCA4_TYPE_MASK_RW)) {
+               set_bit(NFS4CLNT_RECALL_ANY_LAYOUT_RW, &cps->clp->cl_state);
+               schedule_manager = true;
+       }
+       if (schedule_manager)
+               nfs4_schedule_state_manager(cps->clp);
+
 out:
        dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
        return status;