@samitouri / QOSamiQemu / commits / 7fe20a2fca

fuse: Make shared export state atomic

The next commit is going to allow multi-threaded access to a FUSE export. In order to allow safe concurrent SETATTR operations that can modify the shared st_mode, st_uid, and st_gid, make any access to those fields atomic operations. Signed-off-by: Hanna Czenczek <hreitz@redhat.com> Message-ID: <20260309150856.26800-23-hreitz@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>

Hanna Czenczek committed Mar 9, 2026 at 16:08 UTC 7fe20a2fca4819b43374379ded345b012f699650
1 file changed +13 -10
block/export/fuse.c
+13 -10
@@ -156,6 +156,7 @@ typedef struct FuseExport {
156 /* Whether allow_other was used as a mount option or not */
157 bool allow_other;
158
159 + /* All atomic */
160 mode_t st_mode;
161 uid_t st_uid;
162 gid_t st_gid;
@@ -266,6 +267,7 @@ static int fuse_export_create(BlockExport *blk_exp,
267 ERRP_GUARD(); /* ensure clean-up even with error_fatal */
268 FuseExport *exp = container_of(blk_exp, FuseExport, common);
269 BlockExportOptionsFuse *args = &blk_exp_args->u.fuse;
270 + uint32_t st_mode;
271 int ret;
272
273 assert(blk_exp_args->type == BLOCK_EXPORT_TYPE_FUSE);
@@ -334,12 +336,13 @@ static int fuse_export_create(BlockExport *blk_exp,
336 args->allow_other = FUSE_EXPORT_ALLOW_OTHER_AUTO;
337 }
338
337 - exp->st_mode = S_IFREG | S_IRUSR;
339 + st_mode = S_IFREG | S_IRUSR;
340 if (exp->writable) {
339 - exp->st_mode |= S_IWUSR;
341 + st_mode |= S_IWUSR;
342 }
341 - exp->st_uid = getuid();
342 - exp->st_gid = getgid();
343 + qatomic_set(&exp->st_mode, st_mode);
344 + qatomic_set(&exp->st_uid, getuid());
345 + qatomic_set(&exp->st_gid, getgid());
346
347 if (args->allow_other == FUSE_EXPORT_ALLOW_OTHER_AUTO) {
348 /* Try allow_other == true first, ignore errors */
@@ -817,10 +820,10 @@ fuse_co_getattr(FuseExport *exp, struct fuse_attr_out *out)
820 .attr_valid = 1,
821 .attr = {
822 .ino = 1,
820 - .mode = exp->st_mode,
823 + .mode = qatomic_read(&exp->st_mode),
824 .nlink = 1,
822 - .uid = exp->st_uid,
823 - .gid = exp->st_gid,
825 + .uid = qatomic_read(&exp->st_uid),
826 + .gid = qatomic_read(&exp->st_gid),
827 .size = length,
828 .blksize = blk_bs(exp->common.blk)->bl.request_alignment,
829 .blocks = allocated_blocks,
@@ -903,15 +906,15 @@ fuse_co_setattr(FuseExport *exp, struct fuse_attr_out *out, uint32_t to_set,
906
907 if (to_set & FATTR_MODE) {
908 /* Ignore FUSE-supplied file type, only change the mode */
906 - exp->st_mode = (mode & 07777) | S_IFREG;
909 + qatomic_set(&exp->st_mode, (mode & 07777) | S_IFREG);
910 }
911
912 if (to_set & FATTR_UID) {
910 - exp->st_uid = uid;
913 + qatomic_set(&exp->st_uid, uid);
914 }
915
916 if (to_set & FATTR_GID) {
914 - exp->st_gid = gid;
917 + qatomic_set(&exp->st_gid, gid);
918 }
919
920 return fuse_co_getattr(exp, out);