add support for FUSE_NOTIFY_PRUNE

Add fuse_lowlevel_notify_prune() helper, which sends FUSE_NOTIFY_PRUNE
notification to kernel indicating that the server side's inode caches
with resources e.g. file handle could be cleaned up if the corresponding
dentry/inode caches (with dangling references) at the kernel side could
be pruned out.

This is a best-effort operation as inodes with active references are
skipped.

Signed-off-by: Jingbo Xu <jefflexu@linux.alibaba.com>
This commit is contained in:
Jingbo Xu
2025-12-29 18:41:15 +08:00
committed by Bernd Schubert
parent e81cf70c07
commit cba0be1bed
5 changed files with 54 additions and 1 deletions
+1
View File
@@ -27,6 +27,7 @@ notifications:
| RETRIEVE | fuse_lowlevel_notify_retrieve |
| DELETE | fuse_lowlevel_notify_delete |
| RESEND | - |
| PRUNE | fuse_lowlevel_notify_prune |
|-------------+----------------------------------|
One important restriction is that these asynchronous operations SHALL NOT be
+8 -1
View File
@@ -239,6 +239,7 @@
* 7.45
* - add FUSE_COPY_FILE_RANGE_64
* - add struct fuse_copy_file_range_out
* - add FUSE_NOTIFY_PRUNE
*/
#ifndef _LINUX_FUSE_H
@@ -680,7 +681,7 @@ enum fuse_notify_code {
FUSE_NOTIFY_DELETE = 6,
FUSE_NOTIFY_RESEND = 7,
FUSE_NOTIFY_INC_EPOCH = 8,
FUSE_NOTIFY_CODE_MAX,
FUSE_NOTIFY_PRUNE = 9,
};
/* The read buffer is required to be at least 8k, but may be much larger */
@@ -1119,6 +1120,12 @@ struct fuse_notify_retrieve_in {
uint64_t dummy4;
};
struct fuse_notify_prune_out {
uint32_t count;
uint32_t padding;
uint64_t spare;
};
struct fuse_backing_map {
int32_t fd;
uint32_t flags;
+20
View File
@@ -1954,6 +1954,26 @@ int fuse_lowlevel_notify_store(struct fuse_session *se, fuse_ino_t ino,
int fuse_lowlevel_notify_retrieve(struct fuse_session *se, fuse_ino_t ino,
size_t size, off_t offset, void *cookie);
/**
* Notify to prune kernel's own dentry/inode caches
*
* Some fuse servers need to prune their caches, which can only be done if the
* kernel's own dentry/inode caches are pruned first to avoid dangling
* references. Once dangling dentry/inode cache gets pruned, the inode gets
* evicted and thus FUSE_FORGET will be sent to fuse server. On receiving
* FUSE_FORGET, fuse server can free their own inode cache with resources, e.g.
* corresponding file handle.
*
* The notification takes an array of node IDs to try and get rid of. It is
* best-effort as inodes with active references are skipped.
*
* @param se the session object
* @param nodeids the array of node IDs to be pruned
* @param count the length of the nodeids array
* @return zero for success, -errno for failure
*/
int fuse_lowlevel_notify_prune(struct fuse_session *se,
fuse_ino_t *nodeids, uint32_t count);
/* ----------------------------------------------------------- *
* Utility functions *
+24
View File
@@ -3384,6 +3384,30 @@ int fuse_lowlevel_notify_retrieve(struct fuse_session *se, fuse_ino_t ino,
return err;
}
int fuse_lowlevel_notify_prune(struct fuse_session *se,
fuse_ino_t *nodeids, uint32_t count)
{
struct fuse_notify_prune_out outarg;
struct iovec iov[3];
if (!se)
return -EINVAL;
if (se->conn.proto_minor < 45)
return -ENOSYS;
outarg.count = count;
outarg.padding = 0;
outarg.spare = 0;
iov[1].iov_base = &outarg;
iov[1].iov_len = sizeof(outarg);
iov[2].iov_base = (void *)nodeids;
iov[2].iov_len = sizeof(fuse_ino_t) * count;
return send_notify_iov(se, FUSE_NOTIFY_PRUNE, iov, 3);
}
void *fuse_req_userdata(fuse_req_t req)
{
return req->se->userdata;
+1
View File
@@ -226,6 +226,7 @@ FUSE_3.19 {
global:
fuse_session_start_teardown_watchdog;
fuse_session_stop_teardown_watchdog;
fuse_lowlevel_notify_prune;
} FUSE_3.18;
# Local Variables: