NFS support in kmod

This commit is contained in:
Saulius Grusnys
2023-10-02 13:26:03 +00:00
committed by Francesco Mazzoli
parent 3eb784b1cf
commit 40afc8183e
8 changed files with 168 additions and 6 deletions

View File

@@ -6,6 +6,7 @@ obj-m += eggsfs.o
eggsfs-objs += \
dir.o \
err.o \
export.o \
file.o \
inode.o \
kmod.o \

View File

@@ -443,6 +443,7 @@ struct file_operations eggsfs_dir_operations = {
.iterate = eggsfs_dir_read,
.iterate_shared = eggsfs_dir_read,
.release = eggsfs_dir_close,
.llseek = generic_file_llseek,
};
int __init eggsfs_dir_init(void) {

133
kmod/export.c Normal file
View File

@@ -0,0 +1,133 @@
#include "export.h"
#include "inode.h"
#include "metadata.h"
#include <linux/exportfs.h>
enum eggsfs_fid_type {
EGGSFS_FILEID_ROOT = 0,
EGGSFS_FILEID_GEN = 1,
EGGSFS_FILEID_GEN_PARENT = 2,
};
struct eggsfs_fid64 {
u64 ino;
u64 parent_ino;
} __attribute__((packed));
static int eggsfs_fileid_length(int fileid_type) {
switch (fileid_type) {
case EGGSFS_FILEID_GEN:
return 3;
case EGGSFS_FILEID_GEN_PARENT:
return 6;
}
return FILEID_INVALID;
}
static int eggsfs_encode_fh(struct inode *inode, u32 *fh, int *max_len, struct inode *parent) {
struct eggsfs_fid64* fid64 = (struct eggsfs_fid64 *)fh;
int fileid_type;
int len;
if (!parent) {
fileid_type = EGGSFS_FILEID_GEN;
} else {
fileid_type = EGGSFS_FILEID_GEN_PARENT;
}
len = eggsfs_fileid_length(fileid_type);
if (*max_len < len) {
*max_len = len;
return FILEID_INVALID;
}
*max_len = len;
switch (fileid_type) {
case EGGSFS_FILEID_GEN_PARENT:
fid64->parent_ino = EGGSFS_I(parent)->inode.i_ino;
/*FALLTHRU*/
case EGGSFS_FILEID_GEN:
fid64->ino = EGGSFS_I(inode)->inode.i_ino;
break;
}
return fileid_type;
}
static struct inode * eggsfs_nfs_get_inode(struct super_block *sb, u64 ino) {
// NFS can sometimes send requests for ino 0. Fail them gracefully.
if (ino == 0) {
return ERR_PTR(-ESTALE);
}
struct inode *inode = eggsfs_get_inode(sb, NULL, ino);
if (IS_ERR(inode)) {
eggsfs_info("returning error %ld as ESTALE", PTR_ERR(inode));
return ERR_PTR(-ESTALE);
}
return inode;
}
static struct dentry * eggsfs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, int fileid_type) {
struct eggsfs_fid64 *fid64 = (struct eggsfs_fid64 *)fid;
struct inode *inode = NULL;
if (fh_len < eggsfs_fileid_length(fileid_type)) {
return NULL;
}
switch (fileid_type) {
case EGGSFS_FILEID_GEN_PARENT:
case EGGSFS_FILEID_GEN:
inode = eggsfs_nfs_get_inode(sb, fid64->ino);
break;
}
return d_obtain_alias(inode);
}
static struct dentry * eggsfs_fh_to_parent(struct super_block *sb, struct fid *fid, int fh_len, int fileid_type) {
struct eggsfs_fid64 *fid64 = (struct eggsfs_fid64 *)fid;
struct inode *inode = NULL;
if (fh_len < eggsfs_fileid_length(fileid_type)) {
return NULL;
}
switch (fileid_type) {
case EGGSFS_FILEID_GEN_PARENT:
inode = eggsfs_nfs_get_inode(sb, fid64->parent_ino);
break;
}
return d_obtain_alias(inode);
}
static struct dentry * eggsfs_get_parent(struct dentry *child) {
int err;
u64 mtime;
u64 owner;
struct eggsfs_policy_body block_policy;
struct eggsfs_policy_body span_policy;
struct eggsfs_policy_body stripe_policy;
err = eggsfs_shard_getattr_dir(
(struct eggsfs_fs_info *)child->d_inode->i_sb->s_fs_info,
child->d_inode->i_ino,
&mtime,
&owner,
&block_policy,
&span_policy,
&stripe_policy
);
if (err != 0 ) {
return ERR_PTR(err);
}
return d_obtain_alias(eggsfs_nfs_get_inode(child->d_sb, owner));
}
struct export_operations eggsfs_export_ops = {
.encode_fh = eggsfs_encode_fh,
.fh_to_dentry = eggsfs_fh_to_dentry,
.fh_to_parent = eggsfs_fh_to_parent,
.get_parent = eggsfs_get_parent,
};

