Skip to content

Commit 80afe2c

Browse files
committed
Remove unsafe from write_data
With blob files gone there is no longer an invariant to maintain when writing payloads. Signed-off-by: J Robert Ray <[email protected]>
1 parent 0b6baa5 commit 80afe2c

File tree

12 files changed

+30
-100
lines changed

12 files changed

+30
-100
lines changed

crates/spfs/src/server/payload.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,11 +180,7 @@ async fn handle_uncompressed_upload(
180180
repo: Arc<storage::RepositoryHandle>,
181181
reader: Pin<Box<dyn crate::tracking::BlobRead>>,
182182
) -> crate::Result<hyper::Response<ResponseBody>> {
183-
// Safety: it is unsafe to create a payload without its corresponding
184-
// blob, but this payload http server is part of a larger repository
185-
// and does not intend to be responsible for ensuring the integrity
186-
// of the object graph - only the up/down of payload data
187-
let result = unsafe { repo.write_data(reader).await };
183+
let result = repo.write_data(reader).await;
188184
let (digest, size) = result.map_err(|err| {
189185
crate::Error::String(format!(
190186
"An error occurred while spawning a thread for this operation: {err:?}"

crates/spfs/src/storage/fallback/repository.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -284,13 +284,8 @@ impl PayloadStorage for FallbackProxy {
284284
self.primary.iter_payload_digests()
285285
}
286286

287-
async unsafe fn write_data(
288-
&self,
289-
reader: Pin<Box<dyn BlobRead>>,
290-
) -> Result<(encoding::Digest, u64)> {
291-
// Safety: we are wrapping the same underlying unsafe function and
292-
// so the same safety holds for our callers
293-
let res = unsafe { self.primary.write_data(reader).await? };
287+
async fn write_data(&self, reader: Pin<Box<dyn BlobRead>>) -> Result<(encoding::Digest, u64)> {
288+
let res = self.primary.write_data(reader).await?;
294289
Ok(res)
295290
}
296291

crates/spfs/src/storage/fs/payloads.rs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,9 @@ impl crate::storage::PayloadStorage for MaybeOpenFsRepository {
2828
.boxed()
2929
}
3030

31-
async unsafe fn write_data(
32-
&self,
33-
reader: Pin<Box<dyn BlobRead>>,
34-
) -> Result<(encoding::Digest, u64)> {
31+
async fn write_data(&self, reader: Pin<Box<dyn BlobRead>>) -> Result<(encoding::Digest, u64)> {
3532
let opened = self.opened().await?;
36-
// Safety: we are simply deferring this function to the inner
37-
// one and so the same safety rules apply to our caller
38-
unsafe { opened.write_data(reader).await }
33+
opened.write_data(reader).await
3934
}
4035

4136
async fn open_payload(
@@ -61,10 +56,7 @@ impl crate::storage::PayloadStorage for OpenFsRepository {
6156
Box::pin(self.payloads.iter())
6257
}
6358

64-
async unsafe fn write_data(
65-
&self,
66-
reader: Pin<Box<dyn BlobRead>>,
67-
) -> Result<(encoding::Digest, u64)> {
59+
async fn write_data(&self, reader: Pin<Box<dyn BlobRead>>) -> Result<(encoding::Digest, u64)> {
6860
self.payloads.write_data(reader).await
6961
}
7062

crates/spfs/src/storage/handle.rs

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -261,13 +261,8 @@ impl PayloadStorage for RepositoryHandle {
261261
each_variant!(self, repo, { repo.iter_payload_digests() })
262262
}
263263

264-
async unsafe fn write_data(
265-
&self,
266-
reader: Pin<Box<dyn BlobRead>>,
267-
) -> Result<(encoding::Digest, u64)> {
268-
// Safety: we are wrapping the same underlying unsafe function and
269-
// so the same safety holds for our callers
270-
unsafe { each_variant!(self, repo, { repo.write_data(reader).await }) }
264+
async fn write_data(&self, reader: Pin<Box<dyn BlobRead>>) -> Result<(encoding::Digest, u64)> {
265+
each_variant!(self, repo, { repo.write_data(reader).await })
271266
}
272267

273268
async fn open_payload(
@@ -436,13 +431,8 @@ impl PayloadStorage for Arc<RepositoryHandle> {
436431
each_variant!(&**self, repo, { repo.iter_payload_digests() })
437432
}
438433

439-
async unsafe fn write_data(
440-
&self,
441-
reader: Pin<Box<dyn BlobRead>>,
442-
) -> Result<(encoding::Digest, u64)> {
443-
// Safety: we are wrapping the same underlying unsafe function and
444-
// so the same safety holds for our callers
445-
unsafe { each_variant!(&**self, repo, { repo.write_data(reader).await }) }
434+
async fn write_data(&self, reader: Pin<Box<dyn BlobRead>>) -> Result<(encoding::Digest, u64)> {
435+
each_variant!(&**self, repo, { repo.write_data(reader).await })
446436
}
447437

448438
async fn open_payload(

crates/spfs/src/storage/payload.rs

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,7 @@ pub trait PayloadStorage: Sync + Send {
2323
async fn has_payload(&self, digest: encoding::Digest) -> bool;
2424

2525
/// Store the contents of the given stream, returning its digest and size
26-
///
27-
/// # Safety
28-
///
29-
/// It is unsafe to write payload data without also creating a blob
30-
/// to track that payload in the database. Usually, its better to
31-
/// call [`super::RepositoryExt::commit_payload`] instead.
32-
async unsafe fn write_data(
33-
&self,
34-
reader: Pin<Box<dyn BlobRead>>,
35-
) -> Result<(encoding::Digest, u64)>;
26+
async fn write_data(&self, reader: Pin<Box<dyn BlobRead>>) -> Result<(encoding::Digest, u64)>;
3627

3728
/// Return a handle and filename to the full content of a payload.
3829
///
@@ -60,13 +51,8 @@ impl<T: PayloadStorage> PayloadStorage for &T {
6051
PayloadStorage::iter_payload_digests(&**self)
6152
}
6253

63-
async unsafe fn write_data(
64-
&self,
65-
reader: Pin<Box<dyn BlobRead>>,
66-
) -> Result<(encoding::Digest, u64)> {
67-
// Safety: we are wrapping the same underlying unsafe function and
68-
// so the same safety holds for our callers
69-
unsafe { PayloadStorage::write_data(&**self, reader).await }
54+
async fn write_data(&self, reader: Pin<Box<dyn BlobRead>>) -> Result<(encoding::Digest, u64)> {
55+
PayloadStorage::write_data(&**self, reader).await
7056
}
7157

7258
async fn open_payload(

crates/spfs/src/storage/payload_test.rs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,10 @@ async fn test_payload_io(
2323
let bytes = "simple string data".as_bytes();
2424
let reader = Box::pin(bytes);
2525

26-
// Safety: we are intentionally calling this function to test it
27-
let (digest, size) = unsafe {
28-
tmprepo
29-
.write_data(reader)
30-
.await
31-
.expect("failed to write payload data")
32-
};
26+
let (digest, size) = tmprepo
27+
.write_data(reader)
28+
.await
29+
.expect("failed to write payload data");
3330
assert_eq!(size, bytes.len() as u64);
3431

3532
let mut actual = String::new();
@@ -58,13 +55,10 @@ async fn test_payload_existence(
5855
let bytes = "simple string data".as_bytes();
5956
let reader = Box::pin(bytes);
6057

61-
// Safety: we are intentionally calling this unsafe function to test it
62-
let (digest, size) = unsafe {
63-
tmprepo
64-
.write_data(reader)
65-
.await
66-
.expect("failed to write payload data")
67-
};
58+
let (digest, size) = tmprepo
59+
.write_data(reader)
60+
.await
61+
.expect("failed to write payload data");
6862
assert_eq!(size, bytes.len() as u64);
6963

7064
let actual = tmprepo.has_payload(digest).await;

crates/spfs/src/storage/pinned/repository.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -131,17 +131,12 @@ where
131131
self.inner.iter_payload_digests()
132132
}
133133

134-
async unsafe fn write_data(
135-
&self,
136-
reader: Pin<Box<dyn BlobRead>>,
137-
) -> Result<(encoding::Digest, u64)> {
134+
async fn write_data(&self, reader: Pin<Box<dyn BlobRead>>) -> Result<(encoding::Digest, u64)> {
138135
// payloads are stored by digest, not time, and so can still
139136
// be safely written to a past repository view. In practice,
140137
// this allows some recovery and sync operations to still function
141138
// on pinned repositories
142-
143-
// Safety: we are simply calling the same inner unsafe function
144-
unsafe { self.inner.write_data(reader).await }
139+
self.inner.write_data(reader).await
145140
}
146141

147142
async fn open_payload(

crates/spfs/src/storage/proxy/repository.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -220,14 +220,8 @@ impl PayloadStorage for ProxyRepository {
220220
self.primary.iter_payload_digests()
221221
}
222222

223-
async unsafe fn write_data(
224-
&self,
225-
reader: Pin<Box<dyn BlobRead>>,
226-
) -> Result<(encoding::Digest, u64)> {
227-
// Safety: we are wrapping the same underlying unsafe function and
228-
// so the same safety holds for our callers
229-
let res = unsafe { self.primary.write_data(reader).await? };
230-
Ok(res)
223+
async fn write_data(&self, reader: Pin<Box<dyn BlobRead>>) -> Result<(encoding::Digest, u64)> {
224+
self.primary.write_data(reader).await
231225
}
232226

233227
async fn open_payload(

crates/spfs/src/storage/repository.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,7 @@ impl<T> Repository for T where
120120
pub trait RepositoryExt: super::PayloadStorage + graph::DatabaseExt {
121121
/// Commit the data from 'reader' as a payload in this repository
122122
async fn commit_payload(&self, reader: Pin<Box<dyn BlobRead>>) -> Result<encoding::Digest> {
123-
// Safety: it is unsafe to write data without also creating a blob
124-
// to track that payload, which is exactly what this function is doing
125-
let (digest, size) = unsafe { self.write_data(reader).await? };
123+
let (digest, size) = self.write_data(reader).await?;
126124
let blob = graph::Blob::new(digest, size);
127125
self.write_object(&blob).await?;
128126
Ok(digest)

crates/spfs/src/storage/rpc/payload.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,7 @@ impl storage::PayloadStorage for super::RpcRepository {
3939
Box::pin(stream)
4040
}
4141

42-
async unsafe fn write_data(
43-
&self,
44-
reader: Pin<Box<dyn BlobRead>>,
45-
) -> Result<(encoding::Digest, u64)> {
42+
async fn write_data(&self, reader: Pin<Box<dyn BlobRead>>) -> Result<(encoding::Digest, u64)> {
4643
let request = proto::WritePayloadRequest {};
4744
let option = self
4845
.payload_client

0 commit comments

Comments
 (0)