Print this page
8040 NFSv4 client: 3-way deadlock between nfs4_bio(), nfs4_do_delegreturn(), and nfs4_flush_pages()
Reviewed by: Arne Jansen <arne@die-jansens.de>
Reviewed by: Vitaliy Gusev <gusev.vitaliy@icloud.com>
Approved by: Gordon Ross <gordon.w.ross@gmail.com>


2579         rp->created_v4 = 0;
2580         mutex_exit(&rp->r_statev4_lock);
2581 
2582         resop = &res.array[2];
2583         osp->open_stateid = resop->nfs_resop4_u.opclose.open_stateid;
2584         osp->os_valid = 0;
2585 
2586         /*
2587          * This removes the reference obtained at OPEN; ie, when the
2588          * open stream structure was created.
2589          *
2590          * We don't have to worry about calling 'open_stream_rele'
2591          * since we our currently holding a reference to the open
2592          * stream which means the count cannot go to 0 with this
2593          * decrement.
2594          */
2595         ASSERT(osp->os_ref_count >= 2);
2596         osp->os_ref_count--;
2597 
2598         if (ep->error == 0) {
2599                 /*
2600                  * Avoid a deadlock with the r_serial thread waiting for
2601                  * os_sync_lock in nfs4_get_otw_cred_by_osp() which might be
2602                  * held by us. We will wait in nfs4_attr_cache() for the
2603                  * completion of the r_serial thread.
2604                  */
2605                 mutex_exit(&osp->os_sync_lock);
2606                 *have_sync_lockp = 0;
2607 
2608                 nfs4_attr_cache(vp,
2609                     &res.array[1].nfs_resop4_u.opgetattr.ga_res,
2610                     t, cred_otw, TRUE, NULL);
2611         }
2612 
2613         NFS4_DEBUG(nfs4_client_state_debug, (CE_NOTE, "nfs4close_otw:"
2614             " returning %d", ep->error));
2615 
2616         xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&res);
2617 }
2618 
2619 /* ARGSUSED */
2620 static int
2621 nfs4_read(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
2622     caller_context_t *ct)
2623 {
2624         rnode4_t *rp;




2579         rp->created_v4 = 0;
2580         mutex_exit(&rp->r_statev4_lock);
2581 
2582         resop = &res.array[2];
2583         osp->open_stateid = resop->nfs_resop4_u.opclose.open_stateid;
2584         osp->os_valid = 0;
2585 
2586         /*
2587          * This removes the reference obtained at OPEN; ie, when the
2588          * open stream structure was created.
2589          *
2590          * We don't have to worry about calling 'open_stream_rele'
2591          * since we our currently holding a reference to the open
2592          * stream which means the count cannot go to 0 with this
2593          * decrement.
2594          */
2595         ASSERT(osp->os_ref_count >= 2);
2596         osp->os_ref_count--;
2597 
2598         if (ep->error == 0) {






2599                 mutex_exit(&osp->os_sync_lock);
2600                 *have_sync_lockp = 0;
2601 
2602                 nfs4_attr_cache(vp,
2603                     &res.array[1].nfs_resop4_u.opgetattr.ga_res,
2604                     t, cred_otw, TRUE, NULL);
2605         }
2606 
2607         NFS4_DEBUG(nfs4_client_state_debug, (CE_NOTE, "nfs4close_otw:"
2608             " returning %d", ep->error));
2609 
2610         xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&res);
2611 }
2612 
2613 /* ARGSUSED */
2614 static int
2615 nfs4_read(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
2616     caller_context_t *ct)
2617 {
2618         rnode4_t *rp;