@@ -505,37 +505,147 @@ pnfs_destroy_layout(struct nfs_inode *nfsi)
505505}
506506EXPORT_SYMBOL_GPL (pnfs_destroy_layout );
507507
508- /*
509- * Called by the state manger to remove all layouts established under an
510- * expired lease.
511- */
512- void
513- pnfs_destroy_all_layouts (struct nfs_client * clp )
508+ static bool
509+ pnfs_layout_add_bulk_destroy_list (struct inode * inode ,
510+ struct list_head * layout_list )
514511{
515- struct nfs_server * server ;
516512 struct pnfs_layout_hdr * lo ;
517- LIST_HEAD ( tmp_list ) ;
513+ bool ret = false ;
518514
519- nfs4_deviceid_mark_client_invalid (clp );
520- nfs4_deviceid_purge_client (clp );
515+ spin_lock (& inode -> i_lock );
516+ lo = NFS_I (inode )-> layout ;
517+ if (lo != NULL && list_empty (& lo -> plh_bulk_destroy )) {
518+ pnfs_get_layout_hdr (lo );
519+ list_add (& lo -> plh_bulk_destroy , layout_list );
520+ ret = true;
521+ }
522+ spin_unlock (& inode -> i_lock );
523+ return ret ;
524+ }
525+
526+ /* Caller must hold rcu_read_lock and clp->cl_lock */
527+ static int
528+ pnfs_layout_bulk_destroy_byserver_locked (struct nfs_client * clp ,
529+ struct nfs_server * server ,
530+ struct list_head * layout_list )
531+ {
532+ struct pnfs_layout_hdr * lo , * next ;
533+ struct inode * inode ;
534+
535+ list_for_each_entry_safe (lo , next , & server -> layouts , plh_layouts ) {
536+ inode = igrab (lo -> plh_inode );
537+ if (inode == NULL )
538+ continue ;
539+ list_del_init (& lo -> plh_layouts );
540+ if (pnfs_layout_add_bulk_destroy_list (inode , layout_list ))
541+ continue ;
542+ rcu_read_unlock ();
543+ spin_unlock (& clp -> cl_lock );
544+ iput (inode );
545+ spin_lock (& clp -> cl_lock );
546+ rcu_read_lock ();
547+ return - EAGAIN ;
548+ }
549+ return 0 ;
550+ }
551+
552+ static int
553+ pnfs_layout_free_bulk_destroy_list (struct list_head * layout_list ,
554+ bool is_bulk_recall )
555+ {
556+ struct pnfs_layout_hdr * lo ;
557+ struct inode * inode ;
558+ struct pnfs_layout_range range = {
559+ .iomode = IOMODE_ANY ,
560+ .offset = 0 ,
561+ .length = NFS4_MAX_UINT64 ,
562+ };
563+ LIST_HEAD (lseg_list );
564+ int ret = 0 ;
565+
566+ while (!list_empty (layout_list )) {
567+ lo = list_entry (layout_list -> next , struct pnfs_layout_hdr ,
568+ plh_bulk_destroy );
569+ dprintk ("%s freeing layout for inode %lu\n" , __func__ ,
570+ lo -> plh_inode -> i_ino );
571+ inode = lo -> plh_inode ;
572+ spin_lock (& inode -> i_lock );
573+ list_del_init (& lo -> plh_bulk_destroy );
574+ lo -> plh_block_lgets ++ ; /* permanently block new LAYOUTGETs */
575+ if (is_bulk_recall )
576+ set_bit (NFS_LAYOUT_BULK_RECALL , & lo -> plh_flags );
577+ if (pnfs_mark_matching_lsegs_invalid (lo , & lseg_list , & range ))
578+ ret = - EAGAIN ;
579+ spin_unlock (& inode -> i_lock );
580+ pnfs_free_lseg_list (& lseg_list );
581+ pnfs_put_layout_hdr (lo );
582+ iput (inode );
583+ }
584+ return ret ;
585+ }
586+
587+ int
588+ pnfs_destroy_layouts_byfsid (struct nfs_client * clp ,
589+ struct nfs_fsid * fsid ,
590+ bool is_recall )
591+ {
592+ struct nfs_server * server ;
593+ LIST_HEAD (layout_list );
521594
522595 spin_lock (& clp -> cl_lock );
523596 rcu_read_lock ();
597+ restart :
524598 list_for_each_entry_rcu (server , & clp -> cl_superblocks , client_link ) {
525- if (!list_empty (& server -> layouts ))
526- list_splice_init (& server -> layouts , & tmp_list );
599+ if (memcmp (& server -> fsid , fsid , sizeof (* fsid )) != 0 )
600+ continue ;
601+ if (pnfs_layout_bulk_destroy_byserver_locked (clp ,
602+ server ,
603+ & layout_list ) != 0 )
604+ goto restart ;
527605 }
528606 rcu_read_unlock ();
529607 spin_unlock (& clp -> cl_lock );
530608
531- while (!list_empty (& tmp_list )) {
532- lo = list_entry (tmp_list .next , struct pnfs_layout_hdr ,
533- plh_layouts );
534- dprintk ("%s freeing layout for inode %lu\n" , __func__ ,
535- lo -> plh_inode -> i_ino );
536- list_del_init (& lo -> plh_layouts );
537- pnfs_destroy_layout (NFS_I (lo -> plh_inode ));
609+ if (list_empty (& layout_list ))
610+ return 0 ;
611+ return pnfs_layout_free_bulk_destroy_list (& layout_list , is_recall );
612+ }
613+
614+ int
615+ pnfs_destroy_layouts_byclid (struct nfs_client * clp ,
616+ bool is_recall )
617+ {
618+ struct nfs_server * server ;
619+ LIST_HEAD (layout_list );
620+
621+ spin_lock (& clp -> cl_lock );
622+ rcu_read_lock ();
623+ restart :
624+ list_for_each_entry_rcu (server , & clp -> cl_superblocks , client_link ) {
625+ if (pnfs_layout_bulk_destroy_byserver_locked (clp ,
626+ server ,
627+ & layout_list ) != 0 )
628+ goto restart ;
538629 }
630+ rcu_read_unlock ();
631+ spin_unlock (& clp -> cl_lock );
632+
633+ if (list_empty (& layout_list ))
634+ return 0 ;
635+ return pnfs_layout_free_bulk_destroy_list (& layout_list , is_recall );
636+ }
637+
638+ /*
639+ * Called by the state manger to remove all layouts established under an
640+ * expired lease.
641+ */
642+ void
643+ pnfs_destroy_all_layouts (struct nfs_client * clp )
644+ {
645+ nfs4_deviceid_mark_client_invalid (clp );
646+ nfs4_deviceid_purge_client (clp );
647+
648+ pnfs_destroy_layouts_byclid (clp , false);
539649}
540650
541651/*
@@ -888,7 +998,7 @@ alloc_init_layout_hdr(struct inode *ino,
888998 atomic_set (& lo -> plh_refcount , 1 );
889999 INIT_LIST_HEAD (& lo -> plh_layouts );
8901000 INIT_LIST_HEAD (& lo -> plh_segs );
891- INIT_LIST_HEAD (& lo -> plh_bulk_recall );
1001+ INIT_LIST_HEAD (& lo -> plh_bulk_destroy );
8921002 lo -> plh_inode = ino ;
8931003 lo -> plh_lc_cred = get_rpccred (ctx -> state -> owner -> so_cred );
8941004 return lo ;
0 commit comments