kmod: kernel 5.12/5.14 support

This commit is contained in:
Miroslav Crnic
2025-07-02 14:55:39 +01:00
committed by GitHub Enterprise
parent 1404d78eae
commit 88909c1f7c
12 changed files with 83 additions and 32 deletions
+3 -2
View File
@@ -1,5 +1,6 @@
#include "dentry.h"
#include "inode_compat.h"
#include "log.h"
#include "dir.h"
#include "err.h"
@@ -146,7 +147,7 @@ out_err:
}
// vfs: exclusive dir.i_rwsem, lockref dentry
int eggsfs_mkdir(struct inode* dir, struct dentry* dentry, umode_t mode) {
int COMPAT_FUNC_UNS_IMP(eggsfs_mkdir, struct inode* dir, struct dentry* dentry, umode_t mode) {
int err;
struct eggsfs_inode* dir_enode = EGGSFS_I(dir);
@@ -261,7 +262,7 @@ out_err:
}
// vfs: exclusive i_rwsem for all
int eggsfs_rename(struct inode* old_dir, struct dentry* old_dentry, struct inode* new_dir, struct dentry* new_dentry, unsigned int flags) {
int COMPAT_FUNC_UNS_IMP(eggsfs_rename, struct inode* old_dir, struct dentry* old_dentry, struct inode* new_dir, struct dentry* new_dentry, unsigned int flags) {
int err;
trace_eggsfs_vfs_rename_enter(old_dir, old_dentry, new_dir, new_dentry);
+5 -3
View File
@@ -4,19 +4,21 @@
#include <linux/fs.h>
#include "counter.h"
#include "inode_compat.h"
EGGSFS_DECLARE_COUNTER(eggsfs_stat_dir_revalidations);
extern struct dentry_operations eggsfs_dentry_ops;
struct dentry* eggsfs_lookup(struct inode* dir, struct dentry* dentry, unsigned int flags);
int eggsfs_mkdir(struct inode* dir, struct dentry* dentry, umode_t mode);
int eggsfs_rmdir(struct inode* dir, struct dentry* dentry);
int eggsfs_unlink(struct inode* dir, struct dentry* dentry);
int eggsfs_rename(
int COMPAT_FUNC_UNS(eggsfs_mkdir, struct inode* dir, struct dentry* dentry, umode_t mode);
int COMPAT_FUNC_UNS(
eggsfs_rename,
struct inode* old_dir, struct dentry* old_dentry,
struct inode* new_dir, struct dentry* new_dentry,
unsigned int flags
);
#endif
#endif /* _EGGSFS_DENTRY_H */
+1 -1
View File
@@ -18,4 +18,4 @@ tar xf "${version}.tar.gz"
cp config-kasan ${version}/.config
# Create symlink
ln -sf ${version} linux
ln -sf ${version} linux
+2
View File
@@ -1315,7 +1315,9 @@ out:
}
const struct address_space_operations eggsfs_mmap_operations = {
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0))
.readpages = file_readpages,
#endif
.readpage = file_readpage
};
+6 -5
View File
@@ -13,6 +13,7 @@
#include "file.h"
#include "wq.h"
#include "span.h"
#include "inode_compat.h"
// Some services (samba) try to preallocate larger files, but can handle
// the failure or absence of ftruncate().
@@ -427,7 +428,7 @@ out_err:
return ERR_PTR(err);
}
static int eggsfs_create(struct inode* parent, struct dentry* dentry, umode_t mode, bool excl) {
static int COMPAT_FUNC_UNS_IMP(eggsfs_create, struct inode* parent, struct dentry* dentry, umode_t mode, bool excl) {
struct eggsfs_inode* enode = eggsfs_create_internal(parent, EGGSFS_INODE_FILE, dentry);
if (IS_ERR(enode)) { return PTR_ERR(enode); }
@@ -439,7 +440,7 @@ static int eggsfs_create(struct inode* parent, struct dentry* dentry, umode_t mo
}
// vfs: refcount of path->dentry
static int eggsfs_getattr(const struct path* path, struct kstat* stat, u32 request_mask, unsigned int query_flags) {
static int COMPAT_FUNC_UNS_IMP(eggsfs_getattr, const struct path* path, struct kstat* stat, u32 request_mask, unsigned int query_flags) {
struct inode* inode = d_inode(path->dentry);
struct eggsfs_inode* enode = EGGSFS_I(inode);
@@ -467,7 +468,7 @@ static int eggsfs_getattr(const struct path* path, struct kstat* stat, u32 reque
}
done:
generic_fillattr(inode, stat);
COMPAT_FUNC_UNS_CALL(generic_fillattr, inode, stat);
trace_eggsfs_vfs_getattr_exit(inode, 0);
return 0;
}
@@ -508,7 +509,7 @@ static int eggsfs_do_ftruncate(struct dentry* dentry, struct iattr* attr) {
return 0;
}
static int eggsfs_setattr(struct dentry* dentry, struct iattr* attr) {
static int COMPAT_FUNC_UNS_IMP(eggsfs_setattr, struct dentry* dentry, struct iattr* attr) {
// https://elixir.bootlin.com/linux/v5.4/source/fs/open.c#L49 is the only
// place where ATTR_SIZE is set, which means only when truncating.
if (attr->ia_valid & ATTR_SIZE) {
@@ -564,7 +565,7 @@ static int eggsfs_setattr(struct dentry* dentry, struct iattr* attr) {
return 0;
}
static int eggsfs_symlink(struct inode* dir, struct dentry* dentry, const char* path) {
static int COMPAT_FUNC_UNS_IMP(eggsfs_symlink, struct inode* dir, struct dentry* dentry, const char* path) {
struct eggsfs_inode* enode = eggsfs_create_internal(dir, EGGSFS_INODE_SYMLINK, dentry);
if (IS_ERR(enode)) { return PTR_ERR(enode); }
-2
View File
@@ -2,8 +2,6 @@
#define _EGGSFS_INODE_H
#include <linux/fs.h>
#include <linux/spinlock.h>
#include <linux/xarray.h>
#include "latch.h"
#include "bincode.h"
+16
View File
@@ -0,0 +1,16 @@
#ifndef _EGGSFS_INODE_COMPAT_H
#define _EGGSFS_INODE_COMPAT_H
#include <linux/version.h>
// Compatibility for user_namespace struct
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)
#define COMPAT_FUNC_UNS(name, ...) name(__VA_ARGS__);
#define COMPAT_FUNC_UNS_IMP(name, ...) name(__VA_ARGS__)
#define COMPAT_FUNC_UNS_CALL(name, ...) name(__VA_ARGS__);
#else
#define COMPAT_FUNC_UNS(name, ...) name(struct user_namespace*, __VA_ARGS__);
#define COMPAT_FUNC_UNS_IMP(name, ...) name(struct user_namespace* uns, __VA_ARGS__)
#define COMPAT_FUNC_UNS_CALL(name, ...) name(uns, __VA_ARGS__);
#endif
#endif /* _EGGSFS_INODE_COMPAT_H */
+3 -6
View File
@@ -9,13 +9,10 @@
#include "debugfs.h"
#include "metadata.h"
#include "inode.h"
#include "net_compat.h"
#define MSECS_TO_JIFFIES(_ms) ((_ms * HZ) / 1000)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
#define kernel_setsockopt(sock, level, optname, optval, optlen) sock_setsockopt(sock, level, optname, KERNEL_SOCKPTR(optval), optlen)
#endif
unsigned eggsfs_initial_shard_timeout_jiffies = MSECS_TO_JIFFIES(250);
unsigned eggsfs_max_shard_timeout_jiffies = MSECS_TO_JIFFIES(2000);
unsigned eggsfs_overall_shard_timeout_jiffies = MSECS_TO_JIFFIES(10000);
@@ -89,7 +86,7 @@ static void sock_readable(struct sock* sk) {
s = (struct eggsfs_metadata_socket*)sk->sk_user_data;
BUG_ON(!s);
for (;;) {
skb = skb_recv_udp(sk, 0, 1, &err);
skb = COMPAT_SKB_RECV_UDP(sk, MSG_DONTWAIT, &err);
if (!skb) {
read_unlock_bh(&sk->sk_callback_lock);
return;
@@ -193,7 +190,7 @@ int eggsfs_init_shard_socket(struct eggsfs_metadata_socket* s) {
int new_rcvbuf_size = 1024 * 1024;
int optlen = sizeof(new_rcvbuf_size);
err = kernel_setsockopt(s->sock, SOL_SOCKET, SO_RCVBUF, (char *)&new_rcvbuf_size, optlen);
err = COMPAT_SET_SOCKOPT(s->sock, SOL_SOCKET, SO_RCVBUF, &new_rcvbuf_size, optlen);
if (err) { goto out_socket; }
write_lock_bh(&s->sock->sk->sk_callback_lock);
+19
View File
@@ -0,0 +1,19 @@
#ifndef _EGGSFS_NET_COMPAT_H
#define _EGGSFS_NET_COMPAT_H
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 19, 0)
#define COMPAT_SKB_RECV_UDP(sk, flags, err) skb_recv_udp(sk, flags, flags & MSG_DONTWAIT, err)
#else
#define COMPAT_SKB_RECV_UDP(sk, flags, err) skb_recv_udp(sk, flags, err)
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0)
#include <linux/net.h>
#define COMPAT_SET_SOCKOPT(sock, level, op, optval, optlen) kernel_setsockopt(sock, level, op, (char *) optval, optlen)
#else
#include <linux/sockptr.h>
#define COMPAT_SET_SOCKOPT(sock, level, op, optval, optlen) sock_setsockopt(sock, level, op, KERNEL_SOCKPTR(optval), optlen)
#endif
#endif /* _EGGSFS_NET_COMPAT_H */
+5 -8
View File
@@ -9,10 +9,7 @@
#include "log.h"
#include "err.h"
#include "super.h"
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
#define kernel_setsockopt(sock, level, optname, optval, optlen) sock_setsockopt(sock, level, optname, KERNEL_SOCKPTR(optval), optlen)
#endif
#include "net_compat.h"
void eggsfs_write_shuckle_req_header(char* buf, u32 req_len, u8 req_kind) {
put_unaligned_le32(EGGSFS_SHUCKLE_REQ_PROTOCOL_VERSION, buf); buf += 4;
@@ -151,7 +148,7 @@ int eggsfs_create_shuckle_socket(struct eggsfs_shuckle_addr* saddr, struct socke
struct sockaddr_in addrs[2];
memset(&addrs, 0, sizeof(addrs));
err = eggsfs_process_shuckle_addr(saddr, &addrs[0], &addrs[1]);
if (err) {
return err;
@@ -167,19 +164,19 @@ int eggsfs_create_shuckle_socket(struct eggsfs_shuckle_addr* saddr, struct socke
struct __kernel_sock_timeval tv;
tv.tv_sec = 10;
tv.tv_usec = 0;
err = kernel_setsockopt(*sock, SOL_SOCKET, SO_RCVTIMEO_NEW, (char *)&tv, sizeof(tv));
err = COMPAT_SET_SOCKOPT(*sock, SOL_SOCKET, SO_RCVTIMEO_NEW, &tv, sizeof(tv));
if (err < 0) {
eggsfs_warn("could not set receive timeout on shuckle socket: %d", err);
goto out_sock;
}
err = kernel_setsockopt(*sock, SOL_SOCKET, SO_SNDTIMEO_NEW, (char *)&tv, sizeof(tv));
err = COMPAT_SET_SOCKOPT(*sock, SOL_SOCKET, SO_SNDTIMEO_NEW, &tv, sizeof(tv));
if (err < 0) {
eggsfs_warn("could not set send timeout on shuckle socket: %d", err);
goto out_sock;
}
int syn_count = 3;
err = kernel_setsockopt(*sock, SOL_TCP, TCP_SYNCNT, (char *)&syn_count, sizeof(syn_count));
err = COMPAT_SET_SOCKOPT(*sock, SOL_TCP, TCP_SYNCNT, &syn_count, sizeof(syn_count));
if (err < 0) {
eggsfs_warn("could not set TCP_SYNCNT=%d on shuckle socket: %d", syn_count, err);
goto out_sock;
+3 -3
View File
@@ -11,10 +11,10 @@
#include "block.h"
#include "metadata.h"
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
#define __sysctl_buffer __kernel
#else
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
#define __sysctl_buffer __user
#else
#define __sysctl_buffer __kernel
#endif
int eggsfs_debug_output = 0;
+20 -2
View File
@@ -27,11 +27,13 @@ TRACE_DEFINE_ENUM(LOOKUP_OPEN);
TRACE_DEFINE_ENUM(LOOKUP_CREATE);
TRACE_DEFINE_ENUM(LOOKUP_EXCL);
TRACE_DEFINE_ENUM(LOOKUP_RENAME_TARGET);
TRACE_DEFINE_ENUM(LOOKUP_JUMPED);
TRACE_DEFINE_ENUM(LOOKUP_ROOT);
TRACE_DEFINE_ENUM(LOOKUP_EMPTY);
TRACE_DEFINE_ENUM(LOOKUP_DOWN);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0))
TRACE_DEFINE_ENUM(LOOKUP_JUMPED);
TRACE_DEFINE_ENUM(LOOKUP_ROOT);
#define show_lookup_flags(flags) \
__print_flags(flags, "|", \
{ LOOKUP_FOLLOW, "FOLLOW" }, \
@@ -48,7 +50,23 @@ TRACE_DEFINE_ENUM(LOOKUP_DOWN);
{ LOOKUP_ROOT, "ROOT" }, \
{ LOOKUP_EMPTY, "EMPTY" }, \
{ LOOKUP_DOWN, "DOWN" })
#else
#define show_lookup_flags(flags) \
__print_flags(flags, "|", \
{ LOOKUP_FOLLOW, "FOLLOW" }, \
{ LOOKUP_DIRECTORY, "DIRECTORY" }, \
{ LOOKUP_AUTOMOUNT, "AUTOMOUNT" }, \
{ LOOKUP_PARENT, "PARENT" }, \
{ LOOKUP_REVAL, "REVAL" }, \
{ LOOKUP_RCU, "RCU" }, \
{ LOOKUP_OPEN, "OPEN" }, \
{ LOOKUP_CREATE, "CREATE" }, \
{ LOOKUP_EXCL, "EXCL" }, \
{ LOOKUP_RENAME_TARGET, "RENAME_TARGET" }, \
{ LOOKUP_EMPTY, "EMPTY" }, \
{ LOOKUP_DOWN, "DOWN" })
#endif
#define EGGSFS_TRACE_EVENT_inode(_name) \
TRACE_EVENT(eggsfs_##_name, \