diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-08-02 03:00:29 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-08-02 03:00:29 +0000 |
commit | 0abbe299f08448856ba8cde44e9124dcc3a7a0e4 (patch) | |
tree | cd87675190dc011a7714d5b0a9b1e93ecd498eaa | |
parent | f4141658b798dd4deac913a02ee9bcfd0c1ba3f9 (diff) | |
parent | 5c7ff5dc7aace613470615ca3453d37c407a3551 (diff) | |
download | common-android-gs-bluejay-5.10-u-beta5.tar.gz |
Snap for 10566483 from 5c7ff5dc7aace613470615ca3453d37c407a3551 to android13-gs-pixel-5.10-releaseandroid-u-beta-5_r0.7android-u-beta-5_r0.5android-u-beta-5_r0.4android-u-beta-5_r0.3android-u-beta-5_r0.2android-u-beta-5_r0.1android-u-beta-5.2_r0.7android-u-beta-5.2_r0.6android-u-beta-5.2_r0.5android-u-beta-5.2_r0.3android-u-beta-5.2_r0.1android-gs-tangorpro-5.10-u-beta5.2android-gs-tangorpro-5.10-u-beta5android-gs-raviole-5.10-u-beta5.2android-gs-raviole-5.10-u-beta5android-gs-pantah-5.10-u-beta5android-gs-lynx-5.10-u-beta5.2android-gs-lynx-5.10-u-beta5android-gs-felix-5.10-u-beta5.2android-gs-felix-5.10-u-beta5android-gs-bluejay-5.10-u-beta5.2android-gs-bluejay-5.10-u-beta5
Change-Id: Ibcc2b9edd46f82307af8c5eba41a6897a614168a
-rw-r--r-- | fs/f2fs/f2fs.h | 1 | ||||
-rw-r--r-- | fs/f2fs/super.c | 1 | ||||
-rw-r--r-- | fs/f2fs/xattr.c | 31 | ||||
-rw-r--r-- | fs/fuse/backing.c | 81 | ||||
-rw-r--r-- | fs/fuse/dev.c | 2 | ||||
-rw-r--r-- | fs/fuse/dir.c | 33 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 14 | ||||
-rw-r--r-- | fs/fuse/inode.c | 23 | ||||
-rw-r--r-- | fs/notify/inotify/inotify_user.c | 8 | ||||
-rw-r--r-- | include/linux/fsnotify.h | 5 |
10 files changed, 120 insertions, 79 deletions
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index d9e038d42548..91458b9dcb2b 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -808,7 +808,6 @@ struct f2fs_inode_info { /* avoid racing between foreground op and gc */ struct f2fs_rwsem i_gc_rwsem[2]; struct f2fs_rwsem i_mmap_sem; - struct f2fs_rwsem i_xattr_sem; /* avoid racing between reading and changing EAs */ int i_extra_isize; /* size of extra space located in i_addr */ kprojid_t i_projid; /* id for project quota */ diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 0d20b52ae247..eb34fed89b8f 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1390,7 +1390,6 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) init_f2fs_rwsem(&fi->i_gc_rwsem[READ]); init_f2fs_rwsem(&fi->i_gc_rwsem[WRITE]); init_f2fs_rwsem(&fi->i_mmap_sem); - init_f2fs_rwsem(&fi->i_xattr_sem); /* Will be used by directory only */ fi->i_dir_level = F2FS_SB(sb)->dir_level; diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 8d1c8efb643c..5b48357a7e91 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -428,7 +428,7 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize, { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); size_t inline_size = inline_xattr_size(inode); - struct page *in_page = NULL; + struct page *in_page = ipage; void *xattr_addr; void *inline_addr = NULL; struct page *xpage; @@ -441,29 +441,19 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize, /* write to inline xattr */ if (inline_size) { - if (ipage) { - inline_addr = inline_xattr_addr(inode, ipage); - } else { + if (!in_page) { in_page = f2fs_get_node_page(sbi, inode->i_ino); if (IS_ERR(in_page)) { f2fs_alloc_nid_failed(sbi, new_nid); return PTR_ERR(in_page); } - inline_addr = inline_xattr_addr(inode, in_page); } + inline_addr = inline_xattr_addr(inode, in_page); - f2fs_wait_on_page_writeback(ipage ? ipage : in_page, - NODE, true, true); - /* no need to use xattr node block */ + f2fs_wait_on_page_writeback(in_page, NODE, true, true); if (hsize <= inline_size) { - err = f2fs_truncate_xattr_node(inode); - f2fs_alloc_nid_failed(sbi, new_nid); - if (err) { - f2fs_put_page(in_page, 1); - return err; - } memcpy(inline_addr, txattr_addr, inline_size); - set_page_dirty(ipage ? ipage : in_page); + set_page_dirty(in_page); goto in_page_out; } } @@ -497,12 +487,13 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize, memcpy(xattr_addr, txattr_addr + inline_size, VALID_XATTR_BLOCK_SIZE); if (inline_size) - set_page_dirty(ipage ? ipage : in_page); + set_page_dirty(in_page); set_page_dirty(xpage); f2fs_put_page(xpage, 1); in_page_out: - f2fs_put_page(in_page, 1); + if (in_page != ipage) + f2fs_put_page(in_page, 1); return err; } @@ -523,10 +514,8 @@ int f2fs_getxattr(struct inode *inode, int index, const char *name, if (len > F2FS_NAME_LEN) return -ERANGE; - f2fs_down_read(&F2FS_I(inode)->i_xattr_sem); error = lookup_all_xattrs(inode, ipage, index, len, name, &entry, &base_addr, &base_size, &is_inline); - f2fs_up_read(&F2FS_I(inode)->i_xattr_sem); if (error) return error; @@ -560,9 +549,7 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) int error; size_t rest = buffer_size; - f2fs_down_read(&F2FS_I(inode)->i_xattr_sem); error = read_all_xattrs(inode, NULL, &base_addr); - f2fs_up_read(&F2FS_I(inode)->i_xattr_sem); if (error) return error; @@ -784,9 +771,7 @@ int f2fs_setxattr(struct inode *inode, int index, const char *name, f2fs_balance_fs(sbi, true); f2fs_lock_op(sbi); - f2fs_down_write(&F2FS_I(inode)->i_xattr_sem); err = __f2fs_setxattr(inode, index, name, value, size, ipage, flags); - f2fs_up_write(&F2FS_I(inode)->i_xattr_sem); f2fs_unlock_op(sbi); f2fs_update_time(sbi, REQ_TIME); diff --git a/fs/fuse/backing.c b/fs/fuse/backing.c index 8ab36055c967..19e690aaffb1 100644 --- a/fs/fuse/backing.c +++ b/fs/fuse/backing.c @@ -1222,8 +1222,6 @@ int fuse_handle_backing(struct fuse_entry_bpf *feb, struct inode **backing_inode path_put(backing_path); *backing_path = backing_file->f_path; path_get(backing_path); - - fput(backing_file); break; } @@ -1237,39 +1235,36 @@ int fuse_handle_backing(struct fuse_entry_bpf *feb, struct inode **backing_inode int fuse_handle_bpf_prog(struct fuse_entry_bpf *feb, struct inode *parent, struct bpf_prog **bpf) { - struct bpf_prog *new_bpf; - - /* Parent isn't presented, but we want to keep - * Don't touch bpf program at all in this case - */ - if (feb->out.bpf_action == FUSE_ACTION_KEEP && !parent) - return 0; + struct bpf_prog *new_bpf = NULL; switch (feb->out.bpf_action) { case FUSE_ACTION_KEEP: { - struct fuse_inode *pi = get_fuse_inode(parent); + /* Parent isn't presented, but we want to keep + * Don't touch bpf program at all in this case + */ + if (!parent) + return 0; - new_bpf = pi->bpf; + new_bpf = get_fuse_inode(parent)->bpf; if (new_bpf) bpf_prog_inc(new_bpf); break; } case FUSE_ACTION_REMOVE: - new_bpf = NULL; break; case FUSE_ACTION_REPLACE: { struct file *bpf_file = feb->bpf_file; - struct bpf_prog *bpf_prog = ERR_PTR(-EINVAL); - if (bpf_file && !IS_ERR(bpf_file)) - bpf_prog = fuse_get_bpf_prog(bpf_file); - - if (IS_ERR(bpf_prog)) - return PTR_ERR(bpf_prog); + if (!bpf_file) + return -EINVAL; + if (IS_ERR(bpf_file)) + return PTR_ERR(bpf_file); - new_bpf = bpf_prog; + new_bpf = fuse_get_bpf_prog(bpf_file); + if (IS_ERR(new_bpf)) + return PTR_ERR(new_bpf); break; } @@ -1279,7 +1274,8 @@ int fuse_handle_bpf_prog(struct fuse_entry_bpf *feb, struct inode *parent, /* Cannot change existing program */ if (*bpf) { - bpf_prog_put(new_bpf); + if (new_bpf) + bpf_prog_put(new_bpf); return new_bpf == *bpf ? 0 : -EINVAL; } @@ -1299,36 +1295,55 @@ struct dentry *fuse_lookup_finalize(struct fuse_bpf_args *fa, struct inode *dir, struct fuse_entry_bpf *feb = container_of(febo, struct fuse_entry_bpf, out); int error = -1; u64 target_nodeid = 0; + struct dentry *ret; fd = get_fuse_dentry(entry); - if (!fd) - return ERR_PTR(-EIO); + if (!fd) { + ret = ERR_PTR(-EIO); + goto out; + } + bd = fd->backing_path.dentry; - if (!bd) - return ERR_PTR(-ENOENT); + if (!bd) { + ret = ERR_PTR(-ENOENT); + goto out; + } + backing_inode = bd->d_inode; - if (!backing_inode) - return 0; + if (!backing_inode) { + ret = 0; + goto out; + } if (d_inode) target_nodeid = get_fuse_inode(d_inode)->nodeid; inode = fuse_iget_backing(dir->i_sb, target_nodeid, backing_inode); - if (IS_ERR(inode)) - return ERR_PTR(PTR_ERR(inode)); + if (IS_ERR(inode)) { + ret = ERR_PTR(PTR_ERR(inode)); + goto out; + } error = fuse_handle_bpf_prog(feb, dir, &get_fuse_inode(inode)->bpf); - if (error) - return ERR_PTR(error); + if (error) { + ret = ERR_PTR(error); + goto out; + } error = fuse_handle_backing(feb, &get_fuse_inode(inode)->backing_inode, &fd->backing_path); - if (error) - return ERR_PTR(error); + if (error) { + ret = ERR_PTR(error); + goto out; + } get_fuse_inode(inode)->nodeid = feo->nodeid; - return d_splice_alias(inode, entry); + ret = d_splice_alias(inode, entry); +out: + if (feb->backing_file) + fput(feb->backing_file); + return ret; } int fuse_revalidate_backing(struct dentry *entry, unsigned int flags) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index c13be2fa891f..23445c452b45 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1945,7 +1945,7 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud, err = copy_out_args(cs, req->args, nbytes); fuse_copy_finish(cs); - if (!err && req->in.h.opcode == FUSE_CANONICAL_PATH) { + if (!err && req->in.h.opcode == FUSE_CANONICAL_PATH && !oh.error) { char *path = (char *)req->args->out_args[0].value; path[req->args->out_args[0].size - 1] = 0; diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 25ddb77d7266..e522ef1af731 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -183,8 +183,10 @@ static bool backing_data_changed(struct fuse_inode *fi, struct dentry *entry, int err; bool ret = true; - if (!entry) - return false; + if (!entry) { + ret = false; + goto put_backing_file; + } get_fuse_backing_path(entry, &new_backing_path); new_backing_inode = fi->backing_inode; @@ -207,6 +209,9 @@ put_bpf: put_inode: iput(new_backing_inode); path_put(&new_backing_path); +put_backing_file: + if (bpf_arg->backing_file) + fput(bpf_arg->backing_file); return ret; } #endif @@ -474,13 +479,18 @@ static void fuse_dentry_canonical_path(const struct path *path, fuse_canonical_path_backing, fuse_canonical_path_finalize, path, canonical_path); - if (fer.ret) + if (fer.ret) { + if (IS_ERR(fer.result)) + canonical_path->dentry = fer.result; return; + } #endif path_name = (char *)get_zeroed_page(GFP_KERNEL); - if (!path_name) - goto default_path; + if (!path_name) { + canonical_path->dentry = ERR_PTR(-ENOMEM); + return; + } args.opcode = FUSE_CANONICAL_PATH; args.nodeid = get_node_id(inode); @@ -495,10 +505,15 @@ static void fuse_dentry_canonical_path(const struct path *path, free_page((unsigned long)path_name); if (err > 0) return; -default_path: + if (err < 0) { + canonical_path->dentry = ERR_PTR(err); + return; + } + canonical_path->dentry = path->dentry; canonical_path->mnt = path->mnt; path_get(canonical_path); + return; } const struct dentry_operations fuse_dentry_operations = { @@ -582,7 +597,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name backing_inode = backing_file->f_inode; *inode = fuse_iget_backing(sb, outarg->nodeid, backing_inode); if (!*inode) - goto bpf_arg_out; + goto out; err = fuse_handle_backing(&bpf_arg, &get_fuse_inode(*inode)->backing_inode, @@ -593,8 +608,6 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name err = fuse_handle_bpf_prog(&bpf_arg, NULL, &get_fuse_inode(*inode)->bpf); if (err) goto out; -bpf_arg_out: - fput(backing_file); } else #endif { @@ -626,6 +639,8 @@ out_queue_forget: out_put_forget: kfree(forget); out: + if (bpf_arg.backing_file) + fput(bpf_arg.backing_file); return err; } diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index a1fee82265ea..e76ae9f2671c 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -1832,6 +1832,16 @@ void __exit fuse_bpf_cleanup(void); ssize_t fuse_bpf_simple_request(struct fuse_mount *fm, struct fuse_bpf_args *args); +static inline int fuse_bpf_run(struct bpf_prog *prog, struct fuse_bpf_args *fba) +{ + int ret; + + migrate_disable(); + ret = BPF_PROG_RUN(prog, fba); + migrate_enable(); + return ret; +} + /* * expression statement to wrap the backing filter logic * struct inode *inode: inode with bpf and backing inode @@ -1883,7 +1893,7 @@ ssize_t fuse_bpf_simple_request(struct fuse_mount *fm, struct fuse_bpf_args *arg fa.out_numargs = fa.in_numargs; \ \ ext_flags = fuse_inode->bpf ? \ - BPF_PROG_RUN(fuse_inode->bpf, &fa) : \ + fuse_bpf_run(fuse_inode->bpf, &fa) : \ FUSE_BPF_BACKING; \ if (ext_flags < 0) { \ fer = (struct fuse_err_ret) { \ @@ -1938,7 +1948,7 @@ ssize_t fuse_bpf_simple_request(struct fuse_mount *fm, struct fuse_bpf_args *arg .size = fa.out_args[i].size, \ .value = fa.out_args[i].value, \ }; \ - ext_flags = BPF_PROG_RUN(fuse_inode->bpf, &fa); \ + ext_flags = fuse_bpf_run(fuse_inode->bpf, &fa); \ if (ext_flags < 0) { \ fer = (struct fuse_err_ret) { \ ERR_PTR(ext_flags), \ diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index e1de6b1807dd..c67c6680dc87 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -115,6 +115,10 @@ static void fuse_free_inode(struct inode *inode) #ifdef CONFIG_FUSE_DAX kfree(fi->dax); #endif +#ifdef CONFIG_FUSE_BPF + if (fi->bpf) + bpf_prog_put(fi->bpf); +#endif kmem_cache_free(fuse_inode_cachep, fi); } @@ -125,13 +129,6 @@ static void fuse_evict_inode(struct inode *inode) /* Will write inode on close/munmap and in all other dirtiers */ WARN_ON(inode->i_state & I_DIRTY_INODE); -#ifdef CONFIG_FUSE_BPF - iput(fi->backing_inode); - if (fi->bpf) - bpf_prog_put(fi->bpf); - fi->bpf = NULL; -#endif - truncate_inode_pages_final(&inode->i_data); clear_inode(inode); if (inode->i_sb->s_flags & SB_ACTIVE) { @@ -151,6 +148,15 @@ static void fuse_evict_inode(struct inode *inode) } } +#ifdef CONFIG_FUSE_BPF +static void fuse_destroy_inode(struct inode *inode) +{ + struct fuse_inode *fi = get_fuse_inode(inode); + + iput(fi->backing_inode); +} +#endif + static int fuse_reconfigure(struct fs_context *fc) { struct super_block *sb = fc->root->d_sb; @@ -1084,6 +1090,9 @@ static const struct export_operations fuse_export_operations = { static const struct super_operations fuse_super_operations = { .alloc_inode = fuse_alloc_inode, +#ifdef CONFIG_FUSE_BPF + .destroy_inode = fuse_destroy_inode, +#endif .free_inode = fuse_free_inode, .evict_inode = fuse_evict_inode, .write_inode = fuse_write_inode, diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 9ea915e9d2a1..a392e40a89cb 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -699,7 +699,7 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname, struct fsnotify_group *group; struct inode *inode; struct path path; - struct path alteredpath; + struct path alteredpath = {}; struct path *canonical_path = &path; struct fd f; int ret; @@ -752,6 +752,11 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname, if (path.dentry->d_op->d_canonical_path) { path.dentry->d_op->d_canonical_path(&path, &alteredpath); + if (IS_ERR(alteredpath.dentry)) { + ret = PTR_ERR(alteredpath.dentry); + goto path_put_and_out; + } + canonical_path = &alteredpath; path_put(&path); } @@ -763,6 +768,7 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname, /* create/update an inode mark */ ret = inotify_update_watch(group, inode, mask); +path_put_and_out: path_put(canonical_path); fput_and_out: fdput(f); diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 37eba54836d1..c286ab3dcce5 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -93,10 +93,13 @@ static inline int fsnotify_file(struct file *file, __u32 mask) if (mask & FS_OPEN) { if (path->dentry->d_op && path->dentry->d_op->d_canonical_path) { - struct path lower_path; + struct path lower_path = {}; int ret; path->dentry->d_op->d_canonical_path(path, &lower_path); + if (IS_ERR(lower_path.dentry)) + return PTR_ERR(lower_path.dentry); + ret = fsnotify_parent(lower_path.dentry, mask, &lower_path, FSNOTIFY_EVENT_PATH); path_put(&lower_path); |