linux/fs/fuse/dir.c

/*
  FUSE: Filesystem in Userspace
  Copyright (C) 2001-2008  Miklos Szeredi <[email protected]>

  This program can be distributed under the terms of the GNU GPL.
  See the file COPYING.
*/

#include "fuse_i.h"

#include <linux/pagemap.h>
#include <linux/file.h>
#include <linux/fs_context.h>
#include <linux/moduleparam.h>
#include <linux/sched.h>
#include <linux/namei.h>
#include <linux/slab.h>
#include <linux/xattr.h>
#include <linux/iversion.h>
#include <linux/posix_acl.h>
#include <linux/security.h>
#include <linux/types.h>
#include <linux/kernel.h>

static bool __read_mostly allow_sys_admin_access;
module_param(allow_sys_admin_access, bool, 0644);
MODULE_PARM_DESC();

static void fuse_advise_use_readdirplus(struct inode *dir)
{}

#if BITS_PER_LONG >= 64
static inline void __fuse_dentry_settime(struct dentry *entry, u64 time)
{}

static inline u64 fuse_dentry_time(const struct dentry *entry)
{}

#else
union fuse_dentry {
	u64 time;
	struct rcu_head rcu;
};

static inline void __fuse_dentry_settime(struct dentry *dentry, u64 time)
{
	((union fuse_dentry *) dentry->d_fsdata)->time = time;
}

static inline u64 fuse_dentry_time(const struct dentry *entry)
{
	return ((union fuse_dentry *) entry->d_fsdata)->time;
}
#endif

static void fuse_dentry_settime(struct dentry *dentry, u64 time)
{}

/*
 * FUSE caches dentries and attributes with separate timeout.  The
 * time in jiffies until the dentry/attributes are valid is stored in
 * dentry->d_fsdata and fuse_inode->i_time respectively.
 */

/*
 * Calculate the time in jiffies until a dentry/attributes are valid
 */
u64 fuse_time_to_jiffies(u64 sec, u32 nsec)
{}

/*
 * Set dentry and possibly attribute timeouts from the lookup/mk*
 * replies
 */
void fuse_change_entry_timeout(struct dentry *entry, struct fuse_entry_out *o)
{}

void fuse_invalidate_attr_mask(struct inode *inode, u32 mask)
{}

/*
 * Mark the attributes as stale, so that at the next call to
 * ->getattr() they will be fetched from userspace
 */
void fuse_invalidate_attr(struct inode *inode)
{}

static void fuse_dir_changed(struct inode *dir)
{}

/*
 * Mark the attributes as stale due to an atime change.  Avoid the invalidate if
 * atime is not used.
 */
void fuse_invalidate_atime(struct inode *inode)
{}

/*
 * Just mark the entry as stale, so that a next attempt to look it up
 * will result in a new lookup call to userspace
 *
 * This is called when a dentry is about to become negative and the
 * timeout is unknown (unlink, rmdir, rename and in some cases
 * lookup)
 */
void fuse_invalidate_entry_cache(struct dentry *entry)
{}

/*
 * Same as fuse_invalidate_entry_cache(), but also try to remove the
 * dentry from the hash
 */
static void fuse_invalidate_entry(struct dentry *entry)
{}

static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args,
			     u64 nodeid, const struct qstr *name,
			     struct fuse_entry_out *outarg)
{}

/*
 * Check whether the dentry is still valid
 *
 * If the entry validity timeout has expired and the dentry is
 * positive, try to redo the lookup.  If the lookup results in a
 * different inode, then let the VFS invalidate the dentry and redo
 * the lookup once more.  If the lookup results in the same inode,
 * then refresh the attributes, timeouts and mark the dentry valid.
 */
static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
{}

#if BITS_PER_LONG < 64
static int fuse_dentry_init(struct dentry *dentry)
{
	dentry->d_fsdata = kzalloc(sizeof(union fuse_dentry),
				   GFP_KERNEL_ACCOUNT | __GFP_RECLAIMABLE);

	return dentry->d_fsdata ? 0 : -ENOMEM;
}
static void fuse_dentry_release(struct dentry *dentry)
{
	union fuse_dentry *fd = dentry->d_fsdata;

	kfree_rcu(fd, rcu);
}
#endif

