2025-08-10 01:34:16 +02:00

206 lines
6.4 KiB
C

#ifndef FHGFSOPSFILE_H_
#define FHGFSOPSFILE_H_
#include <app/App.h>
#include <common/threading/Mutex.h>
#include <common/toolkit/Time.h>
#include <net/filesystem/FhgfsOpsRemoting.h>
#include <filesystem/FsDirInfo.h>
#include <filesystem/FsFileInfo.h>
#include <toolkit/NoAllocBufferStore.h>
#include <common/toolkit/MetadataTk.h>
#include <common/Common.h>
#include "FhgfsOps_versions.h"
#include "FhgfsOpsInode.h"
#include <linux/fs.h>
#include <linux/vfs.h>
#include <linux/pagemap.h>
#include <linux/uio.h>
#ifndef SEEK_SET
#define SEEK_SET 0 /* seek relative to beginning of file */
#define SEEK_CUR 1 /* seek relative to current file position */
#define SEEK_END 2 /* seek relative to end of file */
#endif
// forward declaration
struct App;
extern struct file_operations fhgfs_file_buffered_ops;
extern struct file_operations fhgfs_file_pagecache_ops;
extern struct file_operations fhgfs_dir_ops;
extern struct address_space_operations fhgfs_address_ops;
extern struct address_space_operations fhgfs_address_pagecache_ops;
extern loff_t FhgfsOps_llseekdir(struct file *file, loff_t offset, int origin);
extern loff_t FhgfsOps_llseek(struct file *file, loff_t offset, int origin);
extern int FhgfsOps_opendirIncremental(struct inode* inode, struct file* file);
extern int FhgfsOps_releasedir(struct inode* inode, struct file* file);
#ifdef KERNEL_HAS_ITERATE_DIR
extern int FhgfsOps_iterateIncremental(struct file* file, struct dir_context* ctx);
#else
extern int FhgfsOps_readdirIncremental(struct file* file, void* buf, filldir_t filldir);
#endif // LINUX_VERSION_CODE
extern int FhgfsOps_open(struct inode* inode, struct file* file);
extern int FhgfsOps_openReferenceHandle(App* app, struct inode* inode, struct file* file,
unsigned openFlags, LookupIntentInfoOut* lookupInfo, uint32_t* outVersion);
extern int FhgfsOps_release(struct inode* inode, struct file* file);
#ifdef KERNEL_HAS_FSYNC_RANGE /* added in vanilla 3.1 */
int FhgfsOps_fsync(struct file* file, loff_t start, loff_t end, int datasync);
#elif !defined(KERNEL_HAS_FSYNC_DENTRY)
int FhgfsOps_fsync(struct file* file, int datasync);
#else
/* LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,34) */
int FhgfsOps_fsync(struct file* file, struct dentry* dentry, int datasync);
#endif // LINUX_VERSION_CODE
extern int __FhgfsOps_flush(App* app, struct file *file, bool discardCacheOnError,
bool forceRemoteFlush, bool checkSession, bool isClose);
extern int FhgfsOps_flock(struct file* file, int cmd, struct file_lock* fileLock);
extern int FhgfsOps_lock(struct file* file, int cmd, struct file_lock* fileLock);
extern int FhgfsOps_readlink(struct dentry* dentry, char __user* buf, int size);
extern ssize_t FhgfsOps_read(struct file* file, char __user *buf, size_t size,
loff_t* offsetPointer);
extern ssize_t FhgfsOps_write(struct file* file, const char __user *buf, size_t size,
loff_t* offsetPointer);
ssize_t FhgfsOps_read_iter(struct kiocb *iocb, struct iov_iter *to);
ssize_t FhgfsOps_write_iter(struct kiocb *iocb, struct iov_iter *from);
extern int FhgfsOps_mmap(struct file *, struct vm_area_struct *);
extern ssize_t FhgfsOps_directIO(struct kiocb *iocb, struct iov_iter *iter);
extern int FhgfsOps_releaseCancelLocks(struct inode* inode, struct file* file);
extern ssize_t __FhgfsOps_readSparse(struct file* file, struct iov_iter *iter, size_t size,
loff_t offset);
// getters & setters
static inline FsObjectInfo* __FhgfsOps_getObjectInfo(struct file* file);
static inline FsDirInfo* __FhgfsOps_getDirInfo(struct file* file);
static inline void __FhgfsOps_setDirInfo(FsDirInfo* dirInfo, struct file* outFile);
static inline FsFileInfo* __FhgfsOps_getFileInfo(struct file* file);
static inline void __FhgfsOps_setFileInfo(FsFileInfo* fileInfo, struct file* outFile);
static inline int __FhgfsOps_getCurrentLockPID(void);
static inline int64_t __FhgfsOps_getCurrentLockFD(struct file* file);
FsObjectInfo* __FhgfsOps_getObjectInfo(struct file* file)
{
return (FsObjectInfo*)file->private_data;
}
FsDirInfo* __FhgfsOps_getDirInfo(struct file* file)
{
return (FsDirInfo*)file->private_data;
}
void __FhgfsOps_setDirInfo(FsDirInfo* dirInfo, struct file* outFile)
{
outFile->private_data = dirInfo;
}
FsFileInfo* __FhgfsOps_getFileInfo(struct file* file)
{
return (FsFileInfo*)file->private_data;
}
void __FhgfsOps_setFileInfo(FsFileInfo* fileInfo, struct file* outFile)
{
outFile->private_data = fileInfo;
}
/**
* @return lock pid of the current process (which is _not_ current->pid)
*/
int __FhgfsOps_getCurrentLockPID(void)
{
/* note: tgid (not current->pid) is the actual equivalent of the number that getpid() returns to
user-space and is also the thing that is assigned to fl_pid in "<kernel>/fs/locks.c" */
return current->tgid;
}
/**
* @return virtual file descriptor for entry locking (which is _not_ the user-space fd)
*/
int64_t __FhgfsOps_getCurrentLockFD(struct file* file)
{
/* note: we can't get the user-space fd here and the rest of the kernel entry locking routines
in "<kernel>/fs/locks.c" also uses the struct file pointer for comparison instead, so we
return that one here. */
return (size_t)file;
}
#ifdef KERNEL_WRITE_BEGIN_USES_FOLIO
typedef struct folio* beegfs_pgfol_t;
#else
typedef struct page* beegfs_pgfol_t;
#endif
#ifdef KERNEL_WRITE_BEGIN_HAS_FLAGS
#define BEEGFS_HAS_WRITE_FLAGS 1
#else
#define BEEGFS_HAS_WRITE_FLAGS 0
#endif
/**
* Converts a struct page* into a beegfs_pgfol_t, which may be a folio* or page*.
*/
static inline beegfs_pgfol_t beegfs_to_pgfol(struct page *page)
{
#ifdef KERNEL_WRITE_BEGIN_USES_FOLIO
return page_folio(page);
#else
return page;
#endif
}
/**
* Retrieves the struct page* from a beegfs_pgfol_t (whether folio or page).
*/
static inline struct page* beegfs_get_page(beegfs_pgfol_t pgfol)
{
#ifdef KERNEL_WRITE_BEGIN_USES_FOLIO
return &pgfol->page;
#else
return pgfol;
#endif
}
/**
* Wrapper for grab_cache_page_write_begin that accounts for whether the kernel
* expects a flags parameter or not.
*/
static inline struct page* beegfs_grab_cache_page(struct address_space* mapping,
pgoff_t index,
unsigned flags)
{
#ifdef KERNEL_WRITE_BEGIN_HAS_FLAGS
return grab_cache_page_write_begin(mapping, index, flags);
#else
IGNORE_UNUSED_VARIABLE(flags);
return grab_cache_page_write_begin(mapping, index);
#endif
}
#endif /*FHGFSOPSFILE_H_*/