Skip to content
GitLab
Explore
Sign in
Commits on Source (2)
some comments and gkfs init
· bc835b43
sevenuz
authored
Jul 25, 2025
bc835b43
first draft for gkfs
· 9936cd50
sevenuz
authored
Jul 29, 2025
9936cd50
Expand all
Show whitespace changes
Inline
Side-by-side
include/client/fuse/fuse_client.hpp
View file @
9936cd50
/*
Copyright 2018-2025, Barcelona Supercomputing Center (BSC), Spain
Copyright 2015-2025, Johannes Gutenberg Universitaet Mainz, Germany
This software was partially supported by the
EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu).
This software was partially supported by the
ADA-FS project under the SPPEXA project funded by the DFG.
This software was partially supported by the
the European Union’s Horizon 2020 JTI-EuroHPC research and
innovation programme, by the project ADMIRE (Project ID: 956748,
admire-eurohpc.eu)
This project was partially promoted by the Ministry for Digital Transformation
and the Civil Service, within the framework of the Recovery,
Transformation and Resilience Plan - Funded by the European Union
-NextGenerationEU.
This file is part of GekkoFS' POSIX interface.
GekkoFS' POSIX interface is free software: you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
GekkoFS' POSIX interface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with GekkoFS' POSIX interface. If not, see
<https://www.gnu.org/licenses/>.
SPDX-License-Identifier: LGPL-3.0-or-later
*/
#ifndef GKFS_CLIENT_FUSE_CONTEXT_HPP
#ifndef GKFS_CLIENT_FUSE_CONTEXT_HPP
#define GKFS_CLIENT_FUSE_CONTEXT_HPP
#define GKFS_CLIENT_FUSE_CONTEXT_HPP
#include
"fuse_log.h"
#include
<utility>
extern
"C"
{
extern
"C"
{
#define FUSE_USE_VERSION FUSE_MAKE_VERSION(3, 12)
#define FUSE_USE_VERSION FUSE_MAKE_VERSION(3, 12)
#include
<fuse3/fuse_lowlevel.h>
#include
<fuse3/fuse_lowlevel.h>
...
@@ -37,42 +78,32 @@ struct _uintptr_to_must_hold_fuse_ino_t_dummy_struct {
...
@@ -37,42 +78,32 @@ struct _uintptr_to_must_hold_fuse_ino_t_dummy_struct {
};
};
#endif
#endif
/*
* FUSE: Filesystem in Userspace
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE
*/
#include
<errno.h>
#include
<errno.h>
#include
<fcntl.h>
#include
<fcntl.h>
#include
<string.h>
#include
<string.h>
#include
<sys/stat.h>
#include
<sys/stat.h>
#include
<unistd.h>
#include
<unistd.h>
#include
<filesystem>
#include
<unordered_map>
#include
<string>
#include
<mutex>
#ifdef __FreeBSD__
#ifdef __FreeBSD__
#include
<sys/socket.h>
#include
<sys/socket.h>
#include
<sys/un.h>
#include
<sys/un.h>
#endif
#endif
// GekkoFS Project Headers
#include
<common/path_util.hpp>
#include
<client/hooks.hpp>
#include
<client/logging.hpp>
// Assumed to provide LOG and CTX
#include
<client/open_dir.hpp>
#include
<client/open_file_map.hpp>
#include
<client/preload.hpp>
#include
<client/preload_context.hpp>
#include
<client/user_functions.hpp>
#include
<client/gkfs_libc.hpp>
static
inline
int
static
inline
int
do_fallocate
(
int
fd
,
int
mode
,
off_t
offset
,
off_t
length
)
{
do_fallocate
(
int
fd
,
int
mode
,
off_t
offset
,
off_t
length
)
{
#ifdef HAVE_FALLOCATE
#ifdef HAVE_FALLOCATE
...
@@ -103,6 +134,142 @@ do_fallocate(int fd, int mode, off_t offset, off_t length) {
...
@@ -103,6 +134,142 @@ do_fallocate(int fd, int mode, off_t offset, off_t length) {
#endif // HAVE_FALLOCATE
#endif // HAVE_FALLOCATE
}
}
// all from the gkfs_libc
enum
class
PathStatus
{
External
,
Internal
,
Error
};
/**
* @brief Resolves a path in the context of GekkoFS.
* (Details as in original comment)
*/
static
inline
PathStatus
resolve_gkfs_path
(
int
dirfd
,
const
char
*
path
,
std
::
string
&
resolved
,
int
flags
=
0
,
bool
resolve_last_link
=
true
)
{
const
auto
status
=
CTX
->
relativize_fd_path
(
dirfd
,
path
,
resolved
,
flags
,
resolve_last_link
);
switch
(
status
)
{
case
gkfs
::
preload
::
RelativizeStatus
::
internal
:
return
PathStatus
::
Internal
;
case
gkfs
::
preload
::
RelativizeStatus
::
fd_not_a_dir
:
errno
=
ENOTDIR
;
return
PathStatus
::
Error
;
case
gkfs
::
preload
::
RelativizeStatus
::
fd_unknown
:
errno
=
EBADF
;
return
PathStatus
::
Error
;
default:
// Assuming other statuses mean external or not applicable
return
PathStatus
::
External
;
}
}
#define DEBUG_INFO(...) \
do { \
if(CTX->interception_enabled()) \
LOG(DEBUG, __VA_ARGS__); \
} while(0)
#define GKFS_PATH_OPERATION(name, dirfd, path, ...) \
if(CTX->interception_enabled()) { \
std::string resolved; \
switch(resolve_gkfs_path(dirfd, path, resolved)) { \
case PathStatus::Internal: \
fuse_log(FUSE_LOG_DEBUG, "[GKFS] {}(path='{}')\n", #name, \
resolved.c_str()); \
return gkfs::syscall::gkfs_##name(resolved, __VA_ARGS__); \
case PathStatus::Error: \
return -1; \
default:
/* External */
\
break; \
} \
}
#define GKFS_PATH_OPERATION1(name, dirfd, path) \
if(CTX->interception_enabled()) { \
std::string resolved; \
switch(resolve_gkfs_path(dirfd, path, resolved)) { \
case PathStatus::Internal: \
fuse_log(FUSE_LOG_DEBUG, "[GKFS] {}(path='{}')\n", #name, \
resolved.c_str()); \
gkfs::syscall::gkfs_##name(resolved); \
case PathStatus::Error: \
fuse_reply_err(req, -1); \
default:
/* External */
\
fuse_reply_err(req, -1); \
} \
}
struct
GkfsDir
{
// Hypothetical structure that might be used if DIR is cast
int
fd
;
long
int
tell_pos
;
// for telldir/seekdir
char
*
path
;
// other members libc DIR might have
};
static
inline
std
::
pair
<
int
,
std
::
string
>
lol_path
(
int
dfd
,
const
char
*
path
,
int
flags
)
{
std
::
string
resolved
=
""
;
int
err
=
0
;
if
(
CTX
->
interception_enabled
())
{
// AT_SYMLINK_NOFOLLOW means lstat behavior, otherwise stat behavior.
bool
follow_link
=
!
(
flags
&
AT_SYMLINK_NOFOLLOW
);
// Path resolution needs to know if it's for lstat or stat context for
// the final component. resolve_gkfs_path's `resolve_last_link`
// parameter handles this.
switch
(
resolve_gkfs_path
(
dfd
,
path
,
resolved
,
flags
,
follow_link
))
{
case
PathStatus
::
Internal
:
break
;
case
PathStatus
::
Error
:
err
=
-
1
;
break
;
default:
// External
break
;
}
}
return
std
::
make_pair
(
err
,
resolved
);
}
static
inline
int
lol_fstatat
(
int
dfd
,
const
char
*
path
,
struct
stat
*
buf
,
int
flags
)
{
if
(
CTX
->
interception_enabled
())
{
std
::
string
resolved
;
// AT_SYMLINK_NOFOLLOW means lstat behavior, otherwise stat behavior.
bool
follow_link
=
!
(
flags
&
AT_SYMLINK_NOFOLLOW
);
// Path resolution needs to know if it's for lstat or stat context for
// the final component. resolve_gkfs_path's `resolve_last_link`
// parameter handles this.
switch
(
resolve_gkfs_path
(
dfd
,
path
,
resolved
,
flags
,
follow_link
))
{
case
PathStatus
::
Internal
:
return
gkfs
::
syscall
::
gkfs_stat
(
resolved
,
buf
,
follow_link
);
case
PathStatus
::
Error
:
return
-
1
;
// errno set
default:
// External
break
;
}
}
return
-
1
;
}
static
inline
int
lol_openat
(
int
dfd
,
const
char
*
path
,
mode_t
mode
,
int
flags
)
{
if
(
CTX
->
interception_enabled
())
{
std
::
string
resolved
;
// AT_SYMLINK_NOFOLLOW means lstat behavior, otherwise stat behavior.
bool
follow_link
=
!
(
flags
&
AT_SYMLINK_NOFOLLOW
);
// Path resolution needs to know if it's for lstat or stat context for
// the final component. resolve_gkfs_path's `resolve_last_link`
// parameter handles this.
switch
(
resolve_gkfs_path
(
dfd
,
path
,
resolved
,
flags
,
follow_link
))
{
case
PathStatus
::
Internal
:
fuse_log
(
FUSE_LOG_DEBUG
,
"lol_openat internal
\n
"
);
return
gkfs
::
syscall
::
gkfs_open
(
resolved
,
mode
,
follow_link
);
case
PathStatus
::
Error
:
return
-
1
;
// errno set
default:
// External
break
;
}
}
return
-
1
;
}
/*
/*
* Creates files on the underlying file system in response to a FUSE_MKNOD
* Creates files on the underlying file system in response to a FUSE_MKNOD
* operation
* operation
...
@@ -110,18 +277,28 @@ do_fallocate(int fd, int mode, off_t offset, off_t length) {
...
@@ -110,18 +277,28 @@ do_fallocate(int fd, int mode, off_t offset, off_t length) {
static
inline
int
static
inline
int
mknod_wrapper
(
int
dirfd
,
const
char
*
path
,
const
char
*
link
,
int
mode
,
mknod_wrapper
(
int
dirfd
,
const
char
*
path
,
const
char
*
link
,
int
mode
,
dev_t
rdev
)
{
dev_t
rdev
)
{
int
res
;
fuse_log
(
FUSE_LOG_DEBUG
,
"mknod_wrapper
\n
"
);
int
res
=
-
1
;
if
(
S_ISREG
(
mode
))
{
if
(
S_ISREG
(
mode
))
{
res
=
openat
(
dirfd
,
path
,
O_CREAT
|
O_EXCL
|
O_WRONLY
,
mode
);
res
=
lol_openat
(
dirfd
,
path
,
mode
,
O_CREAT
|
O_EXCL
|
O_WRONLY
);
fuse_log
(
FUSE_LOG_DEBUG
,
"lol_openat internal %s
\n
"
,
res
);
if
(
res
>=
0
)
if
(
res
>=
0
)
res
=
close
(
res
);
res
=
gkfs
::
syscall
::
gkfs_
close
(
res
);
}
else
if
(
S_ISDIR
(
mode
))
{
}
else
if
(
S_ISDIR
(
mode
))
{
res
=
mkdirat
(
dirfd
,
path
,
mode
);
GKFS_PATH_OPERATION
(
create
,
dirfd
,
path
,
mode
|
S_IFDIR
)
// res = gkfs::syscall::gkfs_create(resolved, mode | S_IFDIR);
// res = mkdirat(dirfd, path, mode);
}
else
if
(
S_ISLNK
(
mode
)
&&
link
!=
NULL
)
{
}
else
if
(
S_ISLNK
(
mode
)
&&
link
!=
NULL
)
{
res
=
symlinkat
(
link
,
dirfd
,
path
);
fuse_log
(
FUSE_LOG_ERR
,
"fifo in mknod_wrapper not supported
\n
"
);
errno
=
ENOTSUP
;
return
-
1
;
// res = symlinkat(link, dirfd, path);
}
else
if
(
S_ISFIFO
(
mode
))
{
}
else
if
(
S_ISFIFO
(
mode
))
{
res
=
mkfifoat
(
dirfd
,
path
,
mode
);
fuse_log
(
FUSE_LOG_ERR
,
"fifo in mknod_wrapper not supported
\n
"
);
errno
=
ENOTSUP
;
return
-
1
;
// res = mkfifoat(dirfd, path, mode);
#ifdef __FreeBSD__
#ifdef __FreeBSD__
}
else
if
(
S_ISSOCK
(
mode
))
{
}
else
if
(
S_ISSOCK
(
mode
))
{
struct
sockaddr_un
su
;
struct
sockaddr_un
su
;
...
@@ -148,7 +325,10 @@ mknod_wrapper(int dirfd, const char* path, const char* link, int mode,
...
@@ -148,7 +325,10 @@ mknod_wrapper(int dirfd, const char* path, const char* link, int mode,
}
}
#endif
#endif
}
else
{
}
else
{
res
=
mknodat
(
dirfd
,
path
,
mode
,
rdev
);
fuse_log
(
FUSE_LOG_ERR
,
"mknodat in mknod_wrapper not supported
\n
"
);
errno
=
ENOTSUP
;
return
-
1
;
// res = mknodat(dirfd, path, mode, rdev);
}
}
return
res
;
return
res
;
...
...
src/client/CMakeLists.txt
View file @
9936cd50
...
@@ -118,8 +118,10 @@ target_sources(fuse_client
...
@@ -118,8 +118,10 @@ target_sources(fuse_client
)
)
target_link_libraries
(
fuse_client
target_link_libraries
(
fuse_client
PRIVATE gkfs_common metadata distributor env_util arithmetic path_util rpc_utils
${
FUSE3_LIBRARIES
}
${
FUSE3_LIBRARIES
}
gkfs_user_lib
gkfs_user_lib
gkfs_libc_intercept
)
)
target_include_directories
(
fuse_client
target_include_directories
(
fuse_client
...
...
src/client/fuse/fuse_client.cpp
View file @
9936cd50
This diff is collapsed.
Click to expand it.
src/client/gkfs_functions.cpp
View file @
9936cd50
...
@@ -185,7 +185,7 @@ test_lock_file(const std::string& path) {
...
@@ -185,7 +185,7 @@ test_lock_file(const std::string& path) {
* @param path
* @param path
* @param mode
* @param mode
* @param flags
* @param flags
* @return
0
on success, -1 on failure
* @return
fd
on success, -1 on failure
*/
*/
int
int
gkfs_open
(
const
std
::
string
&
path
,
mode_t
mode
,
int
flags
)
{
gkfs_open
(
const
std
::
string
&
path
,
mode_t
mode
,
int
flags
)
{
...
@@ -1451,7 +1451,7 @@ gkfs_readv(int fd, const struct iovec* iov, int iovcnt) {
...
@@ -1451,7 +1451,7 @@ gkfs_readv(int fd, const struct iovec* iov, int iovcnt) {
* wrapper function for opening directories
* wrapper function for opening directories
* errno may be set
* errno may be set
* @param path
* @param path
* @return
0
on success or -1 on error
* @return
fd
on success or -1 on error
*/
*/
int
int
gkfs_opendir
(
const
std
::
string
&
path
)
{
gkfs_opendir
(
const
std
::
string
&
path
)
{
...
...
src/client/rpc/forward_metadata.cpp
View file @
9936cd50
...
@@ -664,7 +664,7 @@ forward_get_metadentry_size(const std::string& path, const int copy) {
...
@@ -664,7 +664,7 @@ forward_get_metadentry_size(const std::string& path, const int copy) {
/**
/**
* Send an RPC request to receive all entries of a directory.
* Send an RPC request to receive all entries of a directory.
* @param open_dir
* @param open_dir
* @return error code
* @return error code
, OpenDir
*/
*/
pair
<
int
,
shared_ptr
<
gkfs
::
filemap
::
OpenDir
>>
pair
<
int
,
shared_ptr
<
gkfs
::
filemap
::
OpenDir
>>
forward_get_dirents
(
const
string
&
path
)
{
forward_get_dirents
(
const
string
&
path
)
{
...
...