mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +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_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*
|
* Set dentry and possibly attribute timeouts from the lookup/mk*
|
||||||
* replies
|
* 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));
|
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)
|
u64 entry_attr_timeout(struct fuse_entry_out *o)
|
||||||
{
|
{
|
||||||
return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
|
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;
|
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)
|
struct kstat *stat)
|
||||||
{
|
{
|
||||||
unsigned int blkbits;
|
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);
|
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
|
* 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;
|
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 */
|
/** FUSE page descriptor */
|
||||||
struct fuse_page_desc {
|
struct fuse_page_desc {
|
||||||
unsigned int length;
|
unsigned int length;
|
||||||
unsigned int offset;
|
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_pages {
|
||||||
struct fuse_args args;
|
struct fuse_args args;
|
||||||
struct page **pages;
|
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);
|
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
|
* 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_write_iter(struct kiocb *iocb, struct iov_iter *from);
|
||||||
ssize_t fuse_passthrough_mmap(struct file *file, struct vm_area_struct *vma);
|
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 */
|
#endif /* _FS_FUSE_I_H */
|
||||||
|
|||||||
@@ -161,6 +161,28 @@ static ino_t fuse_squash_ino(u64 ino64)
|
|||||||
return ino;
|
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,
|
void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
|
||||||
u64 attr_valid)
|
u64 attr_valid)
|
||||||
{
|
{
|
||||||
@@ -1253,28 +1275,6 @@ void fuse_dev_free(struct fuse_dev *fud)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(fuse_dev_free);
|
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)
|
static void fuse_sb_defaults(struct super_block *sb)
|
||||||
{
|
{
|
||||||
sb->s_magic = FUSE_SUPER_MAGIC;
|
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)
|
if (parent_sb->s_subtype && !sb->s_subtype)
|
||||||
return -ENOMEM;
|
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);
|
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
|
* 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);
|
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)
|
struct dir_context *ctx)
|
||||||
{
|
{
|
||||||
while (nbytes >= FUSE_NAME_OFFSET) {
|
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,
|
res = parse_dirplusfile(page_address(page), res,
|
||||||
file, ctx, attr_version);
|
file, ctx, attr_version);
|
||||||
} else {
|
} else {
|
||||||
res = parse_dirfile(page_address(page), res, file,
|
res = fuse_parse_dirfile(page_address(page), res, file,
|
||||||
ctx);
|
ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -634,6 +634,12 @@ struct fuse_read_in {
|
|||||||
uint32_t padding;
|
uint32_t padding;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct fuse_read_out {
|
||||||
|
uint64_t offset;
|
||||||
|
uint32_t again;
|
||||||
|
uint32_t padding;
|
||||||
|
};
|
||||||
|
|
||||||
#define FUSE_COMPAT_WRITE_IN_SIZE 24
|
#define FUSE_COMPAT_WRITE_IN_SIZE 24
|
||||||
|
|
||||||
struct fuse_write_in {
|
struct fuse_write_in {
|
||||||
@@ -942,4 +948,41 @@ struct fuse_removemapping_one {
|
|||||||
#define FUSE_REMOVEMAPPING_MAX_ENTRY \
|
#define FUSE_REMOVEMAPPING_MAX_ENTRY \
|
||||||
(PAGE_SIZE / sizeof(struct fuse_removemapping_one))
|
(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 */
|
#endif /* _LINUX_FUSE_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user