static int fuse_dentry_delete(const struct dentry *dentry)
{}

/*
 * Create a fuse_mount object with a new superblock (with path->dentry
 * as the root), and return that mount so it can be auto-mounted on
 * @path.
 */
static struct vfsmount *fuse_dentry_automount(struct path *path)
{}

const struct dentry_operations fuse_dentry_operations =;

const struct dentry_operations fuse_root_dentry_operations =;

int fuse_valid_type(int m)
{}

static bool fuse_valid_size(u64 size)
{}

bool fuse_invalid_attr(struct fuse_attr *attr)
{}

int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
		     struct fuse_entry_out *outarg, struct inode **inode)
{}

static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
				  unsigned int flags)
{}

static int get_security_context(struct dentry *entry, umode_t mode,
				struct fuse_in_arg *ext)
{}

static void *extend_arg(struct fuse_in_arg *buf, u32 bytes)
{}

static u32 fuse_ext_size(size_t size)
{}

/*
 * This adds just a single supplementary group that matches the parent's group.
 */
static int get_create_supp_group(struct inode *dir, struct fuse_in_arg *ext)
{}

static int get_create_ext(struct fuse_args *args,
			  struct inode *dir, struct dentry *dentry,
			  umode_t mode)
{}

static void free_ext_value(struct fuse_args *args)
{}

/*
 * Atomic create+open operation
 *
 * If the filesystem doesn't support this, then fall back to separate
 * 'mknod' + 'open' requests.
 */
static int fuse_create_open(struct inode *dir, struct dentry *entry,
			    struct file *file, unsigned int flags,
			    umode_t mode, u32 opcode)
{}

static int fuse_mknod(struct mnt_idmap *, struct inode *, struct dentry *,
		      umode_t, dev_t);
static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
			    struct file *file, unsigned flags,
			    umode_t mode)
{}

/*
 * Code shared between mknod, mkdir, symlink and link
 */
static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args,
			    struct inode *dir, struct dentry *entry,
			    umode_t mode)
{}

static int fuse_mknod(struct mnt_idmap *idmap, struct inode *dir,
		      struct dentry *entry, umode_t mode, dev_t rdev)
{}

static int fuse_create(struct mnt_idmap *idmap, struct inode *dir,
		       struct dentry *entry, umode_t mode, bool excl)
{}

static int fuse_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
			struct file *file, umode_t mode)
{}

static int fuse_mkdir(struct mnt_idmap *idmap, struct inode *dir,
		      struct dentry *entry, umode_t mode)
{}

static int fuse_symlink(struct mnt_idmap *idmap, struct inode *dir,
			struct dentry *entry, const char *link)
{}

void fuse_flush_time_update(struct inode *inode)
{}

static void fuse_update_ctime_in_cache(struct inode *inode)
{}

void fuse_update_ctime(struct inode *inode)
{}

static void fuse_entry_unlinked(struct dentry *entry)
{}

static int fuse_unlink(struct inode *dir, struct dentry *entry)
{}

static int fuse_rmdir(struct inode *dir, struct dentry *entry)
{}

static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
			      struct inode *newdir, struct dentry *newent,
			      unsigned int flags, int opcode, size_t argsize)
{}

static int fuse_rename2(struct mnt_idmap *idmap, struct inode *olddir,
			struct dentry *oldent, struct inode *newdir,
			struct dentry *newent, unsigned int flags)
{}

static int fuse_link(struct dentry *entry, struct inode *newdir,
		     struct dentry *newent)
{}

static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
			  struct kstat *stat)
{}

static void fuse_statx_to_attr(struct fuse_statx *sx, struct fuse_attr *attr)
{}

static int fuse_do_statx(struct inode *inode, struct file *file,
			 struct kstat *stat)
{}

static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
			   struct file *file)
{}

static int fuse_update_get_attr(struct inode *inode, struct file *file,
				struct kstat *stat, u32 request_mask,
				unsigned int flags)
{}

