This is an automated email from the ASF dual-hosted git repository.

jshao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new e85e47dcd8 [#6320] feat (gvfs-fuse): Support mount and umount command 
for gvfs-fuse command line tools (#6321)
e85e47dcd8 is described below

commit e85e47dcd859008a123f141945cc70546f36f725
Author: Yuhui <h...@datastrato.com>
AuthorDate: Fri Feb 7 14:28:20 2025 +0800

    [#6320] feat (gvfs-fuse): Support mount and umount command for gvfs-fuse 
command line tools (#6321)
    
    ### What changes were proposed in this pull request?
    
    1. Support mount and umount command
    2. Make mount create a daemon process to run background
    
    
    ### Why are the changes needed?
    
    Fix: #6320
    
    ### Does this PR introduce _any_ user-facing change?
    
    No
    
    ### How was this patch tested?
    
    IT
    
    ---------
    
    Co-authored-by: Qiming Teng <ten...@outlook.com>
---
 clients/filesystem-fuse/Cargo.toml                 |   2 +
 clients/filesystem-fuse/conf/gvfs_fuse.toml        |   1 +
 clients/filesystem-fuse/src/command_args.rs        |  59 ++++++
 clients/filesystem-fuse/src/config.rs              |  72 +++++--
 clients/filesystem-fuse/src/fuse_server.rs         |   3 +-
 clients/filesystem-fuse/src/lib.rs                 |   3 +
 clients/filesystem-fuse/src/main.rs                | 229 ++++++++++++++++++---
 clients/filesystem-fuse/src/s3_filesystem.rs       |   2 +-
 clients/filesystem-fuse/tests/bin/gvfs_fuse.sh     |   9 +-
 .../filesystem-fuse/tests/conf/config_test.toml    |   2 +
 .../filesystem-fuse/tests/conf/gvfs_fuse_s3.toml   |   1 +
 clients/filesystem-fuse/tests/fuse_test.rs         |   2 +-
 12 files changed, 328 insertions(+), 57 deletions(-)

diff --git a/clients/filesystem-fuse/Cargo.toml 
b/clients/filesystem-fuse/Cargo.toml
index 3760bd5285..e600683689 100644
--- a/clients/filesystem-fuse/Cargo.toml
+++ b/clients/filesystem-fuse/Cargo.toml
@@ -35,7 +35,9 @@ name = "gvfs_fuse"
 [dependencies]
 async-trait = "0.1"
 bytes = "1.6.0"
+clap = { version = "4.5.24", features = ["derive"] }
 config = "0.13"
+daemonize = "0.5.0"
 dashmap = "6.1.0"
 fuse3 = { version = "0.8.1", "features" = ["tokio-runtime", "unprivileged"] }
 futures-util = "0.3.30"
diff --git a/clients/filesystem-fuse/conf/gvfs_fuse.toml 
b/clients/filesystem-fuse/conf/gvfs_fuse.toml
index 4bde0e9e1b..27e52fc7d5 100644
--- a/clients/filesystem-fuse/conf/gvfs_fuse.toml
+++ b/clients/filesystem-fuse/conf/gvfs_fuse.toml
@@ -20,6 +20,7 @@
 file_mask = 0o600
 dir_mask = 0o700
 fs_type = "memory"
+data_path = "target/gvfs-fuse"
 
 [fuse.properties]
 
diff --git a/clients/filesystem-fuse/src/command_args.rs 
b/clients/filesystem-fuse/src/command_args.rs
new file mode 100644
index 0000000000..bb442f167d
--- /dev/null
+++ b/clients/filesystem-fuse/src/command_args.rs
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+use clap::{Parser, Subcommand};
+
+#[derive(Parser, Debug)]
+#[command(
+    name = "gvfs-fuse",
+    version = "0.1",
+    about = "A FUSE-based file system client"
+)]
+pub(crate) struct Arguments {
+    #[command(subcommand)]
+    pub(crate) command: Commands,
+}
+
+#[derive(Subcommand, Debug)]
+pub(crate) enum Commands {
+    Mount {
+        #[arg(help = "Mount point for the filesystem")]
+        mount_point: String,
+
+        #[arg(
+            help = "The URI of the GVFS fileset, like 
gvfs://fileset/my_catalog/my_schema/my_fileset"
+        )]
+        fileset_location: String,
+
+        #[arg(short, long, help = "Path to the configuration file")]
+        config: Option<String>,
+
+        #[arg(short, long, help = "Debug level", default_value_t = 0)]
+        debug: u8,
+
+        #[arg(short, long, default_value_t = false, help = "Run in 
foreground")]
+        foreground: bool,
+    },
+    Umount {
+        #[arg(help = "Mount point to umount")]
+        mount_point: String,
+
+        #[arg(short, long, help = "Force umount")]
+        force: bool,
+    },
+}
diff --git a/clients/filesystem-fuse/src/config.rs 
b/clients/filesystem-fuse/src/config.rs
index 17908fd08f..890cb7d31d 100644
--- a/clients/filesystem-fuse/src/config.rs
+++ b/clients/filesystem-fuse/src/config.rs
@@ -24,6 +24,7 @@ use serde::Deserialize;
 use std::collections::HashMap;
 use std::fs;
 
