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::SGTable Date: Thu, 23 Apr 2026 08:09:06 +1000 Message-ID: In-Reply-To: <20260421234234.638503-5-lyude@redhat.com> References: <20260421234234.638503-1-lyude@redhat.com> <20260421234234.638503-5-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 This is the most complex patch. Several observations: **1. `SGTableMap` holds a raw `NonNull` without a refcount:** ```rust pub struct SGTableMap { obj: NonNull>, } ``` This is initialized from `self.into()` which for `&Object` creates a `No= nNull` from the reference. The `SGTableMap` is stored inside a `Devres` whi= ch is stored in an `UnsafeCell` on the `Object` itself. So the `SGTableM= ap` points back to its owning object. This creates a self-referential struc= ture. It should be safe because: - The `Devres>` is stored in the `Object` itself via `sgt_= res` - The `Devres` will be dropped before `obj` (field ordering guarantees this= as of patch 5) However, in patch 4, the field ordering is: ```rust pub struct Object { obj: Opaque, parent_resv_obj: Option>>, sgt_res: UnsafeCell>>>, inner: T, } ``` Here `sgt_res` is *after* `obj`, meaning `obj` would be dropped first, whic= h could be problematic. This is fixed in patch 5 which moves `sgt_res` to t= he top. **This means patches 4 and 5 must not be applied independently** = =E2=80=94 patch 4 in isolation has incorrect field drop ordering. **2. Lock/unlock pattern in `get_sg_table` doesn't use RAII guards:** ```rust unsafe { bindings::dma_resv_lock(self.raw_dma_resv(), ptr::null_mut()) }; // ... lots of code with multiple return paths ... unsafe { bindings::dma_resv_unlock(self.raw_dma_resv()) }; ``` The code between lock and unlock assigns to `ret` and then unlocks after. T= his is correct because `ret` captures all exit paths, but it's fragile =E2= =80=94 any early return would deadlock. The TODO at the top of the file ack= nowledges this limitation. **3. `get_sg_table` returns a reference to a Devres stored in the UnsafeCel= l:** ```rust fn get_sg_table<'a>( &'a self, dev: &'a device::Device, ) -> Result<&'a Devres>> { ``` The returned reference's lifetime is tied to `&'a self`, which is correct. = The `UnsafeCell` access is protected by the dma_resv lock during the initia= lization phase, and subsequent reads return the already-initialized value. = This is sound because the `Option>` goes from `None` to `Some` = exactly once and never goes back. **4. The `SGTableMap::Drop` acquires the dma_resv lock:** ```rust impl Drop for SGTableMap { fn drop(&mut self) { let obj =3D unsafe { self.obj.as_ref() }; unsafe { bindings::dma_resv_lock(obj.raw_dma_resv(), ptr::null_mut(= )) }; unsafe { bindings::__drm_gem_shmem_free_sgt_locked(obj.as_raw_shmem= ()) }; unsafe { bindings::dma_resv_unlock(obj.raw_dma_resv()) }; } } ``` This will be called from the devres callback on driver unbind. At that poin= t, taking the dma_resv lock should be fine since the driver is being unboun= d. However, it could also be dropped during normal Object cleanup when the = Object is freed. In `free_callback`, `drm_gem_shmem_release()` is called fi= rst (which already handles the sgt under lock), then the `KBox::from_raw` d= rops the Rust fields including `sgt_res`. If `drm_gem_shmem_release()` alre= ady freed the sgt (setting `shmem->sgt =3D NULL`), then the devres is still= `Some(...)` but the `SGTableMap::drop` will call `__drm_gem_shmem_free_sgt= _locked` on a NULL sgt =E2=80=94 **linking back to the concern in patch 2 a= bout the missing NULL check**. Actually, looking more carefully: the `Devres` drop path would revoke the `= Revocable`, which may or may not call `SGTableMap::drop`. If the devres = callback already fired (device unbind happened), the `Revocable` is already= revoked, so dropping the `Devres` won't drop the inner `SGTableMap` again.= But if device unbind hasn't happened yet, the `Devres::drop` would call `d= evm_remove_action_nowarn` and then drop the `Arc>`. This needs= careful analysis of the ordering between `drm_gem_shmem_release` (called i= n `free_callback`) and the devres/`sgt_res` drop. This is a subtle interaction that deserves either a safety comment or a res= tructuring to make the ordering explicit. --- --- Generated by Claude Code Patch Reviewer