@@ -129,6 +129,95 @@ static int uverbs_try_lock_object(struct ib_uobject *uobj, bool exclusive)
129
129
return atomic_cmpxchg (& uobj -> usecnt , 0 , -1 ) == 0 ? 0 : - EBUSY ;
130
130
}
131
131
132
+ static void assert_uverbs_usecnt (struct ib_uobject * uobj , bool exclusive )
133
+ {
134
+ #ifdef CONFIG_LOCKDEP
135
+ if (exclusive )
136
+ WARN_ON (atomic_read (& uobj -> usecnt ) != -1 );
137
+ else
138
+ WARN_ON (atomic_read (& uobj -> usecnt ) <= 0 );
139
+ #endif
140
+ }
141
+
142
+ /*
143
+ * This must be called with the hw_destroy_rwsem locked (except for
144
+ * RDMA_REMOVE_ABORT) for read or write, also The uobject itself must be
145
+ * locked for write.
146
+ *
147
+ * Upon return the HW object is guaranteed to be destroyed.
148
+ *
149
+ * For RDMA_REMOVE_ABORT, the hw_destroy_rwsem is not required to be held,
150
+ * however the type's allocat_commit function cannot have been called and the
151
+ * uobject cannot be on the uobjects_lists
152
+ *
153
+ * For RDMA_REMOVE_DESTROY the caller shold be holding a kref (eg via
154
+ * rdma_lookup_get_uobject) and the object is left in a state where the caller
155
+ * needs to call rdma_lookup_put_uobject.
156
+ *
157
+ * For all other destroy modes this function internally unlocks the uobject
158
+ * and consumes the kref on the uobj.
159
+ */
160
+ static int uverbs_destroy_uobject (struct ib_uobject * uobj ,
161
+ enum rdma_remove_reason reason )
162
+ {
163
+ struct ib_uverbs_file * ufile = uobj -> ufile ;
164
+ unsigned long flags ;
165
+ int ret ;
166
+
167
+ assert_uverbs_usecnt (uobj , true);
168
+
169
+ if (uobj -> object ) {
170
+ ret = uobj -> type -> type_class -> remove_commit (uobj , reason );
171
+ if (ret ) {
172
+ if (ib_is_destroy_retryable (ret , reason , uobj ))
173
+ return ret ;
174
+
175
+ /* Nothing to be done, dangle the memory and move on */
176
+ WARN (true,
177
+ "ib_uverbs: failed to remove uobject id %d, driver err=%d" ,
178
+ uobj -> id , ret );
179
+ }
180
+
181
+ uobj -> object = NULL ;
182
+ }
183
+
184
+ if (reason == RDMA_REMOVE_ABORT ) {
185
+ WARN_ON (!list_empty (& uobj -> list ));
186
+ WARN_ON (!uobj -> context );
187
+ uobj -> type -> type_class -> alloc_abort (uobj );
188
+ }
189
+
190
+ uobj -> context = NULL ;
191
+
192
+ /*
193
+ * For DESTROY the usecnt is held write locked, the caller is expected
194
+ * to put it unlock and put the object when done with it.
195
+ */
196
+ if (reason != RDMA_REMOVE_DESTROY )
197
+ atomic_set (& uobj -> usecnt , 0 );
198
+
199
+ if (!list_empty (& uobj -> list )) {
200
+ spin_lock_irqsave (& ufile -> uobjects_lock , flags );
201
+ list_del_init (& uobj -> list );
202
+ spin_unlock_irqrestore (& ufile -> uobjects_lock , flags );
203
+
204
+ /*
205
+ * Pairs with the get in rdma_alloc_commit_uobject(), could
206
+ * destroy uobj.
207
+ */
208
+ uverbs_uobject_put (uobj );
209
+ }
210
+
211
+ /*
212
+ * When aborting the stack kref remains owned by the core code, and is
213
+ * not transferred into the type. Pairs with the get in alloc_uobj
214
+ */
215
+ if (reason == RDMA_REMOVE_ABORT )
216
+ uverbs_uobject_put (uobj );
217
+
218
+ return 0 ;
219
+ }
220
+
132
221
/*
133
222
* uobj_get_destroy destroys the HW object and returns a handle to the uobj
134
223
* with a NULL object pointer. The caller must pair this with
@@ -171,6 +260,7 @@ int __uobj_perform_destroy(const struct uverbs_obj_type *type, u32 id,
171
260
return success_res ;
172
261
}
173
262
263
+ /* alloc_uobj must be undone by uverbs_destroy_uobject() */
174
264
static struct ib_uobject * alloc_uobj (struct ib_uverbs_file * ufile ,
175
265
const struct uverbs_obj_type * type )
176
266
{
@@ -379,6 +469,16 @@ struct ib_uobject *rdma_alloc_begin_uobject(const struct uverbs_obj_type *type,
379
469
return type -> type_class -> alloc_begin (type , ufile );
380
470
}
381
471
472
+ static void alloc_abort_idr_uobject (struct ib_uobject * uobj )
473
+ {
474
+ ib_rdmacg_uncharge (& uobj -> cg_obj , uobj -> context -> device ,
475
+ RDMACG_RESOURCE_HCA_OBJECT );
476
+
477
+ spin_lock (& uobj -> ufile -> idr_lock );
478
+ idr_remove (& uobj -> ufile -> idr , uobj -> id );
479
+ spin_unlock (& uobj -> ufile -> idr_lock );
480
+ }
481
+
382
482
static int __must_check remove_commit_idr_uobject (struct ib_uobject * uobj ,
383
483
enum rdma_remove_reason why )
384
484
{
@@ -395,25 +495,19 @@ static int __must_check remove_commit_idr_uobject(struct ib_uobject *uobj,
395
495
if (ib_is_destroy_retryable (ret , why , uobj ))
396
496
return ret ;
397
497
398
- ib_rdmacg_uncharge (& uobj -> cg_obj , uobj -> context -> device ,
399
- RDMACG_RESOURCE_HCA_OBJECT );
400
-
401
- spin_lock (& uobj -> ufile -> idr_lock );
402
- idr_remove (& uobj -> ufile -> idr , uobj -> id );
403
- spin_unlock (& uobj -> ufile -> idr_lock );
498
+ if (why == RDMA_REMOVE_ABORT )
499
+ return 0 ;
404
500
501
+ alloc_abort_idr_uobject (uobj );
405
502
/* Matches the kref in alloc_commit_idr_uobject */
406
503
uverbs_uobject_put (uobj );
407
504
408
- return ret ;
505
+ return 0 ;
409
506
}
410
507
411
508
static void alloc_abort_fd_uobject (struct ib_uobject * uobj )
412
509
{
413
510
put_unused_fd (uobj -> id );
414
-
415
- /* Pairs with the kref from alloc_begin_idr_uobject */
416
- uverbs_uobject_put (uobj );
417
511
}
418
512
419
513
static int __must_check remove_commit_fd_uobject (struct ib_uobject * uobj ,
@@ -426,47 +520,7 @@ static int __must_check remove_commit_fd_uobject(struct ib_uobject *uobj,
426
520
if (ib_is_destroy_retryable (ret , why , uobj ))
427
521
return ret ;
428
522
429
- if (why == RDMA_REMOVE_DURING_CLEANUP ) {
430
- alloc_abort_fd_uobject (uobj );
431
- return ret ;
432
- }
433
-
434
- uobj -> context = NULL ;
435
- return ret ;
436
- }
437
-
438
- static void assert_uverbs_usecnt (struct ib_uobject * uobj , bool exclusive )
439
- {
440
- #ifdef CONFIG_LOCKDEP
441
- if (exclusive )
442
- WARN_ON (atomic_read (& uobj -> usecnt ) != -1 );
443
- else
444
- WARN_ON (atomic_read (& uobj -> usecnt ) <= 0 );
445
- #endif
446
- }
447
-
448
- static int __must_check _rdma_remove_commit_uobject (struct ib_uobject * uobj ,
449
- enum rdma_remove_reason why )
450
- {
451
- struct ib_uverbs_file * ufile = uobj -> ufile ;
452
- int ret ;
453
-
454
- if (!uobj -> object )
455
- return 0 ;
456
-
457
- ret = uobj -> type -> type_class -> remove_commit (uobj , why );
458
- if (ib_is_destroy_retryable (ret , why , uobj ))
459
- return ret ;
460
-
461
- uobj -> object = NULL ;
462
-
463
- spin_lock_irq (& ufile -> uobjects_lock );
464
- list_del (& uobj -> list );
465
- spin_unlock_irq (& ufile -> uobjects_lock );
466
- /* Pairs with the get in rdma_alloc_commit_uobject() */
467
- uverbs_uobject_put (uobj );
468
-
469
- return ret ;
523
+ return 0 ;
470
524
}
471
525
472
526
int rdma_explicit_destroy (struct ib_uobject * uobject )
@@ -479,8 +533,8 @@ int rdma_explicit_destroy(struct ib_uobject *uobject)
479
533
WARN (true, "ib_uverbs: Cleanup is running while removing an uobject\n" );
480
534
return 0 ;
481
535
}
482
- assert_uverbs_usecnt ( uobject , true);
483
- ret = _rdma_remove_commit_uobject (uobject , RDMA_REMOVE_DESTROY );
536
+
537
+ ret = uverbs_destroy_uobject (uobject , RDMA_REMOVE_DESTROY );
484
538
485
539
up_read (& ufile -> hw_destroy_rwsem );
486
540
return ret ;
@@ -554,24 +608,14 @@ int __must_check rdma_alloc_commit_uobject(struct ib_uobject *uobj)
554
608
/* Cleanup is running. Calling this should have been impossible */
555
609
if (!down_read_trylock (& ufile -> hw_destroy_rwsem )) {
556
610
WARN (true, "ib_uverbs: Cleanup is running while allocating an uobject\n" );
557
- ret = uobj -> type -> type_class -> remove_commit (uobj ,
558
- RDMA_REMOVE_DURING_CLEANUP );
559
- if (ret )
560
- pr_warn ("ib_uverbs: cleanup of idr object %d failed\n" ,
561
- uobj -> id );
562
- return ret ;
611
+ uverbs_destroy_uobject (uobj , RDMA_REMOVE_ABORT );
612
+ return - EINVAL ;
563
613
}
564
614
565
- assert_uverbs_usecnt (uobj , true);
566
-
567
615
/* alloc_commit consumes the uobj kref */
568
616
ret = uobj -> type -> type_class -> alloc_commit (uobj );
569
617
if (ret ) {
570
- if (uobj -> type -> type_class -> remove_commit (
571
- uobj , RDMA_REMOVE_DURING_CLEANUP ))
572
- pr_warn ("ib_uverbs: cleanup of idr object %d failed\n" ,
573
- uobj -> id );
574
- up_read (& ufile -> hw_destroy_rwsem );
618
+ uverbs_destroy_uobject (uobj , RDMA_REMOVE_ABORT );
575
619
return ret ;
576
620
}
577
621
@@ -589,27 +633,14 @@ int __must_check rdma_alloc_commit_uobject(struct ib_uobject *uobj)
589
633
return 0 ;
590
634
}
591
635
592
- static void alloc_abort_idr_uobject (struct ib_uobject * uobj )
593
- {
594
- ib_rdmacg_uncharge (& uobj -> cg_obj , uobj -> context -> device ,
595
- RDMACG_RESOURCE_HCA_OBJECT );
596
-
597
- spin_lock (& uobj -> ufile -> idr_lock );
598
- /* The value of the handle in the IDR is NULL at this point. */
599
- idr_remove (& uobj -> ufile -> idr , uobj -> id );
600
- spin_unlock (& uobj -> ufile -> idr_lock );
601
-
602
- /* Pairs with the kref from alloc_begin_idr_uobject */
603
- uverbs_uobject_put (uobj );
604
- }
605
-
606
636
/*
607
637
* This consumes the kref for uobj. It is up to the caller to unwind the HW
608
638
* object and anything else connected to uobj before calling this.
609
639
*/
610
640
void rdma_alloc_abort_uobject (struct ib_uobject * uobj )
611
641
{
612
- uobj -> type -> type_class -> alloc_abort (uobj );
642
+ uobj -> object = NULL ;
643
+ uverbs_destroy_uobject (uobj , RDMA_REMOVE_ABORT );
613
644
}
614
645
615
646
static void lookup_put_idr_uobject (struct ib_uobject * uobj , bool exclusive )
@@ -667,45 +698,23 @@ const struct uverbs_obj_type_class uverbs_idr_class = {
667
698
};
668
699
EXPORT_SYMBOL (uverbs_idr_class );
669
700
670
- static void _uverbs_close_fd (struct ib_uobject * uobj )
671
- {
672
- int ret ;
673
-
674
- /*
675
- * uobject was already cleaned up, remove_commit_fd_uobject
676
- * sets this
677
- */
678
- if (!uobj -> context )
679
- return ;
680
-
681
- /*
682
- * lookup_get_fd_uobject holds the kref on the struct file any time a
683
- * FD uobj is locked, which prevents this release method from being
684
- * invoked. Meaning we can always get the write lock here, or we have
685
- * a kernel bug. If so dangle the pointers and bail.
686
- */
687
- ret = uverbs_try_lock_object (uobj , true);
688
- if (WARN (ret , "uverbs_close_fd() racing with lookup_get_fd_uobject()" ))
689
- return ;
690
-
691
- ret = _rdma_remove_commit_uobject (uobj , RDMA_REMOVE_CLOSE );
692
- if (ret )
693
- pr_warn ("Unable to clean up uobject file in %s\n" , __func__ );
694
-
695
- atomic_set (& uobj -> usecnt , 0 );
696
- }
697
-
698
701
void uverbs_close_fd (struct file * f )
699
702
{
700
703
struct ib_uobject * uobj = f -> private_data ;
701
704
struct ib_uverbs_file * ufile = uobj -> ufile ;
702
705
703
706
if (down_read_trylock (& ufile -> hw_destroy_rwsem )) {
704
- _uverbs_close_fd (uobj );
707
+ /*
708
+ * lookup_get_fd_uobject holds the kref on the struct file any
709
+ * time a FD uobj is locked, which prevents this release
710
+ * method from being invoked. Meaning we can always get the
711
+ * write lock here, or we have a kernel bug.
712
+ */
713
+ WARN_ON (uverbs_try_lock_object (uobj , true));
714
+ uverbs_destroy_uobject (uobj , RDMA_REMOVE_CLOSE );
705
715
up_read (& ufile -> hw_destroy_rwsem );
706
716
}
707
717
708
- uobj -> object = NULL ;
709
718
/* Matches the get in alloc_begin_fd_uobject */
710
719
kref_put (& ufile -> ref , ib_uverbs_release_file );
711
720
@@ -783,7 +792,6 @@ static int __uverbs_cleanup_ufile(struct ib_uverbs_file *ufile,
783
792
{
784
793
struct ib_uobject * obj , * next_obj ;
785
794
int ret = - EINVAL ;
786
- int err = 0 ;
787
795
788
796
/*
789
797
* This shouldn't run while executing other commands on this
@@ -800,23 +808,8 @@ static int __uverbs_cleanup_ufile(struct ib_uverbs_file *ufile,
800
808
* racing with a lookup_get.
801
809
*/
802
810
WARN_ON (uverbs_try_lock_object (obj , true));
803
- err = obj -> type -> type_class -> remove_commit (obj , reason );
804
-
805
- if (ib_is_destroy_retryable (err , reason , obj )) {
806
- pr_debug ("ib_uverbs: failed to remove uobject id %d err %d\n" ,
807
- obj -> id , err );
808
- atomic_set (& obj -> usecnt , 0 );
809
- continue ;
810
- }
811
-
812
- if (err )
813
- pr_err ("ib_uverbs: unable to remove uobject id %d err %d\n" ,
814
- obj -> id , err );
815
-
816
- list_del (& obj -> list );
817
- /* Pairs with the get in rdma_alloc_commit_uobject() */
818
- uverbs_uobject_put (obj );
819
- ret = 0 ;
811
+ if (!uverbs_destroy_uobject (obj , reason ))
812
+ ret = 0 ;
820
813
}
821
814
return ret ;
822
815
}
0 commit comments