summaryrefslogtreecommitdiffstats
path: root/fs/ceph/cache.c
diff options
context:
space:
mode:
authorEduard Zingerman <eddyz87@gmail.com>2026-09-04 17:05:56 -0700
committerAlexei Starovoitov <ast@kernel.org>2026-09-04 18:17:30 -0700
commit506ada89629ec7059b96ecfb0dc7d33ece0103ca (patch)
tree0b07297409b68d2333fb4f0eae7f3b072eb68d4c /fs/ceph/cache.c
downloadlinux-stable-506ada89629ec7059b96ecfb0dc7d33ece0103ca.tar.gz
linux-stable-506ada89629ec7059b96ecfb0dc7d33ece0103ca.zip
bpf: mark a NULL kfunc argument precisegrafted
check_kfunc_arg() allows bpf_register_is_null() for nullable arguments w/o marking the underlying scalar register precise. Hence a checkpoint created on such a path would prune against arbitrary scalar value. Fixes: 3bda08b63670 ("bpf: Allow NULL buffers in bpf_dynptr_slice(_rw)") Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Link: https://lore.kernel.org/r/20260904-register-is-null-precise-fixes-v1-5-0f5a360ff15d@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'fs/ceph/cache.c')
-rw-r--r--fs/ceph/cache.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/fs/ceph/cache.c b/fs/ceph/cache.c
new file mode 100644
index 000000000..f678bab18
--- /dev/null
+++ b/fs/ceph/cache.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Ceph cache definitions.
+ *
+ * Copyright (C) 2013 by Adfin Solutions, Inc. All Rights Reserved.
+ * Written by Milosz Tanski (milosz@adfin.com)
+ */
+
+#include <linux/ceph/ceph_debug.h>
+
+#include <linux/fs_context.h>
+#include "super.h"
+#include "cache.h"
+
+void ceph_fscache_register_inode_cookie(struct inode *inode)
+{
+ struct ceph_inode_info *ci = ceph_inode(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
+
+ /* No caching for filesystem? */
+ if (!fsc->fscache)
+ return;
+
+ /* Regular files only */
+ if (!S_ISREG(inode->i_mode))
+ return;
+
+ /* Only new inodes! */
+ if (!(inode_state_read_once(inode) & I_NEW))
+ return;
+
+ WARN_ON_ONCE(ci->netfs.cache);
+
+ ci->netfs.cache =
+ fscache_acquire_cookie(fsc->fscache, 0,
+ &ci->i_vino, sizeof(ci->i_vino),
+ &ci->i_version, sizeof(ci->i_version),
+ i_size_read(inode));
+ if (ci->netfs.cache)
+ mapping_set_release_always(inode->i_mapping);
+}
+
+void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info *ci)
+{
+ fscache_relinquish_cookie(ceph_fscache_cookie(ci), false);
+}
+
+void ceph_fscache_use_cookie(struct inode *inode, bool will_modify)
+{
+ struct ceph_inode_info *ci = ceph_inode(inode);
+
+ fscache_use_cookie(ceph_fscache_cookie(ci), will_modify);
+}
+
+void ceph_fscache_unuse_cookie(struct inode *inode, bool update)
+{
+ struct ceph_inode_info *ci = ceph_inode(inode);
+
+ if (update) {
+ loff_t i_size = i_size_read(inode);
+
+ fscache_unuse_cookie(ceph_fscache_cookie(ci),
+ &ci->i_version, &i_size);
+ } else {
+ fscache_unuse_cookie(ceph_fscache_cookie(ci), NULL, NULL);
+ }
+}
+
+void ceph_fscache_update(struct inode *inode)
+{
+ struct ceph_inode_info *ci = ceph_inode(inode);
+ loff_t i_size = i_size_read(inode);
+
+ fscache_update_cookie(ceph_fscache_cookie(ci), &ci->i_version, &i_size);
+}
+
+void ceph_fscache_invalidate(struct inode *inode, bool dio_write)
+{
+ struct ceph_inode_info *ci = ceph_inode(inode);
+
+ fscache_invalidate(ceph_fscache_cookie(ci),
+ &ci->i_version, i_size_read(inode),
+ dio_write ? FSCACHE_INVAL_DIO_WRITE : 0);
+}
+
+int ceph_fscache_register_fs(struct ceph_fs_client* fsc, struct fs_context *fc)
+{
+ const struct ceph_fsid *fsid = &fsc->client->fsid;
+ const char *fscache_uniq = fsc->mount_options->fscache_uniq;
+ size_t uniq_len = fscache_uniq ? strlen(fscache_uniq) : 0;
+ char *name;
+ int err = 0;
+
+ name = kasprintf(GFP_KERNEL, "ceph,%pU%s%s", fsid, uniq_len ? "," : "",
+ uniq_len ? fscache_uniq : "");
+ if (!name)
+ return -ENOMEM;
+
+ fsc->fscache = fscache_acquire_volume(name, NULL, NULL, 0);
+ if (IS_ERR_OR_NULL(fsc->fscache)) {
+ errorfc(fc, "Unable to register fscache cookie for %s", name);
+ err = fsc->fscache ? PTR_ERR(fsc->fscache) : -EOPNOTSUPP;
+ fsc->fscache = NULL;
+ }
+ kfree(name);
+ return err;
+}
+
+void ceph_fscache_unregister_fs(struct ceph_fs_client* fsc)
+{
+ fscache_relinquish_volume(fsc->fscache, NULL, false);
+}