+// FuseConfig
 pub(crate) const CONF_FUSE_FILE_MASK: ConfigEntity<u32> = ConfigEntity::new(
     FuseConfig::MODULE_NAME,
     "file_mask",
@@ -45,13 +46,28 @@ pub(crate) const CONF_FUSE_FS_TYPE: ConfigEntity<&'static 
str> = ConfigEntity::n
     "memory",
 );
 
-pub(crate) const CONF_FUSE_CONFIG_PATH: ConfigEntity<&'static str> = 
ConfigEntity::new(
+pub(crate) const CONF_FUSE_CONFIG_FILE_PATH: ConfigEntity<&'static str> = 
ConfigEntity::new(
     FuseConfig::MODULE_NAME,
     "config_path",
     "The path of the FUSE configuration file",
-    "/etc/gvfs/gvfs.toml",
+    "/etc/gvfs-fuse/config.toml",
 );
 
+pub(crate) const CONF_FUSE_DATA_DIR: ConfigEntity<&'static str> = 
ConfigEntity::new(
+    FuseConfig::MODULE_NAME,
+    "data_dir",
+    "The data path of GVFS FUSE",
+    "/var/data/gvfs-fuse",
+);
+
+pub(crate) const CONF_FUSE_LOG_DIR: ConfigEntity<&'static str> = 
ConfigEntity::new(
+    FuseConfig::MODULE_NAME,
+    "log_dir",
+    "The log path of GVFS FUSE",
+    "logs", //relative to the data path
+);
+
+// FilesystemConfig
 pub(crate) const CONF_FILESYSTEM_BLOCK_SIZE: ConfigEntity<u32> = 
ConfigEntity::new(
     FilesystemConfig::MODULE_NAME,
     "block_size",
@@ -59,6 +75,7 @@ pub(crate) const CONF_FILESYSTEM_BLOCK_SIZE: 
ConfigEntity<u32> = ConfigEntity::n
     4096,
 );
 
+// GravitinoConfig
 pub(crate) const CONF_GRAVITINO_URI: ConfigEntity<&'static str> = 
ConfigEntity::new(
     GravitinoConfig::MODULE_NAME,
     "uri",
@@ -125,22 +142,32 @@ impl Default for DefaultConfig {
             ConfigValue::String(CONF_FUSE_FS_TYPE),
         );
         configs.insert(
-            Self::compose_key(CONF_FUSE_CONFIG_PATH),
-            ConfigValue::String(CONF_FUSE_CONFIG_PATH),
+            Self::compose_key(CONF_FUSE_CONFIG_FILE_PATH),
+            ConfigValue::String(CONF_FUSE_CONFIG_FILE_PATH),
         );
         configs.insert(
-            Self::compose_key(CONF_GRAVITINO_URI),
-            ConfigValue::String(CONF_GRAVITINO_URI),
+            Self::compose_key(CONF_FUSE_DATA_DIR),
+            ConfigValue::String(CONF_FUSE_DATA_DIR),
         );
         configs.insert(
-            Self::compose_key(CONF_GRAVITINO_METALAKE),
-            ConfigValue::String(CONF_GRAVITINO_METALAKE),
+            Self::compose_key(CONF_FUSE_LOG_DIR),
+            ConfigValue::String(CONF_FUSE_LOG_DIR),
         );
+
         configs.insert(
             Self::compose_key(CONF_FILESYSTEM_BLOCK_SIZE),
             ConfigValue::U32(CONF_FILESYSTEM_BLOCK_SIZE),
         );
 
+        configs.insert(
+            Self::compose_key(CONF_GRAVITINO_URI),
+            ConfigValue::String(CONF_GRAVITINO_URI),
+        );
+        configs.insert(
+            Self::compose_key(CONF_GRAVITINO_METALAKE),
+            ConfigValue::String(CONF_GRAVITINO_METALAKE),
+        );
+
         DefaultConfig { configs }
     }
 }
