@@ -180,7 +180,7 @@ static int uverbs_destroy_uobject(struct ib_uobject *uobj,
180
180
assert_uverbs_usecnt (uobj , UVERBS_LOOKUP_WRITE );
181
181
182
182
if (uobj -> object ) {
183
- ret = uobj -> type -> type_class -> remove_commit (uobj , reason );
183
+ ret = uobj -> type -> type_class -> destroy_hw (uobj , reason );
184
184
if (ret ) {
185
185
if (ib_is_destroy_retryable (ret , reason , uobj ))
186
186
return ret ;
@@ -204,10 +204,13 @@ static int uverbs_destroy_uobject(struct ib_uobject *uobj,
204
204
205
205
/*
206
206
* For DESTROY the usecnt is held write locked, the caller is expected
207
- * to put it unlock and put the object when done with it.
207
+ * to put it unlock and put the object when done with it. Only DESTROY
208
+ * can remove the IDR handle.
208
209
*/
209
210
if (reason != RDMA_REMOVE_DESTROY )
210
211
atomic_set (& uobj -> usecnt , 0 );
212
+ else
213
+ uobj -> type -> type_class -> remove_handle (uobj );
211
214
212
215
if (!list_empty (& uobj -> list )) {
213
216
spin_lock_irqsave (& ufile -> uobjects_lock , flags );
@@ -554,8 +557,8 @@ static void alloc_abort_idr_uobject(struct ib_uobject *uobj)
554
557
spin_unlock (& uobj -> ufile -> idr_lock );
555
558
}
556
559
557
- static int __must_check remove_commit_idr_uobject (struct ib_uobject * uobj ,
558
- enum rdma_remove_reason why )
560
+ static int __must_check destroy_hw_idr_uobject (struct ib_uobject * uobj ,
561
+ enum rdma_remove_reason why )
559
562
{
560
563
const struct uverbs_obj_idr_type * idr_type =
561
564
container_of (uobj -> type , struct uverbs_obj_idr_type ,
@@ -573,20 +576,28 @@ static int __must_check remove_commit_idr_uobject(struct ib_uobject *uobj,
573
576
if (why == RDMA_REMOVE_ABORT )
574
577
return 0 ;
575
578
576
- alloc_abort_idr_uobject (uobj );
577
- /* Matches the kref in alloc_commit_idr_uobject */
578
- uverbs_uobject_put (uobj );
579
+ ib_rdmacg_uncharge (& uobj -> cg_obj , uobj -> context -> device ,
580
+ RDMACG_RESOURCE_HCA_OBJECT );
579
581
580
582
return 0 ;
581
583
}
582
584
585
+ static void remove_handle_idr_uobject (struct ib_uobject * uobj )
586
+ {
587
+ spin_lock (& uobj -> ufile -> idr_lock );
588
+ idr_remove (& uobj -> ufile -> idr , uobj -> id );
589
+ spin_unlock (& uobj -> ufile -> idr_lock );
590
+ /* Matches the kref in alloc_commit_idr_uobject */
591
+ uverbs_uobject_put (uobj );
592
+ }
593
+
583
594
static void alloc_abort_fd_uobject (struct ib_uobject * uobj )
584
595
{
585
596
put_unused_fd (uobj -> id );
586
597
}
587
598
588
- static int __must_check remove_commit_fd_uobject (struct ib_uobject * uobj ,
589
- enum rdma_remove_reason why )
599
+ static int __must_check destroy_hw_fd_uobject (struct ib_uobject * uobj ,
600
+ enum rdma_remove_reason why )
590
601
{
591
602
const struct uverbs_obj_fd_type * fd_type =
592
603
container_of (uobj -> type , struct uverbs_obj_fd_type , type );
@@ -598,6 +609,10 @@ static int __must_check remove_commit_fd_uobject(struct ib_uobject *uobj,
598
609
return 0 ;
599
610
}
600
611
612
+ static void remove_handle_fd_uobject (struct ib_uobject * uobj )
613
+ {
614
+ }
615
+
601
616
static int alloc_commit_idr_uobject (struct ib_uobject * uobj )
602
617
{
603
618
struct ib_uverbs_file * ufile = uobj -> ufile ;
@@ -741,13 +756,41 @@ void rdma_lookup_put_uobject(struct ib_uobject *uobj,
741
756
uverbs_uobject_put (uobj );
742
757
}
743
758
759
+ void setup_ufile_idr_uobject (struct ib_uverbs_file * ufile )
760
+ {
761
+ spin_lock_init (& ufile -> idr_lock );
762
+ idr_init (& ufile -> idr );
763
+ }
764
+
765
+ void release_ufile_idr_uobject (struct ib_uverbs_file * ufile )
766
+ {
767
+ struct ib_uobject * entry ;
768
+ int id ;
769
+
770
+ /*
771
+ * At this point uverbs_cleanup_ufile() is guaranteed to have run, and
772
+ * there are no HW objects left, however the IDR is still populated
773
+ * with anything that has not been cleaned up by userspace. Since the
774
+ * kref on ufile is 0, nothing is allowed to call lookup_get.
775
+ *
776
+ * This is an optimized equivalent to remove_handle_idr_uobject
777
+ */
778
+ idr_for_each_entry (& ufile -> idr , entry , id ) {
779
+ WARN_ON (entry -> object );
780
+ uverbs_uobject_put (entry );
781
+ }
782
+
783
+ idr_destroy (& ufile -> idr );
784
+ }
785
+
744
786
const struct uverbs_obj_type_class uverbs_idr_class = {
745
787
.alloc_begin = alloc_begin_idr_uobject ,
746
788
.lookup_get = lookup_get_idr_uobject ,
747
789
.alloc_commit = alloc_commit_idr_uobject ,
748
790
.alloc_abort = alloc_abort_idr_uobject ,
749
791
.lookup_put = lookup_put_idr_uobject ,
750
- .remove_commit = remove_commit_idr_uobject ,
792
+ .destroy_hw = destroy_hw_idr_uobject ,
793
+ .remove_handle = remove_handle_idr_uobject ,
751
794
/*
752
795
* When we destroy an object, we first just lock it for WRITE and
753
796
* actually DESTROY it in the finalize stage. So, the problematic
@@ -945,7 +988,8 @@ const struct uverbs_obj_type_class uverbs_fd_class = {
945
988
.alloc_commit = alloc_commit_fd_uobject ,
946
989
.alloc_abort = alloc_abort_fd_uobject ,
947
990
.lookup_put = lookup_put_fd_uobject ,
948
- .remove_commit = remove_commit_fd_uobject ,
991
+ .destroy_hw = destroy_hw_fd_uobject ,
992
+ .remove_handle = remove_handle_fd_uobject ,
949
993
.needs_kfree_rcu = false,
950
994
};
951
995
EXPORT_SYMBOL (uverbs_fd_class );
0 commit comments