Antonio SJ Musumeci 9 months ago
parent
commit
bb7ad3f6d9
  1. 929
      libfuse/include/fuse_lowlevel.h
  2. 9
      libfuse/lib/crc32b.h
  3. 2
      libfuse/lib/fmp.h
  4. 185
      libfuse/lib/fuse.cpp
  5. 12
      libfuse/lib/node.h

929
libfuse/include/fuse_lowlevel.h

@ -131,891 +131,52 @@ 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 (*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 (*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 (*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);
};
/**

9
libfuse/lib/crc32b.h

@ -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

2
libfuse/lib/fmp.h

@ -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);

185
libfuse/lib/fuse.c → libfuse/lib/fuse.cpp

@ -7,7 +7,9 @@
*/
/* For pthread_rwlock_t */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include "crc32b.h"
#include "fuse_node.h"
@ -104,13 +106,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 +213,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 +379,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 +445,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 +790,7 @@ add_name(char **buf,
newbufsize *= 2;
}
newbuf = realloc(*buf,newbufsize);
newbuf = (char*)realloc(*buf,newbufsize);
if(newbuf == NULL)
return NULL;
@ -857,7 +852,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 +1557,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 +1623,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 +1640,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 +1668,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 +1730,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 +1791,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 +1848,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 +1904,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 +1956,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 +1986,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 +2019,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 +2047,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 +2079,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 +2117,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 +2181,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 +2282,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 +2327,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 +2360,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 +2371,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 +2395,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 +2430,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 +2517,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 +2561,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 +2602,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 +2631,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 +2683,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 +2736,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 +2797,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 +2837,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 +2862,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 +2922,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 +3021,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 +3050,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 +3059,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 +3080,7 @@ locks_insert(node_t *node,
lp = &l->next;
continue;
delete:
delete_lock:
delete_lock(lp);
}
if(lock->type != F_UNLCK)
@ -3168,7 +3163,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 +3201,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 +3260,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 +3336,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 +3368,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 +3398,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 +3436,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 +3471,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 +3489,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 +3825,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,
@ -3911,7 +3906,7 @@ fuse_invalidate_all_nodes()
syslog(LOG_INFO,"invalidating file entries");
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;

12
libfuse/lib/node.h

@ -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
Loading…
Cancel
Save