@@ -205,38 +232,39 @@ impl AppConfig {
             .unwrap_or_else(|e| panic!("Failed to set default for {}: {}", 
entity.name, e))
     }
 
-    pub fn from_file(config_file_path: Option<&str>) -> GvfsResult<AppConfig> {
+    pub fn from_file(config_file_path: Option<String>) -> 
GvfsResult<AppConfig> {
         let builder = Self::crete_default_config_builder();
 
         let config_path = {
             if config_file_path.is_some() {
                 let path = config_file_path.unwrap();
                 //check config file exists
-                if fs::metadata(path).is_err() {
+                if fs::metadata(&path).is_err() {
                     return Err(
                         ConfigNotFound.to_error("The configuration file not 
found".to_string())
                     );
                 }
-                info!("Use configuration file: {}", path);
+                info!("Use configuration file: {}", &path);
                 path
             } else {
-                //use default config
-                if fs::metadata(CONF_FUSE_CONFIG_PATH.default).is_err() {
+                if fs::metadata(CONF_FUSE_CONFIG_FILE_PATH.default).is_err() {
+                    //use default config
                     warn!(
                         "The default configuration file is not found, using 
the default configuration"
                     );
                     return Ok(AppConfig::default());
                 } else {
+                    //use the default configuration file
                     warn!(
                         "Using the default config file {}",
-                        CONF_FUSE_CONFIG_PATH.default
+                        CONF_FUSE_CONFIG_FILE_PATH.default
                     );
                 }
-                CONF_FUSE_CONFIG_PATH.default
+                CONF_FUSE_CONFIG_FILE_PATH.default.to_string()
             }
         };
         let config = builder
-            .add_source(config::File::with_name(config_path).required(true))
+            .add_source(config::File::with_name(&config_path).required(true))
             .build();
         if let Err(e) = config {
             let msg = format!("Failed to build configuration: {}", e);
@@ -265,7 +293,11 @@ pub struct FuseConfig {
     #[serde(default)]
     pub fs_type: String,
     #[serde(default)]
-    pub config_path: String,
+    pub config_file_path: String,
+    #[serde(default)]
+    pub data_dir: String,
+    #[serde(default)]
+    pub log_dir: String,
     #[serde(default)]
     pub properties: HashMap<String, String>,
 }
@@ -302,9 +334,11 @@ mod test {
 
     #[test]
     fn test_config_from_file() {
-        let config = 
AppConfig::from_file(Some("tests/conf/config_test.toml")).unwrap();
+        let config = 
AppConfig::from_file(Some("tests/conf/config_test.toml".to_string())).unwrap();
         assert_eq!(config.fuse.file_mask, 0o644);
         assert_eq!(config.fuse.dir_mask, 0o755);
+        assert_eq!(config.fuse.data_dir, "/target/gvfs-fuse");
+        assert_eq!(config.fuse.log_dir, "/target/gvfs-fuse/logs");
         assert_eq!(config.filesystem.block_size, 8192);
         assert_eq!(config.gravitino.uri, "http://localhost:8090";);
         assert_eq!(config.gravitino.metalake, "test");
@@ -323,6 +357,8 @@ mod test {
         let config = AppConfig::default();
         assert_eq!(config.fuse.file_mask, 0o600);
         assert_eq!(config.fuse.dir_mask, 0o700);
+        assert_eq!(config.fuse.data_dir, "/var/data/gvfs-fuse");
+        assert_eq!(config.fuse.log_dir, "logs");
         assert_eq!(config.filesystem.block_size, 4096);
         assert_eq!(config.gravitino.uri, "http://localhost:8090";);
         assert_eq!(config.gravitino.metalake, "");
diff --git a/clients/filesystem-fuse/src/fuse_server.rs 
b/clients/filesystem-fuse/src/fuse_server.rs
index a059686e16..0e8bd51833 100644
--- a/clients/filesystem-fuse/src/fuse_server.rs
+++ b/clients/filesystem-fuse/src/fuse_server.rs
@@ -20,6 +20,7 @@ use crate::utils::GvfsResult;
 use fuse3::raw::{Filesystem, Session};
 use fuse3::MountOptions;
 use log::{error, info};
+use std::path::Path;
 use std::process::exit;
 use std::sync::Arc;
 use tokio::select;
@@ -46,7 +47,7 @@ impl FuseServer {
     /// Starts the FUSE filesystem and blocks until it is stopped.
     pub async fn start(&self, fuse_fs: impl Filesystem + Sync + 'static) -> 
GvfsResult<()> {
         //check if the mount point exists
-        if !std::path::Path::new(&self.mount_point).exists() {
+        if !Path::new(&self.mount_point).exists() {
             error!("Mount point {} does not exist", self.mount_point);
             exit(libc::ENOENT);
         }
diff --git a/clients/filesystem-fuse/src/lib.rs 
b/clients/filesystem-fuse/src/lib.rs
index 41a9a5335d..65cd878f34 100644
--- a/clients/filesystem-fuse/src/lib.rs
+++ b/clients/filesystem-fuse/src/lib.rs
@@ -49,6 +49,9 @@ macro_rules! test_enable_with {
 pub const RUN_TEST_WITH_S3: &str = "RUN_TEST_WITH_S3";
 pub const RUN_TEST_WITH_FUSE: &str = "RUN_TEST_WITH_FUSE";
 
+pub const LOG_FILE_NAME: &str = "gvfs-fuse.log";
+pub const PID_FILE_NAME: &str = "gvfs-fuse.pid";
+
 pub async fn gvfs_mount(mount_to: &str, mount_from: &str, config: &AppConfig) 
-> GvfsResult<()> {
     gvfs_fuse::mount(mount_to, mount_from, config).await
 }
diff --git a/clients/filesystem-fuse/src/main.rs 
b/clients/filesystem-fuse/src/main.rs
index 4e517c76b3..6c8c0f4e0e 100644
--- a/clients/filesystem-fuse/src/main.rs
+++ b/clients/filesystem-fuse/src/main.rs
@@ -16,49 +16,214 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-use fuse3::Errno;
+mod command_args;
+
+use crate::command_args::Commands;
+use clap::Parser;
+use daemonize::Daemonize;
 use gvfs_fuse::config::AppConfig;
-use gvfs_fuse::{gvfs_mount, gvfs_unmount};
+use gvfs_fuse::{gvfs_mount, gvfs_unmount, LOG_FILE_NAME, PID_FILE_NAME};
 use log::{error, info};
+use std::fs::{create_dir, OpenOptions};
+use std::io;
+use std::path::Path;
+use std::process::Command;
+use tokio::runtime::Runtime;
 use tokio::signal;
+use tokio::signal::unix::{signal, SignalKind};
 
-#[tokio::main]
-async fn main() -> fuse3::Result<()> {
-    tracing_subscriber::fmt::init();
-
-    // todo need inmprove the args parsing
-    let args: Vec<String> = std::env::args().collect();
-    let (mount_point, mount_from, config_path) = match args.len() {
-        4 => (args[1].clone(), args[2].clone(), args[3].clone()),
-        _ => {
-            error!("Usage: {} <mount_point> <mount_from> <config>", args[0]);
-            return Err(Errno::from(libc::EINVAL));
-        }
+fn init_work_dirs(config: &AppConfig, mount_point: &str) -> io::Result<()> {
+    let data_dir_name = Path::new(&config.fuse.data_dir).to_path_buf();
+    let data_dir_name = data_dir_name.canonicalize()?;
+    if !data_dir_name.exists() {
+        Err(io::Error::new(
+            io::ErrorKind::NotFound,
+            format!("Data directory {} not found", &config.fuse.data_dir),
+        ))?
+    };
+
+    let mount_point_name = data_dir_name.join(mount_point);
+    if !mount_point_name.exists() {
+        create_dir(&mount_point_name)?
+    };
+
+    let log_dir_name = data_dir_name.join(&config.fuse.log_dir);
+    if !log_dir_name.exists() {
+        create_dir(&log_dir_name)?
     };
 
-    //todo(read config file from args)
-    let config = AppConfig::from_file(Some(&config_path));
-    if let Err(e) = &config {
-        error!("Failed to load config: {:?}", e);
-        return Err(Errno::from(libc::EINVAL));
+    Ok(())
+}
+
+fn make_daemon(config: &AppConfig) -> io::Result<()> {
+    let data_dir_name = Path::new(&config.fuse.data_dir);
+    let log_dir_name = data_dir_name.join(&config.fuse.log_dir);
+    let log_file_name = log_dir_name.join(LOG_FILE_NAME);
+    let log_file = OpenOptions::new()
+        .create(true)
+        .append(true)
+        .open(&log_file_name)
+        .unwrap();
+    let log_err_file = 
OpenOptions::new().append(true).open(log_file_name).unwrap();
+
+    let pid_file_name = data_dir_name.join(PID_FILE_NAME);
+
+    let daemonize = Daemonize::new()
+        .pid_file(pid_file_name)
+        .chown_pid_file(true)
+        .working_directory(data_dir_name)
+        .stdout(log_file)
+        .stderr(log_err_file);
+
+    match daemonize.start() {
+        Ok(_) => info!("Gvfs-fuse Daemon started successfully"),
+        Err(e) => {
+            return Err(io::Error::new(
+                io::ErrorKind::Other,
+                format!("Gvfs-fuse Daemon failed to start: {:?}", e),
+            ))
+        }
     }
-    let config = config.unwrap();
-    let handle = tokio::spawn(async move {
-        let result = gvfs_mount(&mount_point, &mount_from, &config).await;
-        if let Err(e) = result {
-            error!("Failed to mount gvfs: {:?}", e);
-            return Err(Errno::from(libc::EINVAL));
+    Ok(())
+}
+
+fn mount_fuse(config: AppConfig, mount_point: String, target: String) -> 
io::Result<()> {
+    let rt = Runtime::new()?;
+    rt.block_on(async {
+        let handle = tokio::spawn(async move {
+            let result = gvfs_mount(&mount_point, &target, &config).await;
+            if let Err(e) = result {
+                error!("Failed to mount gvfs: {:?}", e);
+                return Err(io::Error::from(io::ErrorKind::InvalidInput));
+            }
+            Ok(())
+        });
+
+        let mut term_signal = signal(SignalKind::terminate())?;
+        tokio::select! {
+            _ = handle => {}
+            _ = signal::ctrl_c() => {
+                    info!("Received Ctrl+C, unmounting gvfs...")
+                }
+            _ = term_signal.recv()=> {
+                    info!("Received SIGTERM, unmounting gvfs...")
+                }
         }
+
+        let _ = gvfs_unmount().await;
         Ok(())
-    });
+    })
+}
 
-    tokio::select! {
-        _ = handle => {}
-        _ = signal::ctrl_c() => {
-            info!("Received Ctrl+C, unmounting gvfs...");
+#[cfg(target_os = "macos")]
+fn do_umount(mp: &str, force: bool) -> std::io::Result<()> {
+    let cmd_result = if force {
+        Command::new("umount").arg("-f").arg(mp).output()
+    } else {
+        Command::new("umount").arg(mp).output()
+    };
+
+    handle_command_result(cmd_result)
+}
+
+#[cfg(target_os = "linux")]
+fn do_umount(mp: &str, force: bool) -> std::io::Result<()> {
+    let cmd_result =
+        if Path::new("/bin/fusermount").exists() || 
Path::new("/usr/bin/fusermount").exists() {
+            if force {
+                Command::new("fusermount").arg("-uz").arg(mp).output()
+            } else {
+                Command::new("fusermount").arg("-u").arg(mp).output()
+            }
+        } else if force {
+            Command::new("umount").arg("-l").arg(mp).output()
+        } else {
+            Command::new("umount").arg(mp).output()
+        };
+
+    handle_command_result(cmd_result)
+}
+
+fn handle_command_result(cmd_result: io::Result<std::process::Output>) -> 
io::Result<()> {
+    match cmd_result {
+        Ok(output) => {
+            if !output.status.success() {
+                let stderr = String::from_utf8_lossy(&output.stderr);
+                Err(io::Error::new(io::ErrorKind::Other, stderr.to_string()))
+            } else {
+                Ok(())
+            }
         }
+        Err(e) => Err(e),
     }
+}
 
-    let _ = gvfs_unmount().await;
-    Ok(())
+#[cfg(not(any(target_os = "macos", target_os = "linux")))]
+fn do_umount(_mp: &str, _force: bool) -> std::io::Result<()> {
+    Err(std::io::Error::new(
+        std::io::ErrorKind::Other,
+        format!("OS {} is not supported", env::consts::OS),
+    ))
+}
+
+fn main() -> Result<(), i32> {
+    tracing_subscriber::fmt().init();
+    let args = command_args::Arguments::parse();
+    match args.command {
+        Commands::Mount {
+            mount_point,
+            fileset_location,
+            config,
+            debug: _,
+            foreground,
+        } => {
+            let app_config = AppConfig::from_file(config);
+            if let Err(e) = &app_config {
+                error!("Failed to load config: {:?}", e);
+                return Err(-1);
+            };
+            let app_config = app_config.unwrap();
+
+            let mount_point = {
+                let path = Path::new(&mount_point).canonicalize();
+                if let Err(e) = path {
+                    error!("Failed to resolve mount point: {:?}", e);
+                    return Err(-1);
+                };
+                let path = path.unwrap();
+                path.to_string_lossy().to_string()
+            };
+
+            let result = init_work_dirs(&app_config, &mount_point);
+            if let Err(e) = result {
+                error!("Failed to initialize working directories: {:?}", e);
+                return Err(-1);
+            }
+
+            let result = if foreground {
+                mount_fuse(app_config, mount_point, fileset_location)
+            } else {
+                let result = make_daemon(&app_config);
+                if let Err(e) = result {
+                    error!("Failed to daemonize: {:?}", e);
+                    return Err(-1);
+                };
+                mount_fuse(app_config, mount_point, fileset_location)
+            };
+
+            if let Err(e) = result {
+                error!("Failed to mount gvfs: {:?}", e.to_string());
+                return Err(-1);
+            };
+            Ok(())
+        }
+        Commands::Umount { mount_point, force } => {
+            let result = do_umount(&mount_point, force);
+            if let Err(e) = result {
+                error!("Failed to unmount gvfs: {:?}", e.to_string());
+                return Err(-1);
+            };
+            Ok(())
+        }
+    }
 }
diff --git a/clients/filesystem-fuse/src/s3_filesystem.rs 
b/clients/filesystem-fuse/src/s3_filesystem.rs
index 35a091b3fe..e397d31ccf 100644
--- a/clients/filesystem-fuse/src/s3_filesystem.rs
+++ b/clients/filesystem-fuse/src/s3_filesystem.rs
@@ -255,7 +255,7 @@ pub(crate) mod tests {
             config_file_name = source_file_name;
         }
 
-        AppConfig::from_file(Some(config_file_name)).unwrap()
+        AppConfig::from_file(Some(config_file_name.to_string())).unwrap()
     }
 
     #[tokio::test]
diff --git a/clients/filesystem-fuse/tests/bin/gvfs_fuse.sh 
b/clients/filesystem-fuse/tests/bin/gvfs_fuse.sh
index e706d8e2c0..3089a9a1a1 100644
--- a/clients/filesystem-fuse/tests/bin/gvfs_fuse.sh
+++ b/clients/filesystem-fuse/tests/bin/gvfs_fuse.sh
@@ -52,14 +52,15 @@ start_gvfs_fuse() {
   make build
 
   echo "Starting gvfs-fuse-daemon"
-  $CLIENT_FUSE_DIR/target/debug/gvfs-fuse $MOUNT_DIR $MOUNT_FROM_LOCATION 
$TEST_CONFIG_FILE > \
+  mkdir -p target/debug/gvfs-dir
+  $CLIENT_FUSE_DIR/target/debug/gvfs-fuse mount $MOUNT_DIR 
$MOUNT_FROM_LOCATION -c $TEST_CONFIG_FILE -f > \
     $CLIENT_FUSE_DIR/target/debug/fuse.log 2>&1 &
   check_gvfs_fuse_ready
   cd -
 }
 
 stop_gvfs_fuse() {
-  # Stop the gvfs-fuse process if it's running
-  pkill -INT gvfs-fuse || true
+  # Unmount the gvfs-fuse
+  $CLIENT_FUSE_DIR/target/debug/gvfs-fuse umount $MOUNT_DIR
   echo "Stopping gvfs-fuse-daemon"
-}
\ No newline at end of file
+}
diff --git a/clients/filesystem-fuse/tests/conf/config_test.toml 
b/clients/filesystem-fuse/tests/conf/config_test.toml
index 524e0aa94f..e7cbf02c7f 100644
--- a/clients/filesystem-fuse/tests/conf/config_test.toml
+++ b/clients/filesystem-fuse/tests/conf/config_test.toml
@@ -20,6 +20,8 @@
 file_mask= 0o644
 dir_mask= 0o755
 fs_type = "memory"
+data_dir = "/target/gvfs-fuse"
+log_dir = "/target/gvfs-fuse/logs"
 
 [fuse.properties]
 key1 = "value1"
diff --git a/clients/filesystem-fuse/tests/conf/gvfs_fuse_s3.toml 
b/clients/filesystem-fuse/tests/conf/gvfs_fuse_s3.toml
index d0ff8e5dde..69a3fcaf36 100644
--- a/clients/filesystem-fuse/tests/conf/gvfs_fuse_s3.toml
+++ b/clients/filesystem-fuse/tests/conf/gvfs_fuse_s3.toml
@@ -20,6 +20,7 @@
 file_mask= 0o600
 dir_mask= 0o700
 fs_type = "gvfs"
+data_dir = "target/debug/gvfs-dir"
 
 [fuse.properties]
 key1 = "value1"
diff --git a/clients/filesystem-fuse/tests/fuse_test.rs 
b/clients/filesystem-fuse/tests/fuse_test.rs
index 1d1ef80b78..cd7dbf7ea9 100644
--- a/clients/filesystem-fuse/tests/fuse_test.rs
+++ b/clients/filesystem-fuse/tests/fuse_test.rs
@@ -45,7 +45,7 @@ impl FuseTestEnv {
         info!("Start gvfs fuse server");
         let mount_point = self.mount_point.clone();
 
-        let config = 
AppConfig::from_file(Some("tests/conf/gvfs_fuse_memory.toml"))
+        let config = 
AppConfig::from_file(Some("tests/conf/gvfs_fuse_memory.toml".to_string()))
             .expect("Failed to load config");
         ASYNC_RUNTIME.spawn(async move {
             let result = gvfs_mount(&mount_point, "", &config).await;

Reply via email to