ANDROID: fuse: Move functions in preparation for fuse-bpf

Bug: 202785178
Test: test_fuse passes on linux, feature works on cuttlefish
Signed-off-by: Paul Lawrence <paullawrence@google.com>
Signed-off-by: Daniel Rosenberg <drosen@google.com>
Change-Id: Ie738893a821d1f5f252c4c6e86274d55a6f09965
This commit is contained in:
Daniel Rosenberg
2021-12-02 13:50:02 -08:00
committed by Paul Lawrence
parent f70f7045c1
commit 88b7179fcd
5 changed files with 154 additions and 139 deletions

View File

@@ -74,28 +74,6 @@ static void fuse_dentry_settime(struct dentry *dentry, u64 time)
__fuse_dentry_settime(dentry, 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
*/
static u64 time_to_jiffies(u64 sec, u32 nsec)
{
if (sec || nsec) {
struct timespec64 ts = {
sec,
min_t(u32, nsec, NSEC_PER_SEC - 1)
};
return get_jiffies_64() + timespec64_to_jiffies(&ts);
} else
return 0;
}
/*
* Set dentry and possibly attribute timeouts from the lookup/mk*
* replies
@@ -106,11 +84,6 @@ void fuse_change_entry_timeout(struct dentry *entry, struct fuse_entry_out *o)
time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
}
static u64 attr_timeout(struct fuse_attr_out *o)
{
return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
}
u64 entry_attr_timeout(struct fuse_entry_out *o)
{
return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
@@ -1033,7 +1006,7 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
return err;
}
static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
struct kstat *stat)
{
unsigned int blkbits;
@@ -1494,58 +1467,6 @@ static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
}
static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
{
/* Always update if mtime is explicitly set */
if (ivalid & ATTR_MTIME_SET)
return true;
/* Or if kernel i_mtime is the official one */
if (trust_local_mtime)
return true;
/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
return false;
/* In all other cases update */
return true;
}
static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr,
struct fuse_setattr_in *arg, bool trust_local_cmtime)
{
unsigned ivalid = iattr->ia_valid;
if (ivalid & ATTR_MODE)
arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
if (ivalid & ATTR_UID)
arg->valid |= FATTR_UID, arg->uid = from_kuid(fc->user_ns, iattr->ia_uid);
if (ivalid & ATTR_GID)
arg->valid |= FATTR_GID, arg->gid = from_kgid(fc->user_ns, iattr->ia_gid);
if (ivalid & ATTR_SIZE)
arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
if (ivalid & ATTR_ATIME) {
arg->valid |= FATTR_ATIME;
arg->atime = iattr->ia_atime.tv_sec;
arg->atimensec = iattr->ia_atime.tv_nsec;
if (!(ivalid & ATTR_ATIME_SET))
arg->valid |= FATTR_ATIME_NOW;
}
if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
arg->valid |= FATTR_MTIME;
arg->mtime = iattr->ia_mtime.tv_sec;
arg->mtimensec = iattr->ia_mtime.tv_nsec;
if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
arg->valid |= FATTR_MTIME_NOW;
}
if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
arg->valid |= FATTR_CTIME;
arg->ctime = iattr->ia_ctime.tv_sec;
arg->ctimensec = iattr->ia_ctime.tv_nsec;
}
}
/*
* Prevent concurrent writepages on inode
*

View File

@@ -249,46 +249,12 @@ struct fuse_file {
bool flock:1;
};
/** One input argument of a request */
struct fuse_in_arg {
unsigned size;
const void *value;
};
/** One output argument of a request */
struct fuse_arg {
unsigned size;
void *value;
};
/** FUSE page descriptor */
struct fuse_page_desc {
unsigned int length;
unsigned int offset;
};
struct fuse_args {
uint64_t nodeid;
uint32_t opcode;
unsigned short in_numargs;
unsigned short out_numargs;
bool force:1;
bool noreply:1;
bool nocreds:1;
bool in_pages:1;
bool out_pages:1;
bool out_argvar:1;
bool page_zeroing:1;
bool page_replace:1;
bool may_block:1;
struct fuse_in_arg in_args[3];
struct fuse_arg out_args[2];
void (*end)(struct fuse_mount *fm, struct fuse_args *args, int error);
/* Path used for completing d_canonical_path */
struct path *canonical_path;
};
struct fuse_args_pages {
struct fuse_args args;
struct page **pages;
@@ -954,6 +920,9 @@ void fuse_read_args_fill(struct fuse_io_args *ia, struct file *file, loff_t pos,
size_t count, int opcode);
int fuse_parse_dirfile(char *buf, size_t nbytes, struct file *file,
struct dir_context *ctx);
/**
* Send OPEN or OPENDIR request
*/
@@ -1264,4 +1233,86 @@ ssize_t fuse_passthrough_read_iter(struct kiocb *iocb, struct iov_iter *to);
ssize_t fuse_passthrough_write_iter(struct kiocb *iocb, struct iov_iter *from);
ssize_t fuse_passthrough_mmap(struct file *file, struct vm_area_struct *vma);
/*
* 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
*/
static inline u64 time_to_jiffies(u64 sec, u32 nsec)
{
if (sec || nsec) {
struct timespec64 ts = {
sec,
min_t(u32, nsec, NSEC_PER_SEC - 1)
};
return get_jiffies_64() + timespec64_to_jiffies(&ts);
} else
return 0;
}
static inline u64 attr_timeout(struct fuse_attr_out *o)
{
return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
}
static inline bool update_mtime(unsigned ivalid, bool trust_local_mtime)
{
/* Always update if mtime is explicitly set */
if (ivalid & ATTR_MTIME_SET)
return true;
/* Or if kernel i_mtime is the official one */
if (trust_local_mtime)
return true;
/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
return false;
/* In all other cases update */
return true;
}
void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
struct kstat *stat);
static inline void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr,
struct fuse_setattr_in *arg, bool trust_local_cmtime)
{
unsigned ivalid = iattr->ia_valid;
if (ivalid & ATTR_MODE)
arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
if (ivalid & ATTR_UID)
arg->valid |= FATTR_UID, arg->uid = from_kuid(fc->user_ns, iattr->ia_uid);
if (ivalid & ATTR_GID)
arg->valid |= FATTR_GID, arg->gid = from_kgid(fc->user_ns, iattr->ia_gid);
if (ivalid & ATTR_SIZE)
arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
if (ivalid & ATTR_ATIME) {
arg->valid |= FATTR_ATIME;
arg->atime = iattr->ia_atime.tv_sec;
arg->atimensec = iattr->ia_atime.tv_nsec;
if (!(ivalid & ATTR_ATIME_SET))
arg->valid |= FATTR_ATIME_NOW;
}
if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
arg->valid |= FATTR_MTIME;
arg->mtime = iattr->ia_mtime.tv_sec;
arg->mtimensec = iattr->ia_mtime.tv_nsec;
if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
arg->valid |= FATTR_MTIME_NOW;
}
if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
arg->valid |= FATTR_CTIME;
arg->ctime = iattr->ia_ctime.tv_sec;
arg->ctimensec = iattr->ia_ctime.tv_nsec;
}
}
#endif /* _FS_FUSE_I_H */

