From 6b1612e3a85b993f82124cccf149df3830e4a9c5 Mon Sep 17 00:00:00 2001 From: HereThereBeDragons Date: Thu, 27 Oct 2022 17:52:10 +0200 Subject: [PATCH] adding comments and capability discovery, enum for flags moved to top of file --- example/printcap.c | 2 ++ include/fuse_common.h | 16 ++++++++++++++++ include/fuse_lowlevel.h | 40 ++++++++++++++++++++++++++++++++++++---- lib/fuse_lowlevel.c | 2 ++ 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/example/printcap.c b/example/printcap.c index edfd8f531..48679883c 100644 --- a/example/printcap.c +++ b/example/printcap.c @@ -79,6 +79,8 @@ printf("\tFUSE_CAP_POSIX_ACL\n"); if(conn->capable & FUSE_CAP_CACHE_SYMLINKS) printf("\tFUSE_CAP_CACHE_SYMLINKS\n"); + if(conn->capable & FUSE_CAP_EXPIRE_ONLY) + printf("\tFUSE_CAP_EXPIRE_ONLY\n"); fuse_session_exit(se); } diff --git a/include/fuse_common.h b/include/fuse_common.h index e9d874556..dbba05af8 100644 --- a/include/fuse_common.h +++ b/include/fuse_common.h @@ -338,6 +338,22 @@ #define FUSE_CAP_CACHE_SYMLINKS (1 << 23) /** + * Indicates support that dentries can be expired or invalidated. + * + * Expiring dentries, instead of invalidating them, makes a difference for + * overmounted dentries, where plain invalidation would detach all submounts + * before dropping the dentry from the cache. If only expiry is set on the + * dentry, then any overmounts are left alone and until ->d_revalidate() + * is called. + * + * Note: ->d_revalidate() is not called for the case of following a submount, + * so invalidation will only be triggered for the non-overmounted case. + * The dentry could also be mounted in a different mount instance, in which case + * any submounts will still be detached. +*/ +#define FUSE_CAP_EXPIRE_ONLY (1 << 26) + +/** * Ioctl flags * * FUSE_IOCTL_COMPAT: 32bit compat ioctl on 64bit machine diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h index c955cc4bb..6a1a5d534 100644 --- a/include/fuse_lowlevel.h +++ b/include/fuse_lowlevel.h @@ -127,6 +127,15 @@ struct fuse_forget_data { uint64_t nlookup; }; +/** + * Flags for fuse_lowlevel_notify_expire_entry() + * 0 = invalidate entry + * FUSE_LL_EXPIRE_ONLY = expire entry +*/ +enum fuse_expire_flags { + FUSE_LL_EXPIRE_ONLY = (1 << 0), +}; + /* 'to_set' flags in setattr */ #define FUSE_SET_ATTR_MODE (1 << 0) #define FUSE_SET_ATTR_UID (1 << 1) @@ -1675,10 +1684,33 @@ int fuse_lowlevel_notify_inval_inode(struct fuse_session *se, fuse_ino_t ino, int fuse_lowlevel_notify_inval_entry(struct fuse_session *se, fuse_ino_t parent, const char *name, size_t namelen); -enum fuse_expire_flags { - FUSE_LL_EXPIRE_ONLY = (1 << 0), -}; - +/** + * Notify to expire or invalidate parent attributes and the dentry + * matching parent/name + * + * Underlying function for fuse_lowlevel_notify_inval_entry(). + * + * In addition to invalidating an entry, it also allows to expire an entry. + * In that case, the entry is not forcefully removed from kernel cache + * but instead the next access to it forces a lookup from the filesystem. + * + * This makes a difference for overmounted dentries, where plain invalidation + * would detach all submounts before dropping the dentry from the cache. + * If only expiry is set on the dentry, then any overmounts are left alone and + * until ->d_revalidate() is called. + * + * Note: ->d_revalidate() is not called for the case of following a submount, + * so invalidation will only be triggered for the non-overmounted case. + * The dentry could also be mounted in a different mount instance, in which case + * any submounts will still be detached. + * + * @param se the session object + * @param parent inode number + * @param name file name + * @param namelen strlen() of file name + * @param flags flags to control if the entry should be expired or invalidated + * @return zero for success, -errno for failure +*/ int fuse_lowlevel_notify_expire_entry(struct fuse_session *se, fuse_ino_t parent, const char *name, size_t namelen, enum fuse_expire_flags flags); diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index 7b9d71043..7d7630925 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -1991,6 +1991,8 @@ void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) bufsize = max_bufsize; } } + if (arg->minor >= 38) + se->conn.capable |= FUSE_CAP_EXPIRE_ONLY; } else { se->conn.max_readahead = 0; }