int fuse_update_attributes(struct inode *inode, struct file *file, u32 mask)
{}

int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid,
			     u64 child_nodeid, struct qstr *name, u32 flags)
{}

static inline bool fuse_permissible_uidgid(struct fuse_conn *fc)
{}

/*
 * Calling into a user-controlled filesystem gives the filesystem
 * daemon ptrace-like capabilities over the current process.  This
 * means, that the filesystem daemon is able to record the exact
 * filesystem operations performed, and can also control the behavior
 * of the requester process in otherwise impossible ways.  For example
 * it can delay the operation for arbitrary length of time allowing
 * DoS against the requester.
 *
 * For this reason only those processes can call into the filesystem,
 * for which the owner of the mount has ptrace privilege.  This
 * excludes processes started by other users, suid or sgid processes.
 */
bool fuse_allow_current_process(struct fuse_conn *fc)
{}

static int fuse_access(struct inode *inode, int mask)
{}

static int fuse_perm_getattr(struct inode *inode, int mask)
{}

/*
 * Check permission.  The two basic access models of FUSE are:
 *
 * 1) Local access checking ('default_permissions' mount option) based
 * on file mode.  This is the plain old disk filesystem permission
 * model.
 *
 * 2) "Remote" access checking, where server is responsible for
 * checking permission in each inode operation.  An exception to this
 * is if ->permission() was invoked from sys_access() in which case an
 * access request is sent.  Execute permission is still checked
 * locally based on file mode.
 */
static int fuse_permission(struct mnt_idmap *idmap,
			   struct inode *inode, int mask)
{}

static int fuse_readlink_page(struct inode *inode, struct page *page)
{}

static const char *fuse_get_link(struct dentry *dentry, struct inode *inode,
				 struct delayed_call *callback)
{}

static int fuse_dir_open(struct inode *inode, struct file *file)
{}

static int fuse_dir_release(struct inode *inode, struct file *file)
{}

static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
			  int datasync)
{}

static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
			    unsigned long arg)
{}

static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
				   unsigned long arg)
{}

static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
{}

static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr,
			   struct fuse_setattr_in *arg, bool trust_local_cmtime)
{}

/*
 * Prevent concurrent writepages on inode
 *
 * This is done by adding a negative bias to the inode write counter
 * and waiting for all pending writes to finish.
 */
void fuse_set_nowrite(struct inode *inode)
{}

/*
 * Allow writepages on inode
 *
 * Remove the bias from the writecounter and send any queued
 * writepages.
 */
static void __fuse_release_nowrite(struct inode *inode)
{}

void fuse_release_nowrite(struct inode *inode)
{}

static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args,
			      struct inode *inode,
			      struct fuse_setattr_in *inarg_p,
			      struct fuse_attr_out *outarg_p)
{}

/*
 * Flush inode->i_mtime to the server
 */
int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
{}

/*
 * Set attributes, and at the same time refresh them.
 *
 * Truncation is slightly complicated, because the 'truncate' request
 * may fail, in which case we don't want to touch the mapping.
 * vmtruncate() doesn't allow for this case, so do the rlimit checking
 * and the actual truncation by hand.
 */
int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
		    struct file *file)
{}

static int fuse_setattr(struct mnt_idmap *idmap, struct dentry *entry,
			struct iattr *attr)
{}

static int fuse_getattr(struct mnt_idmap *idmap,
			const struct path *path, struct kstat *stat,
			u32 request_mask, unsigned int flags)
{}

static const struct inode_operations fuse_dir_inode_operations =;

static const struct file_operations fuse_dir_operations =;

static const struct inode_operations fuse_common_inode_operations =;

static const struct inode_operations fuse_symlink_inode_operations =;

void fuse_init_common(struct inode *inode)
{}

void fuse_init_dir(struct inode *inode)
{}

static int fuse_symlink_read_folio(struct file *null, struct folio *folio)
{}

static const struct address_space_operations fuse_symlink_aops =;

void fuse_init_symlink(struct inode *inode)
{}