Viewing: wbcfs.h
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2025-2026, DDN/Whamcloud, Inc.
*/
/*
* Embed memory file system with writeback support that using for OSD.
*
* Author: Yingjin Qian <qian@ddn.com>
*/
#ifndef _OSD_WBCFS_H_
#define _OSD_WBCFS_H_
#include <lustre_compat/linux/mm.h>
#include <linux/spinlock.h>
#include <linux/uidgid.h>
#include <linux/percpu.h>
#include <linux/iversion.h>
#include <lustre_fid.h>
#include "index.h"
/* Pretend that each entry is of this size in directory's i_size */
#define BOGO_DIRENT_SIZE 20
/* Pretend that one inode + its dentry occupy this much memory */
#define BOGO_INODE_SIZE 1024
#define WBCFS_MAGIC 0xbdacbd05
/* In-memory xattr list */
struct mem_xattrs {
spinlock_t mex_lock;
struct list_head mex_xattr_list;
};
struct memfs_options {
unsigned long long meo_blocks;
unsigned long long meo_inodes;
kuid_t meo_uid;
kgid_t meo_gid;
umode_t meo_mode;
bool meo_noswap;
};
struct memfs_sb_info {
/* How many blocks are allowed. */
unsigned long msi_max_blocks;
/* How many blocks are allocated. */
struct percpu_counter msi_used_blocks;
/* How many inodes are allowed. */
unsigned long msi_max_inodes;
/* How much ispace left for allocation. */
unsigned long msi_free_inodes;
/* Serialize memfs_sb_info changes. */
spinlock_t msi_stat_lock;
/* Mount mode for root directory */
umode_t msi_mode;
/* Mount uid for root directory */
kuid_t msi_uid;
/* Mount gid for root directory */
kgid_t msi_gid;
/* Whether enable swap with much larger capacity. */
bool msi_noswap;
/* Whether there is backing persistent store. */
bool msi_no_backing;
/* TODO: Quota limits support for MemFS. */
};
enum index_type {
INDEX_TYPE_NONE = 0,
INDEX_TYPE_HASH,
INDEX_TYPE_MTREE,
};
/* MemFS inode in-kernel data */
struct memfs_inode_info {
__u32 mei_flags;
struct mem_xattrs mei_xattrs;
struct lu_fid mei_fid;
/* Project ID */
kprojid_t mei_projid;
/* File creation time. */
struct timespec64 mei_crtime;
/*
* Index access for dir dentry or indexing KV store.
* Currently only support hash index with linear iterating.
* Next step add Maple Tree index.
* TODO: use maple tree to manage dir entries under this dir.
*/
enum index_type mei_index_type;
struct hash_index mei_hash_index;
/* Stack backing inode with the persistent storage. */
struct inode *mei_backing;
struct inode mei_vfs_inode;
};
#define MEMFS_I(inode) (container_of(inode, struct memfs_inode_info, \
mei_vfs_inode))
#define MEMFS_DIR_EOF ((1ULL << (64 - 1)) - 1)
struct memfs_dir_context {
struct dir_context super;
struct dentry *dentry;
void *cbdata;
};
static inline u32 i_projid_read(struct inode *inode)
{
return (u32)from_kprojid(&init_user_ns, MEMFS_I(inode)->mei_projid);
}
static inline void i_projid_write(struct inode *inode, u32 projid)
{
kprojid_t kprojid;
kprojid = make_kprojid(&init_user_ns, (projid_t)projid);
MEMFS_I(inode)->mei_projid = kprojid;
}
static inline int memfs_test_inode_by_fid(struct inode *inode, void *opaque)
{
return lu_fid_eq(&MEMFS_I(inode)->mei_fid, opaque);
}
static inline __u64 memfs_get_btime(struct inode *inode)
{
return MEMFS_I(inode)->mei_crtime.tv_sec;
}
static inline __u32 memfs_get_flags(struct inode *inode)
{
return MEMFS_I(inode)->mei_flags;
}
static inline unsigned long memfs_default_max_blocks(void)
{
return compat_totalram_pages() / 2;
}
static inline unsigned long memfs_default_max_inodes(void)
{
unsigned long nr_pages = compat_totalram_pages();
/*
* return min(nr_pages - totalhigh_pages(), nr_pages / 2);
*/
return nr_pages / 2;
}
int memfs_xattr_get(struct inode *inode, void *buf, size_t len,
const char *name);
int memfs_xattr_set(struct inode *inode, void *buf, size_t len,
const char *name, int flags);
void memfs_xattr_del(struct inode *inode, const char *name);
struct inode *memfs_create_inode(struct super_block *sb, struct inode *dir,
umode_t mode, struct iattr *iattr, dev_t dev,
bool update_link);
int memfs_init(void);
void memfs_fini(void);
#endif /* _OSD_WBCFS_H_ */