mirror of
https://github.com/trapexit/mergerfs.git
synced 2026-10-20 00:17:43 +00:00
Compare commits
62
Commits
latest-release
...
hash
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c3aaad788d | ||
|
|
0c75265a5c | ||
|
|
1478f6c108 | ||
|
|
a03c1f744c | ||
|
|
fb2d2815dc | ||
|
|
7eed1a1b7e | ||
|
|
12c688b22a | ||
|
|
906869ea99 | ||
|
|
2ffb08cbc5 | ||
|
|
4103e7888f | ||
|
|
d3280318c8 | ||
|
|
7ea1dbdeeb | ||
|
|
8b1ceacac2 | ||
|
|
96b64a3352 | ||
|
|
9805000a06 | ||
|
|
8ede80285b | ||
|
|
128aac3163 | ||
|
|
dde5c1b1c3 | ||
|
|
ff33249ad7 | ||
|
|
51ed4b29c4 | ||
|
|
d33815a815 | ||
|
|
90803f3e60 | ||
|
|
b45ec632ad | ||
|
|
d7fc056fc6 | ||
|
|
ec99ce37ff | ||
|
|
baaa84bbd2 | ||
|
|
acdb8746b8 | ||
|
|
8e6de63a34 | ||
|
|
0b0d0de73a | ||
|
|
c0e806586d | ||
|
|
eaee64365f | ||
|
|
e24d72290a | ||
|
|
e9d653d8c5 | ||
|
|
9633cea1fd | ||
|
|
ef737b6153 | ||
|
|
81a6f7f139 | ||
|
|
9854d99432 | ||
|
|
a1bed8f56e | ||
|
|
b40efff031 | ||
|
|
2d89e4675f | ||
|
|
0295bffcfc | ||
|
|
dea533aa47 | ||
|
|
80d74f33bb | ||
|
|
7b1ba40d49 | ||
|
|
cfb53af882 | ||
|
|
c38c5aefc8 | ||
|
|
a107770099 | ||
|
|
bba4edd434 | ||
|
|
9a99dc21f1 | ||
|
|
bb1081c692 | ||
|
|
49e11a3f0c | ||
|
|
adb0e305c2 | ||
|
|
dc8cc1f3f9 | ||
|
|
03a9c4692f | ||
|
|
ff3f10123d | ||
|
|
390f1e6cc4 | ||
|
|
08446ffde5 | ||
|
|
0fd1822188 | ||
|
|
bc382e0fd2 | ||
|
|
0197984db3 | ||
|
|
248b1aca1c | ||
|
|
9056898bbf |
@@ -71,6 +71,8 @@ CFLAGS := \
|
||||
-Wall \
|
||||
-pipe \
|
||||
-MMD
|
||||
CXXFLAGS ?= \
|
||||
$(OPT_FLAGS)
|
||||
CXXFLAGS := \
|
||||
${CXXFLAGS} \
|
||||
$(LTO_FLAGS) \
|
||||
|
||||
@@ -442,7 +442,7 @@ struct fuse_file_lock {
|
||||
#define FUSE_HANDLE_KILLPRIV_V2 (1 << 28)
|
||||
#define FUSE_SETXATTR_EXT (1 << 29)
|
||||
#define FUSE_INIT_EXT (1 << 30)
|
||||
#define FUSE_INIT_RESERVED (1 << 31)
|
||||
#define FUSE_INIT_RESERVED (1ULL << 31)
|
||||
/* bits 32..63 get shifted down 32 bits into the flags2 field */
|
||||
#define FUSE_SECURITY_CTX (1ULL << 32)
|
||||
#define FUSE_HAS_INODE_DAX (1ULL << 33)
|
||||
|
||||
+48
-884
@@ -131,891 +131,55 @@ struct fuse_ctx
|
||||
*/
|
||||
struct fuse_lowlevel_ops
|
||||
{
|
||||
/**
|
||||
* Initialize filesystem
|
||||
*
|
||||
* Called before any other filesystem method
|
||||
*
|
||||
* There's no reply to this function
|
||||
*
|
||||
* @param userdata the user data passed to fuse_lowlevel_new()
|
||||
*/
|
||||
void (*init)(void *userdata, struct fuse_conn_info *conn);
|
||||
|
||||
/**
|
||||
* Clean up filesystem
|
||||
*
|
||||
* Called on filesystem exit
|
||||
*
|
||||
* There's no reply to this function
|
||||
*
|
||||
* @param userdata the user data passed to fuse_lowlevel_new()
|
||||
*/
|
||||
void (*access)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*bmap)(fuse_req_t req, const struct fuse_in_header *hdr);
|
||||
void (*copy_file_range)(fuse_req_t req, const struct fuse_in_header *hdr);
|
||||
void (*create)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*destroy)(void *userdata);
|
||||
|
||||
/**
|
||||
* Look up a directory entry by name and get its attributes.
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_entry
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param parent inode number of the parent directory
|
||||
* @param name the name to look up
|
||||
*/
|
||||
void (*lookup)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Forget about an inode
|
||||
*
|
||||
* This function is called when the kernel removes an inode
|
||||
* from its internal caches.
|
||||
*
|
||||
* The inode's lookup count increases by one for every call to
|
||||
* fuse_reply_entry and fuse_reply_create. The nlookup parameter
|
||||
* indicates by how much the lookup count should be decreased.
|
||||
*
|
||||
* Inodes with a non-zero lookup count may receive request from
|
||||
* the kernel even after calls to unlink, rmdir or (when
|
||||
* overwriting an existing file) rename. Filesystems must handle
|
||||
* such requests properly and it is recommended to defer removal
|
||||
* of the inode until the lookup count reaches zero. Calls to
|
||||
* unlink, remdir or rename will be followed closely by forget
|
||||
* unless the file or directory is open, in which case the
|
||||
* kernel issues forget only after the release or releasedir
|
||||
* calls.
|
||||
*
|
||||
* Note that if a file system will be exported over NFS the
|
||||
* inodes lifetime must extend even beyond forget. See the
|
||||
* generation field in struct fuse_entry_param above.
|
||||
*
|
||||
* On unmount the lookup count for all inodes implicitly drops
|
||||
* to zero. It is not guaranteed that the file system will
|
||||
* receive corresponding forget messages for the affected
|
||||
* inodes.
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_none
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param nlookup the number of lookups to forget
|
||||
*/
|
||||
void (*forget)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Get file attributes
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_attr
|
||||
* fuse_reply_err
|
||||
*/
|
||||
void (*getattr)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Set file attributes
|
||||
*
|
||||
* In the 'attr' argument only members indicated by the 'to_set'
|
||||
* bitmask contain valid values. Other members contain undefined
|
||||
* values.
|
||||
*
|
||||
* If the setattr was invoked from the ftruncate() system call
|
||||
* under Linux kernel versions 2.6.15 or later, the fi->fh will
|
||||
* contain the value set by the open method or will be undefined
|
||||
* if the open method didn't set any value. Otherwise (not
|
||||
* ftruncate call, or kernel version earlier than 2.6.15) the fi
|
||||
* parameter will be NULL.
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_attr
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param attr the attributes
|
||||
* @param to_set bit mask of attributes which should be set
|
||||
* @param fi file information, or NULL
|
||||
*
|
||||
* Changed in version 2.5:
|
||||
* file information filled in for ftruncate
|
||||
*/
|
||||
void (*setattr)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Read symbolic link
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_readlink
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
*/
|
||||
void (*readlink)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Create file node
|
||||
*
|
||||
* Create a regular file, character device, block device, fifo or
|
||||
* socket node.
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_entry
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param parent inode number of the parent directory
|
||||
* @param name to create
|
||||
* @param mode file type and mode with which to create the new file
|
||||
* @param rdev the device number (only valid if created file is a device)
|
||||
*/
|
||||
void (*mknod)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Create a directory
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_entry
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param parent inode number of the parent directory
|
||||
* @param name to create
|
||||
* @param mode with which to create the new file
|
||||
*/
|
||||
void (*mkdir)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Remove a file
|
||||
*
|
||||
* If the file's inode's lookup count is non-zero, the file
|
||||
* system is expected to postpone any removal of the inode
|
||||
* until the lookup count reaches zero (see description of the
|
||||
* forget function).
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param parent inode number of the parent directory
|
||||
* @param name to remove
|
||||
*/
|
||||
void (*unlink)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Remove a directory
|
||||
*
|
||||
* If the directory's inode's lookup count is non-zero, the
|
||||
* file system is expected to postpone any removal of the
|
||||
* inode until the lookup count reaches zero (see description
|
||||
* of the forget function).
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param parent inode number of the parent directory
|
||||
* @param name to remove
|
||||
*/
|
||||
void (*rmdir)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Create a symbolic link
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_entry
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param link the contents of the symbolic link
|
||||
* @param parent inode number of the parent directory
|
||||
* @param name to create
|
||||
*/
|
||||
void (*symlink)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/** Rename a file
|
||||
*
|
||||
* If the target exists it should be atomically replaced. If
|
||||
* the target's inode's lookup count is non-zero, the file
|
||||
* system is expected to postpone any removal of the inode
|
||||
* until the lookup count reaches zero (see description of the
|
||||
* forget function).
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param parent inode number of the old parent directory
|
||||
* @param name old name
|
||||
* @param newparent inode number of the new parent directory
|
||||
* @param newname new name
|
||||
*/
|
||||
void (*rename)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Create a hard link
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_entry
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the old inode number
|
||||
* @param newparent inode number of the new parent directory
|
||||
* @param newname new name to create
|
||||
*/
|
||||
void (*link)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Open a file
|
||||
*
|
||||
* Open flags (with the exception of O_CREAT, O_EXCL, O_NOCTTY and
|
||||
* O_TRUNC) are available in fi->flags.
|
||||
*
|
||||
* Filesystem may store an arbitrary file handle (pointer, index,
|
||||
* etc) in fi->fh, and use this in other all other file operations
|
||||
* (read, write, flush, release, fsync).
|
||||
*
|
||||
* Filesystem may also implement stateless file I/O and not store
|
||||
* anything in fi->fh.
|
||||
*
|
||||
* There are also some flags (direct_io, keep_cache) which the
|
||||
* filesystem may set in fi, to change the way the file is opened.
|
||||
* See fuse_file_info structure in <fuse_common.h> for more details.
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_open
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param fi file information
|
||||
*/
|
||||
void (*open)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Read data
|
||||
*
|
||||
* Read should send exactly the number of bytes requested except
|
||||
* on EOF or error, otherwise the rest of the data will be
|
||||
* substituted with zeroes. An exception to this is when the file
|
||||
* has been opened in 'direct_io' mode, in which case the return
|
||||
* value of the read system call will reflect the return value of
|
||||
* this operation.
|
||||
*
|
||||
* fi->fh will contain the value set by the open method, or will
|
||||
* be undefined if the open method didn't set any value.
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_buf
|
||||
* fuse_reply_iov
|
||||
* fuse_reply_data
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param size number of bytes to read
|
||||
* @param off offset to read from
|
||||
* @param fi file information
|
||||
*/
|
||||
void (*read)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Write data
|
||||
*
|
||||
* Write should return exactly the number of bytes requested
|
||||
* except on error. An exception to this is when the file has
|
||||
* been opened in 'direct_io' mode, in which case the return value
|
||||
* of the write system call will reflect the return value of this
|
||||
* operation.
|
||||
*
|
||||
* fi->fh will contain the value set by the open method, or will
|
||||
* be undefined if the open method didn't set any value.
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_write
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param buf data to write
|
||||
* @param size number of bytes to write
|
||||
* @param off offset to write to
|
||||
* @param fi file information
|
||||
*/
|
||||
void (*write)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Flush method
|
||||
*
|
||||
* This is called on each close() of the opened file.
|
||||
*
|
||||
* Since file descriptors can be duplicated (dup, dup2, fork), for
|
||||
* one open call there may be many flush calls.
|
||||
*
|
||||
* Filesystems shouldn't assume that flush will always be called
|
||||
* after some writes, or that if will be called at all.
|
||||
*
|
||||
* fi->fh will contain the value set by the open method, or will
|
||||
* be undefined if the open method didn't set any value.
|
||||
*
|
||||
* NOTE: the name of the method is misleading, since (unlike
|
||||
* fsync) the filesystem is not forced to flush pending writes.
|
||||
* One reason to flush data, is if the filesystem wants to return
|
||||
* write errors.
|
||||
*
|
||||
* If the filesystem supports file locking operations (setlk,
|
||||
* getlk) it should remove all locks belonging to 'fi->owner'.
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param fi file information
|
||||
*/
|
||||
void (*flush)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Release an open file
|
||||
*
|
||||
* Release is called when there are no more references to an open
|
||||
* file: all file descriptors are closed and all memory mappings
|
||||
* are unmapped.
|
||||
*
|
||||
* For every open call there will be exactly one release call.
|
||||
*
|
||||
* The filesystem may reply with an error, but error values are
|
||||
* not returned to close() or munmap() which triggered the
|
||||
* release.
|
||||
*
|
||||
* fi->fh will contain the value set by the open method, or will
|
||||
* be undefined if the open method didn't set any value.
|
||||
* fi->flags will contain the same flags as for open.
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param fi file information
|
||||
*/
|
||||
void (*release)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Synchronize file contents
|
||||
*
|
||||
* If the datasync parameter is non-zero, then only the user data
|
||||
* should be flushed, not the meta data.
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param datasync flag indicating if only data should be flushed
|
||||
* @param fi file information
|
||||
*/
|
||||
void (*fsync)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Open a directory
|
||||
*
|
||||
* Filesystem may store an arbitrary file handle (pointer, index,
|
||||
* etc) in fi->fh, and use this in other all other directory
|
||||
* stream operations (readdir, releasedir, fsyncdir).
|
||||
*
|
||||
* Filesystem may also implement stateless directory I/O and not
|
||||
* store anything in fi->fh, though that makes it impossible to
|
||||
* implement standard conforming directory stream operations in
|
||||
* case the contents of the directory can change between opendir
|
||||
* and releasedir.
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_open
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param fi file information
|
||||
*/
|
||||
void (*opendir)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Read directory
|
||||
*
|
||||
* Send a buffer filled using fuse_add_direntry(), with size not
|
||||
* exceeding the requested size. Send an empty buffer on end of
|
||||
* stream.
|
||||
*
|
||||
* fi->fh will contain the value set by the opendir method, or
|
||||
* will be undefined if the opendir method didn't set any value.
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_buf
|
||||
* fuse_reply_data
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param size maximum number of bytes to send
|
||||
* @param off offset to continue reading the directory stream
|
||||
* @param fi file information
|
||||
*/
|
||||
void (*readdir)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
void (*readdir_plus)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Release an open directory
|
||||
*
|
||||
* For every opendir call there will be exactly one releasedir
|
||||
* call.
|
||||
*
|
||||
* fi->fh will contain the value set by the opendir method, or
|
||||
* will be undefined if the opendir method didn't set any value.
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param fi file information
|
||||
*/
|
||||
void (*releasedir)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Synchronize directory contents
|
||||
*
|
||||
* If the datasync parameter is non-zero, then only the directory
|
||||
* contents should be flushed, not the meta data.
|
||||
*
|
||||
* fi->fh will contain the value set by the opendir method, or
|
||||
* will be undefined if the opendir method didn't set any value.
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param datasync flag indicating if only data should be flushed
|
||||
* @param fi file information
|
||||
*/
|
||||
void (*fsyncdir)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Get file system statistics
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_statfs
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number, zero means "undefined"
|
||||
*/
|
||||
void (*statfs)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Set an extended attribute
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_err
|
||||
*/
|
||||
void (*setxattr)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Get an extended attribute
|
||||
*
|
||||
* If size is zero, the size of the value should be sent with
|
||||
* fuse_reply_xattr.
|
||||
*
|
||||
* If the size is non-zero, and the value fits in the buffer, the
|
||||
* value should be sent with fuse_reply_buf.
|
||||
*
|
||||
* If the size is too small for the value, the ERANGE error should
|
||||
* be sent.
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_buf
|
||||
* fuse_reply_data
|
||||
* fuse_reply_xattr
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param name of the extended attribute
|
||||
* @param size maximum size of the value to send
|
||||
*/
|
||||
void (*getxattr)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* List extended attribute names
|
||||
*
|
||||
* If size is zero, the total size of the attribute list should be
|
||||
* sent with fuse_reply_xattr.
|
||||
*
|
||||
* If the size is non-zero, and the null character separated
|
||||
* attribute list fits in the buffer, the list should be sent with
|
||||
* fuse_reply_buf.
|
||||
*
|
||||
* If the size is too small for the list, the ERANGE error should
|
||||
* be sent.
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_buf
|
||||
* fuse_reply_data
|
||||
* fuse_reply_xattr
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param size maximum size of the list to send
|
||||
*/
|
||||
void (*listxattr)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Remove an extended attribute
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param name of the extended attribute
|
||||
*/
|
||||
void (*removexattr)(fuse_req_t req,
|
||||
const struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Check file access permissions
|
||||
*
|
||||
* This will be called for the access() system call. If the
|
||||
* 'default_permissions' mount option is given, this method is not
|
||||
* called.
|
||||
*
|
||||
* This method is not called under Linux kernel versions 2.4.x
|
||||
*
|
||||
* Introduced in version 2.5
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param mask requested access mode
|
||||
*/
|
||||
void (*access)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Create and open a file
|
||||
*
|
||||
* If the file does not exist, first create it with the specified
|
||||
* mode, and then open it.
|
||||
*
|
||||
* Open flags (with the exception of O_NOCTTY) are available in
|
||||
* fi->flags.
|
||||
*
|
||||
* Filesystem may store an arbitrary file handle (pointer, index,
|
||||
* etc) in fi->fh, and use this in other all other file operations
|
||||
* (read, write, flush, release, fsync).
|
||||
*
|
||||
* There are also some flags (direct_io, keep_cache) which the
|
||||
* filesystem may set in fi, to change the way the file is opened.
|
||||
* See fuse_file_info structure in <fuse_common.h> for more details.
|
||||
*
|
||||
* If this method is not implemented or under Linux kernel
|
||||
* versions earlier than 2.6.15, the mknod() and open() methods
|
||||
* will be called instead.
|
||||
*
|
||||
* Introduced in version 2.5
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_create
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param parent inode number of the parent directory
|
||||
* @param name to create
|
||||
* @param mode file type and mode with which to create the new file
|
||||
* @param fi file information
|
||||
*/
|
||||
void (*create)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Test for a POSIX file lock
|
||||
*
|
||||
* Introduced in version 2.6
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_lock
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param fi file information
|
||||
* @param lock the region/type to test
|
||||
*/
|
||||
void (*getlk)(fuse_req_t req,
|
||||
const struct fuse_in_header *hdr);
|
||||
/**
|
||||
* Acquire, modify or release a POSIX file lock
|
||||
*
|
||||
* For POSIX threads (NPTL) there's a 1-1 relation between pid and
|
||||
* owner, but otherwise this is not always the case. For checking
|
||||
* lock ownership, 'fi->owner' must be used. The l_pid field in
|
||||
* 'struct flock' should only be used to fill in this field in
|
||||
* getlk().
|
||||
*
|
||||
* Note: if the locking methods are not implemented, the kernel
|
||||
* will still allow file locking to work locally. Hence these are
|
||||
* only interesting for network filesystems and similar.
|
||||
*
|
||||
* Introduced in version 2.6
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param fi file information
|
||||
* @param lock the region/type to set
|
||||
* @param sleep locking operation may sleep
|
||||
*/
|
||||
void (*setlk)(fuse_req_t req, uint64_t ino,
|
||||
fuse_file_info_t *fi,
|
||||
struct flock *lock, int sleep);
|
||||
|
||||
/**
|
||||
* Map block index within file to block index within device
|
||||
*
|
||||
* Note: This makes sense only for block device backed filesystems
|
||||
* mounted with the 'blkdev' option
|
||||
*
|
||||
* Introduced in version 2.6
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_bmap
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param blocksize unit of block index
|
||||
* @param idx block index within file
|
||||
*/
|
||||
void (*bmap)(fuse_req_t req,
|
||||
const struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Ioctl
|
||||
*
|
||||
* Note: For unrestricted ioctls (not allowed for FUSE
|
||||
* servers), data in and out areas can be discovered by giving
|
||||
* iovs and setting FUSE_IOCTL_RETRY in @flags. For
|
||||
* restricted ioctls, kernel prepares in/out data area
|
||||
* according to the information encoded in cmd.
|
||||
*
|
||||
* Introduced in version 2.8
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_ioctl_retry
|
||||
* fuse_reply_ioctl
|
||||
* fuse_reply_ioctl_iov
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param cmd ioctl command
|
||||
* @param arg ioctl argument
|
||||
* @param fi file information
|
||||
* @param flags for FUSE_IOCTL_* flags
|
||||
* @param in_buf data fetched from the caller
|
||||
* @param in_bufsz number of fetched bytes
|
||||
* @param out_bufsz maximum size of output data
|
||||
*/
|
||||
void (*ioctl)(fuse_req_t req,
|
||||
const struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Poll for IO readiness
|
||||
*
|
||||
* Introduced in version 2.8
|
||||
*
|
||||
* Note: If ph is non-NULL, the client should notify
|
||||
* when IO readiness events occur by calling
|
||||
* fuse_lowelevel_notify_poll() with the specified ph.
|
||||
*
|
||||
* Regardless of the number of times poll with a non-NULL ph
|
||||
* is received, single notification is enough to clear all.
|
||||
* Notifying more times incurs overhead but doesn't harm
|
||||
* correctness.
|
||||
*
|
||||
* The callee is responsible for destroying ph with
|
||||
* fuse_pollhandle_destroy() when no longer in use.
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_poll
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param fi file information
|
||||
* @param ph poll handle to be used for notification
|
||||
*/
|
||||
void (*poll)(fuse_req_t req,
|
||||
const struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Callback function for the retrieve request
|
||||
*
|
||||
* Introduced in version 2.9
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_none
|
||||
*
|
||||
* @param req request handle
|
||||
* @param cookie user data supplied to fuse_lowlevel_notify_retrieve()
|
||||
* @param ino the inode number supplied to fuse_lowlevel_notify_retrieve()
|
||||
* @param offset the offset supplied to fuse_lowlevel_notify_retrieve()
|
||||
* @param bufv the buffer containing the returned data
|
||||
*/
|
||||
void (*retrieve_reply)(fuse_req_t req,
|
||||
void *cookie,
|
||||
uint64_t ino,
|
||||
off_t offset);
|
||||
|
||||
/**
|
||||
* Forget about multiple inodes
|
||||
*
|
||||
* See description of the forget function for more
|
||||
* information.
|
||||
*
|
||||
* Introduced in version 2.9
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_none
|
||||
*
|
||||
* @param req request handle
|
||||
*/
|
||||
void (*forget_multi)(fuse_req_t req,
|
||||
struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Acquire, modify or release a BSD file lock
|
||||
*
|
||||
* Note: if the locking methods are not implemented, the kernel
|
||||
* will still allow file locking to work locally. Hence these are
|
||||
* only interesting for network filesystems and similar.
|
||||
*
|
||||
* Introduced in version 2.9
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param fi file information
|
||||
* @param op the locking operation, see flock(2)
|
||||
*/
|
||||
void (*flock)(fuse_req_t req, uint64_t ino,
|
||||
fuse_file_info_t *fi, int op);
|
||||
|
||||
/**
|
||||
* Allocate requested space. If this function returns success then
|
||||
* subsequent writes to the specified range shall not fail due to the lack
|
||||
* of free space on the file system storage media.
|
||||
*
|
||||
* Introduced in version 2.9
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino the inode number
|
||||
* @param offset starting point for allocated region
|
||||
* @param length size of allocated region
|
||||
* @param mode determines the operation to be performed on the given range,
|
||||
* see fallocate(2)
|
||||
*/
|
||||
void (*fallocate)(fuse_req_t req,
|
||||
const struct fuse_in_header *hdr);
|
||||
|
||||
/**
|
||||
* Copy a range of data from one file to another
|
||||
*
|
||||
* Performs an optimized copy between two file descriptors without
|
||||
* the
|
||||
* additional cost of transferring data through the FUSE kernel
|
||||
* module
|
||||
* to user space (glibc) and then back into the FUSE filesystem
|
||||
* again.
|
||||
*
|
||||
* In case this method is not implemented, glibc falls back to
|
||||
* reading
|
||||
* data from the source and writing to the destination. Effectively
|
||||
* doing an inefficient copy of the data.
|
||||
*
|
||||
* If this request is answered with an error code of ENOSYS, this is
|
||||
* treated as a permanent failure with error code EOPNOTSUPP,
|
||||
* i.e. all
|
||||
* future copy_file_range() requests will fail with EOPNOTSUPP
|
||||
* without
|
||||
* being send to the filesystem process.
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_write
|
||||
* fuse_reply_err
|
||||
*
|
||||
* @param req request handle
|
||||
* @param ino_in the inode number of the source file
|
||||
* @param off_in starting point from were the data should be read
|
||||
* @param fi_in file information of the source file
|
||||
* @param ino_out the inode number of the destination file
|
||||
* @param off_out starting point where the data should be written
|
||||
* @param fi_out file information of the destination file
|
||||
* @param len maximum size of the data to copy
|
||||
* @param flags passed along with the copy_file_range() syscall
|
||||
*/
|
||||
void (*copy_file_range)(fuse_req_t req,
|
||||
const struct fuse_in_header *hdr);
|
||||
|
||||
void (*setupmapping)(fuse_req_t req,
|
||||
const struct fuse_in_header *hdr);
|
||||
void (*removemapping)(fuse_req_t req,
|
||||
const struct fuse_in_header *hdr);
|
||||
void (*syncfs)(fuse_req_t req,
|
||||
const struct fuse_in_header *hdr);
|
||||
void (*tmpfile)(fuse_req_t req,
|
||||
const struct fuse_in_header *hdr);
|
||||
void (*fallocate)(fuse_req_t req, const struct fuse_in_header *hdr);
|
||||
void (*flock)(fuse_req_t req, uint64_t ino, fuse_file_info_t *fi, int op);
|
||||
void (*flush)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*forget)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*forget_multi)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*fsync)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*fsyncdir)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*getattr)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*getlk)(fuse_req_t req, const struct fuse_in_header *hdr);
|
||||
void (*getxattr)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*init)(void *userdata, struct fuse_conn_info *conn);
|
||||
void (*ioctl)(fuse_req_t req, const struct fuse_in_header *hdr);
|
||||
void (*link)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*listxattr)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*lookup)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*lseek)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*mkdir)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*mknod)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*open)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*opendir)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*poll)(fuse_req_t req, const struct fuse_in_header *hdr);
|
||||
void (*read)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*readdir)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*readdir_plus)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*readlink)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*release)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*releasedir)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*removemapping)(fuse_req_t req, const struct fuse_in_header *hdr);
|
||||
void (*removexattr)(fuse_req_t req, const struct fuse_in_header *hdr);
|
||||
void (*rename)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*rename2)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*retrieve_reply)(fuse_req_t req, void *cookie, uint64_t ino, off_t offset);
|
||||
void (*rmdir)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*setattr)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*setlk)(fuse_req_t req, uint64_t ino, fuse_file_info_t *fi, struct flock *lock, int sleep);
|
||||
void (*setupmapping)(fuse_req_t req, const struct fuse_in_header *hdr);
|
||||
void (*setxattr)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*statfs)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*statx)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*symlink)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*syncfs)(fuse_req_t req, const struct fuse_in_header *hdr);
|
||||
void (*tmpfile)(fuse_req_t req, const struct fuse_in_header *hdr);
|
||||
void (*unlink)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
void (*write)(fuse_req_t req, struct fuse_in_header *hdr);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
#ifndef CRC32B_H_INCLUDED
|
||||
#define CRC32B_H_INCLUDED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef unsigned int crc32b_t;
|
||||
|
||||
crc32b_t crc32b_start(void);
|
||||
@@ -29,4 +34,8 @@ crc32b_t crc32b_finish(const crc32b_t crc);
|
||||
|
||||
crc32b_t crc32b(const void *buf, crc32b_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include "fuse_kernel.h"
|
||||
|
||||
@@ -211,7 +213,7 @@ void
|
||||
debug_open_flags(const uint32_t flags_)
|
||||
{
|
||||
fprintf(stderr,"%s, ",open_accmode_to_str(flags_));
|
||||
for(int i = 0; i < (sizeof(flags_) * 8); i++)
|
||||
for(size_t i = 0; i < (sizeof(flags_) * 8); i++)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
@@ -252,11 +254,11 @@ debug_fuse_open_out(const struct fuse_open_out *arg_)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"fuse_open_out:"
|
||||
" fh=0x%"PRIx64";"
|
||||
" fh=0x%" PRIx64 ";"
|
||||
" open_flags=0x%X (",
|
||||
arg_->fh,
|
||||
arg_->open_flags);
|
||||
for(int i = 0; i < (sizeof(arg_->open_flags) * 8); i++)
|
||||
for(size_t i = 0; i < (sizeof(arg_->open_flags) * 8); i++)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
@@ -276,7 +278,7 @@ static
|
||||
void
|
||||
debug_fuse_lookup(const void *arg_)
|
||||
{
|
||||
const char *name = arg_;
|
||||
const char *name = (const char*)arg_;
|
||||
|
||||
fprintf(g_OUTPUT,
|
||||
"fuse_lookup:"
|
||||
@@ -290,12 +292,12 @@ static
|
||||
void
|
||||
debug_fuse_getattr_in(const void *arg_)
|
||||
{
|
||||
const struct fuse_getattr_in *arg = arg_;
|
||||
const struct fuse_getattr_in *arg = (const fuse_getattr_in*)arg_;
|
||||
|
||||
fprintf(g_OUTPUT,
|
||||
"fuse_getattr_in:"
|
||||
" getattr_flags=0x%08X;"
|
||||
" fh=0x%"PRIx64";\n",
|
||||
" fh=0x%" PRIx64 ";\n",
|
||||
arg->getattr_flags,
|
||||
arg->fh);
|
||||
}
|
||||
@@ -304,12 +306,12 @@ static
|
||||
void
|
||||
debug_fuse_setattr_in(const void *arg_)
|
||||
{
|
||||
const struct fuse_setattr_in *arg = arg_;
|
||||
const struct fuse_setattr_in *arg = (const fuse_setattr_in*)arg_;
|
||||
|
||||
fprintf(g_OUTPUT,
|
||||
"fuse_setattr_in:"
|
||||
" valid=%u;"
|
||||
" fh=0x%"PRIx64";"
|
||||
" fh=0x%" PRIx64 ";"
|
||||
" size=%zu;"
|
||||
" lock_owner=%zu;"
|
||||
" atime=%zu;"
|
||||
@@ -342,7 +344,7 @@ static
|
||||
void
|
||||
debug_fuse_access_in(const void *arg_)
|
||||
{
|
||||
const struct fuse_access_in *arg = arg_;
|
||||
const struct fuse_access_in *arg = (const fuse_access_in*)arg_;
|
||||
|
||||
fprintf(g_OUTPUT,
|
||||
"fuse_access_in:"
|
||||
@@ -356,7 +358,7 @@ static
|
||||
void
|
||||
debug_fuse_mknod_in(const void *arg_)
|
||||
{
|
||||
const struct fuse_mknod_in *arg = arg_;
|
||||
const struct fuse_mknod_in *arg = (const fuse_mknod_in*)arg_;
|
||||
|
||||
fprintf(g_OUTPUT,
|
||||
"fuse_mknod_in:"
|
||||
@@ -374,7 +376,7 @@ static
|
||||
void
|
||||
debug_fuse_mkdir_in(const void *arg_)
|
||||
{
|
||||
const struct fuse_mkdir_in *arg = arg_;
|
||||
const struct fuse_mkdir_in *arg = (const fuse_mkdir_in*)arg_;
|
||||
|
||||
fprintf(g_OUTPUT,
|
||||
"fuse_mkdir_in:"
|
||||
@@ -392,7 +394,7 @@ static
|
||||
void
|
||||
debug_fuse_unlink(const void *arg_)
|
||||
{
|
||||
const char *name = arg_;
|
||||
const char *name = (const char*)arg_;
|
||||
|
||||
fprintf(g_OUTPUT,
|
||||
"fuse_unlink:"
|
||||
@@ -406,7 +408,7 @@ static
|
||||
void
|
||||
debug_fuse_rmdir(const void *arg_)
|
||||
{
|
||||
const char *name = arg_;
|
||||
const char *name = (const char*)arg_;
|
||||
|
||||
fprintf(g_OUTPUT,
|
||||
"fuse_mkdir:"
|
||||
@@ -423,7 +425,7 @@ debug_fuse_symlink(const void *arg_)
|
||||
const char *name;
|
||||
const char *linkname;
|
||||
|
||||
name = arg_;
|
||||
name = (const char*)arg_;
|
||||
linkname = (name + (strlen(name) + 1));
|
||||
|
||||
fprintf(g_OUTPUT,
|
||||
@@ -442,7 +444,7 @@ debug_fuse_rename_in(const void *arg_)
|
||||
{
|
||||
const char *oldname;
|
||||
const char *newname;
|
||||
const struct fuse_rename_in *arg = arg_;
|
||||
const struct fuse_rename_in *arg = (const fuse_rename_in*)arg_;
|
||||
|
||||
oldname = PARAM(arg);
|
||||
newname = (oldname + strlen(oldname) + 1);
|
||||
@@ -464,7 +466,7 @@ void
|
||||
debug_fuse_link_in(const void *arg_)
|
||||
{
|
||||
const char *name;
|
||||
const struct fuse_link_in *arg = arg_;
|
||||
const struct fuse_link_in *arg = (const fuse_link_in*)arg_;
|
||||
|
||||
name = PARAM(arg);
|
||||
|
||||
@@ -483,7 +485,7 @@ void
|
||||
debug_fuse_create_in(const void *arg_)
|
||||
{
|
||||
const char *name;
|
||||
const struct fuse_create_in *arg = arg_;
|
||||
const struct fuse_create_in *arg = (const fuse_create_in*)arg_;
|
||||
|
||||
name = PARAM(arg);
|
||||
|
||||
@@ -505,7 +507,7 @@ static
|
||||
void
|
||||
debug_fuse_open_in(const void *arg_)
|
||||
{
|
||||
const struct fuse_open_in *arg = arg_;
|
||||
const struct fuse_open_in *arg = (const fuse_open_in*)arg_;
|
||||
|
||||
fprintf(g_OUTPUT,
|
||||
"fuse_open_in:"
|
||||
@@ -519,15 +521,15 @@ static
|
||||
void
|
||||
debug_fuse_read_in(const void *arg_)
|
||||
{
|
||||
const struct fuse_read_in *arg = arg_;
|
||||
const struct fuse_read_in *arg = (const fuse_read_in*)arg_;
|
||||
|
||||
fprintf(g_OUTPUT,
|
||||
"fuse_read_in:"
|
||||
" fh=0x%"PRIx64";"
|
||||
" fh=0x%" PRIx64 ";"
|
||||
" offset=%zu;"
|
||||
" size=%u;"
|
||||
" read_flags=%X;"
|
||||
" lock_owner=0x%"PRIx64";"
|
||||
" lock_owner=0x%" PRIx64 ";"
|
||||
" flags=0x%X ("
|
||||
,
|
||||
arg->fh,
|
||||
@@ -544,14 +546,14 @@ static
|
||||
void
|
||||
debug_fuse_write_in(const void *arg_)
|
||||
{
|
||||
const struct fuse_write_in *arg = arg_;
|
||||
const struct fuse_write_in *arg = (const fuse_write_in*)arg_;
|
||||
|
||||
fprintf(g_OUTPUT,
|
||||
"fuse_write_in:"
|
||||
" fh=0x%"PRIx64";"
|
||||
" fh=0x%" PRIx64 ";"
|
||||
" offset=%zu;"
|
||||
" size=%u;"
|
||||
" lock_owner=0x%"PRIx64";"
|
||||
" lock_owner=0x%" PRIx64 ";"
|
||||
" flags=0x%X ("
|
||||
,
|
||||
arg->fh,
|
||||
@@ -563,7 +565,7 @@ debug_fuse_write_in(const void *arg_)
|
||||
fprintf(g_OUTPUT,
|
||||
"); write_flags=0x%X (",
|
||||
arg->write_flags);
|
||||
for(int i = 0; i < (sizeof(arg->write_flags) * 8); i++)
|
||||
for(size_t i = 0; i < (sizeof(arg->write_flags) * 8); i++)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
@@ -583,12 +585,12 @@ static
|
||||
void
|
||||
debug_fuse_flush_in(const void *arg_)
|
||||
{
|
||||
const struct fuse_flush_in *arg = arg_;
|
||||
const struct fuse_flush_in *arg = (const fuse_flush_in*)arg_;
|
||||
|
||||
fprintf(g_OUTPUT,
|
||||
"fuse_flush_in:"
|
||||
" fh=0x%"PRIx64";"
|
||||
" lock_owner=0x%"PRIx64";"
|
||||
" fh=0x%" PRIx64 ";"
|
||||
" lock_owner=0x%" PRIx64 ";"
|
||||
"\n"
|
||||
,
|
||||
arg->fh,
|
||||
@@ -599,13 +601,13 @@ static
|
||||
void
|
||||
debug_fuse_release_in(const void *arg_)
|
||||
{
|
||||
const struct fuse_release_in *arg = arg_;
|
||||
const struct fuse_release_in *arg = (const fuse_release_in*)arg_;
|
||||
|
||||
fprintf(g_OUTPUT,
|
||||
"fuse_release_in:"
|
||||
" fh=0x%"PRIx64";"
|
||||
" fh=0x%" PRIx64 ";"
|
||||
" release_flags=0x%X;"
|
||||
" lock_owner=0x%"PRIx64";"
|
||||
" lock_owner=0x%" PRIx64 ";"
|
||||
" flags=0x%X ("
|
||||
,
|
||||
arg->fh,
|
||||
@@ -620,11 +622,11 @@ static
|
||||
void
|
||||
debug_fuse_fsync_in(const void *arg_)
|
||||
{
|
||||
const struct fuse_fsync_in *arg = arg_;
|
||||
const struct fuse_fsync_in *arg = (const fuse_fsync_in*)arg_;
|
||||
|
||||
fprintf(g_OUTPUT,
|
||||
"fuse_fsync_in:"
|
||||
" fh=0x%"PRIx64";"
|
||||
" fh=0x%" PRIx64 ";"
|
||||
" fsync_flags=0x%X;"
|
||||
"\n"
|
||||
,
|
||||
@@ -638,7 +640,7 @@ debug_fuse_setxattr_in(const void *arg_)
|
||||
{
|
||||
const char *name;
|
||||
const char *value;
|
||||
const struct fuse_setxattr_in *arg = arg_;
|
||||
const struct fuse_setxattr_in *arg = (const fuse_setxattr_in*)arg_;
|
||||
|
||||
name = PARAM(arg);
|
||||
value = (name + strlen(name) + 1);
|
||||
@@ -662,7 +664,7 @@ void
|
||||
debug_fuse_getxattr_in(const void *arg_)
|
||||
{
|
||||
const char *name;
|
||||
const struct fuse_getxattr_in *arg = arg_;
|
||||
const struct fuse_getxattr_in *arg = (const fuse_getxattr_in*)arg_;
|
||||
|
||||
name = PARAM(arg);
|
||||
|
||||
@@ -680,7 +682,7 @@ static
|
||||
void
|
||||
debug_fuse_listxattr(const void *arg_)
|
||||
{
|
||||
const struct fuse_getxattr_in *arg = arg_;
|
||||
const struct fuse_getxattr_in *arg = (const fuse_getxattr_in*)arg_;
|
||||
|
||||
fprintf(g_OUTPUT,
|
||||
"fuse_listxattr:"
|
||||
@@ -694,7 +696,7 @@ static
|
||||
void
|
||||
debug_fuse_removexattr(const void *arg_)
|
||||
{
|
||||
const char *name = arg_;
|
||||
const char *name = (const char*)arg_;
|
||||
|
||||
fprintf(g_OUTPUT,
|
||||
"fuse_removexattr:"
|
||||
@@ -708,11 +710,11 @@ static
|
||||
void
|
||||
debug_fuse_fallocate_in(const void *arg_)
|
||||
{
|
||||
const struct fuse_fallocate_in *arg = arg_;
|
||||
const struct fuse_fallocate_in *arg = (const fuse_fallocate_in*)arg_;
|
||||
|
||||
fprintf(g_OUTPUT,
|
||||
"fuse_fallocate_in:"
|
||||
" fh=0x%"PRIx64";"
|
||||
" fh=0x%" PRIx64 ";"
|
||||
" offset=%zu;"
|
||||
" length=%zu;"
|
||||
" mode=%o;"
|
||||
@@ -766,10 +768,10 @@ debug_fuse_init_out(const uint64_t unique_,
|
||||
|
||||
flags = (((uint64_t)arg->flags) | ((uint64_t)arg->flags2) << 32);
|
||||
fprintf(g_OUTPUT,
|
||||
/* "unique=0x%016"PRIx64";" */
|
||||
/* "unique=0x%016" PRIx64 ";" */
|
||||
/* " opcode=RESPONSE;" */
|
||||
/* " error=0 (Success);" */
|
||||
/* " len=%"PRIu64"; || " */
|
||||
/* " len=%" PRIu64 "; || " */
|
||||
"FUSE_INIT_OUT:"
|
||||
" major=%u;"
|
||||
" minor=%u;"
|
||||
@@ -819,14 +821,14 @@ debug_fuse_attr(const struct fuse_attr *attr_)
|
||||
{
|
||||
fprintf(g_OUTPUT,
|
||||
"attr:"
|
||||
" ino=0x%016"PRIx64";"
|
||||
" size=%"PRIu64";"
|
||||
" blocks=%"PRIu64";"
|
||||
" atime=%"PRIu64";"
|
||||
" ino=0x%016" PRIx64 ";"
|
||||
" size=%" PRIu64 ";"
|
||||
" blocks=%" PRIu64 ";"
|
||||
" atime=%" PRIu64 ";"
|
||||
" atimensec=%u;"
|
||||
" mtime=%"PRIu64";"
|
||||
" mtime=%" PRIu64 ";"
|
||||
" mtimensec=%u;"
|
||||
" ctime=%"PRIu64";"
|
||||
" ctime=%" PRIu64 ";"
|
||||
" ctimesec=%u;"
|
||||
" mode=%o;"
|
||||
" nlink=%u;"
|
||||
@@ -858,11 +860,11 @@ debug_fuse_entry(const struct fuse_entry_out *entry_)
|
||||
{
|
||||
fprintf(g_OUTPUT,
|
||||
" fuse_entry_out:"
|
||||
" nodeid=0x%016"PRIx64";"
|
||||
" generation=0x%016"PRIx64";"
|
||||
" entry_valid=%"PRIu64";"
|
||||
" nodeid=0x%016" PRIx64 ";"
|
||||
" generation=0x%016" PRIx64 ";"
|
||||
" entry_valid=%" PRIu64 ";"
|
||||
" entry_valid_nsec=%u;"
|
||||
" attr_valid=%"PRIu64";"
|
||||
" attr_valid=%" PRIu64 ";"
|
||||
" attr_valid_nsec=%u;"
|
||||
" ",
|
||||
entry_->nodeid,
|
||||
@@ -880,10 +882,10 @@ debug_fuse_entry_out(const uint64_t unique_,
|
||||
const uint64_t argsize_)
|
||||
{
|
||||
fprintf(g_OUTPUT,
|
||||
"unique=0x%016"PRIx64";"
|
||||
"unique=0x%016" PRIx64 ";"
|
||||
" opcode=RESPONSE;"
|
||||
" error=0 (Success);"
|
||||
" len=%"PRIu64"; || "
|
||||
" len=%" PRIu64 "; || "
|
||||
,
|
||||
unique_,
|
||||
sizeof(struct fuse_out_header) + argsize_);
|
||||
@@ -897,10 +899,10 @@ debug_fuse_attr_out(const uint64_t unique_,
|
||||
const uint64_t argsize_)
|
||||
{
|
||||
fprintf(g_OUTPUT,
|
||||
"unique=0x%016"PRIx64";"
|
||||
"unique=0x%016" PRIx64 ";"
|
||||
" opcode=RESPONSE;"
|
||||
" error=0 (Success);"
|
||||
" len=%"PRIu64"; || "
|
||||
" len=%" PRIu64 "; || "
|
||||
"fuse_attr_out:"
|
||||
" attr_valid=%zu;"
|
||||
" attr_valid_nsec=%u;"
|
||||
@@ -945,11 +947,11 @@ static
|
||||
void
|
||||
debug_fuse_interrupt_in(const void *arg_)
|
||||
{
|
||||
const struct fuse_interrupt_in *arg = arg_;
|
||||
const struct fuse_interrupt_in *arg = (const fuse_interrupt_in*)arg_;
|
||||
|
||||
fprintf(g_OUTPUT,
|
||||
"fuse_interrupt_in:"
|
||||
" unique=0x%016"PRIx64";"
|
||||
" unique=0x%016" PRIx64 ";"
|
||||
"\n"
|
||||
,
|
||||
arg->unique);
|
||||
@@ -962,53 +964,54 @@ opcode_name(enum fuse_opcode op_)
|
||||
{
|
||||
static const char *names[] =
|
||||
{
|
||||
[FUSE_LOOKUP] = "LOOKUP",
|
||||
[FUSE_FORGET] = "FORGET",
|
||||
[FUSE_GETATTR] = "GETATTR",
|
||||
[FUSE_SETATTR] = "SETATTR",
|
||||
[FUSE_READLINK] = "READLINK",
|
||||
[FUSE_SYMLINK] = "SYMLINK",
|
||||
[FUSE_MKNOD] = "MKNOD",
|
||||
[FUSE_MKDIR] = "MKDIR",
|
||||
[FUSE_UNLINK] = "UNLINK",
|
||||
[FUSE_RMDIR] = "RMDIR",
|
||||
[FUSE_RENAME] = "RENAME",
|
||||
[FUSE_LINK] = "LINK",
|
||||
[FUSE_OPEN] = "OPEN",
|
||||
[FUSE_READ] = "READ",
|
||||
[FUSE_WRITE] = "WRITE",
|
||||
[FUSE_STATFS] = "STATFS",
|
||||
[FUSE_RELEASE] = "RELEASE",
|
||||
[FUSE_FSYNC] = "FSYNC",
|
||||
[FUSE_SETXATTR] = "SETXATTR",
|
||||
[FUSE_GETXATTR] = "GETXATTR",
|
||||
[FUSE_LISTXATTR] = "LISTXATTR",
|
||||
[FUSE_REMOVEXATTR] = "REMOVEXATTR",
|
||||
[FUSE_FLUSH] = "FLUSH",
|
||||
[FUSE_INIT] = "INIT",
|
||||
[FUSE_OPENDIR] = "OPENDIR",
|
||||
[FUSE_READDIR] = "READDIR",
|
||||
[FUSE_RELEASEDIR] = "RELEASEDIR",
|
||||
[FUSE_FSYNCDIR] = "FSYNCDIR",
|
||||
[FUSE_GETLK] = "GETLK",
|
||||
[FUSE_SETLK] = "SETLK",
|
||||
[FUSE_SETLKW] = "SETLKW",
|
||||
[FUSE_ACCESS] = "ACCESS",
|
||||
[FUSE_CREATE] = "CREATE",
|
||||
[FUSE_INTERRUPT] = "INTERRUPT",
|
||||
[FUSE_BMAP] = "BMAP",
|
||||
[FUSE_DESTROY] = "DESTROY",
|
||||
[FUSE_IOCTL] = "IOCTL",
|
||||
[FUSE_POLL] = "POLL",
|
||||
[FUSE_NOTIFY_REPLY] = "NOTIFY_REPLY",
|
||||
[FUSE_BATCH_FORGET] = "BATCH_FORGET",
|
||||
[FUSE_FALLOCATE] = "FALLOCATE",
|
||||
[FUSE_READDIRPLUS] = "READDIRPLUS",
|
||||
[FUSE_RENAME2] = "RENAME2",
|
||||
[FUSE_LSEEK] = "LSEEK",
|
||||
[FUSE_COPY_FILE_RANGE] = "COPY_FILE_RANGE",
|
||||
[FUSE_SETUPMAPPING] = "SETUPMAPPING",
|
||||
[FUSE_REMOVEMAPPING] = "REMOVEMAPPING"
|
||||
"INVALID",
|
||||
"LOOKUP",
|
||||
"FORGET",
|
||||
"GETATTR",
|
||||
"SETATTR",
|
||||
"READLINK",
|
||||
"SYMLINK",
|
||||
"MKNOD",
|
||||
"MKDIR",
|
||||
"UNLINK",
|
||||
"RMDIR",
|
||||
"RENAME",
|
||||
"LINK",
|
||||
"OPEN",
|
||||
"READ",
|
||||
"WRITE",
|
||||
"STATFS",
|
||||
"RELEASE",
|
||||
"FSYNC",
|
||||
"SETXATTR",
|
||||
"GETXATTR",
|
||||
"LISTXATTR",
|
||||
"REMOVEXATTR",
|
||||
"FLUSH",
|
||||
"INIT",
|
||||
"OPENDIR",
|
||||
"READDIR",
|
||||
"RELEASEDIR",
|
||||
"FSYNCDIR",
|
||||
"GETLK",
|
||||
"SETLK",
|
||||
"SETLKW",
|
||||
"ACCESS",
|
||||
"CREATE",
|
||||
"INTERRUPT",
|
||||
"BMAP",
|
||||
"DESTROY",
|
||||
"IOCTL",
|
||||
"POLL",
|
||||
"NOTIFY_REPLY",
|
||||
"BATCH_FORGET",
|
||||
"FALLOCATE",
|
||||
"READDIRPLUS",
|
||||
"RENAME2",
|
||||
"LSEEK",
|
||||
"COPY_FILE_RANGE",
|
||||
"SETUPMAPPING",
|
||||
"REMOVEMAPPING"
|
||||
};
|
||||
|
||||
if(op_ >= (sizeof(names) / sizeof(names[0])))
|
||||
@@ -1023,14 +1026,14 @@ debug_fuse_in_header(const struct fuse_in_header *hdr_)
|
||||
const void *arg = &hdr_[1];
|
||||
|
||||
fprintf(stderr,
|
||||
"unique=0x%016"PRIx64";"
|
||||
"unique=0x%016" PRIx64 ";"
|
||||
" opcode=%s (%u);"
|
||||
" nodeid=%zu;"
|
||||
" uid=%u;"
|
||||
" gid=%u;"
|
||||
" pid=%u; || ",
|
||||
hdr_->unique,
|
||||
opcode_name(hdr_->opcode),
|
||||
opcode_name((fuse_opcode)hdr_->opcode),
|
||||
hdr_->opcode,
|
||||
hdr_->nodeid,
|
||||
hdr_->uid,
|
||||
@@ -1043,7 +1046,7 @@ debug_fuse_in_header(const struct fuse_in_header *hdr_)
|
||||
debug_fuse_lookup(arg);
|
||||
break;
|
||||
case FUSE_INIT:
|
||||
debug_fuse_init_in(arg);
|
||||
debug_fuse_init_in((const fuse_init_in*)arg);
|
||||
break;
|
||||
case FUSE_GETATTR:
|
||||
debug_fuse_getattr_in(arg);
|
||||
@@ -1136,10 +1139,10 @@ void
|
||||
debug_fuse_out_header(const struct fuse_out_header *hdr_)
|
||||
{
|
||||
fprintf(g_OUTPUT,
|
||||
"unique=0x%016"PRIx64";"
|
||||
"unique=0x%016" PRIx64 ";"
|
||||
" opcode=RESPONSE;"
|
||||
" error=%d (%s);"
|
||||
" len=%"PRIu64";"
|
||||
" len=%" PRIu64 ";"
|
||||
,
|
||||
hdr_->unique,
|
||||
hdr_->error,
|
||||
@@ -1153,10 +1156,10 @@ debug_fuse_entry_open_out(const uint64_t unique_,
|
||||
const struct fuse_open_out *open_)
|
||||
{
|
||||
fprintf(g_OUTPUT,
|
||||
"unique=0x%016"PRIx64";"
|
||||
"unique=0x%016" PRIx64 ";"
|
||||
" opcode=RESPONSE;"
|
||||
" error=0 (Success);"
|
||||
" len=%"PRIu64"; || "
|
||||
" len=%" PRIu64 "; || "
|
||||
,
|
||||
unique_,
|
||||
sizeof(struct fuse_entry_out) + sizeof(struct fuse_open_out));
|
||||
@@ -1169,10 +1172,10 @@ debug_fuse_readlink(const uint64_t unique_,
|
||||
const char *linkname_)
|
||||
{
|
||||
fprintf(g_OUTPUT,
|
||||
"unique=0x%016"PRIx64";"
|
||||
"unique=0x%016" PRIx64 ";"
|
||||
" opcode=RESPONSE;"
|
||||
" error=0 (Success);"
|
||||
" len=%"PRIu64"; || "
|
||||
" len=%" PRIu64 "; || "
|
||||
"readlink: linkname=%s"
|
||||
"\n"
|
||||
,
|
||||
@@ -1186,10 +1189,10 @@ debug_fuse_write_out(const uint64_t unique_,
|
||||
const struct fuse_write_out *arg_)
|
||||
{
|
||||
fprintf(g_OUTPUT,
|
||||
"unique=0x%016"PRIx64";"
|
||||
"unique=0x%016" PRIx64 ";"
|
||||
" opcode=RESPONSE;"
|
||||
" error=0 (Success);"
|
||||
" len=%"PRIu64"; || "
|
||||
" len=%" PRIu64 "; || "
|
||||
" fuse_write_out:"
|
||||
" size=%u"
|
||||
"\n"
|
||||
@@ -1204,16 +1207,16 @@ debug_fuse_statfs_out(const uint64_t unique_,
|
||||
const struct fuse_statfs_out *arg_)
|
||||
{
|
||||
fprintf(g_OUTPUT,
|
||||
"unique=0x%016"PRIx64";"
|
||||
"unique=0x%016" PRIx64 ";"
|
||||
" opcode=RESPONSE;"
|
||||
" error=0 (Success);"
|
||||
" len=%"PRIu64"; || "
|
||||
" len=%" PRIu64 "; || "
|
||||
" fuse_statfs_out:"
|
||||
" blocks=%"PRIu64";"
|
||||
" bfree=%"PRIu64";"
|
||||
" bavail=%"PRIu64";"
|
||||
" files=%"PRIu64";"
|
||||
" ffree=%"PRIu64";"
|
||||
" blocks=%" PRIu64 ";"
|
||||
" bfree=%" PRIu64 ";"
|
||||
" bavail=%" PRIu64 ";"
|
||||
" files=%" PRIu64 ";"
|
||||
" ffree=%" PRIu64 ";"
|
||||
" bsize=%u;"
|
||||
" namelen=%u;"
|
||||
" frsize=%u;"
|
||||
@@ -1236,10 +1239,10 @@ debug_fuse_getxattr_out(const uint64_t unique_,
|
||||
const struct fuse_getxattr_out *arg_)
|
||||
{
|
||||
fprintf(g_OUTPUT,
|
||||
"unique=0x%016"PRIx64";"
|
||||
"unique=0x%016" PRIx64 ";"
|
||||
" opcode=RESPONSE;"
|
||||
" error=0 (Success);"
|
||||
" len=%"PRIu64"; || "
|
||||
" len=%" PRIu64 "; || "
|
||||
" fuse_getxattr_out:"
|
||||
" size=%u;"
|
||||
"\n"
|
||||
@@ -1255,13 +1258,13 @@ debug_fuse_lk_out(const uint64_t unique_,
|
||||
const struct fuse_lk_out *arg_)
|
||||
{
|
||||
fprintf(g_OUTPUT,
|
||||
"unique=0x%016"PRIx64";"
|
||||
"unique=0x%016" PRIx64 ";"
|
||||
" opcode=RESPONSE;"
|
||||
" error=0 (Success);"
|
||||
" len=%"PRIu64"; || "
|
||||
" len=%" PRIu64 "; || "
|
||||
" fuse_file_lock:"
|
||||
" start=%"PRIu64";"
|
||||
" end=%"PRIu64";"
|
||||
" start=%" PRIu64 ";"
|
||||
" end=%" PRIu64 ";"
|
||||
" type=%u;"
|
||||
" pid=%u;"
|
||||
"\n"
|
||||
@@ -1279,12 +1282,12 @@ debug_fuse_bmap_out(const uint64_t unique_,
|
||||
const struct fuse_bmap_out *arg_)
|
||||
{
|
||||
fprintf(g_OUTPUT,
|
||||
"unique=0x%016"PRIx64";"
|
||||
"unique=0x%016" PRIx64 ";"
|
||||
" opcode=RESPONSE;"
|
||||
" error=0 (Success);"
|
||||
" len=%"PRIu64"; || "
|
||||
" len=%" PRIu64 "; || "
|
||||
" fuse_bmap_out:"
|
||||
" block=%"PRIu64";"
|
||||
" block=%" PRIu64 ";"
|
||||
"\n"
|
||||
,
|
||||
unique_,
|
||||
+1
-1
@@ -328,7 +328,7 @@ fmp_gc_slab(fmp_t *fmp_,
|
||||
|
||||
slab_idx_ = (slab_idx_ % kv_size(fmp_->slabs));
|
||||
|
||||
slab = kv_A(fmp_->slabs,slab_idx_);
|
||||
slab = (char*)kv_A(fmp_->slabs,slab_idx_);
|
||||
|
||||
objs_per_slab = fmp_objs_per_slab(fmp_);
|
||||
objs_in_slab = fmp_objs_in_slab(fmp_,slab);
|
||||
|
||||
@@ -7,11 +7,12 @@
|
||||
*/
|
||||
|
||||
/* For pthread_rwlock_t */
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include "crc32b.h"
|
||||
#include "fuse_node.h"
|
||||
#include "khash.h"
|
||||
#include "kvec.h"
|
||||
|
||||
#include "node.h"
|
||||
@@ -25,6 +26,9 @@
|
||||
#include "fuse_pollhandle.h"
|
||||
#include "fuse_msgbuf.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <assert.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
@@ -104,13 +108,6 @@ struct node_table
|
||||
size_t split;
|
||||
};
|
||||
|
||||
#define container_of(ptr,type,member) ({ \
|
||||
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
|
||||
(type *)( (char *)__mptr - offsetof(type,member) );})
|
||||
|
||||
#define list_entry(ptr,type,member) \
|
||||
container_of(ptr,type,member)
|
||||
|
||||
struct list_head
|
||||
{
|
||||
struct list_head *next;
|
||||
@@ -218,32 +215,32 @@ fuse_hdr_arg(const struct fuse_in_header *hdr_)
|
||||
|
||||
static
|
||||
void
|
||||
list_add(struct list_head *new,
|
||||
struct list_head *prev,
|
||||
struct list_head *next)
|
||||
list_add(struct list_head *new_,
|
||||
struct list_head *prev_,
|
||||
struct list_head *next_)
|
||||
{
|
||||
next->prev = new;
|
||||
new->next = next;
|
||||
new->prev = prev;
|
||||
prev->next = new;
|
||||
next_->prev = new_;
|
||||
new_->next = next_;
|
||||
new_->prev = prev_;
|
||||
prev_->next = new_;
|
||||
}
|
||||
|
||||
static
|
||||
inline
|
||||
void
|
||||
list_add_head(struct list_head *new,
|
||||
struct list_head *head)
|
||||
list_add_head(struct list_head *new_,
|
||||
struct list_head *head_)
|
||||
{
|
||||
list_add(new,head,head->next);
|
||||
list_add(new_,head_,head_->next);
|
||||
}
|
||||
|
||||
static
|
||||
inline
|
||||
void
|
||||
list_add_tail(struct list_head *new,
|
||||
struct list_head *head)
|
||||
list_add_tail(struct list_head *new_,
|
||||
struct list_head *head_)
|
||||
{
|
||||
list_add(new,head->prev,head);
|
||||
list_add(new_,head_->prev,head_);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -384,7 +381,7 @@ node_table_reduce(struct node_table *t)
|
||||
|
||||
newarray = realloc(t->array,sizeof(node_t*) * newsize);
|
||||
if(newarray != NULL)
|
||||
t->array = newarray;
|
||||
t->array = (node_t**)newarray;
|
||||
|
||||
t->size = newsize;
|
||||
t->split = t->size / 2;
|
||||
@@ -450,7 +447,7 @@ node_table_resize(struct node_table *t)
|
||||
if(newarray == NULL)
|
||||
return -1;
|
||||
|
||||
t->array = newarray;
|
||||
t->array = (node_t**)newarray;
|
||||
memset(t->array + t->size,0,t->size * sizeof(node_t*));
|
||||
t->size = newsize;
|
||||
t->split = 0;
|
||||
@@ -795,7 +792,7 @@ add_name(char **buf,
|
||||
newbufsize *= 2;
|
||||
}
|
||||
|
||||
newbuf = realloc(*buf,newbufsize);
|
||||
newbuf = (char*)realloc(*buf,newbufsize);
|
||||
if(newbuf == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -857,7 +854,7 @@ try_get_path(struct fuse *f,
|
||||
*path = NULL;
|
||||
|
||||
err = -ENOMEM;
|
||||
buf = malloc(bufsize);
|
||||
buf = (char*)malloc(bufsize);
|
||||
if(buf == NULL)
|
||||
goto out_err;
|
||||
|
||||
@@ -1562,7 +1559,7 @@ fuse_lib_lookup(fuse_req_t req,
|
||||
node_t *dot = NULL;
|
||||
struct fuse_entry_param e = {0};
|
||||
|
||||
name = fuse_hdr_arg(hdr_);
|
||||
name = (const char*)fuse_hdr_arg(hdr_);
|
||||
nodeid = hdr_->nodeid;
|
||||
f = req_fuse_prepare(req);
|
||||
|
||||
@@ -1628,7 +1625,7 @@ fuse_lib_forget(fuse_req_t req,
|
||||
struct fuse_forget_in *arg;
|
||||
|
||||
f = req_fuse(req);
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_forget_in*)fuse_hdr_arg(hdr_);
|
||||
|
||||
forget_node(f,hdr_->nodeid,arg->nlookup);
|
||||
|
||||
@@ -1645,8 +1642,8 @@ fuse_lib_forget_multi(fuse_req_t req,
|
||||
struct fuse_forget_one *entry;
|
||||
|
||||
f = req_fuse(req);
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
entry = PARAM(arg);
|
||||
arg = (fuse_batch_forget_in*)fuse_hdr_arg(hdr_);
|
||||
entry = (fuse_forget_one*)PARAM(arg);
|
||||
|
||||
for(uint32_t i = 0; i < arg->count; i++)
|
||||
{
|
||||
@@ -1673,7 +1670,7 @@ fuse_lib_getattr(fuse_req_t req,
|
||||
fuse_file_info_t ffi = {0};
|
||||
const struct fuse_getattr_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_getattr_in*)fuse_hdr_arg(hdr_);
|
||||
f = req_fuse_prepare(req);
|
||||
|
||||
if(arg->getattr_flags & FUSE_GETATTR_FH)
|
||||
@@ -1735,7 +1732,7 @@ fuse_lib_setattr(fuse_req_t req,
|
||||
fuse_file_info_t ffi = {0};
|
||||
struct fuse_setattr_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_setattr_in*)fuse_hdr_arg(hdr_);
|
||||
|
||||
fi = NULL;
|
||||
if(arg->valid & FATTR_FH)
|
||||
@@ -1796,12 +1793,12 @@ fuse_lib_setattr(fuse_req_t req,
|
||||
if(arg->valid & FATTR_ATIME_NOW)
|
||||
tv[0].tv_nsec = UTIME_NOW;
|
||||
else if(arg->valid & FATTR_ATIME)
|
||||
tv[0] = (struct timespec){ arg->atime, arg->atimensec };
|
||||
tv[0] = (struct timespec){ static_cast<time_t>(arg->atime), arg->atimensec };
|
||||
|
||||
if(arg->valid & FATTR_MTIME_NOW)
|
||||
tv[1].tv_nsec = UTIME_NOW;
|
||||
else if(arg->valid & FATTR_MTIME)
|
||||
tv[1] = (struct timespec){ arg->mtime, arg->mtimensec };
|
||||
tv[1] = (struct timespec){ static_cast<time_t>(arg->mtime), arg->mtimensec };
|
||||
|
||||
err = ((fi == NULL) ?
|
||||
f->fs->op.utimens(path,tv) :
|
||||
@@ -1853,7 +1850,7 @@ fuse_lib_access(fuse_req_t req,
|
||||
struct fuse *f;
|
||||
struct fuse_access_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_access_in*)fuse_hdr_arg(hdr_);
|
||||
|
||||
f = req_fuse_prepare(req);
|
||||
|
||||
@@ -1909,8 +1906,8 @@ fuse_lib_mknod(fuse_req_t req,
|
||||
struct fuse_entry_param e;
|
||||
struct fuse_mknod_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
name = PARAM(arg);
|
||||
arg = (fuse_mknod_in*)fuse_hdr_arg(hdr_);
|
||||
name = (const char*)PARAM(arg);
|
||||
if(req->f->conn.proto_minor >= 12)
|
||||
req->ctx.umask = arg->umask;
|
||||
else
|
||||
@@ -1961,8 +1958,8 @@ fuse_lib_mkdir(fuse_req_t req,
|
||||
struct fuse_entry_param e;
|
||||
struct fuse_mkdir_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
name = PARAM(arg);
|
||||
arg = (fuse_mkdir_in*)fuse_hdr_arg(hdr_);
|
||||
name = (const char*)PARAM(arg);
|
||||
if(req->f->conn.proto_minor >= 12)
|
||||
req->ctx.umask = arg->umask;
|
||||
|
||||
@@ -1991,7 +1988,7 @@ fuse_lib_unlink(fuse_req_t req,
|
||||
const char *name;
|
||||
node_t *wnode;
|
||||
|
||||
name = PARAM(hdr_);
|
||||
name = (const char*)PARAM(hdr_);
|
||||
|
||||
f = req_fuse_prepare(req);
|
||||
err = get_path_wrlock(f,hdr_->nodeid,name,&path,&wnode);
|
||||
@@ -2024,7 +2021,7 @@ fuse_lib_rmdir(fuse_req_t req,
|
||||
const char *name;
|
||||
node_t *wnode;
|
||||
|
||||
name = PARAM(hdr_);
|
||||
name = (const char*)PARAM(hdr_);
|
||||
|
||||
f = req_fuse_prepare(req);
|
||||
|
||||
@@ -2052,7 +2049,7 @@ fuse_lib_symlink(fuse_req_t req_,
|
||||
const char *linkname;
|
||||
struct fuse_entry_param e = {0};
|
||||
|
||||
name = fuse_hdr_arg(hdr_);
|
||||
name = (const char*)fuse_hdr_arg(hdr_);
|
||||
linkname = (name + strlen(name) + 1);
|
||||
|
||||
f = req_fuse_prepare(req_);
|
||||
@@ -2084,8 +2081,8 @@ fuse_lib_rename(fuse_req_t req,
|
||||
node_t *wnode2;
|
||||
struct fuse_rename_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
oldname = PARAM(arg);
|
||||
arg = (fuse_rename_in*)fuse_hdr_arg(hdr_);
|
||||
oldname = (const char*)PARAM(arg);
|
||||
newname = (oldname + strlen(oldname) + 1);
|
||||
|
||||
f = req_fuse_prepare(req);
|
||||
@@ -2122,8 +2119,8 @@ fuse_lib_link(fuse_req_t req,
|
||||
struct fuse_link_in *arg;
|
||||
struct fuse_entry_param e = {0};
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
newname = PARAM(arg);
|
||||
arg = (fuse_link_in*)fuse_hdr_arg(hdr_);
|
||||
newname = (const char*)PARAM(arg);
|
||||
|
||||
f = req_fuse_prepare(req);
|
||||
|
||||
@@ -2186,8 +2183,8 @@ fuse_lib_create(fuse_req_t req,
|
||||
struct fuse_entry_param e;
|
||||
struct fuse_create_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
name = PARAM(arg);
|
||||
arg = (fuse_create_in*)fuse_hdr_arg(hdr_);
|
||||
name = (const char*)PARAM(arg);
|
||||
|
||||
ffi.flags = arg->flags;
|
||||
|
||||
@@ -2287,7 +2284,7 @@ fuse_lib_open(fuse_req_t req,
|
||||
fuse_file_info_t ffi = {0};
|
||||
struct fuse_open_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_open_in*)fuse_hdr_arg(hdr_);
|
||||
|
||||
ffi.flags = arg->flags;
|
||||
|
||||
@@ -2332,7 +2329,7 @@ fuse_lib_read(fuse_req_t req,
|
||||
struct fuse_read_in *arg;
|
||||
fuse_msgbuf_t *msgbuf;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_read_in*)fuse_hdr_arg(hdr_);
|
||||
ffi.fh = arg->fh;
|
||||
if(req->f->conn.proto_minor >= 9)
|
||||
{
|
||||
@@ -2365,7 +2362,7 @@ fuse_lib_write(fuse_req_t req,
|
||||
fuse_file_info_t ffi = {0};
|
||||
struct fuse_write_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_write_in*)fuse_hdr_arg(hdr_);
|
||||
ffi.fh = arg->fh;
|
||||
ffi.writepage = !!(arg->write_flags & 1);
|
||||
if(req->f->conn.proto_minor < 9)
|
||||
@@ -2376,7 +2373,7 @@ fuse_lib_write(fuse_req_t req,
|
||||
{
|
||||
ffi.flags = arg->flags;
|
||||
ffi.lock_owner = arg->lock_owner;
|
||||
data = PARAM(arg);
|
||||
data = (char*)PARAM(arg);
|
||||
}
|
||||
|
||||
f = req_fuse_prepare(req);
|
||||
@@ -2400,7 +2397,7 @@ fuse_lib_fsync(fuse_req_t req,
|
||||
struct fuse_fsync_in *arg;
|
||||
fuse_file_info_t ffi = {0};
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_fsync_in*)fuse_hdr_arg(hdr_);
|
||||
ffi.fh = arg->fh;
|
||||
|
||||
f = req_fuse_prepare(req);
|
||||
@@ -2435,7 +2432,7 @@ fuse_lib_opendir(fuse_req_t req,
|
||||
struct fuse *f;
|
||||
struct fuse_open_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_open_in*)fuse_hdr_arg(hdr_);
|
||||
llffi.flags = arg->flags;
|
||||
|
||||
f = req_fuse_prepare(req);
|
||||
@@ -2522,7 +2519,7 @@ fuse_lib_readdir(fuse_req_t req_,
|
||||
fuse_file_info_t llffi = {0};
|
||||
struct fuse_read_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_read_in*)fuse_hdr_arg(hdr_);
|
||||
size = arg->size;
|
||||
llffi.fh = arg->fh;
|
||||
|
||||
@@ -2566,7 +2563,7 @@ fuse_lib_readdir_plus(fuse_req_t req_,
|
||||
fuse_file_info_t llffi = {0};
|
||||
struct fuse_read_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_read_in*)fuse_hdr_arg(hdr_);
|
||||
size = arg->size;
|
||||
llffi.fh = arg->fh;
|
||||
|
||||
@@ -2607,7 +2604,7 @@ fuse_lib_releasedir(fuse_req_t req_,
|
||||
fuse_file_info_t llffi = {0};
|
||||
struct fuse_release_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_release_in*)fuse_hdr_arg(hdr_);
|
||||
llffi.fh = arg->fh;
|
||||
llffi.flags = arg->flags;
|
||||
|
||||
@@ -2636,7 +2633,7 @@ fuse_lib_fsyncdir(fuse_req_t req,
|
||||
fuse_file_info_t llffi = {0};
|
||||
struct fuse_fsync_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_fsync_in*)fuse_hdr_arg(hdr_);
|
||||
llffi.fh = arg->fh;
|
||||
|
||||
f = req_fuse_prepare(req);
|
||||
@@ -2688,9 +2685,9 @@ fuse_lib_setxattr(fuse_req_t req,
|
||||
struct fuse *f;
|
||||
struct fuse_setxattr_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_setxattr_in*)fuse_hdr_arg(hdr_);
|
||||
if((req->f->conn.capable & FUSE_SETXATTR_EXT) && (req->f->conn.want & FUSE_SETXATTR_EXT))
|
||||
name = PARAM(arg);
|
||||
name = (const char*)PARAM(arg);
|
||||
else
|
||||
name = (((char*)arg) + FUSE_COMPAT_SETXATTR_IN_SIZE);
|
||||
|
||||
@@ -2741,8 +2738,8 @@ fuse_lib_getxattr(fuse_req_t req,
|
||||
const char* name;
|
||||
struct fuse_getxattr_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
name = PARAM(arg);
|
||||
arg = (fuse_getxattr_in*)fuse_hdr_arg(hdr_);
|
||||
name = (const char*)PARAM(arg);
|
||||
|
||||
f = req_fuse_prepare(req);
|
||||
|
||||
@@ -2802,7 +2799,7 @@ fuse_lib_listxattr(fuse_req_t req,
|
||||
struct fuse *f;
|
||||
struct fuse_getxattr_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_getxattr_in*)fuse_hdr_arg(hdr_);
|
||||
|
||||
f = req_fuse_prepare(req);
|
||||
|
||||
@@ -2842,7 +2839,7 @@ fuse_lib_removexattr(fuse_req_t req,
|
||||
const char *name;
|
||||
struct fuse *f;
|
||||
|
||||
name = fuse_hdr_arg(hdr_);
|
||||
name = (const char*)fuse_hdr_arg(hdr_);
|
||||
|
||||
f = req_fuse_prepare(req);
|
||||
|
||||
@@ -2867,7 +2864,7 @@ fuse_lib_copy_file_range(fuse_req_t req_,
|
||||
fuse_file_info_t ffi_out = {0};
|
||||
const struct fuse_copy_file_range_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_copy_file_range_in*)fuse_hdr_arg(hdr_);
|
||||
ffi_in.fh = arg->fh_in;
|
||||
ffi_out.fh = arg->fh_out;
|
||||
|
||||
@@ -2927,8 +2924,8 @@ fuse_lib_tmpfile(fuse_req_t req_,
|
||||
struct fuse_entry_param e;
|
||||
struct fuse_create_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
name = PARAM(arg);
|
||||
arg = (fuse_create_in*)fuse_hdr_arg(hdr_);
|
||||
name = (const char*)PARAM(arg);
|
||||
|
||||
ffi.flags = arg->flags;
|
||||
|
||||
@@ -3026,8 +3023,8 @@ locks_insert(node_t *node,
|
||||
|
||||
if(lock->type != F_UNLCK || lock->start != 0 || lock->end != OFFSET_MAX)
|
||||
{
|
||||
newl1 = malloc(sizeof(lock_t));
|
||||
newl2 = malloc(sizeof(lock_t));
|
||||
newl1 = (lock_t*)malloc(sizeof(lock_t));
|
||||
newl2 = (lock_t*)malloc(sizeof(lock_t));
|
||||
|
||||
if(!newl1 || !newl2)
|
||||
{
|
||||
@@ -3055,7 +3052,7 @@ locks_insert(node_t *node,
|
||||
lock->start = l->start;
|
||||
if(lock->end < l->end)
|
||||
lock->end = l->end;
|
||||
goto delete;
|
||||
goto delete_lock;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3064,7 +3061,7 @@ locks_insert(node_t *node,
|
||||
if(lock->end < l->start)
|
||||
break;
|
||||
if(lock->start <= l->start && l->end <= lock->end)
|
||||
goto delete;
|
||||
goto delete_lock;
|
||||
if(l->end <= lock->end)
|
||||
{
|
||||
l->end = lock->start - 1;
|
||||
@@ -3085,7 +3082,7 @@ locks_insert(node_t *node,
|
||||
lp = &l->next;
|
||||
continue;
|
||||
|
||||
delete:
|
||||
delete_lock:
|
||||
delete_lock(lp);
|
||||
}
|
||||
if(lock->type != F_UNLCK)
|
||||
@@ -3168,7 +3165,7 @@ fuse_lib_release(fuse_req_t req,
|
||||
fuse_file_info_t ffi = {0};
|
||||
struct fuse_release_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_release_in*)fuse_hdr_arg(hdr_);
|
||||
ffi.fh = arg->fh;
|
||||
ffi.flags = arg->flags;
|
||||
if(req->f->conn.proto_minor >= 8)
|
||||
@@ -3206,7 +3203,7 @@ fuse_lib_flush(fuse_req_t req,
|
||||
fuse_file_info_t ffi = {0};
|
||||
struct fuse_flush_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_flush_in*)fuse_hdr_arg(hdr_);
|
||||
|
||||
ffi.fh = arg->fh;
|
||||
ffi.flush = 1;
|
||||
@@ -3265,7 +3262,7 @@ fuse_lib_getlk(fuse_req_t req,
|
||||
fuse_file_info_t ffi = {0};
|
||||
const struct fuse_lk_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_lk_in*)fuse_hdr_arg(hdr_);
|
||||
ffi.fh = arg->fh;
|
||||
ffi.lock_owner = arg->owner;
|
||||
|
||||
@@ -3341,7 +3338,7 @@ fuse_lib_bmap(fuse_req_t req,
|
||||
uint64_t block;
|
||||
const struct fuse_bmap_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_bmap_in*)fuse_hdr_arg(hdr_);
|
||||
block = arg->block;
|
||||
|
||||
f = req_fuse_prepare(req);
|
||||
@@ -3373,7 +3370,7 @@ fuse_lib_ioctl(fuse_req_t req,
|
||||
uint32_t out_size;
|
||||
const struct fuse_ioctl_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_ioctl_in*)fuse_hdr_arg(hdr_);
|
||||
if((arg->flags & FUSE_IOCTL_DIR) && !(req->f->conn.want & FUSE_CAP_IOCTL_DIR))
|
||||
{
|
||||
fuse_reply_err(req,ENOTTY);
|
||||
@@ -3403,7 +3400,7 @@ fuse_lib_ioctl(fuse_req_t req,
|
||||
if(out_size)
|
||||
{
|
||||
err = -ENOMEM;
|
||||
out_buf = malloc(out_size);
|
||||
out_buf = (char*)malloc(out_size);
|
||||
if(!out_buf)
|
||||
goto err;
|
||||
}
|
||||
@@ -3441,7 +3438,7 @@ fuse_lib_poll(fuse_req_t req,
|
||||
fuse_pollhandle_t *ph = NULL;
|
||||
const struct fuse_poll_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_poll_in*)fuse_hdr_arg(hdr_);
|
||||
ffi.fh = arg->fh;
|
||||
|
||||
if(arg->flags & FUSE_POLL_SCHEDULE_NOTIFY)
|
||||
@@ -3476,7 +3473,7 @@ fuse_lib_fallocate(fuse_req_t req,
|
||||
fuse_file_info_t ffi = {0};
|
||||
const struct fuse_fallocate_in *arg;
|
||||
|
||||
arg = fuse_hdr_arg(hdr_);
|
||||
arg = (fuse_fallocate_in*)fuse_hdr_arg(hdr_);
|
||||
ffi.fh = arg->fh;
|
||||
|
||||
f = req_fuse_prepare(req);
|
||||
@@ -3494,8 +3491,8 @@ int
|
||||
remembered_node_cmp(const void *a_,
|
||||
const void *b_)
|
||||
{
|
||||
const remembered_node_t *a = a_;
|
||||
const remembered_node_t *b = b_;
|
||||
const remembered_node_t *a = (const remembered_node_t*)a_;
|
||||
const remembered_node_t *b = (const remembered_node_t*)b_;
|
||||
|
||||
return (a->time - b->time);
|
||||
}
|
||||
@@ -3830,21 +3827,21 @@ metrics_log_nodes_info(struct fuse *f_,
|
||||
|
||||
snprintf(buf,sizeof(buf),
|
||||
"time: %s\n"
|
||||
"sizeof(node): %"PRIu64"\n"
|
||||
"node id_table size: %"PRIu64"\n"
|
||||
"node id_table usage: %"PRIu64"\n"
|
||||
"node id_table total allocated memory: %"PRIu64"\n"
|
||||
"node name_table size: %"PRIu64"\n"
|
||||
"node name_table usage: %"PRIu64"\n"
|
||||
"node name_table total allocated memory: %"PRIu64"\n"
|
||||
"node memory pool slab count: %"PRIu64"\n"
|
||||
"sizeof(node): %" PRIu64 "\n"
|
||||
"node id_table size: %" PRIu64 "\n"
|
||||
"node id_table usage: %" PRIu64 "\n"
|
||||
"node id_table total allocated memory: %" PRIu64 "\n"
|
||||
"node name_table size: %" PRIu64 "\n"
|
||||
"node name_table usage: %" PRIu64 "\n"
|
||||
"node name_table total allocated memory: %" PRIu64 "\n"
|
||||
"node memory pool slab count: %" PRIu64 "\n"
|
||||
"node memory pool usage ratio: %f\n"
|
||||
"node memory pool avail objs: %"PRIu64"\n"
|
||||
"node memory pool total allocated memory: %"PRIu64"\n"
|
||||
"msgbuf bufsize: %"PRIu64"\n"
|
||||
"msgbuf allocation count: %"PRIu64"\n"
|
||||
"msgbuf available count: %"PRIu64"\n"
|
||||
"msgbuf total allocated memory: %"PRIu64"\n"
|
||||
"node memory pool avail objs: %" PRIu64 "\n"
|
||||
"node memory pool total allocated memory: %" PRIu64 "\n"
|
||||
"msgbuf bufsize: %" PRIu64 "\n"
|
||||
"msgbuf allocation count: %" PRIu64 "\n"
|
||||
"msgbuf available count: %" PRIu64 "\n"
|
||||
"msgbuf total allocated memory: %" PRIu64 "\n"
|
||||
"\n"
|
||||
,
|
||||
time_str,
|
||||
@@ -3907,11 +3904,10 @@ void
|
||||
fuse_invalidate_all_nodes()
|
||||
{
|
||||
struct fuse *f = fuse_get_fuse_obj();
|
||||
|
||||
syslog(LOG_INFO,"invalidating file entries");
|
||||
std::vector<std::string> names;
|
||||
|
||||
pthread_mutex_lock(&f->lock);
|
||||
for(int i = 0; i < f->id_table.size; i++)
|
||||
for(size_t i = 0; i < f->id_table.size; i++)
|
||||
{
|
||||
node_t *node;
|
||||
|
||||
@@ -3919,16 +3915,28 @@ fuse_invalidate_all_nodes()
|
||||
{
|
||||
if(node->nodeid == FUSE_ROOT_ID)
|
||||
continue;
|
||||
if(node->name == NULL)
|
||||
continue;
|
||||
if(node->parent == NULL)
|
||||
continue;
|
||||
if(node->parent->nodeid != FUSE_ROOT_ID)
|
||||
continue;
|
||||
|
||||
fuse_lowlevel_notify_inval_entry(f->se->ch,
|
||||
node->parent->nodeid,
|
||||
node->name,
|
||||
strlen(node->name));
|
||||
names.emplace_back(node->name);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&f->lock);
|
||||
|
||||
syslog(LOG_INFO,
|
||||
"invalidating %ld file entries",
|
||||
names.size());
|
||||
for(auto &name : names)
|
||||
{
|
||||
fuse_lowlevel_notify_inval_entry(f->se->ch,
|
||||
FUSE_ROOT_ID,
|
||||
name.c_str(),
|
||||
name.size());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -6,12 +6,14 @@
|
||||
See the file COPYING.LIB
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include "lfmp.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "debug.hpp"
|
||||
#include "fuse_i.h"
|
||||
#include "fuse_kernel.h"
|
||||
#include "fuse_opt.h"
|
||||
@@ -41,7 +43,7 @@
|
||||
#define OFFSET_MAX 0x7fffffffffffffffLL
|
||||
|
||||
#define container_of(ptr, type, member) ({ \
|
||||
const typeof( ((type*)0)->member ) *__mptr = (ptr); \
|
||||
const decltype( ((type*)0)->member ) *__mptr = (ptr); \
|
||||
(type *)( (char*)__mptr - offsetof(type,member) );})
|
||||
|
||||
static size_t pagesize;
|
||||
@@ -135,7 +137,7 @@ fuse_send_msg(struct fuse_ll *f,
|
||||
int count)
|
||||
{
|
||||
int rv;
|
||||
struct fuse_out_header *out = iov[0].iov_base;
|
||||
struct fuse_out_header *out = (fuse_out_header*)iov[0].iov_base;
|
||||
|
||||
out->len = iov_length(iov, count);
|
||||
|
||||
@@ -410,7 +412,7 @@ fuse_send_data_iov_fallback(struct fuse_ll *f,
|
||||
return -ENOMEM;
|
||||
|
||||
mem_buf.buf[0].mem = msgbuf->mem;
|
||||
res = fuse_buf_copy(&mem_buf, buf, 0);
|
||||
res = fuse_buf_copy(&mem_buf, buf, (fuse_buf_copy_flags)0);
|
||||
if(res < 0)
|
||||
{
|
||||
msgbuf_free(msgbuf);
|
||||
@@ -550,7 +552,7 @@ fuse_ioctl_iovec_copy(const struct iovec *iov,
|
||||
struct fuse_ioctl_iovec *fiov;
|
||||
size_t i;
|
||||
|
||||
fiov = malloc(sizeof(fiov[0]) * count);
|
||||
fiov = (fuse_ioctl_iovec*)malloc(sizeof(fiov[0]) * count);
|
||||
if(!fiov)
|
||||
return NULL;
|
||||
|
||||
@@ -683,7 +685,7 @@ fuse_reply_ioctl_iov(fuse_req_t req,
|
||||
struct fuse_ioctl_out arg = {0};
|
||||
int res;
|
||||
|
||||
padded_iov = malloc((count + 2) * sizeof(struct iovec));
|
||||
padded_iov = (iovec*)malloc((count + 2) * sizeof(struct iovec));
|
||||
if(padded_iov == NULL)
|
||||
return fuse_reply_err(req, ENOMEM);
|
||||
|
||||
@@ -896,8 +898,8 @@ do_readdir(fuse_req_t req,
|
||||
|
||||
static
|
||||
void
|
||||
do_readdir_plus(fuse_req_t req_,
|
||||
struct fuse_in_header *hdr_)
|
||||
do_readdirplus(fuse_req_t req_,
|
||||
struct fuse_in_header *hdr_)
|
||||
{
|
||||
req_->f->op.readdir_plus(req_,hdr_);
|
||||
}
|
||||
@@ -1372,7 +1374,6 @@ void
|
||||
do_setupmapping(fuse_req_t req_,
|
||||
struct fuse_in_header *hdr_)
|
||||
{
|
||||
printf("setupmapping\n");
|
||||
req_->f->op.setupmapping(req_,hdr_);
|
||||
}
|
||||
|
||||
@@ -1381,7 +1382,6 @@ void
|
||||
do_removemapping(fuse_req_t req_,
|
||||
struct fuse_in_header *hdr_)
|
||||
{
|
||||
printf("removemapping\n");
|
||||
req_->f->op.removemapping(req_,hdr_);
|
||||
}
|
||||
|
||||
@@ -1390,7 +1390,6 @@ void
|
||||
do_syncfs(fuse_req_t req_,
|
||||
struct fuse_in_header *hdr_)
|
||||
{
|
||||
printf("syncfs\n");
|
||||
req_->f->op.syncfs(req_,hdr_);
|
||||
}
|
||||
|
||||
@@ -1399,10 +1398,33 @@ void
|
||||
do_tmpfile(fuse_req_t req_,
|
||||
struct fuse_in_header *hdr_)
|
||||
{
|
||||
printf("tmpfile\n");
|
||||
req_->f->op.tmpfile(req_,hdr_);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
do_statx(fuse_req_t req_,
|
||||
struct fuse_in_header *hdr_)
|
||||
{
|
||||
req_->f->op.statx(req_,hdr_);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
do_rename2(fuse_req_t req_,
|
||||
struct fuse_in_header *hdr_)
|
||||
{
|
||||
req_->f->op.rename2(req_,hdr_);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
do_lseek(fuse_req_t req_,
|
||||
struct fuse_in_header *hdr_)
|
||||
{
|
||||
req_->f->op.lseek(req_,hdr_);
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
send_notify_iov(struct fuse_ll *f,
|
||||
@@ -1624,7 +1646,7 @@ fuse_lowlevel_notify_retrieve(struct fuse_chan *ch,
|
||||
if(f->conn.proto_minor < 15)
|
||||
return -ENOSYS;
|
||||
|
||||
rreq = malloc(sizeof(*rreq));
|
||||
rreq = (fuse_retrieve_req*)malloc(sizeof(*rreq));
|
||||
if(rreq == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1668,61 +1690,69 @@ fuse_req_ctx(fuse_req_t req)
|
||||
return &req->ctx;
|
||||
}
|
||||
|
||||
static struct {
|
||||
void (*func)(fuse_req_t, struct fuse_in_header *);
|
||||
const char *name;
|
||||
} fuse_ll_ops[] =
|
||||
#define FUSE_OPCODE_LEN (FUSE_STATX + 1)
|
||||
|
||||
typedef void (*fuse_ll_func)(fuse_req_t, struct fuse_in_header *);
|
||||
const
|
||||
fuse_ll_func
|
||||
fuse_ll_funcs[FUSE_OPCODE_LEN] =
|
||||
{
|
||||
[FUSE_LOOKUP] = { do_lookup, "LOOKUP" },
|
||||
[FUSE_FORGET] = { do_forget, "FORGET" },
|
||||
[FUSE_GETATTR] = { do_getattr, "GETATTR" },
|
||||
[FUSE_SETATTR] = { do_setattr, "SETATTR" },
|
||||
[FUSE_READLINK] = { do_readlink, "READLINK" },
|
||||
[FUSE_SYMLINK] = { do_symlink, "SYMLINK" },
|
||||
[FUSE_MKNOD] = { do_mknod, "MKNOD" },
|
||||
[FUSE_MKDIR] = { do_mkdir, "MKDIR" },
|
||||
[FUSE_UNLINK] = { do_unlink, "UNLINK" },
|
||||
[FUSE_RMDIR] = { do_rmdir, "RMDIR" },
|
||||
[FUSE_RENAME] = { do_rename, "RENAME" },
|
||||
[FUSE_LINK] = { do_link, "LINK" },
|
||||
[FUSE_OPEN] = { do_open, "OPEN" },
|
||||
[FUSE_READ] = { do_read, "READ" },
|
||||
[FUSE_WRITE] = { do_write, "WRITE" },
|
||||
[FUSE_STATFS] = { do_statfs, "STATFS" },
|
||||
[FUSE_RELEASE] = { do_release, "RELEASE" },
|
||||
[FUSE_FSYNC] = { do_fsync, "FSYNC" },
|
||||
[FUSE_SETXATTR] = { do_setxattr, "SETXATTR" },
|
||||
[FUSE_GETXATTR] = { do_getxattr, "GETXATTR" },
|
||||
[FUSE_LISTXATTR] = { do_listxattr, "LISTXATTR" },
|
||||
[FUSE_REMOVEXATTR] = { do_removexattr, "REMOVEXATTR" },
|
||||
[FUSE_FLUSH] = { do_flush, "FLUSH" },
|
||||
[FUSE_INIT] = { do_init, "INIT" },
|
||||
[FUSE_OPENDIR] = { do_opendir, "OPENDIR" },
|
||||
[FUSE_READDIR] = { do_readdir, "READDIR" },
|
||||
[FUSE_READDIRPLUS] = { do_readdir_plus, "READDIR_PLUS" },
|
||||
[FUSE_RELEASEDIR] = { do_releasedir, "RELEASEDIR" },
|
||||
[FUSE_FSYNCDIR] = { do_fsyncdir, "FSYNCDIR" },
|
||||
[FUSE_GETLK] = { do_getlk, "GETLK" },
|
||||
[FUSE_SETLK] = { do_setlk, "SETLK" },
|
||||
[FUSE_SETLKW] = { do_setlkw, "SETLKW" },
|
||||
[FUSE_ACCESS] = { do_access, "ACCESS" },
|
||||
[FUSE_CREATE] = { do_create, "CREATE" },
|
||||
[FUSE_INTERRUPT] = { do_interrupt, "INTERRUPT" },
|
||||
[FUSE_BMAP] = { do_bmap, "BMAP" },
|
||||
[FUSE_IOCTL] = { do_ioctl, "IOCTL" },
|
||||
[FUSE_POLL] = { do_poll, "POLL" },
|
||||
[FUSE_FALLOCATE] = { do_fallocate, "FALLOCATE" },
|
||||
[FUSE_DESTROY] = { do_destroy, "DESTROY" },
|
||||
[FUSE_NOTIFY_REPLY] = { do_notify_reply, "NOTIFY_REPLY" },
|
||||
[FUSE_BATCH_FORGET] = { do_batch_forget, "BATCH_FORGET" },
|
||||
[FUSE_COPY_FILE_RANGE] = { do_copy_file_range, "COPY_FILE_RANGE" },
|
||||
[FUSE_SETUPMAPPING] = { do_setupmapping, "SETUPMAPPING" },
|
||||
[FUSE_REMOVEMAPPING] = { do_removemapping, "REMOVEMAPPING" },
|
||||
[FUSE_SYNCFS] = { do_syncfs, "SYNCFS" },
|
||||
[FUSE_TMPFILE] = { do_tmpfile, "TMPFILE" }
|
||||
NULL,
|
||||
do_lookup,
|
||||
do_forget,
|
||||
do_getattr,
|
||||
do_setattr,
|
||||
do_readlink,
|
||||
do_symlink,
|
||||
NULL,
|
||||
do_mknod,
|
||||
do_mkdir,
|
||||
do_unlink,
|
||||
do_rmdir,
|
||||
do_rename,
|
||||
do_link,
|
||||
do_open,
|
||||
do_read,
|
||||
do_write,
|
||||
do_statfs,
|
||||
do_release,
|
||||
NULL,
|
||||
do_fsync,
|
||||
do_setxattr,
|
||||
do_getxattr,
|
||||
do_listxattr,
|
||||
do_removexattr,
|
||||
do_flush,
|
||||
do_init,
|
||||
do_opendir,
|
||||
do_readdir,
|
||||
do_releasedir,
|
||||
do_fsyncdir,
|
||||
do_getlk,
|
||||
do_setlk,
|
||||
do_setlkw,
|
||||
do_access,
|
||||
do_create,
|
||||
do_interrupt,
|
||||
do_bmap,
|
||||
do_destroy,
|
||||
do_ioctl,
|
||||
do_poll,
|
||||
do_notify_reply,
|
||||
do_batch_forget,
|
||||
do_fallocate,
|
||||
do_readdirplus,
|
||||
do_rename2,
|
||||
do_lseek,
|
||||
do_copy_file_range,
|
||||
do_setupmapping,
|
||||
do_removemapping,
|
||||
do_syncfs,
|
||||
do_tmpfile,
|
||||
do_statx
|
||||
};
|
||||
|
||||
#define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0]))
|
||||
#define FUSE_MAXOPS (sizeof(fuse_ll_funcs) / sizeof(fuse_ll_funcs[0]))
|
||||
|
||||
enum {
|
||||
KEY_HELP,
|
||||
@@ -1816,7 +1846,7 @@ fuse_ll_destroy(void *data)
|
||||
f->op.destroy(f->userdata);
|
||||
}
|
||||
|
||||
llp = pthread_getspecific(f->pipe_key);
|
||||
llp = (fuse_ll_pipe*)pthread_getspecific(f->pipe_key);
|
||||
if(llp != NULL)
|
||||
fuse_ll_pipe_free(llp);
|
||||
pthread_key_delete(f->pipe_key);
|
||||
@@ -1830,7 +1860,7 @@ static
|
||||
void
|
||||
fuse_ll_pipe_destructor(void *data)
|
||||
{
|
||||
struct fuse_ll_pipe *llp = data;
|
||||
struct fuse_ll_pipe *llp = (fuse_ll_pipe*)data;
|
||||
fuse_ll_pipe_free(llp);
|
||||
}
|
||||
|
||||
@@ -1872,7 +1902,7 @@ fuse_ll_buf_receive_read(struct fuse_session *se_,
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
if(rv < sizeof(struct fuse_in_header))
|
||||
if(rv < (int)sizeof(struct fuse_in_header))
|
||||
{
|
||||
fprintf(stderr, "short read from fuse device\n");
|
||||
return -EIO;
|
||||
@@ -1892,8 +1922,6 @@ fuse_ll_buf_process_read(struct fuse_session *se_,
|
||||
|
||||
in = (struct fuse_in_header*)msgbuf_->mem;
|
||||
|
||||
// printf("%d\n",in->opcode);
|
||||
|
||||
req = fuse_ll_alloc_req(se_->f);
|
||||
if(req == NULL)
|
||||
return fuse_send_enomem(se_->f,se_->ch,in->unique);
|
||||
@@ -1905,12 +1933,12 @@ fuse_ll_buf_process_read(struct fuse_session *se_,
|
||||
req->ch = se_->ch;
|
||||
|
||||
err = ENOSYS;
|
||||
if(in->opcode >= FUSE_MAXOP)
|
||||
if(in->opcode >= FUSE_MAXOPS)
|
||||
goto reply_err;
|
||||
if(fuse_ll_ops[in->opcode].func == NULL)
|
||||
if(fuse_ll_funcs[in->opcode] == NULL)
|
||||
goto reply_err;
|
||||
|
||||
fuse_ll_ops[in->opcode].func(req, in);
|
||||
fuse_ll_funcs[in->opcode](req, in);
|
||||
|
||||
return;
|
||||
|
||||
@@ -1943,12 +1971,12 @@ fuse_ll_buf_process_read_init(struct fuse_session *se_,
|
||||
err = EIO;
|
||||
if(in->opcode != FUSE_INIT)
|
||||
goto reply_err;
|
||||
if(fuse_ll_ops[in->opcode].func == NULL)
|
||||
if(fuse_ll_funcs[FUSE_INIT] == NULL)
|
||||
goto reply_err;
|
||||
|
||||
se_->process_buf = fuse_ll_buf_process_read;
|
||||
|
||||
fuse_ll_ops[in->opcode].func(req, in);
|
||||
fuse_ll_funcs[in->opcode](req,in);
|
||||
|
||||
return;
|
||||
|
||||
@@ -2007,9 +2035,9 @@ fuse_lowlevel_new_common(struct fuse_args *args,
|
||||
f->userdata = userdata;
|
||||
|
||||
se = fuse_session_new(f,
|
||||
fuse_ll_buf_receive_read,
|
||||
fuse_ll_buf_process_read_init,
|
||||
fuse_ll_destroy);
|
||||
(void*)fuse_ll_buf_receive_read,
|
||||
(void*)fuse_ll_buf_process_read_init,
|
||||
(void*)fuse_ll_destroy);
|
||||
|
||||
if(!se)
|
||||
goto out_key_destroy;
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "lock.h"
|
||||
#include "lfmp.h"
|
||||
|
||||
@@ -23,8 +25,18 @@ struct node_s
|
||||
uint8_t is_stat_cache_valid:1;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
node_t *node_alloc();
|
||||
void node_free(node_t*);
|
||||
int node_gc1();
|
||||
void node_gc();
|
||||
lfmp_t *node_lfmp();
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
+38
-19
@@ -18,22 +18,45 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "khash.h"
|
||||
#include "wyhash.h"
|
||||
#define RAPIDHASH_FAST
|
||||
#define RAPIDHASH_UNROLLED
|
||||
|
||||
KHASH_SET_INIT_INT64(hashset);
|
||||
static
|
||||
inline
|
||||
uint64_t
|
||||
vt_hash_u64(const uint64_t hash_)
|
||||
{
|
||||
return hash_;
|
||||
}
|
||||
|
||||
static
|
||||
inline
|
||||
bool
|
||||
vt_cmpr_u64(const uint64_t key_1,
|
||||
const uint64_t key_2)
|
||||
{
|
||||
return (key_1 == key_2);
|
||||
}
|
||||
|
||||
#define NAME u64_set
|
||||
#define KEY_TY uint64_t
|
||||
#define HASH_FN vt_hash_u64
|
||||
#define CMPR_FN vt_cmpr_u64
|
||||
#include "verstable.h"
|
||||
#include "rapidhash.h"
|
||||
#include <cstdint>
|
||||
|
||||
class HashSet
|
||||
{
|
||||
public:
|
||||
HashSet()
|
||||
{
|
||||
_set = kh_init(hashset);
|
||||
u64_set_init(&_u64_set);
|
||||
}
|
||||
|
||||
~HashSet()
|
||||
{
|
||||
kh_destroy(hashset,_set);
|
||||
u64_set_cleanup(&_u64_set);
|
||||
}
|
||||
|
||||
inline
|
||||
@@ -41,19 +64,15 @@ public:
|
||||
put(const char *str_,
|
||||
const uint64_t len_)
|
||||
{
|
||||
int rv;
|
||||
uint64_t h;
|
||||
khint_t key;
|
||||
uint64_t hashval;
|
||||
size_t size;
|
||||
|
||||
h = wyhash(str_,len_,0x7472617065786974,_wyp);
|
||||
hashval = rapidhash((void*)str_,len_);
|
||||
|
||||
size = u64_set_size(&_u64_set);
|
||||
u64_set_get_or_insert(&_u64_set,hashval);
|
||||
|
||||
key = kh_put(hashset,_set,h,&rv);
|
||||
if(rv == 0)
|
||||
return 0;
|
||||
|
||||
kh_key(_set,key) = h;
|
||||
|
||||
return rv;
|
||||
return (size != u64_set_size(&_u64_set));
|
||||
}
|
||||
|
||||
inline
|
||||
@@ -64,12 +83,12 @@ public:
|
||||
}
|
||||
|
||||
inline
|
||||
int
|
||||
size_t
|
||||
size(void)
|
||||
{
|
||||
return kh_size(_set);
|
||||
return u64_set_size(&_u64_set);
|
||||
}
|
||||
|
||||
private:
|
||||
khash_t(hashset) *_set;
|
||||
u64_set _u64_set;
|
||||
};
|
||||
|
||||
+323
@@ -0,0 +1,323 @@
|
||||
/*
|
||||
* rapidhash - Very fast, high quality, platform-independent hashing algorithm.
|
||||
* Copyright (C) 2024 Nicolas De Carli
|
||||
*
|
||||
* Based on 'wyhash', by Wang Yi <godspeed_china@yeah.net>
|
||||
*
|
||||
* BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * 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 COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||
* OWNER 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.
|
||||
*
|
||||
* You can contact the author at:
|
||||
* - rapidhash source repository: https://github.com/Nicoshev/rapidhash
|
||||
*/
|
||||
|
||||
/*
|
||||
* Includes.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#if defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#if defined(_M_X64) && !defined(_M_ARM64EC)
|
||||
#pragma intrinsic(_umul128)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* C++ macros.
|
||||
*
|
||||
* RAPIDHASH_INLINE can be overridden to be stronger than a hint, i.e. by adding __attribute__((always_inline)).
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#define RAPIDHASH_NOEXCEPT noexcept
|
||||
#define RAPIDHASH_CONSTEXPR constexpr
|
||||
#ifndef RAPIDHASH_INLINE
|
||||
#define RAPIDHASH_INLINE inline
|
||||
#endif
|
||||
#else
|
||||
#define RAPIDHASH_NOEXCEPT
|
||||
#define RAPIDHASH_CONSTEXPR static const
|
||||
#ifndef RAPIDHASH_INLINE
|
||||
#define RAPIDHASH_INLINE static inline
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Protection macro, alters behaviour of rapid_mum multiplication function.
|
||||
*
|
||||
* RAPIDHASH_FAST: Normal behavior, max speed.
|
||||
* RAPIDHASH_PROTECTED: Extra protection against entropy loss.
|
||||
*/
|
||||
#ifndef RAPIDHASH_PROTECTED
|
||||
#define RAPIDHASH_FAST
|
||||
#elif defined(RAPIDHASH_FAST)
|
||||
#error "cannot define RAPIDHASH_PROTECTED and RAPIDHASH_FAST simultaneously."
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Unrolling macros, changes code definition for main hash function.
|
||||
*
|
||||
* RAPIDHASH_COMPACT: Legacy variant, each loop process 48 bytes.
|
||||
* RAPIDHASH_UNROLLED: Unrolled variant, each loop process 96 bytes.
|
||||
*
|
||||
* Most modern CPUs should benefit from having RAPIDHASH_UNROLLED.
|
||||
*
|
||||
* These macros do not alter the output hash.
|
||||
*/
|
||||
#ifndef RAPIDHASH_COMPACT
|
||||
#define RAPIDHASH_UNROLLED
|
||||
#elif defined(RAPIDHASH_UNROLLED)
|
||||
#error "cannot define RAPIDHASH_COMPACT and RAPIDHASH_UNROLLED simultaneously."
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Likely and unlikely macros.
|
||||
*/
|
||||
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
|
||||
#define _likely_(x) __builtin_expect(x,1)
|
||||
#define _unlikely_(x) __builtin_expect(x,0)
|
||||
#else
|
||||
#define _likely_(x) (x)
|
||||
#define _unlikely_(x) (x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Endianness macros.
|
||||
*/
|
||||
#ifndef RAPIDHASH_LITTLE_ENDIAN
|
||||
#if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||
#define RAPIDHASH_LITTLE_ENDIAN
|
||||
#elif defined(__BIG_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
#define RAPIDHASH_BIG_ENDIAN
|
||||
#else
|
||||
#warning "could not determine endianness! Falling back to little endian."
|
||||
#define RAPIDHASH_LITTLE_ENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Default seed.
|
||||
*/
|
||||
#define RAPID_SEED (0xbdd89aa982704029ull)
|
||||
|
||||
/*
|
||||
* Default secret parameters.
|
||||
*/
|
||||
RAPIDHASH_CONSTEXPR uint64_t rapid_secret[3] = {0x2d358dccaa6c78a5ull, 0x8bb84b93962eacc9ull, 0x4b33a62ed433d4a3ull};
|
||||
|
||||
/*
|
||||
* 64*64 -> 128bit multiply function.
|
||||
*
|
||||
* @param A Address of 64-bit number.
|
||||
* @param B Address of 64-bit number.
|
||||
*
|
||||
* Calculates 128-bit C = *A * *B.
|
||||
*
|
||||
* When RAPIDHASH_FAST is defined:
|
||||
* Overwrites A contents with C's low 64 bits.
|
||||
* Overwrites B contents with C's high 64 bits.
|
||||
*
|
||||
* When RAPIDHASH_PROTECTED is defined:
|
||||
* Xors and overwrites A contents with C's low 64 bits.
|
||||
* Xors and overwrites B contents with C's high 64 bits.
|
||||
*/
|
||||
RAPIDHASH_INLINE void rapid_mum(uint64_t *A, uint64_t *B) RAPIDHASH_NOEXCEPT {
|
||||
#if defined(__SIZEOF_INT128__)
|
||||
__uint128_t r=*A; r*=*B;
|
||||
#ifdef RAPIDHASH_PROTECTED
|
||||
*A^=(uint64_t)r; *B^=(uint64_t)(r>>64);
|
||||
#else
|
||||
*A=(uint64_t)r; *B=(uint64_t)(r>>64);
|
||||
#endif
|
||||
#elif defined(_MSC_VER) && (defined(_WIN64) || defined(_M_HYBRID_CHPE_ARM64))
|
||||
#if defined(_M_X64)
|
||||
#ifdef RAPIDHASH_PROTECTED
|
||||
uint64_t a, b;
|
||||
a=_umul128(*A,*B,&b);
|
||||
*A^=a; *B^=b;
|
||||
#else
|
||||
*A=_umul128(*A,*B,B);
|
||||
#endif
|
||||
#else
|
||||
#ifdef RAPIDHASH_PROTECTED
|
||||
uint64_t a, b;
|
||||
b = __umulh(*A, *B);
|
||||
a = *A * *B;
|
||||
*A^=a; *B^=b;
|
||||
#else
|
||||
uint64_t c = __umulh(*A, *B);
|
||||
*A = *A * *B;
|
||||
*B = c;
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
uint64_t ha=*A>>32, hb=*B>>32, la=(uint32_t)*A, lb=(uint32_t)*B, hi, lo;
|
||||
uint64_t rh=ha*hb, rm0=ha*lb, rm1=hb*la, rl=la*lb, t=rl+(rm0<<32), c=t<rl;
|
||||
lo=t+(rm1<<32); c+=lo<t; hi=rh+(rm0>>32)+(rm1>>32)+c;
|
||||
#ifdef RAPIDHASH_PROTECTED
|
||||
*A^=lo; *B^=hi;
|
||||
#else
|
||||
*A=lo; *B=hi;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Multiply and xor mix function.
|
||||
*
|
||||
* @param A 64-bit number.
|
||||
* @param B 64-bit number.
|
||||
*
|
||||
* Calculates 128-bit C = A * B.
|
||||
* Returns 64-bit xor between high and low 64 bits of C.
|
||||
*/
|
||||
RAPIDHASH_INLINE uint64_t rapid_mix(uint64_t A, uint64_t B) RAPIDHASH_NOEXCEPT { rapid_mum(&A,&B); return A^B; }
|
||||
|
||||
/*
|
||||
* Read functions.
|
||||
*/
|
||||
#ifdef RAPIDHASH_LITTLE_ENDIAN
|
||||
RAPIDHASH_INLINE uint64_t rapid_read64(const uint8_t *p) RAPIDHASH_NOEXCEPT { uint64_t v; memcpy(&v, p, sizeof(uint64_t)); return v;}
|
||||
RAPIDHASH_INLINE uint64_t rapid_read32(const uint8_t *p) RAPIDHASH_NOEXCEPT { uint32_t v; memcpy(&v, p, sizeof(uint32_t)); return v;}
|
||||
#elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
|
||||
RAPIDHASH_INLINE uint64_t rapid_read64(const uint8_t *p) RAPIDHASH_NOEXCEPT { uint64_t v; memcpy(&v, p, sizeof(uint64_t)); return __builtin_bswap64(v);}
|
||||
RAPIDHASH_INLINE uint64_t rapid_read32(const uint8_t *p) RAPIDHASH_NOEXCEPT { uint32_t v; memcpy(&v, p, sizeof(uint32_t)); return __builtin_bswap32(v);}
|
||||
#elif defined(_MSC_VER)
|
||||
RAPIDHASH_INLINE uint64_t rapid_read64(const uint8_t *p) RAPIDHASH_NOEXCEPT { uint64_t v; memcpy(&v, p, sizeof(uint64_t)); return _byteswap_uint64(v);}
|
||||
RAPIDHASH_INLINE uint64_t rapid_read32(const uint8_t *p) RAPIDHASH_NOEXCEPT { uint32_t v; memcpy(&v, p, sizeof(uint32_t)); return _byteswap_ulong(v);}
|
||||
#else
|
||||
RAPIDHASH_INLINE uint64_t rapid_read64(const uint8_t *p) RAPIDHASH_NOEXCEPT {
|
||||
uint64_t v; memcpy(&v, p, 8);
|
||||
return (((v >> 56) & 0xff)| ((v >> 40) & 0xff00)| ((v >> 24) & 0xff0000)| ((v >> 8) & 0xff000000)| ((v << 8) & 0xff00000000)| ((v << 24) & 0xff0000000000)| ((v << 40) & 0xff000000000000)| ((v << 56) & 0xff00000000000000));
|
||||
}
|
||||
RAPIDHASH_INLINE uint64_t rapid_read32(const uint8_t *p) RAPIDHASH_NOEXCEPT {
|
||||
uint32_t v; memcpy(&v, p, 4);
|
||||
return (((v >> 24) & 0xff)| ((v >> 8) & 0xff00)| ((v << 8) & 0xff0000)| ((v << 24) & 0xff000000));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Reads and combines 3 bytes of input.
|
||||
*
|
||||
* @param p Buffer to read from.
|
||||
* @param k Length of @p, in bytes.
|
||||
*
|
||||
* Always reads and combines 3 bytes from memory.
|
||||
* Guarantees to read each buffer position at least once.
|
||||
*
|
||||
* Returns a 64-bit value containing all three bytes read.
|
||||
*/
|
||||
RAPIDHASH_INLINE uint64_t rapid_readSmall(const uint8_t *p, size_t k) RAPIDHASH_NOEXCEPT { return (((uint64_t)p[0])<<56)|(((uint64_t)p[k>>1])<<32)|p[k-1];}
|
||||
|
||||
/*
|
||||
* rapidhash main function.
|
||||
*
|
||||
* @param key Buffer to be hashed.
|
||||
* @param len @key length, in bytes.
|
||||
* @param seed 64-bit seed used to alter the hash result predictably.
|
||||
* @param secret Triplet of 64-bit secrets used to alter hash result predictably.
|
||||
*
|
||||
* Returns a 64-bit hash.
|
||||
*/
|
||||
RAPIDHASH_INLINE uint64_t rapidhash_internal(const void *key, size_t len, uint64_t seed, const uint64_t* secret) RAPIDHASH_NOEXCEPT {
|
||||
const uint8_t *p=(const uint8_t *)key; seed^=rapid_mix(seed^secret[0],secret[1])^len; uint64_t a, b;
|
||||
if(_likely_(len<=16)){
|
||||
if(_likely_(len>=4)){
|
||||
const uint8_t * plast = p + len - 4;
|
||||
a = (rapid_read32(p) << 32) | rapid_read32(plast);
|
||||
const uint64_t delta = ((len&24)>>(len>>3));
|
||||
b = ((rapid_read32(p + delta) << 32) | rapid_read32(plast - delta)); }
|
||||
else if(_likely_(len>0)){ a=rapid_readSmall(p,len); b=0;}
|
||||
else a=b=0;
|
||||
}
|
||||
else{
|
||||
size_t i=len;
|
||||
if(_unlikely_(i>48)){
|
||||
uint64_t see1=seed, see2=seed;
|
||||
#ifdef RAPIDHASH_UNROLLED
|
||||
while(_likely_(i>=96)){
|
||||
seed=rapid_mix(rapid_read64(p)^secret[0],rapid_read64(p+8)^seed);
|
||||
see1=rapid_mix(rapid_read64(p+16)^secret[1],rapid_read64(p+24)^see1);
|
||||
see2=rapid_mix(rapid_read64(p+32)^secret[2],rapid_read64(p+40)^see2);
|
||||
seed=rapid_mix(rapid_read64(p+48)^secret[0],rapid_read64(p+56)^seed);
|
||||
see1=rapid_mix(rapid_read64(p+64)^secret[1],rapid_read64(p+72)^see1);
|
||||
see2=rapid_mix(rapid_read64(p+80)^secret[2],rapid_read64(p+88)^see2);
|
||||
p+=96; i-=96;
|
||||
}
|
||||
if(_unlikely_(i>=48)){
|
||||
seed=rapid_mix(rapid_read64(p)^secret[0],rapid_read64(p+8)^seed);
|
||||
see1=rapid_mix(rapid_read64(p+16)^secret[1],rapid_read64(p+24)^see1);
|
||||
see2=rapid_mix(rapid_read64(p+32)^secret[2],rapid_read64(p+40)^see2);
|
||||
p+=48; i-=48;
|
||||
}
|
||||
#else
|
||||
do {
|
||||
seed=rapid_mix(rapid_read64(p)^secret[0],rapid_read64(p+8)^seed);
|
||||
see1=rapid_mix(rapid_read64(p+16)^secret[1],rapid_read64(p+24)^see1);
|
||||
see2=rapid_mix(rapid_read64(p+32)^secret[2],rapid_read64(p+40)^see2);
|
||||
p+=48; i-=48;
|
||||
} while (_likely_(i>=48));
|
||||
#endif
|
||||
seed^=see1^see2;
|
||||
}
|
||||
if(i>16){
|
||||
seed=rapid_mix(rapid_read64(p)^secret[2],rapid_read64(p+8)^seed^secret[1]);
|
||||
if(i>32)
|
||||
seed=rapid_mix(rapid_read64(p+16)^secret[2],rapid_read64(p+24)^seed);
|
||||
}
|
||||
a=rapid_read64(p+i-16); b=rapid_read64(p+i-8);
|
||||
}
|
||||
a^=secret[1]; b^=seed; rapid_mum(&a,&b);
|
||||
return rapid_mix(a^secret[0]^len,b^secret[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
* rapidhash default seeded hash function.
|
||||
*
|
||||
* @param key Buffer to be hashed.
|
||||
* @param len @key length, in bytes.
|
||||
* @param seed 64-bit seed used to alter the hash result predictably.
|
||||
*
|
||||
* Calls rapidhash_internal using provided parameters and default secrets.
|
||||
*
|
||||
* Returns a 64-bit hash.
|
||||
*/
|
||||
RAPIDHASH_INLINE uint64_t rapidhash_withSeed(const void *key, size_t len, uint64_t seed) RAPIDHASH_NOEXCEPT {
|
||||
return rapidhash_internal(key, len, seed, rapid_secret);
|
||||
}
|
||||
|
||||
/*
|
||||
* rapidhash default hash function.
|
||||
*
|
||||
* @param key Buffer to be hashed.
|
||||
* @param len @key length, in bytes.
|
||||
*
|
||||
* Calls rapidhash_withSeed using provided parameters and the default seed.
|
||||
*
|
||||
* Returns a 64-bit hash.
|
||||
*/
|
||||
RAPIDHASH_INLINE uint64_t rapidhash(const void *key, size_t len) RAPIDHASH_NOEXCEPT {
|
||||
return rapidhash_withSeed(key, len, RAPID_SEED);
|
||||
}
|
||||
+1946
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user