summaryrefslogtreecommitdiffstats
path: root/fs/fuse/xattr.c
diff options
context:
space:
mode:
authorYijie Yang <yijie.yang@oss.qualcomm.com>2026-08-11 16:46:47 +0800
committerRob Herring (Arm) <robh@kernel.org>2026-08-15 15:46:52 -0500
commite1c13aed4a1641550e8c9518c96f016e1d52d09b (patch)
tree61c2297688373db165cc857b7c7adcb147a5c419 /fs/fuse/xattr.c
downloadlinux-stable-e1c13aed4a1641550e8c9518c96f016e1d52d09b.tar.gz
linux-stable-e1c13aed4a1641550e8c9518c96f016e1d52d09b.zip
dt-bindings: interconnect: qcom-bwmon: Add Maili cpu-bwmon compatiblegrafted
Add the Qualcomm Maili SoC compatible string for the CPU bandwidth monitor (BWMONv4). This falls back to the sdm845-bwmon compatible, consistent with the existing pattern used by other recent SoCs such as sm8750 and kaanapali. Signed-off-by: Yijie Yang <yijie.yang@oss.qualcomm.com> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com> Reviewed-by: Jingyi Wang <jingyi.wang@oss.qualcomm.com> Link: https://patch.msgid.link/20260811-bwmon-v2-1-80f7f150ab9e@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
Diffstat (limited to 'fs/fuse/xattr.c')
-rw-r--r--fs/fuse/xattr.c214
1 files changed, 214 insertions, 0 deletions
diff --git a/fs/fuse/xattr.c b/fs/fuse/xattr.c
new file mode 100644
index 000000000..cab2685ac
--- /dev/null
+++ b/fs/fuse/xattr.c
@@ -0,0 +1,214 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * FUSE: Filesystem in Userspace
+ * Copyright (C) 2001-2016 Miklos Szeredi <miklos@szeredi.hu>
+ */
+
+#include "fuse_i.h"
+
+#include <linux/xattr.h>
+#include <linux/posix_acl_xattr.h>
+
+int fuse_setxattr(struct inode *inode, const char *name, const void *value,
+ size_t size, int flags, unsigned int extra_flags)
+{
+ struct fuse_mount *fm = get_fuse_mount(inode);
+ FUSE_ARGS(args);
+ struct fuse_setxattr_in inarg;
+ int err;
+
+ if (fm->fc->no_setxattr)
+ return -EOPNOTSUPP;
+
+ memset(&inarg, 0, sizeof(inarg));
+ inarg.size = size;
+ inarg.flags = flags;
+ inarg.setxattr_flags = extra_flags;
+
+ args.opcode = FUSE_SETXATTR;
+ args.nodeid = get_node_id(inode);
+ args.in_numargs = 3;
+ args.in_args[0].size = fm->fc->setxattr_ext ?
+ sizeof(inarg) : FUSE_COMPAT_SETXATTR_IN_SIZE;
+ args.in_args[0].value = &inarg;
+ args.in_args[1].size = strlen(name) + 1;
+ args.in_args[1].value = name;
+ args.in_args[2].size = size;
+ args.in_args[2].value = value;
+ err = fuse_simple_request(fm, &args);
+ if (err == -ENOSYS) {
+ fm->fc->no_setxattr = 1;
+ err = -EOPNOTSUPP;
+ }
+ if (!err)
+ fuse_update_ctime(inode);
+
+ return err;
+}
+
+ssize_t fuse_getxattr(struct inode *inode, const char *name, void *value,
+ size_t size)
+{
+ struct fuse_mount *fm = get_fuse_mount(inode);
+ FUSE_ARGS(args);
+ struct fuse_getxattr_in inarg;
+ struct fuse_getxattr_out outarg;
+ ssize_t ret;
+
+ if (fm->fc->no_getxattr)
+ return -EOPNOTSUPP;
+
+ memset(&inarg, 0, sizeof(inarg));
+ inarg.size = size;
+ args.opcode = FUSE_GETXATTR;
+ args.nodeid = get_node_id(inode);
+ args.in_numargs = 2;
+ args.in_args[0].size = sizeof(inarg);
+ args.in_args[0].value = &inarg;
+ args.in_args[1].size = strlen(name) + 1;
+ args.in_args[1].value = name;
+ /* This is really two different operations rolled into one */
+ args.out_numargs = 1;
+ if (size) {
+ args.out_argvar = true;
+ args.out_args[0].size = size;
+ args.out_args[0].value = value;
+ } else {
+ args.out_args[0].size = sizeof(outarg);
+ args.out_args[0].value = &outarg;
+ }
+ ret = fuse_simple_request(fm, &args);
+ if (!ret && !size)
+ ret = min_t(size_t, outarg.size, XATTR_SIZE_MAX);
+ if (ret == -ENOSYS) {
+ fm->fc->no_getxattr = 1;
+ ret = -EOPNOTSUPP;
+ }
+ return ret;
+}
+
+static int fuse_verify_xattr_list(char *list, size_t size)
+{
+ size_t origsize = size;
+
+ while (size) {
+ size_t thislen = strnlen(list, size);
+
+ if (!thislen || thislen == size)
+ return -EIO;
+
+ size -= thislen + 1;
+ list += thislen + 1;
+ }
+
+ return origsize;
+}
+
+ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
+{
+ struct inode *inode = d_inode(entry);
+ struct fuse_mount *fm = get_fuse_mount(inode);
+ FUSE_ARGS(args);
+ struct fuse_getxattr_in inarg;
+ struct fuse_getxattr_out outarg;
+ ssize_t ret;
+
+ if (fuse_is_bad(inode))
+ return -EIO;
+
+ if (!fuse_allow_current_process(fm->fc))
+ return -EACCES;
+
+ if (fm->fc->no_listxattr)
+ return -EOPNOTSUPP;
+
+ memset(&inarg, 0, sizeof(inarg));
+ inarg.size = size;
+ args.opcode = FUSE_LISTXATTR;
+ args.nodeid = get_node_id(inode);
+ args.in_numargs = 1;
+ args.in_args[0].size = sizeof(inarg);
+ args.in_args[0].value = &inarg;
+ /* This is really two different operations rolled into one */
+ args.out_numargs = 1;
+ if (size) {
+ args.out_argvar = true;
+ args.out_args[0].size = size;
+ args.out_args[0].value = list;
+ } else {
+ args.out_args[0].size = sizeof(outarg);
+ args.out_args[0].value = &outarg;
+ }
+ ret = fuse_simple_request(fm, &args);
+ if (!ret && !size)
+ ret = min_t(size_t, outarg.size, XATTR_LIST_MAX);
+ if (ret > 0 && size)
+ ret = fuse_verify_xattr_list(list, ret);
+ if (ret == -ENOSYS) {
+ fm->fc->no_listxattr = 1;
+ ret = -EOPNOTSUPP;
+ }
+ return ret;
+}
+
+int fuse_removexattr(struct inode *inode, const char *name)
+{
+ struct fuse_mount *fm = get_fuse_mount(inode);
+ FUSE_ARGS(args);
+ int err;
+
+ if (fm->fc->no_removexattr)
+ return -EOPNOTSUPP;
+
+ args.opcode = FUSE_REMOVEXATTR;
+ args.nodeid = get_node_id(inode);
+ args.in_numargs = 2;
+ fuse_set_zero_arg0(&args);
+ args.in_args[1].size = strlen(name) + 1;
+ args.in_args[1].value = name;
+ err = fuse_simple_request(fm, &args);
+ if (err == -ENOSYS) {
+ fm->fc->no_removexattr = 1;
+ err = -EOPNOTSUPP;
+ }
+ if (!err)
+ fuse_update_ctime(inode);
+
+ return err;
+}
+
+static int fuse_xattr_get(const struct xattr_handler *handler,
+ struct dentry *dentry, struct inode *inode,
+ const char *name, void *value, size_t size)
+{
+ if (fuse_is_bad(inode))
+ return -EIO;
+
+ return fuse_getxattr(inode, name, value, size);
+}
+
+static int fuse_xattr_set(const struct xattr_handler *handler,
+ struct mnt_idmap *idmap,
+ struct dentry *dentry, struct inode *inode,
+ const char *name, const void *value, size_t size,
+ int flags)
+{
+ if (fuse_is_bad(inode))
+ return -EIO;
+
+ if (!value)
+ return fuse_removexattr(inode, name);
+
+ return fuse_setxattr(inode, name, value, size, flags, 0);
+}
+
+static const struct xattr_handler fuse_xattr_handler = {
+ .prefix = "",
+ .get = fuse_xattr_get,
+ .set = fuse_xattr_set,
+};
+
+const struct xattr_handler * const fuse_xattr_handlers[] = {
+ &fuse_xattr_handler,
+ NULL
+};