@@ -130,7 +130,11 @@ static int uverbs_destroy_uobject(struct ib_uobject *uobj,
130130 lockdep_assert_held (& ufile -> hw_destroy_rwsem );
131131 assert_uverbs_usecnt (uobj , UVERBS_LOOKUP_WRITE );
132132
133- if (uobj -> object ) {
133+ if (reason == RDMA_REMOVE_ABORT ) {
134+ WARN_ON (!list_empty (& uobj -> list ));
135+ WARN_ON (!uobj -> context );
136+ uobj -> uapi_object -> type_class -> alloc_abort (uobj );
137+ } else if (uobj -> object ) {
134138 ret = uobj -> uapi_object -> type_class -> destroy_hw (uobj , reason ,
135139 attrs );
136140 if (ret ) {
@@ -146,12 +150,6 @@ static int uverbs_destroy_uobject(struct ib_uobject *uobj,
146150 uobj -> object = NULL ;
147151 }
148152
149- if (reason == RDMA_REMOVE_ABORT ) {
150- WARN_ON (!list_empty (& uobj -> list ));
151- WARN_ON (!uobj -> context );
152- uobj -> uapi_object -> type_class -> alloc_abort (uobj );
153- }
154-
155153 uobj -> context = NULL ;
156154
157155 /*
@@ -450,22 +448,40 @@ static struct ib_uobject *
450448alloc_begin_fd_uobject (const struct uverbs_api_object * obj ,
451449 struct ib_uverbs_file * ufile )
452450{
451+ const struct uverbs_obj_fd_type * fd_type =
452+ container_of (obj -> type_attrs , struct uverbs_obj_fd_type , type );
453453 int new_fd ;
454454 struct ib_uobject * uobj ;
455+ struct file * filp ;
456+
457+ if (WARN_ON (fd_type -> fops -> release != & uverbs_uobject_fd_release ))
458+ return ERR_PTR (- EINVAL );
455459
456460 new_fd = get_unused_fd_flags (O_CLOEXEC );
457461 if (new_fd < 0 )
458462 return ERR_PTR (new_fd );
459463
460464 uobj = alloc_uobj (ufile , obj );
461- if (IS_ERR (uobj )) {
462- put_unused_fd (new_fd );
463- return uobj ;
465+ if (IS_ERR (uobj ))
466+ goto err_fd ;
467+
468+ /* Note that uverbs_uobject_fd_release() is called during abort */
469+ filp = anon_inode_getfile (fd_type -> name , fd_type -> fops , NULL ,
470+ fd_type -> flags );
471+ if (IS_ERR (filp )) {
472+ uobj = ERR_CAST (filp );
473+ goto err_uobj ;
464474 }
475+ uobj -> object = filp ;
465476
466477 uobj -> id = new_fd ;
467478 uobj -> ufile = ufile ;
479+ return uobj ;
468480
481+ err_uobj :
482+ uverbs_uobject_put (uobj );
483+ err_fd :
484+ put_unused_fd (new_fd );
469485 return uobj ;
470486}
471487
@@ -539,6 +555,9 @@ static void remove_handle_idr_uobject(struct ib_uobject *uobj)
539555
540556static void alloc_abort_fd_uobject (struct ib_uobject * uobj )
541557{
558+ struct file * filp = uobj -> object ;
559+
560+ fput (filp );
542561 put_unused_fd (uobj -> id );
543562}
544563
@@ -560,7 +579,7 @@ static void remove_handle_fd_uobject(struct ib_uobject *uobj)
560579{
561580}
562581
563- static int alloc_commit_idr_uobject (struct ib_uobject * uobj )
582+ static void alloc_commit_idr_uobject (struct ib_uobject * uobj )
564583{
565584 struct ib_uverbs_file * ufile = uobj -> ufile ;
566585 void * old ;
@@ -574,31 +593,12 @@ static int alloc_commit_idr_uobject(struct ib_uobject *uobj)
574593 */
575594 old = xa_store (& ufile -> idr , uobj -> id , uobj , GFP_KERNEL );
576595 WARN_ON (old != NULL );
577-
578- return 0 ;
579596}
580597
581- static int alloc_commit_fd_uobject (struct ib_uobject * uobj )
598+ static void alloc_commit_fd_uobject (struct ib_uobject * uobj )
582599{
583- const struct uverbs_obj_fd_type * fd_type = container_of (
584- uobj -> uapi_object -> type_attrs , struct uverbs_obj_fd_type , type );
585600 int fd = uobj -> id ;
586- struct file * filp ;
587-
588- /*
589- * The kref for uobj is moved into filp->private data and put in
590- * uverbs_close_fd(). Once alloc_commit() succeeds
591- * uverbs_uobject_fd_release() must be guaranteed to be called from
592- * the provided fops release callback.
593- */
594- filp = anon_inode_getfile (fd_type -> name ,
595- fd_type -> fops ,
596- uobj ,
597- fd_type -> flags );
598- if (IS_ERR (filp ))
599- return PTR_ERR (filp );
600-
601- uobj -> object = filp ;
601+ struct file * filp = uobj -> object ;
602602
603603 /* Matching put will be done in uverbs_uobject_fd_release() */
604604 kref_get (& uobj -> ufile -> ref );
@@ -610,29 +610,22 @@ static int alloc_commit_fd_uobject(struct ib_uobject *uobj)
610610 * NOTE: Once we install the file we loose ownership of our kref on
611611 * uobj. It will be put by uverbs_uobject_fd_release()
612612 */
613+ filp -> private_data = uobj ;
613614 fd_install (fd , filp );
614-
615- return 0 ;
616615}
617616
618617/*
619618 * In all cases rdma_alloc_commit_uobject() consumes the kref to uobj and the
620619 * caller can no longer assume uobj is valid. If this function fails it
621620 * destroys the uboject, including the attached HW object.
622621 */
623- int __must_check rdma_alloc_commit_uobject (struct ib_uobject * uobj ,
624- struct uverbs_attr_bundle * attrs )
622+ void rdma_alloc_commit_uobject (struct ib_uobject * uobj ,
623+ struct uverbs_attr_bundle * attrs )
625624{
626625 struct ib_uverbs_file * ufile = attrs -> ufile ;
627- int ret ;
628626
629627 /* alloc_commit consumes the uobj kref */
630- ret = uobj -> uapi_object -> type_class -> alloc_commit (uobj );
631- if (ret ) {
632- uverbs_destroy_uobject (uobj , RDMA_REMOVE_ABORT , attrs );
633- up_read (& ufile -> hw_destroy_rwsem );
634- return ret ;
635- }
628+ uobj -> uapi_object -> type_class -> alloc_commit (uobj );
636629
637630 /* kref is held so long as the uobj is on the uobj list. */
638631 uverbs_uobject_get (uobj );
@@ -645,8 +638,6 @@ int __must_check rdma_alloc_commit_uobject(struct ib_uobject *uobj,
645638
646639 /* Matches the down_read in rdma_alloc_begin_uobject */
647640 up_read (& ufile -> hw_destroy_rwsem );
648-
649- return 0 ;
650641}
651642
652643/*
@@ -658,7 +649,6 @@ void rdma_alloc_abort_uobject(struct ib_uobject *uobj,
658649{
659650 struct ib_uverbs_file * ufile = uobj -> ufile ;
660651
661- uobj -> object = NULL ;
662652 uverbs_destroy_uobject (uobj , RDMA_REMOVE_ABORT , attrs );
663653
664654 /* Matches the down_read in rdma_alloc_begin_uobject */
@@ -751,14 +741,23 @@ EXPORT_SYMBOL(uverbs_idr_class);
751741 */
752742int uverbs_uobject_fd_release (struct inode * inode , struct file * filp )
753743{
754- struct ib_uobject * uobj = filp -> private_data ;
755- struct ib_uverbs_file * ufile = uobj -> ufile ;
756- struct uverbs_attr_bundle attrs = {
757- .context = uobj -> context ,
758- .ufile = ufile ,
759- };
744+ struct ib_uverbs_file * ufile ;
745+ struct ib_uobject * uobj ;
746+
747+ /*
748+ * This can only happen if the fput came from alloc_abort_fd_uobject()
749+ */
750+ if (!filp -> private_data )
751+ return 0 ;
752+ uobj = filp -> private_data ;
753+ ufile = uobj -> ufile ;
760754
761755 if (down_read_trylock (& ufile -> hw_destroy_rwsem )) {
756+ struct uverbs_attr_bundle attrs = {
757+ .context = uobj -> context ,
758+ .ufile = ufile ,
759+ };
760+
762761 /*
763762 * lookup_get_fd_uobject holds the kref on the struct file any
764763 * time a FD uobj is locked, which prevents this release
@@ -770,7 +769,7 @@ int uverbs_uobject_fd_release(struct inode *inode, struct file *filp)
770769 up_read (& ufile -> hw_destroy_rwsem );
771770 }
772771
773- /* Matches the get in alloc_begin_fd_uobject */
772+ /* Matches the get in alloc_commit_fd_uobject() */
774773 kref_put (& ufile -> ref , ib_uverbs_release_file );
775774
776775 /* Pairs with filp->private_data in alloc_begin_fd_uobject */
@@ -938,12 +937,10 @@ uverbs_get_uobject_from_file(u16 object_id, enum uverbs_obj_access access,
938937 }
939938}
940939
941- int uverbs_finalize_object (struct ib_uobject * uobj ,
942- enum uverbs_obj_access access , bool commit ,
943- struct uverbs_attr_bundle * attrs )
940+ void uverbs_finalize_object (struct ib_uobject * uobj ,
941+ enum uverbs_obj_access access , bool commit ,
942+ struct uverbs_attr_bundle * attrs )
944943{
945- int ret = 0 ;
946-
947944 /*
948945 * refcounts should be handled at the object level and not at the
949946 * uobject level. Refcounts of the objects themselves are done in
@@ -963,14 +960,11 @@ int uverbs_finalize_object(struct ib_uobject *uobj,
963960 break ;
964961 case UVERBS_ACCESS_NEW :
965962 if (commit )
966- ret = rdma_alloc_commit_uobject (uobj , attrs );
963+ rdma_alloc_commit_uobject (uobj , attrs );
967964 else
968965 rdma_alloc_abort_uobject (uobj , attrs );
969966 break ;
970967 default :
971968 WARN_ON (true);
972- ret = - EOPNOTSUPP ;
973969 }
974-
975- return ret ;
976970}
0 commit comments