Snap for 10566483 from 5c7ff5dc7aace613470615ca3453d37c407a3551 to android13-gs-pixel-5.10-release

Change-Id: Ibcc2b9edd46f82307af8c5eba41a6897a614168a
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index d9e038d..91458b9 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -808,7 +808,6 @@
 	/* 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 0d20b52..eb34fed 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1390,7 +1390,6 @@
 	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 8d1c8ef..5b48357 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -428,7 +428,7 @@
 {
 	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 @@
 
 	/* 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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 8ab3605..19e690a 100644
--- a/fs/fuse/backing.c
+++ b/fs/fuse/backing.c
@@ -1222,8 +1222,6 @@
 		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_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 (!bpf_file)
+			return -EINVAL;
+		if (IS_ERR(bpf_file))
+			return PTR_ERR(bpf_file);
 
-		if (IS_ERR(bpf_prog))
-			return PTR_ERR(bpf_prog);
-
-		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 @@
 
 	/* 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 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 c13be2fa..23445c4 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1945,7 +1945,7 @@
 		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 25ddb77..e522ef1 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -183,8 +183,10 @@
 	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_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 @@
 			       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 @@
 	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 @@
 		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 @@
 		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_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 a1fee82..e76ae9f 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -1832,6 +1832,16 @@
 
 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 @@
 		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 @@
 					.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 e1de6b1..c67c668 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -115,6 +115,10 @@
 #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 @@
 	/* 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 @@
 	}
 }
 
+#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 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 9ea915e..a392e40 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -699,7 +699,7 @@
 	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 @@
 		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 @@
 
 	/* 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 37eba54..c286ab3 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -93,10 +93,13 @@
 	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);