Direct S3 writes target the primary device and may leave the selected
blob device shorter than its allocated extent.

Write objects at device-relative offsets on the selected device
and extend it to the final block boundary.

Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Yifan Zhao <[email protected]>
---
Changes since v1:
- Correct the author and Signed-off-by email address.

 lib/remotes/s3.c | 29 +++++++++++++++++++++++++----
 1 file changed, 25 insertions(+), 4 deletions(-)

diff --git a/lib/remotes/s3.c b/lib/remotes/s3.c
index 56ab808..feba9b4 100644
--- a/lib/remotes/s3.c
+++ b/lib/remotes/s3.c
@@ -15,6 +15,7 @@
 #include "erofs/internal.h"
 #include "erofs/print.h"
 #include "erofs/inode.h"
+#include "../liberofs_cache.h"
 #include "../liberofs_chunk.h"
 #include "erofs/diskbuf.h"
 #include "erofs/importer.h"
@@ -1017,6 +1018,11 @@ struct s3erofs_curl_getobject_resp {
        erofs_off_t pos, end;
 };
 
+static bool s3erofs_could_write_directly(const struct erofs_importer *im)
+{
+       return !im->sbi->available_compr_algs && im->params->no_datainline;
+}
+
 static size_t s3erofs_remote_getobject_cb(void *contents, size_t size,
                                          size_t nmemb, void *userp)
 {
@@ -1053,16 +1059,20 @@ static int s3erofs_remote_getobject(struct 
erofs_importer *im,
                return -EIO;
 
        resp.pos = 0;
-       if (!sbi->available_compr_algs && im->params->no_datainline) {
+       if (s3erofs_could_write_directly(im)) {
+               unsigned int device_id = im->params->ddev_id_def;
+
                inode->datalayout = EROFS_INODE_FLAT_PLAIN;
                inode->idata_size = 0;
                ret = erofs_allocate_inode_bh_data(inode,
                                DIV_ROUND_UP(inode->i_size, 1U << 
sbi->blkszbits),
-                               im->params->ddev_id_def);
+                               device_id);
                if (ret)
                        return ret;
-               resp.vf = &sbi->bdev;
-               resp.pos = erofs_pos(inode->sbi, inode->u.i_blkaddr);
+               resp.vf = device_id ?
+                       sbi->devs[device_id - 1].bmgr->vf : &sbi->bdev;
+               if (inode->i_size)
+                       resp.pos = erofs_pos(sbi, erofs_inode_dev_baddr(inode));
                inode->datasource = EROFS_INODE_DATA_SOURCE_NONE;
        } else {
                if (!inode->i_diskbuf) {
@@ -1189,6 +1199,17 @@ int s3erofs_build_trees(struct erofs_importer *im, 
struct erofs_s3 *s3,
                        goto err_iter;
        }
 
+       if (!fillzero && s3erofs_could_write_directly(im) &&
+           im->params->ddev_id_def) {
+               struct erofs_bufmgr *bmgr =
+                       sbi->devs[im->params->ddev_id_def - 1].bmgr;
+
+               ret = erofs_io_ftruncate(bmgr->vf,
+                               erofs_pos(sbi, erofs_mapbh(bmgr, NULL)));
+               if (ret)
+                       goto err_iter;
+       }
+
 err_iter:
        s3erofs_destroy_object_iterator(iter);
 err_global:

base-commit: 65645313de60a42d6d93389a6658317f8b1e6b8e
-- 
2.55.0


Reply via email to