mirror of
https://github.com/hardkernel/linux.git
synced 2026-03-26 12:30:23 +09:00
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:
committed by
Paul Lawrence
parent
f70f7045c1
commit
88b7179fcd
@@ -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
|
||||
*
|
||||
|
||||
119
fs/fuse/fuse_i.h
119
fs/fuse/fuse_i.h
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user