8
kmod/export.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef _EGGSFS_EXPORT_H
#define _EGGSFS_EXPORT_H
#include <linux/fs.h>
extern struct export_operations eggsfs_export_ops;
#endif /* _EGGSFS_EXPORT_H */

View File

@@ -91,6 +91,7 @@ again: // progress: whoever wins the lock won't try again
bool has_atime = false;
u64 atime;
if (S_ISDIR(enode->inode.i_mode)) {
u64 owner;
struct eggsfs_policy_body block_policy;
struct eggsfs_policy_body span_policy;
struct eggsfs_policy_body stripe_policy;
@@ -98,6 +99,7 @@ again: // progress: whoever wins the lock won't try again
(struct eggsfs_fs_info*)enode->inode.i_sb->s_fs_info,
enode->inode.i_ino,
&mtime,
&owner,
&block_policy,
&span_policy,
&stripe_policy
@@ -178,6 +180,12 @@ static struct eggsfs_inode* eggsfs_create_internal(struct inode* parent, int ity
BUG_ON(dentry->d_inode);
if (current->group_leader->mm == NULL) {
// internal-repo/blob/main/docs/kmod-file-tracking.md
eggsfs_warn("current->group_leader->mm = NULL, called from kernel thread?");
return(ERR_PTR(-EIO));
}
struct eggsfs_inode* parent_enode = EGGSFS_I(parent);
if (dentry->d_name.len > EGGSFS_MAX_FILENAME) { return ERR_PTR(-ENAMETOOLONG); }
@@ -424,10 +432,16 @@ struct inode* eggsfs_get_inode(struct super_block* sb, struct eggsfs_inode* pare
enode->span_policy = parent->span_policy;
enode->stripe_policy = parent->stripe_policy;
} else {
BUG_ON(ino != EGGSFS_ROOT_INODE);
enode->block_policy = NULL;
enode->span_policy = NULL;
enode->stripe_policy = NULL;
if (ino != EGGSFS_ROOT_INODE) {
struct eggsfs_inode* root = EGGSFS_I(sb->s_root->d_inode);
enode->block_policy = root->block_policy;
enode->span_policy = root->span_policy;
enode->stripe_policy = root->stripe_policy;
} else {
enode->block_policy = NULL;
enode->span_policy = NULL;
enode->stripe_policy = NULL;
}
}
unlock_new_inode(inode);

View File

@@ -482,6 +482,7 @@ int eggsfs_shard_getattr_dir(
struct eggsfs_fs_info* info,
u64 dir,
u64* mtime,
u64* owner,
struct eggsfs_policy_body* block_policies,
struct eggsfs_policy_body* span_policies,
struct eggsfs_policy_body* stripe_policy
@@ -508,8 +509,8 @@ int eggsfs_shard_getattr_dir(
PREPARE_SHARD_RESP_CTX();
eggsfs_stat_directory_resp_get_start(&ctx, start);
eggsfs_stat_directory_resp_get_mtime(&ctx, start, resp_mtime);
eggsfs_stat_directory_resp_get_owner(&ctx, resp_mtime, owner);
eggsfs_stat_directory_resp_get_info(&ctx, owner, resp_info);
eggsfs_stat_directory_resp_get_owner(&ctx, resp_mtime, resp_owner);
eggsfs_stat_directory_resp_get_info(&ctx, resp_owner, resp_info);
eggsfs_directory_info_get_entries(&ctx, resp_info, entries);
int i;
for (i = 0; i < entries.len; i++) {
@@ -536,6 +537,7 @@ int eggsfs_shard_getattr_dir(
eggsfs_stat_directory_resp_get_finish(&ctx, end);
FINISH_RESP();
*mtime = resp_mtime.x;
*owner = resp_owner.x;
}
return 0;

View File

@@ -26,6 +26,7 @@ int eggsfs_shard_getattr_dir(
struct eggsfs_fs_info* info,
u64 file,
u64* mtime,
u64* owner,
struct eggsfs_policy_body* block_policies,
struct eggsfs_policy_body* span_policies,
struct eggsfs_policy_body* stripe_policy

View File

@@ -7,6 +7,7 @@
#include "log.h"
#include "inode.h"
#include "export.h"
#include "metadata.h"
#include "dentry.h"
#include "net.h"
@@ -337,6 +338,7 @@ static struct dentry* eggsfs_mount(struct file_system_type* fs_type, int flags,
sb->s_op = &eggsfs_super_ops;
sb->s_d_op = &eggsfs_dentry_ops;
sb->s_export_op = &eggsfs_export_ops;
sb->s_time_gran = 1;
sb->s_time_min = 0;