mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-05 19:31:57 -04:00
BACKPORT: ANDROID: fuse: Move functions in preparation for fuse-bpf
Contains squash of this commit:
Author: Nathan Chancellor <nathan@kernel.org>
Date: Fri Jan 20 09:40:12 2023 -0700
ANDROID: fuse: Restore upstream type of bitfields in fuse_args
Commit 88b7179fcdb59 ("ANDROID: fuse: Move functions in preparation for
fuse-bpf") changed the type of these bitfields from the upstream type of
'bool' to 'int', which causes several warnings with recent versions of
clang:
/builds/linux/fs/fuse/dir.c:168:19: error: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Werror,-Wsingle-bi
t-bitfield-constant-conversion]
args->out_argvar = true;
^ ~~~~
/builds/linux/fs/fuse/dir.c:492:18: error: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Werror,-Wsingle-bi
t-bitfield-constant-conversion]
args.out_argvar = 1;
^ ~
/builds/linux/fs/fuse/dir.c:1649:20: error: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Werror,-Wsingle-b
it-bitfield-constant-conversion]
ap.args.out_pages = true;
^ ~~~~
/builds/linux/fs/fuse/dir.c:1650:21: error: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Werror,-Wsingle-b
it-bitfield-constant-conversion]
ap.args.out_argvar = true;
^ ~~~~
/builds/linux/fs/fuse/dir.c:1651:23: error: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Werror,-Wsingle-b
it-bitfield-constant-conversion]
ap.args.page_zeroing = true;
^ ~~~~
5 errors generated.
When fuse_args was moved back to the internal implementation in commit
9a5023967b4d2 ("ANDROID: fuse-bpf: Use fuse_bpf_args in uapi"), the type
was not restored. Do so now to fix the warnings and reduce the delta
with upstream.
Bug: 265200230
Change-Id: I4d51f331d842a1faff9a937140f0275130e70d73
Signed-off-by: Nathan Chancellor <nathan@kernel.org>
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:
parent
26f1e21656
commit
2e6dc19099
5 changed files with 155 additions and 140 deletions
|
|
@ -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);
|
||||
|
|
@ -1031,7 +1004,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;
|
||||
|
|
@ -1492,58 +1465,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
|
||||
*
|
||||
|
|
|
|||
120
fs/fuse/fuse_i.h
120
fs/fuse/fuse_i.h
|
|
@ -249,47 +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 user_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 +919,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 +1232,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)
|
||||
{
|
||||
|
|
@ -1266,28 +1288,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;
|
||||
|
|
@ -1331,7 +1331,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) {
|
||||
|
|
@ -368,7 +368,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,42 @@ 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;
|
||||
bool force:1;
|
||||
bool noreply:1;
|
||||
bool nocreds:1;
|
||||
bool in_pages:1;
|
||||
bool out_pages:1;
|
||||
bool user_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;
|
||||
};
|
||||
|
||||
#endif /* _LINUX_FUSE_H */
|
||||
|
|
|
|||
Loading…
Reference in a new issue