From mboxrd@z Thu Jan 1 00:00:00 1970 From: Claude Code Review Bot To: dri-devel-reviews@example.com Subject: Claude review: rust: drm: gem: Introduce shmem::Object::sg_table() Date: Thu, 04 Jun 2026 12:29:54 +1000 Message-ID: In-Reply-To: <20260602172807.1051806-7-lyude@redhat.com> References: <20260602172807.1051806-1-lyude@redhat.com> <20260602172807.1051806-7-lyude@redhat.com> X-Mailer: Claude Code Patch Reviewer Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Patch Review The most complex patch. Several observations: **Missing C-side function**: `SGTableMap::drop` calls: ```rust unsafe { bindings::__drm_gem_shmem_free_sgt_locked(obj.as_raw_shmem()) }; ``` This function does not exist in the current drm-next tree. It presumably li= ves in the "first half" of the series already pushed to drm-rust-next. If i= t's missing from the base, this won't compile. This should be verified agai= nst the actual base tree. **Import restructuring**: The patch changes `device` from `crate::drm::devi= ce` to `crate::device`: ```rust + device::{ + self, + Bound, // + }, drm::{ + driver, + gem, + private::Sealed, Device, // }, ``` This changes the meaning of `device::Device` in the existing `de= v()` method. On the actual drm-rust-next base, this may already be reconcil= ed. Worth verifying. **Double-checked locking in `sg_table()`**: The pattern is correct: ```rust if let Some(sgt_res) =3D self.sgt_res.as_ref() { // fast path (Acquire) break 'out sgt_res; } let _guard =3D self.sgt_lock.lock(); // slow path if let Some(sgt_res) =3D self.sgt_res.as_ref() { // re-check break 'out sgt_res; } self.sgt_res.populate(...); // Release ``` The `SetOnce` uses `Acquire` on read and `Release` on write, which provides= the necessary happens-before guarantees for the double-checked locking pat= tern. **SGTableMap lifetime safety**: `SGTableMap` holds `NonNull>` wit= hout an `ARef`: ```rust pub struct SGTableMap { obj: NonNull>, } ``` This is safe because `SGTableMap` is stored inside the `Object` itself (= via `sgt_res`), so the object outlives the mapping. The `free_callback` exp= licitly resets `sgt_res` before releasing the GEM object: ```rust unsafe { &mut (*this).sgt_res }.reset(); // drops SGTableMap first unsafe { bindings::drm_gem_shmem_release(base) }; // then releases GEM let _ =3D unsafe { KBox::from_raw(this) }; // then frees memory ``` This ordering is correct and critical. **Device identity check**: ```rust if dev.as_raw() !=3D self.dev().as_ref().as_raw() { return Err(EINVAL); } ``` Comparing raw device pointers to verify the caller passed the correct devic= e is a good defensive check. The test `fail_sg_table_on_wrong_dev` verifies= this works. **`SGTableMap::new` discards the sg_table pointer**: ```rust fn new(obj: &Object) -> impl Init { from_err_ptr(unsafe { bindings::drm_gem_shmem_get_pages_sgt(obj.as_raw_= shmem()) })?; Ok(Self { obj: obj.into() }) } ``` The returned `sg_table*` is discarded. This is correct because `drm_gem_shm= em_get_pages_sgt` stores the SGT internally in `shmem->sgt`, which is what = `SGTableMap::deref` reads later. **Minor style**: The `#[pin]` attribute appears before the doc comment on `= sgt_lock`: ```rust + #[pin] + /// Lock for protecting initialization of `sgt_res`. + sgt_lock: Mutex<()>, ``` Convention is doc comments before attributes, though both orderings are val= id Rust. **Test coverage**: The `fail_sg_table_on_wrong_dev` test is good but limite= d =E2=80=94 as the TODOs note, testing the success path requires mock DMA o= ps. The comment is honest about this limitation, which is appreciated. --- Generated by Claude Code Patch Reviewer