@@ -542,6 +542,45 @@ struct inode *fuse_ilookup(struct fuse_conn *fc, u64 nodeid,
542542 return NULL ;
543543}
544544
545+ static void fuse_prune_aliases (struct inode * inode )
546+ {
547+ struct dentry * dentry ;
548+
549+ spin_lock (& inode -> i_lock );
550+ hlist_for_each_entry (dentry , & inode -> i_dentry , d_u .d_alias ) {
551+ fuse_invalidate_entry_cache (dentry );
552+ }
553+ spin_unlock (& inode -> i_lock );
554+
555+ d_prune_aliases (inode );
556+ }
557+
558+ static void fuse_invalidate_inode_entry (struct inode * inode )
559+ {
560+ struct dentry * dentry ;
561+
562+ if (S_ISDIR (inode -> i_mode )) {
563+ /* For directories, use d_invalidate to handle children and submounts */
564+ dentry = d_find_alias (inode );
565+ if (dentry ) {
566+ d_invalidate (dentry );
567+ fuse_invalidate_entry_cache (dentry );
568+ dput (dentry );
569+ }
570+ } else {
571+ /* For regular files, just unhash the dentry */
572+ spin_lock (& inode -> i_lock );
573+ hlist_for_each_entry (dentry , & inode -> i_dentry , d_u .d_alias ) {
574+ spin_lock (& dentry -> d_lock );
575+ if (!d_unhashed (dentry ))
576+ __d_drop (dentry );
577+ spin_unlock (& dentry -> d_lock );
578+ fuse_invalidate_entry_cache (dentry );
579+ }
580+ spin_unlock (& inode -> i_lock );
581+ }
582+ }
583+
545584int fuse_reverse_inval_inode (struct fuse_conn * fc , u64 nodeid ,
546585 loff_t offset , loff_t len )
547586{
@@ -559,6 +598,11 @@ int fuse_reverse_inval_inode(struct fuse_conn *fc, u64 nodeid,
559598 fi -> attr_version = atomic64_inc_return (& fc -> attr_version );
560599 spin_unlock (& fi -> lock );
561600
601+ if (fc -> inval_inode_entries )
602+ fuse_invalidate_inode_entry (inode );
603+ else if (fc -> expire_inode_entries )
604+ fuse_prune_aliases (inode );
605+
562606 fuse_invalidate_attr (inode );
563607 forget_all_cached_acls (inode );
564608 if (offset >= 0 ) {
@@ -1374,6 +1418,10 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args,
13741418 fc -> io_uring = 1 ;
13751419 if (flags & FUSE_NO_EXPORT_SUPPORT )
13761420 fm -> sb -> s_export_op = & fuse_export_fid_operations ;
1421+ if (flags & FUSE_INVAL_INODE_ENTRY )
1422+ fc -> inval_inode_entries = 1 ;
1423+ if (flags & FUSE_EXPIRE_INODE_ENTRY )
1424+ fc -> expire_inode_entries = 1 ;
13771425 } else {
13781426 ra_pages = fc -> max_read / PAGE_SIZE ;
13791427 fc -> no_lock = 1 ;
@@ -1424,7 +1472,7 @@ void fuse_send_init(struct fuse_mount *fm)
14241472 FUSE_HANDLE_KILLPRIV_V2 | FUSE_SETXATTR_EXT | FUSE_INIT_EXT |
14251473 FUSE_SECURITY_CTX | FUSE_CREATE_SUPP_GROUP |
14261474 FUSE_HAS_EXPIRE_ONLY | FUSE_DIRECT_IO_ALLOW_MMAP |
1427- FUSE_NO_EXPORT_SUPPORT ;
1475+ FUSE_NO_EXPORT_SUPPORT | FUSE_INVAL_INODE_ENTRY | FUSE_EXPIRE_INODE_ENTRY ;
14281476#ifdef CONFIG_FUSE_DAX
14291477 if (fm -> fc -> dax )
14301478 flags |= FUSE_MAP_ALIGNMENT ;
0 commit comments