View File

@@ -161,6 +161,28 @@ static ino_t fuse_squash_ino(u64 ino64)
return ino;
}
static void fuse_fill_attr_from_inode(struct fuse_attr *attr,
const struct inode *inode)
{
*attr = (struct fuse_attr){
.ino = inode->i_ino,
.size = inode->i_size,
.blocks = inode->i_blocks,
.atime = inode->i_atime.tv_sec,
.mtime = inode->i_mtime.tv_sec,
.ctime = inode->i_ctime.tv_sec,
.atimensec = inode->i_atime.tv_nsec,
.mtimensec = inode->i_mtime.tv_nsec,
.ctimensec = inode->i_ctime.tv_nsec,
.mode = inode->i_mode,
.nlink = inode->i_nlink,
.uid = inode->i_uid.val,
.gid = inode->i_gid.val,
.rdev = inode->i_rdev,
.blksize = 1u << inode->i_blkbits,
};
}
void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
u64 attr_valid)
{
@@ -1253,28 +1275,6 @@ void fuse_dev_free(struct fuse_dev *fud)
}
EXPORT_SYMBOL_GPL(fuse_dev_free);
static void fuse_fill_attr_from_inode(struct fuse_attr *attr,
const struct fuse_inode *fi)
{
*attr = (struct fuse_attr){
.ino = fi->inode.i_ino,
.size = fi->inode.i_size,
.blocks = fi->inode.i_blocks,
.atime = fi->inode.i_atime.tv_sec,
.mtime = fi->inode.i_mtime.tv_sec,
.ctime = fi->inode.i_ctime.tv_sec,
.atimensec = fi->inode.i_atime.tv_nsec,
.mtimensec = fi->inode.i_mtime.tv_nsec,
.ctimensec = fi->inode.i_ctime.tv_nsec,
.mode = fi->inode.i_mode,
.nlink = fi->inode.i_nlink,
.uid = fi->inode.i_uid.val,
.gid = fi->inode.i_gid.val,
.rdev = fi->inode.i_rdev,
.blksize = 1u << fi->inode.i_blkbits,
};
}
static void fuse_sb_defaults(struct super_block *sb)
{
sb->s_magic = FUSE_SUPER_MAGIC;
@@ -1318,7 +1318,7 @@ int fuse_fill_super_submount(struct super_block *sb,
if (parent_sb->s_subtype && !sb->s_subtype)
return -ENOMEM;
fuse_fill_attr_from_inode(&root_attr, parent_fi);
fuse_fill_attr_from_inode(&root_attr, &parent_fi->inode);
root = fuse_iget(sb, parent_fi->nodeid, 0, &root_attr, 0, 0);
/*
* This inode is just a duplicate, so it is not looked up and

View File

@@ -121,7 +121,7 @@ static bool fuse_emit(struct file *file, struct dir_context *ctx,
dirent->type);
}
static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
int fuse_parse_dirfile(char *buf, size_t nbytes, struct file *file,
struct dir_context *ctx)
{
while (nbytes >= FUSE_NAME_OFFSET) {
@@ -360,7 +360,7 @@ static int fuse_readdir_uncached(struct file *file, struct dir_context *ctx)
res = parse_dirplusfile(page_address(page), res,
file, ctx, attr_version);
} else {
res = parse_dirfile(page_address(page), res, file,
res = fuse_parse_dirfile(page_address(page), res, file,
ctx);
}
}

View File

@@ -634,6 +634,12 @@ struct fuse_read_in {
uint32_t padding;
};
struct fuse_read_out {
uint64_t offset;
uint32_t again;
uint32_t padding;
};
#define FUSE_COMPAT_WRITE_IN_SIZE 24
struct fuse_write_in {
@@ -942,4 +948,41 @@ struct fuse_removemapping_one {
#define FUSE_REMOVEMAPPING_MAX_ENTRY \
(PAGE_SIZE / sizeof(struct fuse_removemapping_one))
struct fuse_mount;
/** One input argument of a request */
struct fuse_in_arg {
unsigned size;
const void *value;
};
/** One output argument of a request */
struct fuse_arg {
unsigned size;
void *value;
};
struct fuse_args {
uint64_t nodeid;
uint32_t opcode;
uint32_t error_in;
unsigned short in_numargs;
unsigned short out_numargs;
int force:1;
int noreply:1;
int nocreds:1;
int in_pages:1;
int out_pages:1;
int out_argvar:1;
int page_zeroing:1;
int page_replace:1;
int may_block:1;
struct fuse_in_arg in_args[3];
struct fuse_arg out_args[2];
void (*end)(struct fuse_mount *fm, struct fuse_args *args, int error);
/* Path used for completing d_canonical_path */
struct path *canonical_path;
};
#endif /* _LINUX_FUSE_H */